From 0e5af65c467b2423a0b857ae3ad98c91acc1e190 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Mon, 11 Nov 2019 11:38:02 +0100 Subject: Include patched FDK-AAC in the repository The initial idea was to get the DAB+ patch into upstream, but since that follows the android source releases, there is no place for a custom DAB+ patch there. So instead of having to maintain a patched fdk-aac that has to have the same .so version as the distribution package on which it is installed, we prefer having a separate fdk-aac-dab library to avoid collision. At that point, there's no reason to keep fdk-aac in a separate repository, as odr-audioenc is the only tool that needs DAB+ encoding support. Including it here simplifies installation, and makes it consistent with toolame-dab, also shipped in this repository. DAB+ decoding support (needed by ODR-SourceCompanion, dablin, etisnoop, welle.io and others) can be done using upstream FDK-AAC. --- fdk-aac/.clang-format | 4 + fdk-aac/.gitignore | 29 + fdk-aac/Android.bp | 53 + fdk-aac/ChangeLog | 48 + fdk-aac/MODULE_LICENSE_FRAUNHOFER | 0 fdk-aac/Makefile.am | 297 + fdk-aac/Makefile.vc | 321 + fdk-aac/NOTICE | 92 + fdk-aac/OWNERS | 2 + fdk-aac/README.md | 7 + fdk-aac/aac-enc.c | 237 + fdk-aac/autogen.sh | 2 + fdk-aac/bootstrap | 4 + fdk-aac/configure.ac | 38 + fdk-aac/documentation/aacDecoder.pdf | Bin 0 -> 500827 bytes fdk-aac/documentation/aacEncoder.pdf | Bin 0 -> 461225 bytes fdk-aac/fdk-aac.pc.in | 11 + fdk-aac/fdk-aac.sym | 18 + fdk-aac/libAACdec/include/aacdecoder_lib.h | 1090 +++ fdk-aac/libAACdec/src/FDK_delay.cpp | 173 + fdk-aac/libAACdec/src/FDK_delay.h | 152 + fdk-aac/libAACdec/src/aac_ram.cpp | 185 + fdk-aac/libAACdec/src/aac_ram.h | 147 + fdk-aac/libAACdec/src/aac_rom.cpp | 3428 ++++++++++ fdk-aac/libAACdec/src/aac_rom.h | 237 + fdk-aac/libAACdec/src/aacdec_drc.cpp | 1355 ++++ fdk-aac/libAACdec/src/aacdec_drc.h | 192 + fdk-aac/libAACdec/src/aacdec_drc_types.h | 220 + fdk-aac/libAACdec/src/aacdec_hcr.cpp | 1498 +++++ fdk-aac/libAACdec/src/aacdec_hcr.h | 128 + fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp | 164 + fdk-aac/libAACdec/src/aacdec_hcr_bit.h | 114 + fdk-aac/libAACdec/src/aacdec_hcr_types.h | 432 ++ fdk-aac/libAACdec/src/aacdec_hcrs.cpp | 1551 +++++ fdk-aac/libAACdec/src/aacdec_hcrs.h | 176 + fdk-aac/libAACdec/src/aacdec_pns.cpp | 361 + fdk-aac/libAACdec/src/aacdec_pns.h | 129 + fdk-aac/libAACdec/src/aacdec_tns.cpp | 361 + fdk-aac/libAACdec/src/aacdec_tns.h | 149 + fdk-aac/libAACdec/src/aacdecoder.cpp | 3464 ++++++++++ fdk-aac/libAACdec/src/aacdecoder.h | 465 ++ fdk-aac/libAACdec/src/aacdecoder_lib.cpp | 2035 ++++++ fdk-aac/libAACdec/src/arm/block_arm.cpp | 142 + fdk-aac/libAACdec/src/block.cpp | 1260 ++++ fdk-aac/libAACdec/src/block.h | 345 + fdk-aac/libAACdec/src/channel.cpp | 924 +++ fdk-aac/libAACdec/src/channel.h | 160 + fdk-aac/libAACdec/src/channelinfo.cpp | 297 + fdk-aac/libAACdec/src/channelinfo.h | 564 ++ fdk-aac/libAACdec/src/conceal.cpp | 2095 ++++++ fdk-aac/libAACdec/src/conceal.h | 152 + fdk-aac/libAACdec/src/conceal_types.h | 203 + fdk-aac/libAACdec/src/ldfiltbank.cpp | 276 + fdk-aac/libAACdec/src/ldfiltbank.h | 112 + fdk-aac/libAACdec/src/overlapadd.h | 120 + fdk-aac/libAACdec/src/pulsedata.cpp | 164 + fdk-aac/libAACdec/src/pulsedata.h | 150 + fdk-aac/libAACdec/src/rvlc.cpp | 1217 ++++ fdk-aac/libAACdec/src/rvlc.h | 153 + fdk-aac/libAACdec/src/rvlc_info.h | 204 + fdk-aac/libAACdec/src/rvlcbit.cpp | 148 + fdk-aac/libAACdec/src/rvlcbit.h | 111 + fdk-aac/libAACdec/src/rvlcconceal.cpp | 787 +++ fdk-aac/libAACdec/src/rvlcconceal.h | 127 + fdk-aac/libAACdec/src/stereo.cpp | 1250 ++++ fdk-aac/libAACdec/src/stereo.h | 211 + fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp | 439 ++ fdk-aac/libAACdec/src/usacdec_ace_d4t64.h | 117 + fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp | 229 + fdk-aac/libAACdec/src/usacdec_ace_ltp.h | 128 + fdk-aac/libAACdec/src/usacdec_acelp.cpp | 1296 ++++ fdk-aac/libAACdec/src/usacdec_acelp.h | 281 + fdk-aac/libAACdec/src/usacdec_const.h | 203 + fdk-aac/libAACdec/src/usacdec_fac.cpp | 745 +++ fdk-aac/libAACdec/src/usacdec_fac.h | 191 + fdk-aac/libAACdec/src/usacdec_lpc.cpp | 1194 ++++ fdk-aac/libAACdec/src/usacdec_lpc.h | 190 + fdk-aac/libAACdec/src/usacdec_lpd.cpp | 2029 ++++++ fdk-aac/libAACdec/src/usacdec_lpd.h | 198 + fdk-aac/libAACdec/src/usacdec_rom.cpp | 1504 +++++ fdk-aac/libAACdec/src/usacdec_rom.h | 154 + fdk-aac/libAACenc/include/aacenc_lib.h | 1733 +++++ fdk-aac/libAACenc/src/aacEnc_ram.cpp | 208 + fdk-aac/libAACenc/src/aacEnc_ram.h | 249 + fdk-aac/libAACenc/src/aacEnc_rom.cpp | 2486 +++++++ fdk-aac/libAACenc/src/aacEnc_rom.h | 217 + fdk-aac/libAACenc/src/aacenc.cpp | 1057 +++ fdk-aac/libAACenc/src/aacenc.h | 394 ++ fdk-aac/libAACenc/src/aacenc_lib.cpp | 2575 ++++++++ fdk-aac/libAACenc/src/aacenc_pns.cpp | 541 ++ fdk-aac/libAACenc/src/aacenc_pns.h | 124 + fdk-aac/libAACenc/src/aacenc_tns.cpp | 1210 ++++ fdk-aac/libAACenc/src/aacenc_tns.h | 213 + fdk-aac/libAACenc/src/adj_thr.cpp | 2924 +++++++++ fdk-aac/libAACenc/src/adj_thr.h | 166 + fdk-aac/libAACenc/src/adj_thr_data.h | 175 + fdk-aac/libAACenc/src/band_nrg.cpp | 361 + fdk-aac/libAACenc/src/band_nrg.h | 142 + fdk-aac/libAACenc/src/bandwidth.cpp | 360 + fdk-aac/libAACenc/src/bandwidth.h | 114 + fdk-aac/libAACenc/src/bit_cnt.cpp | 950 +++ fdk-aac/libAACenc/src/bit_cnt.h | 200 + fdk-aac/libAACenc/src/bitenc.cpp | 1362 ++++ fdk-aac/libAACenc/src/bitenc.h | 184 + fdk-aac/libAACenc/src/block_switch.cpp | 582 ++ fdk-aac/libAACenc/src/block_switch.h | 162 + fdk-aac/libAACenc/src/channel_map.cpp | 664 ++ fdk-aac/libAACenc/src/channel_map.h | 136 + fdk-aac/libAACenc/src/chaosmeasure.cpp | 191 + fdk-aac/libAACenc/src/chaosmeasure.h | 112 + fdk-aac/libAACenc/src/dyn_bits.cpp | 665 ++ fdk-aac/libAACenc/src/dyn_bits.h | 160 + fdk-aac/libAACenc/src/grp_data.cpp | 264 + fdk-aac/libAACenc/src/grp_data.h | 123 + fdk-aac/libAACenc/src/intensity.cpp | 810 +++ fdk-aac/libAACenc/src/intensity.h | 121 + fdk-aac/libAACenc/src/interface.h | 168 + fdk-aac/libAACenc/src/line_pe.cpp | 234 + fdk-aac/libAACenc/src/line_pe.h | 148 + fdk-aac/libAACenc/src/metadata_compressor.cpp | 1579 +++++ fdk-aac/libAACenc/src/metadata_compressor.h | 255 + fdk-aac/libAACenc/src/metadata_main.cpp | 1191 ++++ fdk-aac/libAACenc/src/metadata_main.h | 226 + fdk-aac/libAACenc/src/mps_main.cpp | 529 ++ fdk-aac/libAACenc/src/mps_main.h | 270 + fdk-aac/libAACenc/src/ms_stereo.cpp | 295 + fdk-aac/libAACenc/src/ms_stereo.h | 117 + fdk-aac/libAACenc/src/noisedet.cpp | 235 + fdk-aac/libAACenc/src/noisedet.h | 116 + fdk-aac/libAACenc/src/pns_func.h | 138 + fdk-aac/libAACenc/src/pnsparam.cpp | 574 ++ fdk-aac/libAACenc/src/pnsparam.h | 149 + fdk-aac/libAACenc/src/pre_echo_control.cpp | 176 + fdk-aac/libAACenc/src/pre_echo_control.h | 118 + fdk-aac/libAACenc/src/psy_configuration.cpp | 801 +++ fdk-aac/libAACenc/src/psy_configuration.h | 171 + fdk-aac/libAACenc/src/psy_const.h | 169 + fdk-aac/libAACenc/src/psy_data.h | 169 + fdk-aac/libAACenc/src/psy_main.cpp | 1348 ++++ fdk-aac/libAACenc/src/psy_main.h | 161 + fdk-aac/libAACenc/src/qc_data.h | 299 + fdk-aac/libAACenc/src/qc_main.cpp | 1555 +++++ fdk-aac/libAACenc/src/qc_main.h | 158 + fdk-aac/libAACenc/src/quantize.cpp | 401 ++ fdk-aac/libAACenc/src/quantize.h | 127 + fdk-aac/libAACenc/src/sf_estim.cpp | 1292 ++++ fdk-aac/libAACenc/src/sf_estim.h | 124 + fdk-aac/libAACenc/src/spreading.cpp | 125 + fdk-aac/libAACenc/src/spreading.h | 113 + fdk-aac/libAACenc/src/tns_func.h | 129 + fdk-aac/libAACenc/src/tonality.cpp | 219 + fdk-aac/libAACenc/src/tonality.h | 115 + fdk-aac/libAACenc/src/transform.cpp | 294 + fdk-aac/libAACenc/src/transform.h | 163 + fdk-aac/libArithCoding/include/ac_arith_coder.h | 142 + fdk-aac/libArithCoding/src/ac_arith_coder.cpp | 785 +++ fdk-aac/libDRCdec/include/FDK_drcDecLib.h | 313 + fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp | 891 +++ fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp | 445 ++ fdk-aac/libDRCdec/src/drcDec_gainDecoder.h | 264 + fdk-aac/libDRCdec/src/drcDec_reader.cpp | 2029 ++++++ fdk-aac/libDRCdec/src/drcDec_reader.h | 130 + fdk-aac/libDRCdec/src/drcDec_rom.cpp | 323 + fdk-aac/libDRCdec/src/drcDec_rom.h | 120 + fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp | 3099 +++++++++ fdk-aac/libDRCdec/src/drcDec_selectionProcess.h | 217 + fdk-aac/libDRCdec/src/drcDec_tools.cpp | 371 ++ fdk-aac/libDRCdec/src/drcDec_tools.h | 146 + fdk-aac/libDRCdec/src/drcDec_types.h | 428 ++ fdk-aac/libDRCdec/src/drcDecoder.h | 142 + fdk-aac/libDRCdec/src/drcGainDec_init.cpp | 344 + fdk-aac/libDRCdec/src/drcGainDec_init.h | 120 + fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp | 715 ++ fdk-aac/libDRCdec/src/drcGainDec_preprocess.h | 111 + fdk-aac/libDRCdec/src/drcGainDec_process.cpp | 532 ++ fdk-aac/libDRCdec/src/drcGainDec_process.h | 119 + fdk-aac/libFDK/include/FDK_archdef.h | 270 + fdk-aac/libFDK/include/FDK_bitbuffer.h | 177 + fdk-aac/libFDK/include/FDK_bitstream.h | 642 ++ fdk-aac/libFDK/include/FDK_core.h | 122 + fdk-aac/libFDK/include/FDK_crc.h | 225 + fdk-aac/libFDK/include/FDK_decorrelate.h | 314 + fdk-aac/libFDK/include/FDK_hybrid.h | 255 + fdk-aac/libFDK/include/FDK_lpc.h | 218 + fdk-aac/libFDK/include/FDK_matrixCalloc.h | 230 + fdk-aac/libFDK/include/FDK_qmf_domain.h | 416 ++ fdk-aac/libFDK/include/FDK_tools_rom.h | 398 ++ fdk-aac/libFDK/include/FDK_trigFcts.h | 258 + fdk-aac/libFDK/include/abs.h | 136 + fdk-aac/libFDK/include/arm/clz_arm.h | 164 + fdk-aac/libFDK/include/arm/cplx_mul_arm.h | 201 + fdk-aac/libFDK/include/arm/fixmadd_arm.h | 220 + fdk-aac/libFDK/include/arm/fixmul_arm.h | 198 + fdk-aac/libFDK/include/arm/scale_arm.h | 163 + fdk-aac/libFDK/include/arm/scramble_arm.h | 174 + fdk-aac/libFDK/include/autocorr2nd.h | 137 + fdk-aac/libFDK/include/clz.h | 205 + fdk-aac/libFDK/include/common_fix.h | 449 ++ fdk-aac/libFDK/include/cplx_mul.h | 266 + fdk-aac/libFDK/include/dct.h | 171 + fdk-aac/libFDK/include/fft.h | 263 + fdk-aac/libFDK/include/fft_rad2.h | 121 + fdk-aac/libFDK/include/fixmadd.h | 333 + fdk-aac/libFDK/include/fixminmax.h | 131 + fdk-aac/libFDK/include/fixmul.h | 298 + fdk-aac/libFDK/include/fixpoint_math.h | 921 +++ fdk-aac/libFDK/include/huff_nodes.h | 258 + fdk-aac/libFDK/include/mdct.h | 253 + fdk-aac/libFDK/include/mips/abs_mips.h | 125 + fdk-aac/libFDK/include/mips/clz_mips.h | 134 + fdk-aac/libFDK/include/mips/cplx_mul_mips.h | 133 + fdk-aac/libFDK/include/mips/fixmul_mips.h | 130 + fdk-aac/libFDK/include/mips/scale_mips.h | 122 + fdk-aac/libFDK/include/mips/scramble_mips.h | 133 + fdk-aac/libFDK/include/nlc_dec.h | 187 + fdk-aac/libFDK/include/ppc/clz_ppc.h | 102 + fdk-aac/libFDK/include/ppc/fixmul_ppc.h | 115 + fdk-aac/libFDK/include/qmf.h | 301 + fdk-aac/libFDK/include/qmf_pcm.h | 405 ++ fdk-aac/libFDK/include/scale.h | 298 + fdk-aac/libFDK/include/scramble.h | 153 + fdk-aac/libFDK/include/x86/abs_x86.h | 123 + fdk-aac/libFDK/include/x86/clz_x86.h | 165 + fdk-aac/libFDK/include/x86/fixmul_x86.h | 187 + fdk-aac/libFDK/include/x86/fixpoint_math_x86.h | 208 + fdk-aac/libFDK/src/FDK_bitbuffer.cpp | 489 ++ fdk-aac/libFDK/src/FDK_core.cpp | 145 + fdk-aac/libFDK/src/FDK_crc.cpp | 526 ++ fdk-aac/libFDK/src/FDK_decorrelate.cpp | 1746 +++++ fdk-aac/libFDK/src/FDK_hybrid.cpp | 813 +++ fdk-aac/libFDK/src/FDK_lpc.cpp | 487 ++ fdk-aac/libFDK/src/FDK_matrixCalloc.cpp | 315 + fdk-aac/libFDK/src/FDK_qmf_domain.cpp | 1018 +++ fdk-aac/libFDK/src/FDK_tools_rom.cpp | 7274 +++++++++++++++++++++ fdk-aac/libFDK/src/FDK_trigFcts.cpp | 340 + fdk-aac/libFDK/src/arm/fft_rad2_arm.cpp | 321 + fdk-aac/libFDK/src/arm/scale_arm.cpp | 174 + fdk-aac/libFDK/src/autocorr2nd.cpp | 293 + fdk-aac/libFDK/src/dct.cpp | 568 ++ fdk-aac/libFDK/src/fft.cpp | 1922 ++++++ fdk-aac/libFDK/src/fft_rad2.cpp | 324 + fdk-aac/libFDK/src/fixpoint_math.cpp | 900 +++ fdk-aac/libFDK/src/huff_nodes.cpp | 1084 +++ fdk-aac/libFDK/src/mdct.cpp | 730 +++ fdk-aac/libFDK/src/mips/fft_rad2_mips.cpp | 165 + fdk-aac/libFDK/src/mips/mips_fft_twiddles.cpp | 931 +++ fdk-aac/libFDK/src/mips/scale_mips.cpp | 133 + fdk-aac/libFDK/src/nlc_dec.cpp | 1071 +++ fdk-aac/libFDK/src/qmf.cpp | 1135 ++++ fdk-aac/libFDK/src/scale.cpp | 720 ++ fdk-aac/libMpegTPDec/include/tp_data.h | 466 ++ fdk-aac/libMpegTPDec/include/tpdec_lib.h | 664 ++ fdk-aac/libMpegTPDec/src/tp_version.h | 118 + fdk-aac/libMpegTPDec/src/tpdec_adif.cpp | 158 + fdk-aac/libMpegTPDec/src/tpdec_adif.h | 134 + fdk-aac/libMpegTPDec/src/tpdec_adts.cpp | 392 ++ fdk-aac/libMpegTPDec/src/tpdec_adts.h | 234 + fdk-aac/libMpegTPDec/src/tpdec_asc.cpp | 2592 ++++++++ fdk-aac/libMpegTPDec/src/tpdec_drm.cpp | 148 + fdk-aac/libMpegTPDec/src/tpdec_drm.h | 202 + fdk-aac/libMpegTPDec/src/tpdec_latm.cpp | 676 ++ fdk-aac/libMpegTPDec/src/tpdec_latm.h | 191 + fdk-aac/libMpegTPDec/src/tpdec_lib.cpp | 1820 ++++++ fdk-aac/libMpegTPEnc/include/tp_data.h | 466 ++ fdk-aac/libMpegTPEnc/include/tpenc_lib.h | 339 + fdk-aac/libMpegTPEnc/src/tp_version.h | 118 + fdk-aac/libMpegTPEnc/src/tpenc_adif.cpp | 186 + fdk-aac/libMpegTPEnc/src/tpenc_adif.h | 146 + fdk-aac/libMpegTPEnc/src/tpenc_adts.cpp | 319 + fdk-aac/libMpegTPEnc/src/tpenc_adts.h | 208 + fdk-aac/libMpegTPEnc/src/tpenc_asc.cpp | 996 +++ fdk-aac/libMpegTPEnc/src/tpenc_asc.h | 147 + fdk-aac/libMpegTPEnc/src/tpenc_dab.cpp | 467 ++ fdk-aac/libMpegTPEnc/src/tpenc_dab.h | 217 + fdk-aac/libMpegTPEnc/src/tpenc_latm.cpp | 850 +++ fdk-aac/libMpegTPEnc/src/tpenc_latm.h | 274 + fdk-aac/libMpegTPEnc/src/tpenc_lib.cpp | 713 ++ fdk-aac/libPCMutils/include/limiter.h | 281 + fdk-aac/libPCMutils/include/pcm_utils.h | 131 + fdk-aac/libPCMutils/include/pcmdmx_lib.h | 460 ++ fdk-aac/libPCMutils/src/limiter.cpp | 570 ++ fdk-aac/libPCMutils/src/pcm_utils.cpp | 195 + fdk-aac/libPCMutils/src/pcmdmx_lib.cpp | 2662 ++++++++ fdk-aac/libPCMutils/src/version.h | 119 + fdk-aac/libSACdec/include/sac_dec_errorcodes.h | 157 + fdk-aac/libSACdec/include/sac_dec_lib.h | 477 ++ fdk-aac/libSACdec/src/sac_bitdec.cpp | 2167 ++++++ fdk-aac/libSACdec/src/sac_bitdec.h | 161 + fdk-aac/libSACdec/src/sac_calcM1andM2.cpp | 848 +++ fdk-aac/libSACdec/src/sac_calcM1andM2.h | 129 + fdk-aac/libSACdec/src/sac_dec.cpp | 1509 +++++ fdk-aac/libSACdec/src/sac_dec.h | 539 ++ fdk-aac/libSACdec/src/sac_dec_conceal.cpp | 392 ++ fdk-aac/libSACdec/src/sac_dec_conceal.h | 187 + fdk-aac/libSACdec/src/sac_dec_interface.h | 335 + fdk-aac/libSACdec/src/sac_dec_lib.cpp | 1995 ++++++ fdk-aac/libSACdec/src/sac_dec_ssc_struct.h | 283 + fdk-aac/libSACdec/src/sac_process.cpp | 1066 +++ fdk-aac/libSACdec/src/sac_process.h | 297 + fdk-aac/libSACdec/src/sac_qmf.cpp | 156 + fdk-aac/libSACdec/src/sac_qmf.h | 143 + fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp | 680 ++ fdk-aac/libSACdec/src/sac_reshapeBBEnv.h | 114 + fdk-aac/libSACdec/src/sac_rom.cpp | 709 ++ fdk-aac/libSACdec/src/sac_rom.h | 230 + fdk-aac/libSACdec/src/sac_smoothing.cpp | 295 + fdk-aac/libSACdec/src/sac_smoothing.h | 114 + fdk-aac/libSACdec/src/sac_stp.cpp | 548 ++ fdk-aac/libSACdec/src/sac_stp.h | 115 + fdk-aac/libSACdec/src/sac_tsd.cpp | 353 + fdk-aac/libSACdec/src/sac_tsd.h | 167 + fdk-aac/libSACenc/include/sacenc_lib.h | 405 ++ fdk-aac/libSACenc/src/sacenc_bitstream.cpp | 826 +++ fdk-aac/libSACenc/src/sacenc_bitstream.h | 296 + fdk-aac/libSACenc/src/sacenc_const.h | 126 + fdk-aac/libSACenc/src/sacenc_delay.cpp | 472 ++ fdk-aac/libSACenc/src/sacenc_delay.h | 175 + fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.cpp | 639 ++ fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.h | 134 + fdk-aac/libSACenc/src/sacenc_filter.cpp | 207 + fdk-aac/libSACenc/src/sacenc_filter.h | 133 + fdk-aac/libSACenc/src/sacenc_framewindowing.cpp | 568 ++ fdk-aac/libSACenc/src/sacenc_framewindowing.h | 181 + fdk-aac/libSACenc/src/sacenc_huff_tab.cpp | 997 +++ fdk-aac/libSACenc/src/sacenc_huff_tab.h | 222 + fdk-aac/libSACenc/src/sacenc_lib.cpp | 2042 ++++++ fdk-aac/libSACenc/src/sacenc_nlc_enc.cpp | 1442 ++++ fdk-aac/libSACenc/src/sacenc_nlc_enc.h | 141 + fdk-aac/libSACenc/src/sacenc_onsetdetect.cpp | 381 ++ fdk-aac/libSACenc/src/sacenc_onsetdetect.h | 154 + fdk-aac/libSACenc/src/sacenc_paramextract.cpp | 725 ++ fdk-aac/libSACenc/src/sacenc_paramextract.h | 214 + fdk-aac/libSACenc/src/sacenc_staticgain.cpp | 446 ++ fdk-aac/libSACenc/src/sacenc_staticgain.h | 177 + fdk-aac/libSACenc/src/sacenc_tree.cpp | 488 ++ fdk-aac/libSACenc/src/sacenc_tree.h | 168 + fdk-aac/libSACenc/src/sacenc_vectorfunctions.cpp | 450 ++ fdk-aac/libSACenc/src/sacenc_vectorfunctions.h | 488 ++ fdk-aac/libSBRdec/include/sbrdecoder.h | 401 ++ fdk-aac/libSBRdec/src/HFgen_preFlat.cpp | 993 +++ fdk-aac/libSBRdec/src/HFgen_preFlat.h | 132 + fdk-aac/libSBRdec/src/arm/lpp_tran_arm.cpp | 159 + fdk-aac/libSBRdec/src/env_calc.cpp | 3158 +++++++++ fdk-aac/libSBRdec/src/env_calc.h | 182 + fdk-aac/libSBRdec/src/env_dec.cpp | 873 +++ fdk-aac/libSBRdec/src/env_dec.h | 119 + fdk-aac/libSBRdec/src/env_extr.cpp | 1728 +++++ fdk-aac/libSBRdec/src/env_extr.h | 415 ++ fdk-aac/libSBRdec/src/hbe.cpp | 2202 +++++++ fdk-aac/libSBRdec/src/hbe.h | 200 + fdk-aac/libSBRdec/src/huff_dec.cpp | 137 + fdk-aac/libSBRdec/src/huff_dec.h | 117 + fdk-aac/libSBRdec/src/lpp_tran.cpp | 1471 +++++ fdk-aac/libSBRdec/src/lpp_tran.h | 275 + fdk-aac/libSBRdec/src/psbitdec.cpp | 594 ++ fdk-aac/libSBRdec/src/psbitdec.h | 116 + fdk-aac/libSBRdec/src/psdec.cpp | 722 ++ fdk-aac/libSBRdec/src/psdec.h | 333 + fdk-aac/libSBRdec/src/psdec_drm.cpp | 108 + fdk-aac/libSBRdec/src/psdec_drm.h | 113 + fdk-aac/libSBRdec/src/psdecrom_drm.cpp | 108 + fdk-aac/libSBRdec/src/pvc_dec.cpp | 683 ++ fdk-aac/libSBRdec/src/pvc_dec.h | 238 + fdk-aac/libSBRdec/src/sbr_crc.cpp | 192 + fdk-aac/libSBRdec/src/sbr_crc.h | 138 + fdk-aac/libSBRdec/src/sbr_deb.cpp | 108 + fdk-aac/libSBRdec/src/sbr_deb.h | 113 + fdk-aac/libSBRdec/src/sbr_dec.cpp | 1480 +++++ fdk-aac/libSBRdec/src/sbr_dec.h | 204 + fdk-aac/libSBRdec/src/sbr_ram.cpp | 191 + fdk-aac/libSBRdec/src/sbr_ram.h | 186 + fdk-aac/libSBRdec/src/sbr_rom.cpp | 1705 +++++ fdk-aac/libSBRdec/src/sbr_rom.h | 216 + fdk-aac/libSBRdec/src/sbrdec_drc.cpp | 528 ++ fdk-aac/libSBRdec/src/sbrdec_drc.h | 149 + fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp | 835 +++ fdk-aac/libSBRdec/src/sbrdec_freq_sca.h | 127 + fdk-aac/libSBRdec/src/sbrdecoder.cpp | 2023 ++++++ fdk-aac/libSBRdec/src/transcendent.h | 372 ++ fdk-aac/libSBRenc/include/sbr_encoder.h | 483 ++ fdk-aac/libSBRenc/src/bit_sbr.cpp | 1049 +++ fdk-aac/libSBRenc/src/bit_sbr.h | 267 + fdk-aac/libSBRenc/src/cmondata.h | 127 + fdk-aac/libSBRenc/src/code_env.cpp | 602 ++ fdk-aac/libSBRenc/src/code_env.h | 161 + fdk-aac/libSBRenc/src/env_bit.cpp | 257 + fdk-aac/libSBRenc/src/env_bit.h | 135 + fdk-aac/libSBRenc/src/env_est.cpp | 1986 ++++++ fdk-aac/libSBRenc/src/env_est.h | 223 + fdk-aac/libSBRenc/src/fram_gen.cpp | 1965 ++++++ fdk-aac/libSBRenc/src/fram_gen.h | 343 + fdk-aac/libSBRenc/src/invf_est.cpp | 610 ++ fdk-aac/libSBRenc/src/invf_est.h | 181 + fdk-aac/libSBRenc/src/mh_det.cpp | 1396 ++++ fdk-aac/libSBRenc/src/mh_det.h | 204 + fdk-aac/libSBRenc/src/nf_est.cpp | 612 ++ fdk-aac/libSBRenc/src/nf_est.h | 185 + fdk-aac/libSBRenc/src/ps_bitenc.cpp | 624 ++ fdk-aac/libSBRenc/src/ps_bitenc.h | 173 + fdk-aac/libSBRenc/src/ps_const.h | 150 + fdk-aac/libSBRenc/src/ps_encode.cpp | 1031 +++ fdk-aac/libSBRenc/src/ps_encode.h | 185 + fdk-aac/libSBRenc/src/ps_main.cpp | 606 ++ fdk-aac/libSBRenc/src/ps_main.h | 270 + fdk-aac/libSBRenc/src/resampler.cpp | 444 ++ fdk-aac/libSBRenc/src/resampler.h | 159 + fdk-aac/libSBRenc/src/sbr.h | 194 + fdk-aac/libSBRenc/src/sbr_def.h | 276 + fdk-aac/libSBRenc/src/sbr_encoder.cpp | 2577 ++++++++ fdk-aac/libSBRenc/src/sbr_misc.cpp | 265 + fdk-aac/libSBRenc/src/sbr_misc.h | 127 + fdk-aac/libSBRenc/src/sbrenc_freq_sca.cpp | 674 ++ fdk-aac/libSBRenc/src/sbrenc_freq_sca.h | 132 + fdk-aac/libSBRenc/src/sbrenc_ram.cpp | 249 + fdk-aac/libSBRenc/src/sbrenc_ram.h | 199 + fdk-aac/libSBRenc/src/sbrenc_rom.cpp | 910 +++ fdk-aac/libSBRenc/src/sbrenc_rom.h | 145 + fdk-aac/libSBRenc/src/ton_corr.cpp | 891 +++ fdk-aac/libSBRenc/src/ton_corr.h | 258 + fdk-aac/libSBRenc/src/tran_det.cpp | 1092 ++++ fdk-aac/libSBRenc/src/tran_det.h | 191 + fdk-aac/libSYS/include/FDK_audio.h | 827 +++ fdk-aac/libSYS/include/genericStds.h | 584 ++ fdk-aac/libSYS/include/machine_type.h | 411 ++ fdk-aac/libSYS/include/syslib_channelMapDescr.h | 202 + fdk-aac/libSYS/src/genericStds.cpp | 419 ++ fdk-aac/libSYS/src/syslib_channelMapDescr.cpp | 315 + fdk-aac/m4/.gitkeep | 0 fdk-aac/wavreader.c | 193 + fdk-aac/wavreader.h | 37 + fdk-aac/win32/getopt.h | 904 +++ 431 files changed, 218009 insertions(+) create mode 100644 fdk-aac/.clang-format create mode 100644 fdk-aac/.gitignore create mode 100644 fdk-aac/Android.bp create mode 100644 fdk-aac/ChangeLog create mode 100644 fdk-aac/MODULE_LICENSE_FRAUNHOFER create mode 100644 fdk-aac/Makefile.am create mode 100644 fdk-aac/Makefile.vc create mode 100644 fdk-aac/NOTICE create mode 100644 fdk-aac/OWNERS create mode 100644 fdk-aac/README.md create mode 100644 fdk-aac/aac-enc.c create mode 100755 fdk-aac/autogen.sh create mode 100755 fdk-aac/bootstrap create mode 100644 fdk-aac/configure.ac create mode 100644 fdk-aac/documentation/aacDecoder.pdf create mode 100644 fdk-aac/documentation/aacEncoder.pdf create mode 100644 fdk-aac/fdk-aac.pc.in create mode 100644 fdk-aac/fdk-aac.sym create mode 100644 fdk-aac/libAACdec/include/aacdecoder_lib.h create mode 100644 fdk-aac/libAACdec/src/FDK_delay.cpp create mode 100644 fdk-aac/libAACdec/src/FDK_delay.h create mode 100644 fdk-aac/libAACdec/src/aac_ram.cpp create mode 100644 fdk-aac/libAACdec/src/aac_ram.h create mode 100644 fdk-aac/libAACdec/src/aac_rom.cpp create mode 100644 fdk-aac/libAACdec/src/aac_rom.h create mode 100644 fdk-aac/libAACdec/src/aacdec_drc.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_drc.h create mode 100644 fdk-aac/libAACdec/src/aacdec_drc_types.h create mode 100644 fdk-aac/libAACdec/src/aacdec_hcr.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_hcr.h create mode 100644 fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_hcr_bit.h create mode 100644 fdk-aac/libAACdec/src/aacdec_hcr_types.h create mode 100644 fdk-aac/libAACdec/src/aacdec_hcrs.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_hcrs.h create mode 100644 fdk-aac/libAACdec/src/aacdec_pns.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_pns.h create mode 100644 fdk-aac/libAACdec/src/aacdec_tns.cpp create mode 100644 fdk-aac/libAACdec/src/aacdec_tns.h create mode 100644 fdk-aac/libAACdec/src/aacdecoder.cpp create mode 100644 fdk-aac/libAACdec/src/aacdecoder.h create mode 100644 fdk-aac/libAACdec/src/aacdecoder_lib.cpp create mode 100644 fdk-aac/libAACdec/src/arm/block_arm.cpp create mode 100644 fdk-aac/libAACdec/src/block.cpp create mode 100644 fdk-aac/libAACdec/src/block.h create mode 100644 fdk-aac/libAACdec/src/channel.cpp create mode 100644 fdk-aac/libAACdec/src/channel.h create mode 100644 fdk-aac/libAACdec/src/channelinfo.cpp create mode 100644 fdk-aac/libAACdec/src/channelinfo.h create mode 100644 fdk-aac/libAACdec/src/conceal.cpp create mode 100644 fdk-aac/libAACdec/src/conceal.h create mode 100644 fdk-aac/libAACdec/src/conceal_types.h create mode 100644 fdk-aac/libAACdec/src/ldfiltbank.cpp create mode 100644 fdk-aac/libAACdec/src/ldfiltbank.h create mode 100644 fdk-aac/libAACdec/src/overlapadd.h create mode 100644 fdk-aac/libAACdec/src/pulsedata.cpp create mode 100644 fdk-aac/libAACdec/src/pulsedata.h create mode 100644 fdk-aac/libAACdec/src/rvlc.cpp create mode 100644 fdk-aac/libAACdec/src/rvlc.h create mode 100644 fdk-aac/libAACdec/src/rvlc_info.h create mode 100644 fdk-aac/libAACdec/src/rvlcbit.cpp create mode 100644 fdk-aac/libAACdec/src/rvlcbit.h create mode 100644 fdk-aac/libAACdec/src/rvlcconceal.cpp create mode 100644 fdk-aac/libAACdec/src/rvlcconceal.h create mode 100644 fdk-aac/libAACdec/src/stereo.cpp create mode 100644 fdk-aac/libAACdec/src/stereo.h create mode 100644 fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_ace_d4t64.h create mode 100644 fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_ace_ltp.h create mode 100644 fdk-aac/libAACdec/src/usacdec_acelp.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_acelp.h create mode 100644 fdk-aac/libAACdec/src/usacdec_const.h create mode 100644 fdk-aac/libAACdec/src/usacdec_fac.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_fac.h create mode 100644 fdk-aac/libAACdec/src/usacdec_lpc.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_lpc.h create mode 100644 fdk-aac/libAACdec/src/usacdec_lpd.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_lpd.h create mode 100644 fdk-aac/libAACdec/src/usacdec_rom.cpp create mode 100644 fdk-aac/libAACdec/src/usacdec_rom.h create mode 100644 fdk-aac/libAACenc/include/aacenc_lib.h create mode 100644 fdk-aac/libAACenc/src/aacEnc_ram.cpp create mode 100644 fdk-aac/libAACenc/src/aacEnc_ram.h create mode 100644 fdk-aac/libAACenc/src/aacEnc_rom.cpp create mode 100644 fdk-aac/libAACenc/src/aacEnc_rom.h create mode 100644 fdk-aac/libAACenc/src/aacenc.cpp create mode 100644 fdk-aac/libAACenc/src/aacenc.h create mode 100644 fdk-aac/libAACenc/src/aacenc_lib.cpp create mode 100644 fdk-aac/libAACenc/src/aacenc_pns.cpp create mode 100644 fdk-aac/libAACenc/src/aacenc_pns.h create mode 100644 fdk-aac/libAACenc/src/aacenc_tns.cpp create mode 100644 fdk-aac/libAACenc/src/aacenc_tns.h create mode 100644 fdk-aac/libAACenc/src/adj_thr.cpp create mode 100644 fdk-aac/libAACenc/src/adj_thr.h create mode 100644 fdk-aac/libAACenc/src/adj_thr_data.h create mode 100644 fdk-aac/libAACenc/src/band_nrg.cpp create mode 100644 fdk-aac/libAACenc/src/band_nrg.h create mode 100644 fdk-aac/libAACenc/src/bandwidth.cpp create mode 100644 fdk-aac/libAACenc/src/bandwidth.h create mode 100644 fdk-aac/libAACenc/src/bit_cnt.cpp create mode 100644 fdk-aac/libAACenc/src/bit_cnt.h create mode 100644 fdk-aac/libAACenc/src/bitenc.cpp create mode 100644 fdk-aac/libAACenc/src/bitenc.h create mode 100644 fdk-aac/libAACenc/src/block_switch.cpp create mode 100644 fdk-aac/libAACenc/src/block_switch.h create mode 100644 fdk-aac/libAACenc/src/channel_map.cpp create mode 100644 fdk-aac/libAACenc/src/channel_map.h create mode 100644 fdk-aac/libAACenc/src/chaosmeasure.cpp create mode 100644 fdk-aac/libAACenc/src/chaosmeasure.h create mode 100644 fdk-aac/libAACenc/src/dyn_bits.cpp create mode 100644 fdk-aac/libAACenc/src/dyn_bits.h create mode 100644 fdk-aac/libAACenc/src/grp_data.cpp create mode 100644 fdk-aac/libAACenc/src/grp_data.h create mode 100644 fdk-aac/libAACenc/src/intensity.cpp create mode 100644 fdk-aac/libAACenc/src/intensity.h create mode 100644 fdk-aac/libAACenc/src/interface.h create mode 100644 fdk-aac/libAACenc/src/line_pe.cpp create mode 100644 fdk-aac/libAACenc/src/line_pe.h create mode 100644 fdk-aac/libAACenc/src/metadata_compressor.cpp create mode 100644 fdk-aac/libAACenc/src/metadata_compressor.h create mode 100644 fdk-aac/libAACenc/src/metadata_main.cpp create mode 100644 fdk-aac/libAACenc/src/metadata_main.h create mode 100644 fdk-aac/libAACenc/src/mps_main.cpp create mode 100644 fdk-aac/libAACenc/src/mps_main.h create mode 100644 fdk-aac/libAACenc/src/ms_stereo.cpp create mode 100644 fdk-aac/libAACenc/src/ms_stereo.h create mode 100644 fdk-aac/libAACenc/src/noisedet.cpp create mode 100644 fdk-aac/libAACenc/src/noisedet.h create mode 100644 fdk-aac/libAACenc/src/pns_func.h create mode 100644 fdk-aac/libAACenc/src/pnsparam.cpp create mode 100644 fdk-aac/libAACenc/src/pnsparam.h create mode 100644 fdk-aac/libAACenc/src/pre_echo_control.cpp create mode 100644 fdk-aac/libAACenc/src/pre_echo_control.h create mode 100644 fdk-aac/libAACenc/src/psy_configuration.cpp create mode 100644 fdk-aac/libAACenc/src/psy_configuration.h create mode 100644 fdk-aac/libAACenc/src/psy_const.h create mode 100644 fdk-aac/libAACenc/src/psy_data.h create mode 100644 fdk-aac/libAACenc/src/psy_main.cpp create mode 100644 fdk-aac/libAACenc/src/psy_main.h create mode 100644 fdk-aac/libAACenc/src/qc_data.h create mode 100644 fdk-aac/libAACenc/src/qc_main.cpp create mode 100644 fdk-aac/libAACenc/src/qc_main.h create mode 100644 fdk-aac/libAACenc/src/quantize.cpp create mode 100644 fdk-aac/libAACenc/src/quantize.h create mode 100644 fdk-aac/libAACenc/src/sf_estim.cpp create mode 100644 fdk-aac/libAACenc/src/sf_estim.h create mode 100644 fdk-aac/libAACenc/src/spreading.cpp create mode 100644 fdk-aac/libAACenc/src/spreading.h create mode 100644 fdk-aac/libAACenc/src/tns_func.h create mode 100644 fdk-aac/libAACenc/src/tonality.cpp create mode 100644 fdk-aac/libAACenc/src/tonality.h create mode 100644 fdk-aac/libAACenc/src/transform.cpp create mode 100644 fdk-aac/libAACenc/src/transform.h create mode 100644 fdk-aac/libArithCoding/include/ac_arith_coder.h create mode 100644 fdk-aac/libArithCoding/src/ac_arith_coder.cpp create mode 100644 fdk-aac/libDRCdec/include/FDK_drcDecLib.h create mode 100644 fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_gainDecoder.h create mode 100644 fdk-aac/libDRCdec/src/drcDec_reader.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_reader.h create mode 100644 fdk-aac/libDRCdec/src/drcDec_rom.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_rom.h create mode 100644 fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_selectionProcess.h create mode 100644 fdk-aac/libDRCdec/src/drcDec_tools.cpp create mode 100644 fdk-aac/libDRCdec/src/drcDec_tools.h create mode 100644 fdk-aac/libDRCdec/src/drcDec_types.h create mode 100644 fdk-aac/libDRCdec/src/drcDecoder.h create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_init.cpp create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_init.h create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_preprocess.h create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_process.cpp create mode 100644 fdk-aac/libDRCdec/src/drcGainDec_process.h create mode 100644 fdk-aac/libFDK/include/FDK_archdef.h create mode 100644 fdk-aac/libFDK/include/FDK_bitbuffer.h create mode 100644 fdk-aac/libFDK/include/FDK_bitstream.h create mode 100644 fdk-aac/libFDK/include/FDK_core.h create mode 100644 fdk-aac/libFDK/include/FDK_crc.h create mode 100644 fdk-aac/libFDK/include/FDK_decorrelate.h create mode 100644 fdk-aac/libFDK/include/FDK_hybrid.h create mode 100644 fdk-aac/libFDK/include/FDK_lpc.h create mode 100644 fdk-aac/libFDK/include/FDK_matrixCalloc.h create mode 100644 fdk-aac/libFDK/include/FDK_qmf_domain.h create mode 100644 fdk-aac/libFDK/include/FDK_tools_rom.h create mode 100644 fdk-aac/libFDK/include/FDK_trigFcts.h create mode 100644 fdk-aac/libFDK/include/abs.h create mode 100644 fdk-aac/libFDK/include/arm/clz_arm.h create mode 100644 fdk-aac/libFDK/include/arm/cplx_mul_arm.h create mode 100644 fdk-aac/libFDK/include/arm/fixmadd_arm.h create mode 100644 fdk-aac/libFDK/include/arm/fixmul_arm.h create mode 100644 fdk-aac/libFDK/include/arm/scale_arm.h create mode 100644 fdk-aac/libFDK/include/arm/scramble_arm.h create mode 100644 fdk-aac/libFDK/include/autocorr2nd.h create mode 100644 fdk-aac/libFDK/include/clz.h create mode 100644 fdk-aac/libFDK/include/common_fix.h create mode 100644 fdk-aac/libFDK/include/cplx_mul.h create mode 100644 fdk-aac/libFDK/include/dct.h create mode 100644 fdk-aac/libFDK/include/fft.h create mode 100644 fdk-aac/libFDK/include/fft_rad2.h create mode 100644 fdk-aac/libFDK/include/fixmadd.h create mode 100644 fdk-aac/libFDK/include/fixminmax.h create mode 100644 fdk-aac/libFDK/include/fixmul.h create mode 100644 fdk-aac/libFDK/include/fixpoint_math.h create mode 100644 fdk-aac/libFDK/include/huff_nodes.h create mode 100644 fdk-aac/libFDK/include/mdct.h create mode 100644 fdk-aac/libFDK/include/mips/abs_mips.h create mode 100644 fdk-aac/libFDK/include/mips/clz_mips.h create mode 100644 fdk-aac/libFDK/include/mips/cplx_mul_mips.h create mode 100644 fdk-aac/libFDK/include/mips/fixmul_mips.h create mode 100644 fdk-aac/libFDK/include/mips/scale_mips.h create mode 100644 fdk-aac/libFDK/include/mips/scramble_mips.h create mode 100644 fdk-aac/libFDK/include/nlc_dec.h create mode 100644 fdk-aac/libFDK/include/ppc/clz_ppc.h create mode 100644 fdk-aac/libFDK/include/ppc/fixmul_ppc.h create mode 100644 fdk-aac/libFDK/include/qmf.h create mode 100644 fdk-aac/libFDK/include/qmf_pcm.h create mode 100644 fdk-aac/libFDK/include/scale.h create mode 100644 fdk-aac/libFDK/include/scramble.h create mode 100644 fdk-aac/libFDK/include/x86/abs_x86.h create mode 100644 fdk-aac/libFDK/include/x86/clz_x86.h create mode 100644 fdk-aac/libFDK/include/x86/fixmul_x86.h create mode 100644 fdk-aac/libFDK/include/x86/fixpoint_math_x86.h create mode 100644 fdk-aac/libFDK/src/FDK_bitbuffer.cpp create mode 100644 fdk-aac/libFDK/src/FDK_core.cpp create mode 100644 fdk-aac/libFDK/src/FDK_crc.cpp create mode 100644 fdk-aac/libFDK/src/FDK_decorrelate.cpp create mode 100644 fdk-aac/libFDK/src/FDK_hybrid.cpp create mode 100644 fdk-aac/libFDK/src/FDK_lpc.cpp create mode 100644 fdk-aac/libFDK/src/FDK_matrixCalloc.cpp create mode 100644 fdk-aac/libFDK/src/FDK_qmf_domain.cpp create mode 100644 fdk-aac/libFDK/src/FDK_tools_rom.cpp create mode 100644 fdk-aac/libFDK/src/FDK_trigFcts.cpp create mode 100644 fdk-aac/libFDK/src/arm/fft_rad2_arm.cpp create mode 100644 fdk-aac/libFDK/src/arm/scale_arm.cpp create mode 100644 fdk-aac/libFDK/src/autocorr2nd.cpp create mode 100644 fdk-aac/libFDK/src/dct.cpp create mode 100644 fdk-aac/libFDK/src/fft.cpp create mode 100644 fdk-aac/libFDK/src/fft_rad2.cpp create mode 100644 fdk-aac/libFDK/src/fixpoint_math.cpp create mode 100644 fdk-aac/libFDK/src/huff_nodes.cpp create mode 100644 fdk-aac/libFDK/src/mdct.cpp create mode 100644 fdk-aac/libFDK/src/mips/fft_rad2_mips.cpp create mode 100644 fdk-aac/libFDK/src/mips/mips_fft_twiddles.cpp create mode 100644 fdk-aac/libFDK/src/mips/scale_mips.cpp create mode 100644 fdk-aac/libFDK/src/nlc_dec.cpp create mode 100644 fdk-aac/libFDK/src/qmf.cpp create mode 100644 fdk-aac/libFDK/src/scale.cpp create mode 100644 fdk-aac/libMpegTPDec/include/tp_data.h create mode 100644 fdk-aac/libMpegTPDec/include/tpdec_lib.h create mode 100644 fdk-aac/libMpegTPDec/src/tp_version.h create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_adif.cpp create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_adif.h create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_adts.cpp create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_adts.h create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_asc.cpp create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_drm.cpp create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_drm.h create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_latm.cpp create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_latm.h create mode 100644 fdk-aac/libMpegTPDec/src/tpdec_lib.cpp create mode 100644 fdk-aac/libMpegTPEnc/include/tp_data.h create mode 100644 fdk-aac/libMpegTPEnc/include/tpenc_lib.h create mode 100644 fdk-aac/libMpegTPEnc/src/tp_version.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_adif.cpp create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_adif.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_adts.cpp create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_adts.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_asc.cpp create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_asc.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_dab.cpp create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_dab.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_latm.cpp create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_latm.h create mode 100644 fdk-aac/libMpegTPEnc/src/tpenc_lib.cpp create mode 100644 fdk-aac/libPCMutils/include/limiter.h create mode 100644 fdk-aac/libPCMutils/include/pcm_utils.h create mode 100644 fdk-aac/libPCMutils/include/pcmdmx_lib.h create mode 100644 fdk-aac/libPCMutils/src/limiter.cpp create mode 100644 fdk-aac/libPCMutils/src/pcm_utils.cpp create mode 100644 fdk-aac/libPCMutils/src/pcmdmx_lib.cpp create mode 100644 fdk-aac/libPCMutils/src/version.h create mode 100644 fdk-aac/libSACdec/include/sac_dec_errorcodes.h create mode 100644 fdk-aac/libSACdec/include/sac_dec_lib.h create mode 100644 fdk-aac/libSACdec/src/sac_bitdec.cpp create mode 100644 fdk-aac/libSACdec/src/sac_bitdec.h create mode 100644 fdk-aac/libSACdec/src/sac_calcM1andM2.cpp create mode 100644 fdk-aac/libSACdec/src/sac_calcM1andM2.h create mode 100644 fdk-aac/libSACdec/src/sac_dec.cpp create mode 100644 fdk-aac/libSACdec/src/sac_dec.h create mode 100644 fdk-aac/libSACdec/src/sac_dec_conceal.cpp create mode 100644 fdk-aac/libSACdec/src/sac_dec_conceal.h create mode 100644 fdk-aac/libSACdec/src/sac_dec_interface.h create mode 100644 fdk-aac/libSACdec/src/sac_dec_lib.cpp create mode 100644 fdk-aac/libSACdec/src/sac_dec_ssc_struct.h create mode 100644 fdk-aac/libSACdec/src/sac_process.cpp create mode 100644 fdk-aac/libSACdec/src/sac_process.h create mode 100644 fdk-aac/libSACdec/src/sac_qmf.cpp create mode 100644 fdk-aac/libSACdec/src/sac_qmf.h create mode 100644 fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp create mode 100644 fdk-aac/libSACdec/src/sac_reshapeBBEnv.h create mode 100644 fdk-aac/libSACdec/src/sac_rom.cpp create mode 100644 fdk-aac/libSACdec/src/sac_rom.h create mode 100644 fdk-aac/libSACdec/src/sac_smoothing.cpp create mode 100644 fdk-aac/libSACdec/src/sac_smoothing.h create mode 100644 fdk-aac/libSACdec/src/sac_stp.cpp create mode 100644 fdk-aac/libSACdec/src/sac_stp.h create mode 100644 fdk-aac/libSACdec/src/sac_tsd.cpp create mode 100644 fdk-aac/libSACdec/src/sac_tsd.h create mode 100644 fdk-aac/libSACenc/include/sacenc_lib.h create mode 100644 fdk-aac/libSACenc/src/sacenc_bitstream.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_bitstream.h create mode 100644 fdk-aac/libSACenc/src/sacenc_const.h create mode 100644 fdk-aac/libSACenc/src/sacenc_delay.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_delay.h create mode 100644 fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.h create mode 100644 fdk-aac/libSACenc/src/sacenc_filter.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_filter.h create mode 100644 fdk-aac/libSACenc/src/sacenc_framewindowing.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_framewindowing.h create mode 100644 fdk-aac/libSACenc/src/sacenc_huff_tab.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_huff_tab.h create mode 100644 fdk-aac/libSACenc/src/sacenc_lib.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_nlc_enc.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_nlc_enc.h create mode 100644 fdk-aac/libSACenc/src/sacenc_onsetdetect.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_onsetdetect.h create mode 100644 fdk-aac/libSACenc/src/sacenc_paramextract.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_paramextract.h create mode 100644 fdk-aac/libSACenc/src/sacenc_staticgain.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_staticgain.h create mode 100644 fdk-aac/libSACenc/src/sacenc_tree.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_tree.h create mode 100644 fdk-aac/libSACenc/src/sacenc_vectorfunctions.cpp create mode 100644 fdk-aac/libSACenc/src/sacenc_vectorfunctions.h create mode 100644 fdk-aac/libSBRdec/include/sbrdecoder.h create mode 100644 fdk-aac/libSBRdec/src/HFgen_preFlat.cpp create mode 100644 fdk-aac/libSBRdec/src/HFgen_preFlat.h create mode 100644 fdk-aac/libSBRdec/src/arm/lpp_tran_arm.cpp create mode 100644 fdk-aac/libSBRdec/src/env_calc.cpp create mode 100644 fdk-aac/libSBRdec/src/env_calc.h create mode 100644 fdk-aac/libSBRdec/src/env_dec.cpp create mode 100644 fdk-aac/libSBRdec/src/env_dec.h create mode 100644 fdk-aac/libSBRdec/src/env_extr.cpp create mode 100644 fdk-aac/libSBRdec/src/env_extr.h create mode 100644 fdk-aac/libSBRdec/src/hbe.cpp create mode 100644 fdk-aac/libSBRdec/src/hbe.h create mode 100644 fdk-aac/libSBRdec/src/huff_dec.cpp create mode 100644 fdk-aac/libSBRdec/src/huff_dec.h create mode 100644 fdk-aac/libSBRdec/src/lpp_tran.cpp create mode 100644 fdk-aac/libSBRdec/src/lpp_tran.h create mode 100644 fdk-aac/libSBRdec/src/psbitdec.cpp create mode 100644 fdk-aac/libSBRdec/src/psbitdec.h create mode 100644 fdk-aac/libSBRdec/src/psdec.cpp create mode 100644 fdk-aac/libSBRdec/src/psdec.h create mode 100644 fdk-aac/libSBRdec/src/psdec_drm.cpp create mode 100644 fdk-aac/libSBRdec/src/psdec_drm.h create mode 100644 fdk-aac/libSBRdec/src/psdecrom_drm.cpp create mode 100644 fdk-aac/libSBRdec/src/pvc_dec.cpp create mode 100644 fdk-aac/libSBRdec/src/pvc_dec.h create mode 100644 fdk-aac/libSBRdec/src/sbr_crc.cpp create mode 100644 fdk-aac/libSBRdec/src/sbr_crc.h create mode 100644 fdk-aac/libSBRdec/src/sbr_deb.cpp create mode 100644 fdk-aac/libSBRdec/src/sbr_deb.h create mode 100644 fdk-aac/libSBRdec/src/sbr_dec.cpp create mode 100644 fdk-aac/libSBRdec/src/sbr_dec.h create mode 100644 fdk-aac/libSBRdec/src/sbr_ram.cpp create mode 100644 fdk-aac/libSBRdec/src/sbr_ram.h create mode 100644 fdk-aac/libSBRdec/src/sbr_rom.cpp create mode 100644 fdk-aac/libSBRdec/src/sbr_rom.h create mode 100644 fdk-aac/libSBRdec/src/sbrdec_drc.cpp create mode 100644 fdk-aac/libSBRdec/src/sbrdec_drc.h create mode 100644 fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp create mode 100644 fdk-aac/libSBRdec/src/sbrdec_freq_sca.h create mode 100644 fdk-aac/libSBRdec/src/sbrdecoder.cpp create mode 100644 fdk-aac/libSBRdec/src/transcendent.h create mode 100644 fdk-aac/libSBRenc/include/sbr_encoder.h create mode 100644 fdk-aac/libSBRenc/src/bit_sbr.cpp create mode 100644 fdk-aac/libSBRenc/src/bit_sbr.h create mode 100644 fdk-aac/libSBRenc/src/cmondata.h create mode 100644 fdk-aac/libSBRenc/src/code_env.cpp create mode 100644 fdk-aac/libSBRenc/src/code_env.h create mode 100644 fdk-aac/libSBRenc/src/env_bit.cpp create mode 100644 fdk-aac/libSBRenc/src/env_bit.h create mode 100644 fdk-aac/libSBRenc/src/env_est.cpp create mode 100644 fdk-aac/libSBRenc/src/env_est.h create mode 100644 fdk-aac/libSBRenc/src/fram_gen.cpp create mode 100644 fdk-aac/libSBRenc/src/fram_gen.h create mode 100644 fdk-aac/libSBRenc/src/invf_est.cpp create mode 100644 fdk-aac/libSBRenc/src/invf_est.h create mode 100644 fdk-aac/libSBRenc/src/mh_det.cpp create mode 100644 fdk-aac/libSBRenc/src/mh_det.h create mode 100644 fdk-aac/libSBRenc/src/nf_est.cpp create mode 100644 fdk-aac/libSBRenc/src/nf_est.h create mode 100644 fdk-aac/libSBRenc/src/ps_bitenc.cpp create mode 100644 fdk-aac/libSBRenc/src/ps_bitenc.h create mode 100644 fdk-aac/libSBRenc/src/ps_const.h create mode 100644 fdk-aac/libSBRenc/src/ps_encode.cpp create mode 100644 fdk-aac/libSBRenc/src/ps_encode.h create mode 100644 fdk-aac/libSBRenc/src/ps_main.cpp create mode 100644 fdk-aac/libSBRenc/src/ps_main.h create mode 100644 fdk-aac/libSBRenc/src/resampler.cpp create mode 100644 fdk-aac/libSBRenc/src/resampler.h create mode 100644 fdk-aac/libSBRenc/src/sbr.h create mode 100644 fdk-aac/libSBRenc/src/sbr_def.h create mode 100644 fdk-aac/libSBRenc/src/sbr_encoder.cpp create mode 100644 fdk-aac/libSBRenc/src/sbr_misc.cpp create mode 100644 fdk-aac/libSBRenc/src/sbr_misc.h create mode 100644 fdk-aac/libSBRenc/src/sbrenc_freq_sca.cpp create mode 100644 fdk-aac/libSBRenc/src/sbrenc_freq_sca.h create mode 100644 fdk-aac/libSBRenc/src/sbrenc_ram.cpp create mode 100644 fdk-aac/libSBRenc/src/sbrenc_ram.h create mode 100644 fdk-aac/libSBRenc/src/sbrenc_rom.cpp create mode 100644 fdk-aac/libSBRenc/src/sbrenc_rom.h create mode 100644 fdk-aac/libSBRenc/src/ton_corr.cpp create mode 100644 fdk-aac/libSBRenc/src/ton_corr.h create mode 100644 fdk-aac/libSBRenc/src/tran_det.cpp create mode 100644 fdk-aac/libSBRenc/src/tran_det.h create mode 100644 fdk-aac/libSYS/include/FDK_audio.h create mode 100644 fdk-aac/libSYS/include/genericStds.h create mode 100644 fdk-aac/libSYS/include/machine_type.h create mode 100644 fdk-aac/libSYS/include/syslib_channelMapDescr.h create mode 100644 fdk-aac/libSYS/src/genericStds.cpp create mode 100644 fdk-aac/libSYS/src/syslib_channelMapDescr.cpp create mode 100644 fdk-aac/m4/.gitkeep create mode 100644 fdk-aac/wavreader.c create mode 100644 fdk-aac/wavreader.h create mode 100644 fdk-aac/win32/getopt.h (limited to 'fdk-aac') diff --git a/fdk-aac/.clang-format b/fdk-aac/.clang-format new file mode 100644 index 0000000..caeb773 --- /dev/null +++ b/fdk-aac/.clang-format @@ -0,0 +1,4 @@ +BasedOnStyle: Google +SortIncludes: false +# Do not reformat the Doxygen-style comments in the code +CommentPragmas : "^ * \\\\" diff --git a/fdk-aac/.gitignore b/fdk-aac/.gitignore new file mode 100644 index 0000000..263e5aa --- /dev/null +++ b/fdk-aac/.gitignore @@ -0,0 +1,29 @@ +*.o +*.lo +*.la +.deps +.libs +.dirstamp +Makefile +Makefile.in +aclocal.m4 +autom4te.cache +configure +fdk-aac.pc +config.guess +config.log +config.status +config.sub +depcomp +install-sh +libtool +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +missing +stamp-h1 +aac-enc +compile diff --git a/fdk-aac/Android.bp b/fdk-aac/Android.bp new file mode 100644 index 0000000..dce6fdd --- /dev/null +++ b/fdk-aac/Android.bp @@ -0,0 +1,53 @@ +cc_library_static { + name: "libFraunhoferAAC", + vendor_available: true, + srcs: [ + "libAACdec/src/*.cpp", + "libAACenc/src/*.cpp", + "libPCMutils/src/*.cpp", + "libFDK/src/*.cpp", + "libSYS/src/*.cpp", + "libMpegTPDec/src/*.cpp", + "libMpegTPEnc/src/*.cpp", + "libSBRdec/src/*.cpp", + "libSBRenc/src/*.cpp", + "libArithCoding/src/*.cpp", + "libDRCdec/src/*.cpp", + "libSACdec/src/*.cpp", + "libSACenc/src/*.cpp", + ], + cflags: [ + "-Werror", + "-Wno-unused-parameter", + "-Wno-#warnings", + "-Wuninitialized", + "-Wno-self-assign", + "-Wno-implicit-fallthrough", + ], + sanitize: { + misc_undefined:[ + "unsigned-integer-overflow", + "signed-integer-overflow", + "bounds", + ], + cfi: true, + }, + shared_libs: [ + "liblog", + ], + export_include_dirs: [ + "libAACdec/include", + "libAACenc/include", + "libPCMutils/include", + "libFDK/include", + "libSYS/include", + "libMpegTPDec/include", + "libMpegTPEnc/include", + "libSBRdec/include", + "libSBRenc/include", + "libArithCoding/include", + "libDRCdec/include", + "libSACdec/include", + "libSACenc/include", + ], +} diff --git a/fdk-aac/ChangeLog b/fdk-aac/ChangeLog new file mode 100644 index 0000000..2675878 --- /dev/null +++ b/fdk-aac/ChangeLog @@ -0,0 +1,48 @@ +2.0.0 + - Major update in the upstream source base, with support for new + profiles and features, and numerous crash/fuzz fixes. The new + upstream version is referred to as FDKv2, thus skipping the + major version 1 and syncing the fdk-aac major version number to 2. + +0.1.6 + - Lots of minor assorted crash/fuzz fixes, mostly for the decoder but + also some for the encoder + +0.1.5 + - Updated upstream sources + - Fixed building with GCC 3.3 and 3.4 + - Fixed building with GCC 6 + - AArch64 optimizations + - Makefiles for building with MSVC + - Support building the code in C++11 mode + +0.1.4 + - Updated upstream sources, with minor changes to the decoder API + breaking the ABI. (Calling code using AUDIO_CHANNEL_TYPE may need to + be updated. A new option AAC_PCM_LIMITER_ENABLE has been added, enabled + by default, which incurs extra decoding delay.) + - PowerPC optimizations, fixes for building on AIX + - Support for reading streamed wav files in the encoder example + - Fix VBR encoding of sample rates over 64 kHz + +0.1.3 + - Updated upstream sources, with a number of crash fixes and new features + (including support for encoding 7.1) + +0.1.2 + - Fix a few more crashes + - Include dependency libs (such as -lm) in the pkg-config file + +0.1.1 + - Updated to a new upstream version from Android 4.2, fixing a lot of crashes + - Cleanup of autotools usage + - Make sure the shared library links to libm if necessary + - Performance improvements on x86 + - Added support for WG4/DVD audio channel mappings + - Minimized the differences to upstream + - Added an example encoder tool + +0.1.0 + - Initial release of fdk-aac + - autotools based build system + - Enable setting VBR bitrate modes diff --git a/fdk-aac/MODULE_LICENSE_FRAUNHOFER b/fdk-aac/MODULE_LICENSE_FRAUNHOFER new file mode 100644 index 0000000..e69de29 diff --git a/fdk-aac/Makefile.am b/fdk-aac/Makefile.am new file mode 100644 index 0000000..9404f8d --- /dev/null +++ b/fdk-aac/Makefile.am @@ -0,0 +1,297 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects + +AM_CPPFLAGS = \ + -I./libAACdec/include \ + -I./libAACenc/include \ + -I./libArithCoding/include \ + -I./libDRCdec/include \ + -I./libSACdec/include \ + -I./libSACenc/include \ + -I./libSBRdec/include \ + -I./libSBRenc/include \ + -I./libMpegTPDec/include \ + -I./libMpegTPEnc/include \ + -I./libSYS/include \ + -I./libFDK/include \ + -I./libPCMutils/include + +AM_CXXFLAGS = -fno-exceptions -fno-rtti +libfdk_aac_dab_la_LINK = $(LINK) $(libfdk_aac_dab_la_LDFLAGS) +# Mention a dummy pure C file to trigger generation of the $(LINK) variable +nodist_EXTRA_libfdk_aac_dab_la_SOURCES = dummy.c + +fdk_aac_dabincludedir = $(includedir)/fdk-aac-dab +fdk_aac_dabinclude_HEADERS = \ + ./libSYS/include/machine_type.h \ + ./libSYS/include/genericStds.h \ + ./libSYS/include/FDK_audio.h \ + ./libSYS/include/syslib_channelMapDescr.h \ + ./libAACenc/include/aacenc_lib.h \ + ./libAACdec/include/aacdecoder_lib.h + +#pkgconfigdir = $(libdir)/pkgconfig +#pkgconfig_DATA = fdk-aac.pc + +lib_LTLIBRARIES = libfdk-aac-dab.la + +libfdk_aac_dab_la_LDFLAGS = -version-info @FDK_AAC_VERSION@ -no-undefined \ + -export-symbols ./fdk-aac.sym + +if EXAMPLE +bin_PROGRAMS = aac-enc$(EXEEXT) + +aac_enc_LDADD = libfdk-aac-dab.la +aac_enc_SOURCES = aac-enc.c wavreader.c + +noinst_HEADERS = wavreader.h +endif + +AACDEC_SRC = \ + libAACdec/src/FDK_delay.cpp \ + libAACdec/src/aac_ram.cpp \ + libAACdec/src/aac_rom.cpp \ + libAACdec/src/aacdec_drc.cpp \ + libAACdec/src/aacdec_hcr.cpp \ + libAACdec/src/aacdec_hcr_bit.cpp \ + libAACdec/src/aacdec_hcrs.cpp \ + libAACdec/src/aacdec_pns.cpp \ + libAACdec/src/aacdec_tns.cpp \ + libAACdec/src/aacdecoder.cpp \ + libAACdec/src/aacdecoder_lib.cpp \ + libAACdec/src/block.cpp \ + libAACdec/src/channel.cpp \ + libAACdec/src/channelinfo.cpp \ + libAACdec/src/conceal.cpp \ + libAACdec/src/ldfiltbank.cpp \ + libAACdec/src/pulsedata.cpp \ + libAACdec/src/rvlc.cpp \ + libAACdec/src/rvlcbit.cpp \ + libAACdec/src/rvlcconceal.cpp \ + libAACdec/src/stereo.cpp \ + libAACdec/src/usacdec_ace_d4t64.cpp \ + libAACdec/src/usacdec_ace_ltp.cpp \ + libAACdec/src/usacdec_acelp.cpp \ + libAACdec/src/usacdec_fac.cpp \ + libAACdec/src/usacdec_lpc.cpp \ + libAACdec/src/usacdec_lpd.cpp \ + libAACdec/src/usacdec_rom.cpp + +AACENC_SRC = \ + libAACenc/src/aacEnc_ram.cpp \ + libAACenc/src/aacEnc_rom.cpp \ + libAACenc/src/aacenc.cpp \ + libAACenc/src/aacenc_lib.cpp \ + libAACenc/src/aacenc_pns.cpp \ + libAACenc/src/aacenc_tns.cpp \ + libAACenc/src/adj_thr.cpp \ + libAACenc/src/band_nrg.cpp \ + libAACenc/src/bandwidth.cpp \ + libAACenc/src/bit_cnt.cpp \ + libAACenc/src/bitenc.cpp \ + libAACenc/src/block_switch.cpp \ + libAACenc/src/channel_map.cpp \ + libAACenc/src/chaosmeasure.cpp \ + libAACenc/src/dyn_bits.cpp \ + libAACenc/src/grp_data.cpp \ + libAACenc/src/intensity.cpp \ + libAACenc/src/line_pe.cpp \ + libAACenc/src/metadata_compressor.cpp \ + libAACenc/src/metadata_main.cpp \ + libAACenc/src/mps_main.cpp \ + libAACenc/src/ms_stereo.cpp \ + libAACenc/src/noisedet.cpp \ + libAACenc/src/pnsparam.cpp \ + libAACenc/src/pre_echo_control.cpp \ + libAACenc/src/psy_configuration.cpp \ + libAACenc/src/psy_main.cpp \ + libAACenc/src/qc_main.cpp \ + libAACenc/src/quantize.cpp \ + libAACenc/src/sf_estim.cpp \ + libAACenc/src/spreading.cpp \ + libAACenc/src/tonality.cpp \ + libAACenc/src/transform.cpp + +ARITHCODING_SRC = \ + libArithCoding/src/ac_arith_coder.cpp + +DRCDEC_SRC = \ + libDRCdec/src/FDK_drcDecLib.cpp \ + libDRCdec/src/drcDec_gainDecoder.cpp \ + libDRCdec/src/drcDec_reader.cpp \ + libDRCdec/src/drcDec_rom.cpp \ + libDRCdec/src/drcDec_selectionProcess.cpp \ + libDRCdec/src/drcDec_tools.cpp \ + libDRCdec/src/drcGainDec_init.cpp \ + libDRCdec/src/drcGainDec_preprocess.cpp \ + libDRCdec/src/drcGainDec_process.cpp + +FDK_SRC = \ + libFDK/src/FDK_bitbuffer.cpp \ + libFDK/src/FDK_core.cpp \ + libFDK/src/FDK_crc.cpp \ + libFDK/src/FDK_decorrelate.cpp \ + libFDK/src/FDK_hybrid.cpp \ + libFDK/src/FDK_lpc.cpp \ + libFDK/src/FDK_matrixCalloc.cpp \ + libFDK/src/FDK_qmf_domain.cpp \ + libFDK/src/FDK_tools_rom.cpp \ + libFDK/src/FDK_trigFcts.cpp \ + libFDK/src/autocorr2nd.cpp \ + libFDK/src/dct.cpp \ + libFDK/src/fft.cpp \ + libFDK/src/fft_rad2.cpp \ + libFDK/src/fixpoint_math.cpp \ + libFDK/src/huff_nodes.cpp \ + libFDK/src/mdct.cpp \ + libFDK/src/nlc_dec.cpp \ + libFDK/src/qmf.cpp \ + libFDK/src/scale.cpp + +MPEGTPDEC_SRC = \ + libMpegTPDec/src/tpdec_adif.cpp \ + libMpegTPDec/src/tpdec_adts.cpp \ + libMpegTPDec/src/tpdec_asc.cpp \ + libMpegTPDec/src/tpdec_drm.cpp \ + libMpegTPDec/src/tpdec_latm.cpp \ + libMpegTPDec/src/tpdec_lib.cpp + +MPEGTPENC_SRC = \ + libMpegTPEnc/src/tpenc_adif.cpp \ + libMpegTPEnc/src/tpenc_adts.cpp \ + libMpegTPEnc/src/tpenc_asc.cpp \ + libMpegTPEnc/src/tpenc_latm.cpp \ + libMpegTPEnc/src/tpenc_lib.cpp \ + libMpegTPEnc/src/tpenc_dab.cpp + +PCMUTILS_SRC = \ + libPCMutils/src/limiter.cpp \ + libPCMutils/src/pcm_utils.cpp \ + libPCMutils/src/pcmdmx_lib.cpp + +SACDEC_SRC = \ + libSACdec/src/sac_bitdec.cpp \ + libSACdec/src/sac_calcM1andM2.cpp \ + libSACdec/src/sac_dec.cpp \ + libSACdec/src/sac_dec_conceal.cpp \ + libSACdec/src/sac_dec_lib.cpp \ + libSACdec/src/sac_process.cpp \ + libSACdec/src/sac_qmf.cpp \ + libSACdec/src/sac_reshapeBBEnv.cpp \ + libSACdec/src/sac_rom.cpp \ + libSACdec/src/sac_smoothing.cpp \ + libSACdec/src/sac_stp.cpp \ + libSACdec/src/sac_tsd.cpp + +SACENC_SRC = \ + libSACenc/src/sacenc_bitstream.cpp \ + libSACenc/src/sacenc_delay.cpp \ + libSACenc/src/sacenc_dmx_tdom_enh.cpp \ + libSACenc/src/sacenc_filter.cpp \ + libSACenc/src/sacenc_framewindowing.cpp \ + libSACenc/src/sacenc_huff_tab.cpp \ + libSACenc/src/sacenc_lib.cpp \ + libSACenc/src/sacenc_nlc_enc.cpp \ + libSACenc/src/sacenc_onsetdetect.cpp \ + libSACenc/src/sacenc_paramextract.cpp \ + libSACenc/src/sacenc_staticgain.cpp \ + libSACenc/src/sacenc_tree.cpp \ + libSACenc/src/sacenc_vectorfunctions.cpp + +SBRDEC_SRC = \ + libSBRdec/src/HFgen_preFlat.cpp \ + libSBRdec/src/env_calc.cpp \ + libSBRdec/src/env_dec.cpp \ + libSBRdec/src/env_extr.cpp \ + libSBRdec/src/hbe.cpp \ + libSBRdec/src/huff_dec.cpp \ + libSBRdec/src/lpp_tran.cpp \ + libSBRdec/src/psbitdec.cpp \ + libSBRdec/src/psdec.cpp \ + libSBRdec/src/psdec_drm.cpp \ + libSBRdec/src/psdecrom_drm.cpp \ + libSBRdec/src/pvc_dec.cpp \ + libSBRdec/src/sbr_crc.cpp \ + libSBRdec/src/sbr_deb.cpp \ + libSBRdec/src/sbr_dec.cpp \ + libSBRdec/src/sbr_ram.cpp \ + libSBRdec/src/sbr_rom.cpp \ + libSBRdec/src/sbrdec_drc.cpp \ + libSBRdec/src/sbrdec_freq_sca.cpp \ + libSBRdec/src/sbrdecoder.cpp + +SBRENC_SRC = \ + libSBRenc/src/bit_sbr.cpp \ + libSBRenc/src/code_env.cpp \ + libSBRenc/src/env_bit.cpp \ + libSBRenc/src/env_est.cpp \ + libSBRenc/src/fram_gen.cpp \ + libSBRenc/src/invf_est.cpp \ + libSBRenc/src/mh_det.cpp \ + libSBRenc/src/nf_est.cpp \ + libSBRenc/src/ps_bitenc.cpp \ + libSBRenc/src/ps_encode.cpp \ + libSBRenc/src/ps_main.cpp \ + libSBRenc/src/resampler.cpp \ + libSBRenc/src/sbr_encoder.cpp \ + libSBRenc/src/sbr_misc.cpp \ + libSBRenc/src/sbrenc_freq_sca.cpp \ + libSBRenc/src/sbrenc_ram.cpp \ + libSBRenc/src/sbrenc_rom.cpp \ + libSBRenc/src/ton_corr.cpp \ + libSBRenc/src/tran_det.cpp + +SYS_SRC = \ + libSYS/src/genericStds.cpp \ + libSYS/src/syslib_channelMapDescr.cpp + +libfdk_aac_dab_la_SOURCES = \ + $(AACDEC_SRC) $(AACENC_SRC) \ + $(ARITHCODING_SRC) \ + $(DRCDEC_SRC) \ + $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ + $(SACDEC_SRC) $(SACENC_SRC) \ + $(SBRDEC_SRC) $(SBRENC_SRC) \ + $(PCMUTILS_SRC) $(FDK_SRC) $(SYS_SRC) + +EXTRA_DIST = \ + ./.clang-format \ + ./autogen.sh \ + ./MODULE_LICENSE_FRAUNHOFER \ + ./NOTICE \ + ./OWNERS \ + ./Android.bp \ + ./fdk-aac.sym \ + ./Makefile.vc \ + ./documentation/*.pdf \ + ./libAACdec/src/*.h \ + ./libAACdec/src/arm/*.cpp \ + ./libAACenc/src/*.h \ + ./libArithCoding/include/*.h \ + ./libDRCdec/include/*.h \ + ./libDRCdec/src/*.h \ + ./libSACdec/include/*.h \ + ./libSACdec/src/*.h \ + ./libSACenc/include/*.h \ + ./libSACenc/src/*.h \ + ./libSBRenc/src/*.h \ + ./libSBRenc/include/*.h \ + ./libSBRdec/src/*.h \ + ./libSBRdec/src/arm/*.cpp \ + ./libSBRdec/include/*.h \ + ./libSYS/include/*.h \ + ./libPCMutils/include/*.h \ + ./libPCMutils/src/*.h \ + ./libMpegTPEnc/include/*.h \ + ./libMpegTPEnc/src/*.h \ + ./libMpegTPDec/include/*.h \ + ./libMpegTPDec/src/*.h \ + ./libFDK/include/*.h \ + ./libFDK/include/arm/*.h \ + ./libFDK/include/mips/*.h \ + ./libFDK/include/ppc/*.h \ + ./libFDK/include/x86/*.h \ + ./libFDK/src/arm/*.cpp \ + ./libFDK/src/mips/*.cpp \ + ./win32/*.h + diff --git a/fdk-aac/Makefile.vc b/fdk-aac/Makefile.vc new file mode 100644 index 0000000..a90b530 --- /dev/null +++ b/fdk-aac/Makefile.vc @@ -0,0 +1,321 @@ +# +# Options: +# prefix=\path\to\install +# +# Compiling: nmake -f Makefile.vc +# Installing: nmake -f Makefile.vc prefix=\path\to\x install +# + +# Linker and librarian commands +LD = link +AR = lib + +!IFDEF HOME +# In case we are using a cross compiler shell. +MKDIR_FLAGS = -p +!ENDIF + +AM_CPPFLAGS = \ + -Iwin32 \ + -IlibAACdec/include \ + -IlibAACenc/include \ + -IlibArithCoding/include \ + -IlibDRCdec/include \ + -IlibSACdec/include \ + -IlibSACenc/include \ + -IlibSBRdec/include \ + -IlibSBRenc/include \ + -IlibMpegTPDec/include \ + -IlibMpegTPEnc/include \ + -IlibSYS/include \ + -IlibFDK/include \ + -IlibPCMutils/include + +AACDEC_SRC = \ + libAACdec/src/FDK_delay.cpp \ + libAACdec/src/aac_ram.cpp \ + libAACdec/src/aac_rom.cpp \ + libAACdec/src/aacdec_drc.cpp \ + libAACdec/src/aacdec_hcr.cpp \ + libAACdec/src/aacdec_hcr_bit.cpp \ + libAACdec/src/aacdec_hcrs.cpp \ + libAACdec/src/aacdec_pns.cpp \ + libAACdec/src/aacdec_tns.cpp \ + libAACdec/src/aacdecoder.cpp \ + libAACdec/src/aacdecoder_lib.cpp \ + libAACdec/src/block.cpp \ + libAACdec/src/channel.cpp \ + libAACdec/src/channelinfo.cpp \ + libAACdec/src/conceal.cpp \ + libAACdec/src/ldfiltbank.cpp \ + libAACdec/src/pulsedata.cpp \ + libAACdec/src/rvlc.cpp \ + libAACdec/src/rvlcbit.cpp \ + libAACdec/src/rvlcconceal.cpp \ + libAACdec/src/stereo.cpp \ + libAACdec/src/usacdec_ace_d4t64.cpp \ + libAACdec/src/usacdec_ace_ltp.cpp \ + libAACdec/src/usacdec_acelp.cpp \ + libAACdec/src/usacdec_fac.cpp \ + libAACdec/src/usacdec_lpc.cpp \ + libAACdec/src/usacdec_lpd.cpp \ + libAACdec/src/usacdec_rom.cpp + +AACENC_SRC = \ + libAACenc/src/aacEnc_ram.cpp \ + libAACenc/src/aacEnc_rom.cpp \ + libAACenc/src/aacenc.cpp \ + libAACenc/src/aacenc_lib.cpp \ + libAACenc/src/aacenc_pns.cpp \ + libAACenc/src/aacenc_tns.cpp \ + libAACenc/src/adj_thr.cpp \ + libAACenc/src/band_nrg.cpp \ + libAACenc/src/bandwidth.cpp \ + libAACenc/src/bit_cnt.cpp \ + libAACenc/src/bitenc.cpp \ + libAACenc/src/block_switch.cpp \ + libAACenc/src/channel_map.cpp \ + libAACenc/src/chaosmeasure.cpp \ + libAACenc/src/dyn_bits.cpp \ + libAACenc/src/grp_data.cpp \ + libAACenc/src/intensity.cpp \ + libAACenc/src/line_pe.cpp \ + libAACenc/src/metadata_compressor.cpp \ + libAACenc/src/metadata_main.cpp \ + libAACenc/src/mps_main.cpp \ + libAACenc/src/ms_stereo.cpp \ + libAACenc/src/noisedet.cpp \ + libAACenc/src/pnsparam.cpp \ + libAACenc/src/pre_echo_control.cpp \ + libAACenc/src/psy_configuration.cpp \ + libAACenc/src/psy_main.cpp \ + libAACenc/src/qc_main.cpp \ + libAACenc/src/quantize.cpp \ + libAACenc/src/sf_estim.cpp \ + libAACenc/src/spreading.cpp \ + libAACenc/src/tonality.cpp \ + libAACenc/src/transform.cpp + +ARITHCODING_SRC = \ + libArithCoding/src/ac_arith_coder.cpp + +DRCDEC_SRC = \ + libDRCdec/src/FDK_drcDecLib.cpp \ + libDRCdec/src/drcDec_gainDecoder.cpp \ + libDRCdec/src/drcDec_reader.cpp \ + libDRCdec/src/drcDec_rom.cpp \ + libDRCdec/src/drcDec_selectionProcess.cpp \ + libDRCdec/src/drcDec_tools.cpp \ + libDRCdec/src/drcGainDec_init.cpp \ + libDRCdec/src/drcGainDec_preprocess.cpp \ + libDRCdec/src/drcGainDec_process.cpp + +FDK_SRC = \ + libFDK/src/FDK_bitbuffer.cpp \ + libFDK/src/FDK_core.cpp \ + libFDK/src/FDK_crc.cpp \ + libFDK/src/FDK_decorrelate.cpp \ + libFDK/src/FDK_hybrid.cpp \ + libFDK/src/FDK_lpc.cpp \ + libFDK/src/FDK_matrixCalloc.cpp \ + libFDK/src/FDK_qmf_domain.cpp \ + libFDK/src/FDK_tools_rom.cpp \ + libFDK/src/FDK_trigFcts.cpp \ + libFDK/src/autocorr2nd.cpp \ + libFDK/src/dct.cpp \ + libFDK/src/fft.cpp \ + libFDK/src/fft_rad2.cpp \ + libFDK/src/fixpoint_math.cpp \ + libFDK/src/huff_nodes.cpp \ + libFDK/src/mdct.cpp \ + libFDK/src/nlc_dec.cpp \ + libFDK/src/qmf.cpp \ + libFDK/src/scale.cpp + +MPEGTPDEC_SRC = \ + libMpegTPDec/src/tpdec_adif.cpp \ + libMpegTPDec/src/tpdec_adts.cpp \ + libMpegTPDec/src/tpdec_asc.cpp \ + libMpegTPDec/src/tpdec_drm.cpp \ + libMpegTPDec/src/tpdec_latm.cpp \ + libMpegTPDec/src/tpdec_lib.cpp + +MPEGTPENC_SRC = \ + libMpegTPEnc/src/tpenc_adif.cpp \ + libMpegTPEnc/src/tpenc_adts.cpp \ + libMpegTPEnc/src/tpenc_asc.cpp \ + libMpegTPEnc/src/tpenc_latm.cpp \ + libMpegTPEnc/src/tpenc_lib.cpp + +PCMUTILS_SRC = \ + libPCMutils/src/limiter.cpp \ + libPCMutils/src/pcm_utils.cpp \ + libPCMutils/src/pcmdmx_lib.cpp + +SACDEC_SRC = \ + libSACdec/src/sac_bitdec.cpp \ + libSACdec/src/sac_calcM1andM2.cpp \ + libSACdec/src/sac_dec.cpp \ + libSACdec/src/sac_dec_conceal.cpp \ + libSACdec/src/sac_dec_lib.cpp \ + libSACdec/src/sac_process.cpp \ + libSACdec/src/sac_qmf.cpp \ + libSACdec/src/sac_reshapeBBEnv.cpp \ + libSACdec/src/sac_rom.cpp \ + libSACdec/src/sac_smoothing.cpp \ + libSACdec/src/sac_stp.cpp \ + libSACdec/src/sac_tsd.cpp + +SACENC_SRC = \ + libSACenc/src/sacenc_bitstream.cpp \ + libSACenc/src/sacenc_delay.cpp \ + libSACenc/src/sacenc_dmx_tdom_enh.cpp \ + libSACenc/src/sacenc_filter.cpp \ + libSACenc/src/sacenc_framewindowing.cpp \ + libSACenc/src/sacenc_huff_tab.cpp \ + libSACenc/src/sacenc_lib.cpp \ + libSACenc/src/sacenc_nlc_enc.cpp \ + libSACenc/src/sacenc_onsetdetect.cpp \ + libSACenc/src/sacenc_paramextract.cpp \ + libSACenc/src/sacenc_staticgain.cpp \ + libSACenc/src/sacenc_tree.cpp \ + libSACenc/src/sacenc_vectorfunctions.cpp + +SBRDEC_SRC = \ + libSBRdec/src/HFgen_preFlat.cpp \ + libSBRdec/src/env_calc.cpp \ + libSBRdec/src/env_dec.cpp \ + libSBRdec/src/env_extr.cpp \ + libSBRdec/src/hbe.cpp \ + libSBRdec/src/huff_dec.cpp \ + libSBRdec/src/lpp_tran.cpp \ + libSBRdec/src/psbitdec.cpp \ + libSBRdec/src/psdec.cpp \ + libSBRdec/src/psdec_drm.cpp \ + libSBRdec/src/psdecrom_drm.cpp \ + libSBRdec/src/pvc_dec.cpp \ + libSBRdec/src/sbr_crc.cpp \ + libSBRdec/src/sbr_deb.cpp \ + libSBRdec/src/sbr_dec.cpp \ + libSBRdec/src/sbr_ram.cpp \ + libSBRdec/src/sbr_rom.cpp \ + libSBRdec/src/sbrdec_drc.cpp \ + libSBRdec/src/sbrdec_freq_sca.cpp \ + libSBRdec/src/sbrdecoder.cpp + +SBRENC_SRC = \ + libSBRenc/src/bit_sbr.cpp \ + libSBRenc/src/code_env.cpp \ + libSBRenc/src/env_bit.cpp \ + libSBRenc/src/env_est.cpp \ + libSBRenc/src/fram_gen.cpp \ + libSBRenc/src/invf_est.cpp \ + libSBRenc/src/mh_det.cpp \ + libSBRenc/src/nf_est.cpp \ + libSBRenc/src/ps_bitenc.cpp \ + libSBRenc/src/ps_encode.cpp \ + libSBRenc/src/ps_main.cpp \ + libSBRenc/src/resampler.cpp \ + libSBRenc/src/sbr_encoder.cpp \ + libSBRenc/src/sbr_misc.cpp \ + libSBRenc/src/sbrenc_freq_sca.cpp \ + libSBRenc/src/sbrenc_ram.cpp \ + libSBRenc/src/sbrenc_rom.cpp \ + libSBRenc/src/ton_corr.cpp \ + libSBRenc/src/tran_det.cpp + +SYS_SRC = \ + libSYS/src/genericStds.cpp \ + libSYS/src/syslib_channelMapDescr.cpp + +libfdk_aac_SOURCES = \ + $(AACDEC_SRC) $(AACENC_SRC) \ + $(ARITHCODING_SRC) \ + $(DRCDEC_SRC) \ + $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ + $(SACDEC_SRC) $(SACENC_SRC) \ + $(SBRDEC_SRC) $(SBRENC_SRC) \ + $(PCMUTILS_SRC) $(FDK_SRC) $(SYS_SRC) + + +aac_enc_SOURCES = aac-enc.c wavreader.c + +prefix = \usr\local +prefix_win = $(prefix:/=\) # In case we are using MSYS or MinGW. + +CFLAGS = /nologo /W3 /Ox /MT /EHsc /Dinline=__inline $(TARGET_FLAGS) $(AM_CPPFLAGS) $(XCFLAGS) +CXXFLAGS = $(CFLAGS) +CPPFLAGS = $(CFLAGS) +LDFLAGS = -nologo $(XLDFLAGS) +ARFLAGS = -nologo + +incdir = $(prefix_win)\include\fdk-aac +bindir = $(prefix_win)\bin +libdir = $(prefix_win)\lib + +INST_DIRS = $(bindir) $(incdir) $(libdir) + +LIB_DEF = fdk-aac.def +STATIC_LIB = fdk-aac.lib +SHARED_LIB = fdk-aac-1.dll +IMP_LIB = fdk-aac.dll.lib + +AAC_ENC_OBJS = $(aac_enc_SOURCES:.c=.obj) +FDK_OBJS = $(libfdk_aac_SOURCES:.cpp=.obj) + +PROGS = aac-enc.exe + + + +all: $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) + +clean: + del /f $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) libfdk-aac.pc 2>NUL + del /f *.obj *.exp 2>NUL + del /f libAACdec\src\*.obj 2>NUL + del /f libAACenc\src\*.obj 2>NUL + del /f libArithCoding\src\*.obj 2>NUL + del /f libDRCdec\src\*.obj 2>NUL + del /f libFDK\src\*.obj 2>NUL + del /f libMpegTPDec\src\*.obj 2>NUL + del /f libMpegTPEnc\src\*.obj 2>NUL + del /f libPCMutils\src\*.obj 2>NUL + del /f libSACdec\src\*.obj 2>NUL + del /f libSACenc\src\*.obj 2>NUL + del /f libSBRdec\src\*.obj 2>NUL + del /f libSBRenc\src\*.obj 2>NUL + del /f libSYS\src\*.obj 2>NUL + +install: $(INST_DIRS) + copy libAACdec\include\aacdecoder_lib.h $(incdir) + copy libAACenc\include\aacenc_lib.h $(incdir) + copy libSYS\include\FDK_audio.h $(incdir) + copy libSYS\include\genericStds.h $(incdir) + copy libSYS\include\machine_type.h $(incdir) + copy libSYS\include\syslib_channelMapDescr.h $(incdir) + copy $(STATIC_LIB) $(libdir) + copy $(IMP_LIB) $(libdir) + copy $(SHARED_LIB) $(bindir) + copy $(PROGS) $(bindir) + copy $(LIB_DEF) $(libdir) + +$(INST_DIRS): + @mkdir $(MKDIR_FLAGS) $@ + +$(STATIC_LIB): $(FDK_OBJS) + $(AR) $(ARFLAGS) -out:$@ $(FDK_OBJS) + +$(IMP_LIB): $(SHARED_LIB) + +$(SHARED_LIB): $(FDK_OBJS) + $(LD) $(LDFLAGS) -OUT:$@ -DEF:$(LIB_DEF) -implib:$(IMP_LIB) -DLL $(FDK_OBJS) + +$(PROGS): $(AAC_ENC_OBJS) + $(LD) $(LDFLAGS) -out:$@ $(AAC_ENC_OBJS) $(STATIC_LIB) + +.cpp.obj: + $(CXX) $(CXXFLAGS) -c -Fo$@ $< + +$(LIB_DEF): + @echo EXPORTS > $(LIB_DEF) + @type fdk-aac.sym >> $(LIB_DEF) diff --git a/fdk-aac/NOTICE b/fdk-aac/NOTICE new file mode 100644 index 0000000..05b32bd --- /dev/null +++ b/fdk-aac/NOTICE @@ -0,0 +1,92 @@ +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de + diff --git a/fdk-aac/OWNERS b/fdk-aac/OWNERS new file mode 100644 index 0000000..ffd753e --- /dev/null +++ b/fdk-aac/OWNERS @@ -0,0 +1,2 @@ +jmtrivi@google.com +gkasten@android.com diff --git a/fdk-aac/README.md b/fdk-aac/README.md new file mode 100644 index 0000000..d427e96 --- /dev/null +++ b/fdk-aac/README.md @@ -0,0 +1,7 @@ +A patched version of fdk-aac with DAB+ support +============================================== + +This is a modified version of fdk-aac that supports the AOTs +required for DAB+ encoding. + +See http://www.opendigitalradio.org for more diff --git a/fdk-aac/aac-enc.c b/fdk-aac/aac-enc.c new file mode 100644 index 0000000..c90ff12 --- /dev/null +++ b/fdk-aac/aac-enc.c @@ -0,0 +1,237 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2011 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include +#include + +#if defined(_MSC_VER) +#include +#else +#include +#endif + +#include +#include "libAACenc/include/aacenc_lib.h" +#include "wavreader.h" + +void usage(const char* name) { + fprintf(stderr, "%s [-r bitrate] [-t aot] [-a afterburner] [-s sbr] [-v vbr] in.wav out.aac\n", name); + fprintf(stderr, "Supported AOTs:\n"); + fprintf(stderr, "\t2\tAAC-LC\n"); + fprintf(stderr, "\t5\tHE-AAC\n"); + fprintf(stderr, "\t29\tHE-AAC v2\n"); + fprintf(stderr, "\t23\tAAC-LD\n"); + fprintf(stderr, "\t39\tAAC-ELD\n"); +} + +int main(int argc, char *argv[]) { + int bitrate = 64000; + int ch; + const char *infile, *outfile; + FILE *out; + void *wav; + int format, sample_rate, channels, bits_per_sample; + int input_size; + uint8_t* input_buf; + int16_t* convert_buf; + int aot = 2; + int afterburner = 1; + int eld_sbr = 0; + int vbr = 0; + HANDLE_AACENCODER handle; + CHANNEL_MODE mode; + AACENC_InfoStruct info = { 0 }; + while ((ch = getopt(argc, argv, "r:t:a:s:v:")) != -1) { + switch (ch) { + case 'r': + bitrate = atoi(optarg); + break; + case 't': + aot = atoi(optarg); + break; + case 'a': + afterburner = atoi(optarg); + break; + case 's': + eld_sbr = atoi(optarg); + break; + case 'v': + vbr = atoi(optarg); + break; + case '?': + default: + usage(argv[0]); + return 1; + } + } + if (argc - optind < 2) { + usage(argv[0]); + return 1; + } + infile = argv[optind]; + outfile = argv[optind + 1]; + + wav = wav_read_open(infile); + if (!wav) { + fprintf(stderr, "Unable to open wav file %s\n", infile); + return 1; + } + if (!wav_get_header(wav, &format, &channels, &sample_rate, &bits_per_sample, NULL)) { + fprintf(stderr, "Bad wav file %s\n", infile); + return 1; + } + if (format != 1) { + fprintf(stderr, "Unsupported WAV format %d\n", format); + return 1; + } + if (bits_per_sample != 16) { + fprintf(stderr, "Unsupported WAV sample depth %d\n", bits_per_sample); + return 1; + } + switch (channels) { + case 1: mode = MODE_1; break; + case 2: mode = MODE_2; break; + case 3: mode = MODE_1_2; break; + case 4: mode = MODE_1_2_1; break; + case 5: mode = MODE_1_2_2; break; + case 6: mode = MODE_1_2_2_1; break; + default: + fprintf(stderr, "Unsupported WAV channels %d\n", channels); + return 1; + } + if (aacEncOpen(&handle, 0, channels) != AACENC_OK) { + fprintf(stderr, "Unable to open encoder\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_AOT, aot) != AACENC_OK) { + fprintf(stderr, "Unable to set the AOT\n"); + return 1; + } + if (aot == 39 && eld_sbr) { + if (aacEncoder_SetParam(handle, AACENC_SBR_MODE, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set SBR mode for ELD\n"); + return 1; + } + } + if (aacEncoder_SetParam(handle, AACENC_SAMPLERATE, sample_rate) != AACENC_OK) { + fprintf(stderr, "Unable to set the AOT\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_CHANNELMODE, mode) != AACENC_OK) { + fprintf(stderr, "Unable to set the channel mode\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_CHANNELORDER, 1) != AACENC_OK) { + fprintf(stderr, "Unable to set the wav channel order\n"); + return 1; + } + if (vbr) { + if (aacEncoder_SetParam(handle, AACENC_BITRATEMODE, vbr) != AACENC_OK) { + fprintf(stderr, "Unable to set the VBR bitrate mode\n"); + return 1; + } + } else { + if (aacEncoder_SetParam(handle, AACENC_BITRATE, bitrate) != AACENC_OK) { + fprintf(stderr, "Unable to set the bitrate\n"); + return 1; + } + } + if (aacEncoder_SetParam(handle, AACENC_TRANSMUX, TT_MP4_ADTS) != AACENC_OK) { + fprintf(stderr, "Unable to set the ADTS transmux\n"); + return 1; + } + if (aacEncoder_SetParam(handle, AACENC_AFTERBURNER, afterburner) != AACENC_OK) { + fprintf(stderr, "Unable to set the afterburner mode\n"); + return 1; + } + if (aacEncEncode(handle, NULL, NULL, NULL, NULL) != AACENC_OK) { + fprintf(stderr, "Unable to initialize the encoder\n"); + return 1; + } + if (aacEncInfo(handle, &info) != AACENC_OK) { + fprintf(stderr, "Unable to get the encoder info\n"); + return 1; + } + + out = fopen(outfile, "wb"); + if (!out) { + perror(outfile); + return 1; + } + + input_size = channels*2*info.frameLength; + input_buf = (uint8_t*) malloc(input_size); + convert_buf = (int16_t*) malloc(input_size); + + while (1) { + AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 }; + AACENC_InArgs in_args = { 0 }; + AACENC_OutArgs out_args = { 0 }; + int in_identifier = IN_AUDIO_DATA; + int in_size, in_elem_size; + int out_identifier = OUT_BITSTREAM_DATA; + int out_size, out_elem_size; + int read, i; + void *in_ptr, *out_ptr; + uint8_t outbuf[20480]; + AACENC_ERROR err; + + read = wav_read_data(wav, input_buf, input_size); + for (i = 0; i < read/2; i++) { + const uint8_t* in = &input_buf[2*i]; + convert_buf[i] = in[0] | (in[1] << 8); + } + in_ptr = convert_buf; + in_size = read; + in_elem_size = 2; + + in_args.numInSamples = read <= 0 ? -1 : read/2; + in_buf.numBufs = 1; + in_buf.bufs = &in_ptr; + in_buf.bufferIdentifiers = &in_identifier; + in_buf.bufSizes = &in_size; + in_buf.bufElSizes = &in_elem_size; + + out_ptr = outbuf; + out_size = sizeof(outbuf); + out_elem_size = 1; + out_buf.numBufs = 1; + out_buf.bufs = &out_ptr; + out_buf.bufferIdentifiers = &out_identifier; + out_buf.bufSizes = &out_size; + out_buf.bufElSizes = &out_elem_size; + + if ((err = aacEncEncode(handle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) { + if (err == AACENC_ENCODE_EOF) + break; + fprintf(stderr, "Encoding failed\n"); + return 1; + } + if (out_args.numOutBytes == 0) + continue; + fwrite(outbuf, 1, out_args.numOutBytes, out); + } + free(input_buf); + free(convert_buf); + fclose(out); + wav_read_close(wav); + aacEncClose(&handle); + + return 0; +} + diff --git a/fdk-aac/autogen.sh b/fdk-aac/autogen.sh new file mode 100755 index 0000000..210ccb8 --- /dev/null +++ b/fdk-aac/autogen.sh @@ -0,0 +1,2 @@ +#!/bin/sh +autoreconf -fiv diff --git a/fdk-aac/bootstrap b/fdk-aac/bootstrap new file mode 100755 index 0000000..a3394ab --- /dev/null +++ b/fdk-aac/bootstrap @@ -0,0 +1,4 @@ +#! /bin/sh + +autoreconf --install && \ + echo "You can call ./configure now" diff --git a/fdk-aac/configure.ac b/fdk-aac/configure.ac new file mode 100644 index 0000000..9c714d7 --- /dev/null +++ b/fdk-aac/configure.ac @@ -0,0 +1,38 @@ +dnl -*- Autoconf -*- +dnl Process this file with autoconf to produce a configure script. + +AC_INIT([fdk-aac], [2.0.0], [http://sourceforge.net/projects/opencore-amr/]) +AC_CONFIG_AUX_DIR(.) +AC_CONFIG_MACRO_DIR([m4]) +AM_INIT_AUTOMAKE([tar-ustar foreign]) +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +dnl Various options for configure +AC_ARG_ENABLE([example], + [AS_HELP_STRING([--enable-example], + [enable example encoding program (default is no)])], + [example=$enableval], [example=no]) + +dnl Automake conditionals to set +AM_CONDITIONAL(EXAMPLE, test x$example = xyes) + +dnl Checks for programs. +AC_PROG_CC +AC_PROG_CXX +LT_INIT + +AC_SEARCH_LIBS([sin], [m]) + +dnl soname version to use +dnl goes by ‘current[:revision[:age]]’ with the soname ending up as +dnl current.age.revision +FDK_AAC_VERSION=2:0:0 + +AS_IF([test x$enable_shared = xyes], [LIBS_PRIVATE=$LIBS], [LIBS_PUBLIC=$LIBS]) +AC_SUBST(FDK_AAC_VERSION) +AC_SUBST(LIBS_PUBLIC) +AC_SUBST(LIBS_PRIVATE) + +AC_CONFIG_FILES([Makefile + fdk-aac.pc]) +AC_OUTPUT diff --git a/fdk-aac/documentation/aacDecoder.pdf b/fdk-aac/documentation/aacDecoder.pdf new file mode 100644 index 0000000..1dec334 Binary files /dev/null and b/fdk-aac/documentation/aacDecoder.pdf differ diff --git a/fdk-aac/documentation/aacEncoder.pdf b/fdk-aac/documentation/aacEncoder.pdf new file mode 100644 index 0000000..e438e27 Binary files /dev/null and b/fdk-aac/documentation/aacEncoder.pdf differ diff --git a/fdk-aac/fdk-aac.pc.in b/fdk-aac/fdk-aac.pc.in new file mode 100644 index 0000000..2edac45 --- /dev/null +++ b/fdk-aac/fdk-aac.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Fraunhofer FDK AAC Codec Library +Description: AAC codec library +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lfdk-aac @LIBS_PUBLIC@ +Libs.private: @LIBS_PRIVATE@ +Cflags: -I${includedir} diff --git a/fdk-aac/fdk-aac.sym b/fdk-aac/fdk-aac.sym new file mode 100644 index 0000000..2a06c41 --- /dev/null +++ b/fdk-aac/fdk-aac.sym @@ -0,0 +1,18 @@ +aacDecoder_AncDataGet +aacDecoder_AncDataInit +aacDecoder_Close +aacDecoder_ConfigRaw +aacDecoder_DecodeFrame +aacDecoder_Fill +aacDecoder_GetFreeBytes +aacDecoder_GetLibInfo +aacDecoder_GetStreamInfo +aacDecoder_Open +aacDecoder_SetParam +aacEncClose +aacEncEncode +aacEncGetLibInfo +aacEncInfo +aacEncOpen +aacEncoder_GetParam +aacEncoder_SetParam diff --git a/fdk-aac/libAACdec/include/aacdecoder_lib.h b/fdk-aac/libAACdec/include/aacdecoder_lib.h new file mode 100644 index 0000000..5f0dd02 --- /dev/null +++ b/fdk-aac/libAACdec/include/aacdecoder_lib.h @@ -0,0 +1,1090 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +#ifndef AACDECODER_LIB_H +#define AACDECODER_LIB_H + +/** + * \file aacdecoder_lib.h + * \brief FDK AAC decoder library interface header file. + * + +\page INTRO Introduction + + +\section SCOPE Scope + +This document describes the high-level application interface and usage of the +ISO/MPEG-2/4 AAC Decoder library developed by the Fraunhofer Institute for +Integrated Circuits (IIS). Depending on the library configuration, decoding of +AAC-LC (Low-Complexity), HE-AAC (High-Efficiency AAC v1 and v2), AAC-LD +(Low-Delay) and AAC-ELD (Enhanced Low-Delay) is implemented. + +All references to SBR (Spectral Band Replication) are only applicable to HE-AAC +and AAC-ELD configurations of the FDK library. All references to PS (Parametric +Stereo) are only applicable to HE-AAC v2 decoder configuration of the library. + +\section DecoderBasics Decoder Basics + +This document can only give a rough overview about the ISO/MPEG-2, ISO/MPEG-4 +AAC audio and MPEG-D USAC coding standards. To understand all details referenced +in this document, you are encouraged to read the following documents. + +- ISO/IEC 13818-7 (MPEG-2 AAC) Standard, defines the syntax of MPEG-2 AAC audio +bitstreams. +- ISO/IEC 14496-3 (MPEG-4 AAC, subpart 1 and 4) Standard, defines the syntax of +MPEG-4 AAC audio bitstreams. +- ISO/IEC 23003-3 (MPEG-D USAC), defines MPEG-D USAC unified speech and audio +codec. +- Lutzky, Schuller, Gayer, Krämer, Wabnik, "A guideline to audio codec +delay", 116th AES Convention, May 8, 2004 + +In short, MPEG Advanced Audio Coding is based on a time-to-frequency mapping of +the signal. The signal is partitioned into overlapping time portions and +transformed into frequency domain. The spectral components are then quantized +and coded using a highly efficient coding scheme.\n Encoded MPEG-2 and MPEG-4 +AAC audio bitstreams are composed of frames. Contrary to MPEG-1/2 Layer-3 (mp3), +the length of individual frames is not restricted to a fixed number of bytes, +but can take any length between 1 and 768 bytes. + +In addition to the above mentioned frequency domain coding mode, MPEG-D USAC +also employs a time domain Algebraic Code-Excited Linear Prediction (ACELP) +speech coder core. This operating mode is selected by the encoder in order to +achieve the optimum audio quality for different content type. Several +enhancements allow achieving higher quality at lower bit rates compared to +MPEG-4 HE-AAC. + + +\page LIBUSE Library Usage + + +\section InterfaceDescritpion API Description + +All API header files are located in the folder /include of the release package. +The contents of each file is described in detail in this document. All header +files are provided for usage in specific C/C++ programs. The main AAC decoder +library API functions are located in aacdecoder_lib.h header file. + +In binary releases the decoder core resides in statically linkable libraries, +for example libAACdec.a. + + +\section Calling_Sequence Calling Sequence + +The following sequence is necessary for proper decoding of ISO/MPEG-2/4 AAC, +HE-AAC v2, or MPEG-D USAC bitstreams. In the following description, input stream +read and output write function details are left out, since they may be +implemented in a variety of configurations depending on the user's specific +requirements. The example implementation uses file-based input/output, and in +such case one may call mpegFileRead_Open() to open an input file and to allocate +memory for the required structures, and the corresponding mpegFileRead_Close() +to close opened files and to de-allocate associated structures. +mpegFileRead_Open() will attempt to detect the bitstream format and in case of +MPEG-4 file format or Raw Packets file format (a proprietary Fraunhofer IIS file +format suitable only for testing) it will read the Audio Specific Config data +(ASC). An unsuccessful attempt to recognize the bitstream format requires the +user to provide this information manually. For any other bitstream formats that +are usually applicable in streaming applications, the decoder itself will try to +synchronize and parse the given bitstream fragment using the FDK transport +library. Hence, for streaming applications (without file access) this step is +not necessary. + + +-# Call aacDecoder_Open() to open and retrieve a handle to a new AAC decoder +instance. \code aacDecoderInfo = aacDecoder_Open(transportType, nrOfLayers); +\endcode +-# If out-of-band config data (Audio Specific Config (ASC) or Stream Mux Config +(SMC)) is available, call aacDecoder_ConfigRaw() to pass this data to the +decoder before beginning the decoding process. If this data is not available in +advance, the decoder will configure itself while decoding, during the +aacDecoder_DecodeFrame() function call. +-# Begin decoding loop. +\code +do { +\endcode +-# Read data from bitstream file or stream buffer in to the driver program +working memory (a client-supplied input buffer "inBuffer" in framework). This +buffer will be used to load AAC bitstream data to the decoder. Only when all +data in this buffer has been processed will the decoder signal an empty buffer. +For file-based input, you may invoke mpegFileRead_Read() to acquire new +bitstream data. +-# Call aacDecoder_Fill() to fill the decoder's internal bitstream input buffer +with the client-supplied bitstream input buffer. Note, if the data loaded in to +the internal buffer is not sufficient to decode a frame, +aacDecoder_DecodeFrame() will return ::AAC_DEC_NOT_ENOUGH_BITS until a +sufficient amount of data is loaded in to the internal buffer. For streaming +formats (ADTS, LOAS), it is acceptable to load more than one frame to the +decoder. However, for RAW file format (Fraunhofer IIS proprietary format), only +one frame may be loaded to the decoder per aacDecoder_DecodeFrame() call. For +least amount of communication delay, fill and decode should be performed on a +frame by frame basis. \code ErrorStatus = aacDecoder_Fill(aacDecoderInfo, +inBuffer, bytesRead, bytesValid); \endcode +-# Call aacDecoder_DecodeFrame(). This function decodes one frame and writes +decoded PCM audio data to a client-supplied buffer. It is the client's +responsibility to allocate a buffer which is large enough to hold the decoded +output data. \code ErrorStatus = aacDecoder_DecodeFrame(aacDecoderInfo, +TimeData, OUT_BUF_SIZE, flags); \endcode If the bitstream configuration (number +of channels, sample rate, frame size) is not known a priori, you may call +aacDecoder_GetStreamInfo() to retrieve a structure that contains this +information. You may use this data to initialize an audio output device. In the +example program, if the number of channels or the sample rate has changed since +program start or the previously decoded frame, the audio output device is then +re-initialized. If WAVE file output is chosen, a new WAVE file for each new +stream configuration is be created. \code p_si = +aacDecoder_GetStreamInfo(aacDecoderInfo); \endcode +-# Repeat steps 5 to 7 until no data is available to decode any more, or in case +of error. \code } while (bytesRead[0] > 0 || doFlush || doBsFlush || +forceContinue); \endcode +-# Call aacDecoder_Close() to de-allocate all AAC decoder and transport layer +structures. \code aacDecoder_Close(aacDecoderInfo); \endcode + +\image latex decode.png "Decode calling sequence" width=11cm + +\image latex change_source.png "Change data source sequence" width 5cm + +\image latex conceal.png "Error concealment sequence" width=14cm + +\subsection Error_Concealment_Sequence Error Concealment Sequence + +There are different strategies to handle bit stream errors. Depending on the +system properties the product designer might choose to take different actions in +case a bit error occurs. In many cases the decoder might be able to do +reasonable error concealment without the need of any additional actions from the +system. But in some cases its not even possible to know how many decoded PCM +output samples are required to fill the gap due to the data error, then the +software surrounding the decoder must deal with the situation. The most simple +way would be to just stop audio playback and resume once enough bit stream data +and/or buffered output samples are available. More sophisticated designs might +also be able to deal with sender/receiver clock drifts or data drop outs by +using a closed loop control of FIFO fulness levels. The chosen strategy depends +on the final product requirements. + +The error concealment sequence diagram illustrates the general execution paths +for error handling. + +The macro IS_OUTPUT_VALID(err) can be used to identify if the audio output +buffer contains valid audio either from error free bit stream data or successful +error concealment. In case the result is false, the decoder output buffer does +not contain meaningful audio samples and should not be passed to any output as +it is. Most likely in case that a continuous audio output PCM stream is +required, the output buffer must be filled with audio data from the calling +framework. This might be e.g. an appropriate number of samples all zero. + +If error code ::AAC_DEC_TRANSPORT_SYNC_ERROR is returned by the decoder, under +some particular conditions it is possible to estimate lost frames due to the bit +stream error. In that case the bit stream is required to have a constant +bitrate, and compatible transport type. Audio samples for the lost frames can be +obtained by calling aacDecoder_DecodeFrame() with flag ::AACDEC_CONCEAL set +n-times where n is the count of lost frames. Please note that the decoder has to +have encountered valid configuration data at least once to be able to generate +concealed data, because at the minimum the sampling rate, frame size and amount +of audio channels needs to be known. + +If it is not possible to get an estimation of lost frames then a constant +fullness of the audio output buffer can be achieved by implementing different +FIFO control techniques e.g. just stop taking of samples from the buffer to +avoid underflow or stop filling new data to the buffer to avoid overflow. But +this techniques are out of scope of this document. + +For a detailed description of a specific error code please refer also to +::AAC_DECODER_ERROR. + +\section BufferSystem Buffer System + +There are three main buffers in an AAC decoder application. One external input +buffer to hold bitstream data from file I/O or elsewhere, one decoder-internal +input buffer, and one to hold the decoded output PCM sample data. In resource +limited applications, the output buffer may be reused as an external input +buffer prior to the subsequence aacDecoder_Fill() function call. + +The external input buffer is set in the example program and its size is defined +by ::IN_BUF_SIZE. You may freely choose different buffer sizes. To feed the data +to the decoder-internal input buffer, use the function aacDecoder_Fill(). This +function returns important information regarding the number of bytes in the +external input buffer that have not yet been copied into the internal input +buffer (variable bytesValid). Once the external buffer has been fully copied, it +can be completely re-filled again. In case you wish to refill the buffer while +there are unprocessed bytes (bytesValid is unequal 0), you should preserve the +unconsumed data. However, we recommend to refill the buffer only when bytesValid +returns 0. + +The bytesValid parameter is an input and output parameter to the FDK decoder. As +an input, it signals how many valid bytes are available in the external buffer. +After consumption of the external buffer using aacDecoder_Fill() function, the +bytesValid parameter indicates if any of the bytes in the external buffer were +not consumed. + +\image latex dec_buffer.png "Life cycle of the external input buffer" width=9cm + +\page OutputFormat Decoder audio output + +\section OutputFormatObtaining Obtaining channel mapping information + +The decoded audio output format is indicated by a set of variables of the +CStreamInfo structure. While the struct members sampleRate, frameSize and +numChannels might be self explanatory, pChannelType and pChannelIndices require +some further explanation. + +These two arrays indicate the configuration of channel data within the output +buffer. Both arrays have CStreamInfo::numChannels number of cells. Each cell of +pChannelType indicates the channel type, which is described in the enum +::AUDIO_CHANNEL_TYPE (defined in FDK_audio.h). The cells of pChannelIndices +indicate the sub index among the channels starting with 0 among channels of the +same audio channel type. + +The indexing scheme is structured as defined in MPEG-2/4 Standards. Indices +start from the front direction (a center channel if available, will always be +index 0) and increment, starting with the left side, pairwise (e.g. L, R) and +from front to back (Front L, Front R, Surround L, Surround R). For detailed +explanation, please refer to ISO/IEC 13818-7:2005(E), chapter 8.5.3.2. + +In case a Program Config is included in the audio configuration, the channel +mapping described within it will be adopted. + +In case of MPEG-D Surround the channel mapping will follow the same criteria +described in ISO/IEC 13818-7:2005(E), but adding corresponding top channels (if +available) to the channel types in order to avoid ambiguity. The examples below +explain these aspects in detail. + +\section OutputFormatChange Changing the audio output format + +For MPEG-4 audio the channel order can be changed at runtime through the +parameter +::AAC_PCM_OUTPUT_CHANNEL_MAPPING. See the description of those +parameters and the decoder library function aacDecoder_SetParam() for more +detail. + +\section OutputFormatExample Channel mapping examples + +The following examples illustrate the location of individual audio samples in +the audio buffer that is passed to aacDecoder_DecodeFrame() and the expected +data in the CStreamInfo structure which can be obtained by calling +aacDecoder_GetStreamInfo(). + +\subsection ExamplesStereo Stereo + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 2 in its audio specific +config would lead to the following values in CStreamInfo: + +CStreamInfo::numChannels = 2 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT } + +CStreamInfo::pChannelIndices = { 0, 1 } + +The output buffer will be formatted as follows: + +\verbatim + ... + ... +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesSurround Surround 5.1 + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +a AAC-LC bit stream which has channelConfiguration = 6 in its audio specific +config, would lead to the following values in CStreamInfo: + +CStreamInfo::numChannels = 6 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_FRONT, ::ACT_LFE, +::ACT_BACK, ::ACT_BACK } + +CStreamInfo::pChannelIndices = { 1, 2, 0, 0, 0, 1 } + +Since ::AAC_PCM_OUTPUT_CHANNEL_MAPPING is 1, WAV file channel ordering will be +used. For a 5.1 channel scheme, thus the channels would be: front left, front +right, center, LFE, surround left, surround right. Thus the third channel is the +center channel, receiving the index 0. The other front channels are front left, +front right being placed as first and second channels with indices 1 and 2 +correspondingly. There is only one LFE, placed as the fourth channel and index +0. Finally both surround channels get the type definition ACT_BACK, and the +indices 0 and 1. + +The output buffer will be formatted as follows: + +\verbatim + +
+ + + +
+ + +... + + +
+ +\endverbatim + +Where N equals to CStreamInfo::frameSize . + +\subsection ExamplesArib ARIB coding mode 2/1 + +In case of ::AAC_PCM_OUTPUT_CHANNEL_MAPPING set to 1, +in case of a ARIB bit stream using coding mode 2/1 as described in ARIB STD-B32 +Part 2 Version 2.1-E1, page 61, would lead to the following values in +CStreamInfo: + +CStreamInfo::numChannels = 3 + +CStreamInfo::pChannelType = { ::ACT_FRONT, ::ACT_FRONT, ::ACT_BACK } + +CStreamInfo::pChannelIndices = { 0, 1, 0 } + +The audio channels will be placed as follows in the audio output buffer: + +\verbatim + + + + +... + + + +Where N equals to CStreamInfo::frameSize . + +\endverbatim + +*/ + +#include "machine_type.h" +#include "FDK_audio.h" + +#include "genericStds.h" + +#define AACDECODER_LIB_VL0 3 +#define AACDECODER_LIB_VL1 0 +#define AACDECODER_LIB_VL2 0 + +/** + * \brief AAC decoder error codes. + */ +typedef enum { + AAC_DEC_OK = + 0x0000, /*!< No error occurred. Output buffer is valid and error free. */ + AAC_DEC_OUT_OF_MEMORY = + 0x0002, /*!< Heap returned NULL pointer. Output buffer is invalid. */ + AAC_DEC_UNKNOWN = + 0x0005, /*!< Error condition is of unknown reason, or from a another + module. Output buffer is invalid. */ + + /* Synchronization errors. Output buffer is invalid. */ + aac_dec_sync_error_start = 0x1000, + AAC_DEC_TRANSPORT_SYNC_ERROR = 0x1001, /*!< The transport decoder had + synchronization problems. Do not + exit decoding. Just feed new + bitstream data. */ + AAC_DEC_NOT_ENOUGH_BITS = 0x1002, /*!< The input buffer ran out of bits. */ + aac_dec_sync_error_end = 0x1FFF, + + /* Initialization errors. Output buffer is invalid. */ + aac_dec_init_error_start = 0x2000, + AAC_DEC_INVALID_HANDLE = + 0x2001, /*!< The handle passed to the function call was invalid (NULL). */ + AAC_DEC_UNSUPPORTED_AOT = + 0x2002, /*!< The AOT found in the configuration is not supported. */ + AAC_DEC_UNSUPPORTED_FORMAT = + 0x2003, /*!< The bitstream format is not supported. */ + AAC_DEC_UNSUPPORTED_ER_FORMAT = + 0x2004, /*!< The error resilience tool format is not supported. */ + AAC_DEC_UNSUPPORTED_EPCONFIG = + 0x2005, /*!< The error protection format is not supported. */ + AAC_DEC_UNSUPPORTED_MULTILAYER = + 0x2006, /*!< More than one layer for AAC scalable is not supported. */ + AAC_DEC_UNSUPPORTED_CHANNELCONFIG = + 0x2007, /*!< The channel configuration (either number or arrangement) is + not supported. */ + AAC_DEC_UNSUPPORTED_SAMPLINGRATE = 0x2008, /*!< The sample rate specified in + the configuration is not + supported. */ + AAC_DEC_INVALID_SBR_CONFIG = + 0x2009, /*!< The SBR configuration is not supported. */ + AAC_DEC_SET_PARAM_FAIL = 0x200A, /*!< The parameter could not be set. Either + the value was out of range or the + parameter does not exist. */ + AAC_DEC_NEED_TO_RESTART = 0x200B, /*!< The decoder needs to be restarted, + since the required configuration change + cannot be performed. */ + AAC_DEC_OUTPUT_BUFFER_TOO_SMALL = + 0x200C, /*!< The provided output buffer is too small. */ + aac_dec_init_error_end = 0x2FFF, + + /* Decode errors. Output buffer is valid but concealed. */ + aac_dec_decode_error_start = 0x4000, + AAC_DEC_TRANSPORT_ERROR = + 0x4001, /*!< The transport decoder encountered an unexpected error. */ + AAC_DEC_PARSE_ERROR = 0x4002, /*!< Error while parsing the bitstream. Most + probably it is corrupted, or the system + crashed. */ + AAC_DEC_UNSUPPORTED_EXTENSION_PAYLOAD = + 0x4003, /*!< Error while parsing the extension payload of the bitstream. + The extension payload type found is not supported. */ + AAC_DEC_DECODE_FRAME_ERROR = 0x4004, /*!< The parsed bitstream value is out of + range. Most probably the bitstream is + corrupt, or the system crashed. */ + AAC_DEC_CRC_ERROR = 0x4005, /*!< The embedded CRC did not match. */ + AAC_DEC_INVALID_CODE_BOOK = 0x4006, /*!< An invalid codebook was signaled. + Most probably the bitstream is corrupt, + or the system crashed. */ + AAC_DEC_UNSUPPORTED_PREDICTION = + 0x4007, /*!< Predictor found, but not supported in the AAC Low Complexity + profile. Most probably the bitstream is corrupt, or has a wrong + format. */ + AAC_DEC_UNSUPPORTED_CCE = 0x4008, /*!< A CCE element was found which is not + supported. Most probably the bitstream is + corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_LFE = 0x4009, /*!< A LFE element was found which is not + supported. Most probably the bitstream is + corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA = + 0x400A, /*!< Gain control data found but not supported. Most probably the + bitstream is corrupt, or has a wrong format. */ + AAC_DEC_UNSUPPORTED_SBA = + 0x400B, /*!< SBA found, but currently not supported in the BSAC profile. + */ + AAC_DEC_TNS_READ_ERROR = 0x400C, /*!< Error while reading TNS data. Most + probably the bitstream is corrupt or the + system crashed. */ + AAC_DEC_RVLC_ERROR = + 0x400D, /*!< Error while decoding error resilient data. */ + aac_dec_decode_error_end = 0x4FFF, + /* Ancillary data errors. Output buffer is valid. */ + aac_dec_anc_data_error_start = 0x8000, + AAC_DEC_ANC_DATA_ERROR = + 0x8001, /*!< Non severe error concerning the ancillary data handling. */ + AAC_DEC_TOO_SMALL_ANC_BUFFER = 0x8002, /*!< The registered ancillary data + buffer is too small to receive the + parsed data. */ + AAC_DEC_TOO_MANY_ANC_ELEMENTS = 0x8003, /*!< More than the allowed number of + ancillary data elements should be + written to buffer. */ + aac_dec_anc_data_error_end = 0x8FFF + +} AAC_DECODER_ERROR; + +/** Macro to identify initialization errors. Output buffer is invalid. */ +#define IS_INIT_ERROR(err) \ + ((((err) >= aac_dec_init_error_start) && ((err) <= aac_dec_init_error_end)) \ + ? 1 \ + : 0) +/** Macro to identify decode errors. Output buffer is valid but concealed. */ +#define IS_DECODE_ERROR(err) \ + ((((err) >= aac_dec_decode_error_start) && \ + ((err) <= aac_dec_decode_error_end)) \ + ? 1 \ + : 0) +/** + * Macro to identify if the audio output buffer contains valid samples after + * calling aacDecoder_DecodeFrame(). Output buffer is valid but can be + * concealed. + */ +#define IS_OUTPUT_VALID(err) (((err) == AAC_DEC_OK) || IS_DECODE_ERROR(err)) + +/*! \enum AAC_MD_PROFILE + * \brief The available metadata profiles which are mostly related to downmixing. The values define the arguments + * for the use with parameter ::AAC_METADATA_PROFILE. + */ +typedef enum { + AAC_MD_PROFILE_MPEG_STANDARD = + 0, /*!< The standard profile creates a mixdown signal based on the + advanced downmix metadata (from a DSE). The equations and default + values are defined in ISO/IEC 14496:3 Ammendment 4. Any other + (legacy) downmix metadata will be ignored. No other parameter will + be modified. */ + AAC_MD_PROFILE_MPEG_LEGACY = + 1, /*!< This profile behaves identical to the standard profile if advanced + downmix metadata (from a DSE) is available. If not, the + matrix_mixdown information embedded in the program configuration + element (PCE) will be applied. If neither is the case, the module + creates a mixdown using the default coefficients as defined in + ISO/IEC 14496:3 AMD 4. The profile can be used to support legacy + digital TV (e.g. DVB) streams. */ + AAC_MD_PROFILE_MPEG_LEGACY_PRIO = + 2, /*!< Similar to the ::AAC_MD_PROFILE_MPEG_LEGACY profile but if both + the advanced (ISO/IEC 14496:3 AMD 4) and the legacy (PCE) MPEG + downmix metadata are available the latter will be applied. + */ + AAC_MD_PROFILE_ARIB_JAPAN = + 3 /*!< Downmix creation as described in ABNT NBR 15602-2. But if advanced + downmix metadata (ISO/IEC 14496:3 AMD 4) is available it will be + preferred because of the higher resolutions. In addition the + metadata expiry time will be set to the value defined in the ARIB + standard (see ::AAC_METADATA_EXPIRY_TIME). + */ +} AAC_MD_PROFILE; + +/*! \enum AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS + * \brief Options for handling of DRC parameters, if presentation mode is not indicated in bitstream + */ +typedef enum { + AAC_DRC_PARAMETER_HANDLING_DISABLED = -1, /*!< DRC parameter handling + disabled, all parameters are + applied as requested. */ + AAC_DRC_PARAMETER_HANDLING_ENABLED = + 0, /*!< Apply changes to requested DRC parameters to prevent clipping. */ + AAC_DRC_PRESENTATION_MODE_1_DEFAULT = + 1, /*!< Use DRC presentation mode 1 as default (e.g. for Nordig) */ + AAC_DRC_PRESENTATION_MODE_2_DEFAULT = + 2 /*!< Use DRC presentation mode 2 as default (e.g. for DTG DBook) */ +} AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS; + +/** + * \brief AAC decoder setting parameters + */ +typedef enum { + AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE = + 0x0002, /*!< Defines how the decoder processes two channel signals: \n + 0: Leave both signals as they are (default). \n + 1: Create a dual mono output signal from channel 1. \n + 2: Create a dual mono output signal from channel 2. \n + 3: Create a dual mono output signal by mixing both channels + (L' = R' = 0.5*Ch1 + 0.5*Ch2). */ + AAC_PCM_OUTPUT_CHANNEL_MAPPING = + 0x0003, /*!< Output buffer channel ordering. 0: MPEG PCE style order, 1: + WAV file channel order (default). */ + AAC_PCM_LIMITER_ENABLE = + 0x0004, /*!< Enable signal level limiting. \n + -1: Auto-config. Enable limiter for all + non-lowdelay configurations by default. \n + 0: Disable limiter in general. \n + 1: Enable limiter always. + It is recommended to call the decoder + with a AACDEC_CLRHIST flag to reset all + states when the limiter switch is changed + explicitly. */ + AAC_PCM_LIMITER_ATTACK_TIME = 0x0005, /*!< Signal level limiting attack time + in ms. Default configuration is 15 + ms. Adjustable range from 1 ms to 15 + ms. */ + AAC_PCM_LIMITER_RELEAS_TIME = 0x0006, /*!< Signal level limiting release time + in ms. Default configuration is 50 + ms. Adjustable time must be larger + than 0 ms. */ + AAC_PCM_MIN_OUTPUT_CHANNELS = + 0x0011, /*!< Minimum number of PCM output channels. If higher than the + number of encoded audio channels, a simple channel extension is + applied (see note 4 for exceptions). \n -1, 0: Disable channel + extension feature. The decoder output contains the same number + of channels as the encoded bitstream. \n 1: This value is + currently needed only together with the mix-down feature. See + ::AAC_PCM_MAX_OUTPUT_CHANNELS and note 2 below. \n + 2: Encoded mono signals will be duplicated to achieve a + 2/0/0.0 channel output configuration. \n 6: The decoder + tries to reorder encoded signals with less than six channels to + achieve a 3/0/2.1 channel output signal. Missing channels will + be filled with a zero signal. If reordering is not possible the + empty channels will simply be appended. Only available if + instance is configured to support multichannel output. \n 8: + The decoder tries to reorder encoded signals with less than + eight channels to achieve a 3/0/4.1 channel output signal. + Missing channels will be filled with a zero signal. If + reordering is not possible the empty channels will simply be + appended. Only available if instance is configured to + support multichannel output.\n NOTE: \n + 1. The channel signaling (CStreamInfo::pChannelType and + CStreamInfo::pChannelIndices) will not be modified. Added empty + channels will be signaled with channel type + AUDIO_CHANNEL_TYPE::ACT_NONE. \n + 2. If the parameter value is greater than that of + ::AAC_PCM_MAX_OUTPUT_CHANNELS both will be set to the same + value. \n + 3. This parameter does not affect MPEG Surround processing. + \n + 4. This parameter will be ignored if the number of encoded + audio channels is greater than 8. */ + AAC_PCM_MAX_OUTPUT_CHANNELS = + 0x0012, /*!< Maximum number of PCM output channels. If lower than the + number of encoded audio channels, downmixing is applied + accordingly (see note 5 for exceptions). If dedicated metadata + is available in the stream it will be used to achieve better + mixing results. \n -1, 0: Disable downmixing feature. The + decoder output contains the same number of channels as the + encoded bitstream. \n 1: All encoded audio configurations + with more than one channel will be mixed down to one mono + output signal. \n 2: The decoder performs a stereo mix-down + if the number encoded audio channels is greater than two. \n 6: + If the number of encoded audio channels is greater than six the + decoder performs a mix-down to meet the target output + configuration of 3/0/2.1 channels. Only available if instance + is configured to support multichannel output. \n 8: This + value is currently needed only together with the channel + extension feature. See ::AAC_PCM_MIN_OUTPUT_CHANNELS and note 2 + below. Only available if instance is configured to support + multichannel output. \n NOTE: \n + 1. Down-mixing of any seven or eight channel configuration + not defined in ISO/IEC 14496-3 PDAM 4 is not supported by this + software version. \n + 2. If the parameter value is greater than zero but smaller + than ::AAC_PCM_MIN_OUTPUT_CHANNELS both will be set to same + value. \n + 3. The operating mode of the MPEG Surround module will be + set accordingly. \n + 4. Setting this parameter with any value will disable the + binaural processing of the MPEG Surround module + 5. This parameter will be ignored if the number of encoded + audio channels is greater than 8. */ + AAC_METADATA_PROFILE = + 0x0020, /*!< See ::AAC_MD_PROFILE for all available values. */ + AAC_METADATA_EXPIRY_TIME = 0x0021, /*!< Defines the time in ms after which all + the bitstream associated meta-data (DRC, + downmix coefficients, ...) will be reset + to default if no update has been + received. Negative values disable the + feature. */ + + AAC_CONCEAL_METHOD = 0x0100, /*!< Error concealment: Processing method. \n + 0: Spectral muting. \n + 1: Noise substitution (see ::CONCEAL_NOISE). + \n 2: Energy interpolation (adds additional + signal delay of one frame, see + ::CONCEAL_INTER. only some AOTs are + supported). \n */ + AAC_DRC_BOOST_FACTOR = + 0x0200, /*!< Dynamic Range Control: Scaling factor for boosting gain + values. Defines how the boosting DRC factors (conveyed in the + bitstream) will be applied to the decoded signal. The valid + values range from 0 (don't apply boost factors) to 127 (fully + apply boost factors). Default value is 0. */ + AAC_DRC_ATTENUATION_FACTOR = + 0x0201, /*!< Dynamic Range Control: Scaling factor for attenuating gain + values. Same as + ::AAC_DRC_BOOST_FACTOR but for attenuating DRC factors. */ + AAC_DRC_REFERENCE_LEVEL = + 0x0202, /*!< Dynamic Range Control (DRC): Target reference level. Defines + the level below full-scale (quantized in steps of 0.25dB) to + which the output audio signal will be normalized to by the DRC + module. The parameter controls loudness normalization for both + MPEG-4 DRC and MPEG-D DRC. The valid values range from 40 (-10 + dBFS) to 127 (-31.75 dBFS). Any value smaller than 0 switches + off loudness normalization and MPEG-4 DRC. By default, loudness + normalization and MPEG-4 DRC is switched off. */ + AAC_DRC_HEAVY_COMPRESSION = + 0x0203, /*!< Dynamic Range Control: En-/Disable DVB specific heavy + compression (aka RF mode). If set to 1, the decoder will apply + the compression values from the DVB specific ancillary data + field. At the same time the MPEG-4 Dynamic Range Control tool + will be disabled. By default, heavy compression is disabled. */ + AAC_DRC_DEFAULT_PRESENTATION_MODE = + 0x0204, /*!< Dynamic Range Control: Default presentation mode (DRC + parameter handling). \n Defines the handling of the DRC + parameters boost factor, attenuation factor and heavy + compression, if no presentation mode is indicated in the + bitstream.\n For options, see + ::AAC_DRC_DEFAULT_PRESENTATION_MODE_OPTIONS.\n Default: + ::AAC_DRC_PARAMETER_HANDLING_DISABLED */ + AAC_DRC_ENC_TARGET_LEVEL = + 0x0205, /*!< Dynamic Range Control: Encoder target level for light (i.e. + not heavy) compression.\n If known, this declares the target + reference level that was assumed at the encoder for calculation + of limiting gains. The valid values range from 0 (full-scale) + to 127 (31.75 dB below full-scale). This parameter is used only + with ::AAC_DRC_PARAMETER_HANDLING_ENABLED and ignored + otherwise.\n Default: 127 (worst-case assumption).\n */ + AAC_QMF_LOWPOWER = 0x0300, /*!< Quadrature Mirror Filter (QMF) Bank processing + mode. \n -1: Use internal default. Implies MPEG + Surround partially complex accordingly. \n 0: + Use complex QMF data mode. \n 1: Use real (low + power) QMF data mode. \n */ + AAC_TPDEC_CLEAR_BUFFER = + 0x0603, /*!< Clear internal bit stream buffer of transport layers. The + decoder will start decoding at new data passed after this event + and any previous data is discarded. */ + AAC_UNIDRC_SET_EFFECT = 0x0903 /*!< MPEG-D DRC: Request a DRC effect type for + selection of a DRC set.\n Supported indices + are:\n -1: DRC off. Completely disables + MPEG-D DRC.\n 0: None (default). Disables + MPEG-D DRC, but automatically enables DRC if + necessary to prevent clipping.\n 1: Late + night\n 2: Noisy environment\n 3: Limited + playback range\n 4: Low playback level\n 5: + Dialog enhancement\n 6: General compression. + Used for generally enabling MPEG-D DRC + without particular request.\n */ + +} AACDEC_PARAM; + +/** + * \brief This structure gives information about the currently decoded audio + * data. All fields are read-only. + */ +typedef struct { + /* These five members are the only really relevant ones for the user. */ + INT sampleRate; /*!< The sample rate in Hz of the decoded PCM audio signal. */ + INT frameSize; /*!< The frame size of the decoded PCM audio signal. \n + Typically this is: \n + 1024 or 960 for AAC-LC \n + 2048 or 1920 for HE-AAC (v2) \n + 512 or 480 for AAC-LD and AAC-ELD \n + 768, 1024, 2048 or 4096 for USAC */ + INT numChannels; /*!< The number of output audio channels before the rendering + module, i.e. the original channel configuration. */ + AUDIO_CHANNEL_TYPE + *pChannelType; /*!< Audio channel type of each output audio channel. */ + UCHAR *pChannelIndices; /*!< Audio channel index for each output audio + channel. See ISO/IEC 13818-7:2005(E), 8.5.3.2 + Explicit channel mapping using a + program_config_element() */ + /* Decoder internal members. */ + INT aacSampleRate; /*!< Sampling rate in Hz without SBR (from configuration + info) divided by a (ELD) downscale factor if present. */ + INT profile; /*!< MPEG-2 profile (from file header) (-1: not applicable (e. g. + MPEG-4)). */ + AUDIO_OBJECT_TYPE + aot; /*!< Audio Object Type (from ASC): is set to the appropriate value + for MPEG-2 bitstreams (e. g. 2 for AAC-LC). */ + INT channelConfig; /*!< Channel configuration (0: PCE defined, 1: mono, 2: + stereo, ... */ + INT bitRate; /*!< Instantaneous bit rate. */ + INT aacSamplesPerFrame; /*!< Samples per frame for the AAC core (from ASC) + divided by a (ELD) downscale factor if present. \n + Typically this is (with a downscale factor of 1): + \n 1024 or 960 for AAC-LC \n 512 or 480 for + AAC-LD and AAC-ELD */ + INT aacNumChannels; /*!< The number of audio channels after AAC core + processing (before PS or MPS processing). CAUTION: This + are not the final number of output channels! */ + AUDIO_OBJECT_TYPE extAot; /*!< Extension Audio Object Type (from ASC) */ + INT extSamplingRate; /*!< Extension sampling rate in Hz (from ASC) divided by + a (ELD) downscale factor if present. */ + + UINT outputDelay; /*!< The number of samples the output is additionally + delayed by.the decoder. */ + UINT flags; /*!< Copy of internal flags. Only to be written by the decoder, + and only to be read externally. */ + + SCHAR epConfig; /*!< epConfig level (from ASC): only level 0 supported, -1 + means no ER (e. g. AOT=2, MPEG-2 AAC, etc.) */ + /* Statistics */ + INT numLostAccessUnits; /*!< This integer will reflect the estimated amount of + lost access units in case aacDecoder_DecodeFrame() + returns AAC_DEC_TRANSPORT_SYNC_ERROR. It will be + < 0 if the estimation failed. */ + + INT64 numTotalBytes; /*!< This is the number of total bytes that have passed + through the decoder. */ + INT64 + numBadBytes; /*!< This is the number of total bytes that were considered + with errors from numTotalBytes. */ + INT64 + numTotalAccessUnits; /*!< This is the number of total access units that + have passed through the decoder. */ + INT64 numBadAccessUnits; /*!< This is the number of total access units that + were considered with errors from numTotalBytes. */ + + /* Metadata */ + SCHAR drcProgRefLev; /*!< DRC program reference level. Defines the reference + level below full-scale. It is quantized in steps of + 0.25dB. The valid values range from 0 (0 dBFS) to 127 + (-31.75 dBFS). It is used to reflect the average + loudness of the audio in LKFS according to ITU-R BS + 1770. If no level has been found in the bitstream the + value is -1. */ + SCHAR + drcPresMode; /*!< DRC presentation mode. According to ETSI TS 101 154, + this field indicates whether light (MPEG-4 Dynamic Range + Control tool) or heavy compression (DVB heavy + compression) dynamic range control shall take priority + on the outputs. For details, see ETSI TS 101 154, table + C.33. Possible values are: \n -1: No corresponding + metadata found in the bitstream \n 0: DRC presentation + mode not indicated \n 1: DRC presentation mode 1 \n 2: + DRC presentation mode 2 \n 3: Reserved */ + +} CStreamInfo; + +typedef struct AAC_DECODER_INSTANCE + *HANDLE_AACDECODER; /*!< Pointer to a AAC decoder instance. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize ancillary data buffer. + * + * \param self AAC decoder handle. + * \param buffer Pointer to (external) ancillary data buffer. + * \param size Size of the buffer pointed to by buffer. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_AncDataInit(HANDLE_AACDECODER self, + UCHAR *buffer, int size); + +/** + * \brief Get one ancillary data element. + * + * \param self AAC decoder handle. + * \param index Index of the ancillary data element to get. + * \param ptr Pointer to a buffer receiving a pointer to the requested + * ancillary data element. + * \param size Pointer to a buffer receiving the length of the requested + * ancillary data element. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_AncDataGet(HANDLE_AACDECODER self, + int index, UCHAR **ptr, + int *size); + +/** + * \brief Set one single decoder parameter. + * + * \param self AAC decoder handle. + * \param param Parameter to be set. + * \param value Parameter value. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_SetParam(const HANDLE_AACDECODER self, + const AACDEC_PARAM param, + const INT value); + +/** + * \brief Get free bytes inside decoder internal buffer. + * \param self Handle of AAC decoder instance. + * \param pFreeBytes Pointer to variable receiving amount of free bytes inside + * decoder internal buffer. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR +aacDecoder_GetFreeBytes(const HANDLE_AACDECODER self, UINT *pFreeBytes); + +/** + * \brief Open an AAC decoder instance. + * \param transportFmt The transport type to be used. + * \param nrOfLayers Number of transport layers. + * \return AAC decoder handle. + */ +LINKSPEC_H HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, + UINT nrOfLayers); + +/** + * \brief Explicitly configure the decoder by passing a raw AudioSpecificConfig + * (ASC) or a StreamMuxConfig (SMC), contained in a binary buffer. This is + * required for MPEG-4 and Raw Packets file format bitstreams as well as for + * LATM bitstreams with no in-band SMC. If the transport format is LATM with or + * without LOAS, configuration is assumed to be an SMC, for all other file + * formats an ASC. + * + * \param self AAC decoder handle. + * \param conf Pointer to an unsigned char buffer containing the binary + * configuration buffer (either ASC or SMC). + * \param length Length of the configuration buffer in bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_ConfigRaw(HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[]); + +/** + * \brief Submit raw ISO base media file format boxes to decoder for parsing + * (only some box types are recognized). + * + * \param self AAC decoder handle. + * \param buffer Pointer to an unsigned char buffer containing the binary box + * data (including size and type, can be a sequence of multiple boxes). + * \param length Length of the data in bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_RawISOBMFFData(HANDLE_AACDECODER self, + UCHAR *buffer, + UINT length); + +/** + * \brief Fill AAC decoder's internal input buffer with bitstream data from the + * external input buffer. The function only copies such data as long as the + * decoder-internal input buffer is not full. So it grabs whatever it can from + * pBuffer and returns information (bytesValid) so that at a subsequent call of + * %aacDecoder_Fill(), the right position in pBuffer can be determined to grab + * the next data. + * + * \param self AAC decoder handle. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required + * because decoder-internally we need the information to calculate the offset to + * pBuffer, where the next available data is, which is then + * fed into the decoder-internal buffer (as much as + * possible). Our example framework implementation fills the + * buffer at pBuffer again, once it contains no available valid bytes anymore + * (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer + * that have not yet been copied into the decoder's internal bitstream buffer by + * calling this function. The value is updated according to + * the amount of newly copied bytes. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *bytesValid); + +#define AACDEC_CONCEAL \ + 1 /*!< Flag for aacDecoder_DecodeFrame(): Trigger the built-in error \ + concealment module to generate a substitute signal for one lost frame. \ + New input data will not be considered. */ +#define AACDEC_FLUSH \ + 2 /*!< Flag for aacDecoder_DecodeFrame(): Flush all filterbanks to get all \ + delayed audio without having new input data. Thus new input data will \ + not be considered.*/ +#define AACDEC_INTR \ + 4 /*!< Flag for aacDecoder_DecodeFrame(): Signal an input bit stream data \ + discontinuity. Resync any internals as necessary. */ +#define AACDEC_CLRHIST \ + 8 /*!< Flag for aacDecoder_DecodeFrame(): Clear all signal delay lines and \ + history buffers. CAUTION: This can cause discontinuities in the output \ + signal. */ + +/** + * \brief Decode one audio frame + * + * \param self AAC decoder handle. + * \param pTimeData Pointer to external output buffer where the decoded PCM + * samples will be stored into. + * \param timeDataSize Size of external output buffer. + * \param flags Bit field with flags for the decoder: \n + * (flags & AACDEC_CONCEAL) == 1: Do concealment. \n + * (flags & AACDEC_FLUSH) == 2: Discard input data. Flush + * filter banks (output delayed audio). \n (flags & AACDEC_INTR) == 4: Input + * data is discontinuous. Resynchronize any internals as + * necessary. \n (flags & AACDEC_CLRHIST) == 8: Clear all signal delay lines and + * history buffers. + * \return Error code. + */ +LINKSPEC_H AAC_DECODER_ERROR aacDecoder_DecodeFrame(HANDLE_AACDECODER self, + INT_PCM *pTimeData, + const INT timeDataSize, + const UINT flags); + +/** + * \brief De-allocate all resources of an AAC decoder instance. + * + * \param self AAC decoder handle. + * \return void. + */ +LINKSPEC_H void aacDecoder_Close(HANDLE_AACDECODER self); + +/** + * \brief Get CStreamInfo handle from decoder. + * + * \param self AAC decoder handle. + * \return Reference to requested CStreamInfo. + */ +LINKSPEC_H CStreamInfo *aacDecoder_GetStreamInfo(HANDLE_AACDECODER self); + +/** + * \brief Get decoder library info. + * + * \param info Pointer to an allocated LIB_INFO structure. + * \return 0 on success. + */ +LINKSPEC_H INT aacDecoder_GetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* AACDECODER_LIB_H */ diff --git a/fdk-aac/libAACdec/src/FDK_delay.cpp b/fdk-aac/libAACdec/src/FDK_delay.cpp new file mode 100644 index 0000000..0ab1a66 --- /dev/null +++ b/fdk-aac/libAACdec/src/FDK_delay.cpp @@ -0,0 +1,173 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: + +*******************************************************************************/ + +#include "FDK_delay.h" + +#include "genericStds.h" + +#define MAX_FRAME_LENGTH (1024) + +INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, + const UCHAR num_channels) { + FDK_ASSERT(data != NULL); + FDK_ASSERT(num_channels > 0); + + if (delay > 0) { + data->delay_line = + (INT_PCM*)FDKcalloc(num_channels * delay, sizeof(INT_PCM)); + if (data->delay_line == NULL) { + return -1; + } + } else { + data->delay_line = NULL; + } + data->num_channels = num_channels; + data->delay = delay; + + return 0; +} + +void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer, + const UINT frame_length, const UCHAR channel) { + FDK_ASSERT(data != NULL); + + if (data->delay > 0) { + C_ALLOC_SCRATCH_START(tmp, FIXP_PCM, MAX_FRAME_LENGTH) + FDK_ASSERT(frame_length <= MAX_FRAME_LENGTH); + FDK_ASSERT(channel < data->num_channels); + FDK_ASSERT(time_buffer != NULL); + if (frame_length >= data->delay) { + FDKmemcpy(tmp, &time_buffer[frame_length - data->delay], + data->delay * sizeof(FIXP_PCM)); + FDKmemmove(&time_buffer[data->delay], &time_buffer[0], + (frame_length - data->delay) * sizeof(FIXP_PCM)); + FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], + data->delay * sizeof(FIXP_PCM)); + FDKmemcpy(&data->delay_line[channel * data->delay], tmp, + data->delay * sizeof(FIXP_PCM)); + } else { + FDKmemcpy(tmp, &time_buffer[0], frame_length * sizeof(FIXP_PCM)); + FDKmemcpy(&time_buffer[0], &data->delay_line[channel * data->delay], + frame_length * sizeof(FIXP_PCM)); + FDKmemcpy(&data->delay_line[channel * data->delay], + &data->delay_line[channel * data->delay + frame_length], + (data->delay - frame_length) * sizeof(FIXP_PCM)); + FDKmemcpy(&data->delay_line[channel * data->delay + + (data->delay - frame_length)], + tmp, frame_length * sizeof(FIXP_PCM)); + } + C_ALLOC_SCRATCH_END(tmp, FIXP_PCM, MAX_FRAME_LENGTH) + } + + return; +} + +void FDK_Delay_Destroy(FDK_SignalDelay* data) { + if (data->delay_line != NULL) { + FDKfree(data->delay_line); + } + data->delay_line = NULL; + data->delay = 0; + data->num_channels = 0; + + return; +} diff --git a/fdk-aac/libAACdec/src/FDK_delay.h b/fdk-aac/libAACdec/src/FDK_delay.h new file mode 100644 index 0000000..f89c3a2 --- /dev/null +++ b/fdk-aac/libAACdec/src/FDK_delay.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: + +*******************************************************************************/ + +#ifndef FDK_DELAY_H +#define FDK_DELAY_H + +#include "aac_rom.h" + +/** + * Structure representing one delay element for multiple channels. + */ +typedef struct { + INT_PCM* delay_line; /*!< Pointer which stores allocated delay line. */ + USHORT delay; /*!< Delay required in samples (per channel). */ + UCHAR num_channels; /*!< Number of channels to delay. */ +} FDK_SignalDelay; + +/** + * \brief Create delay element for multiple channels with fixed delay value. + * + * \param data Pointer delay element structure. + * \param delay Required delay value in samples per channel. + * \param num_channels Required number of channels. + * + * \return -1 on out of memory, else 0 + */ +INT FDK_Delay_Create(FDK_SignalDelay* data, const USHORT delay, + const UCHAR num_channels); + +/** + * \brief Apply delay to one channel (non-interleaved storage assumed). + * + * \param data Pointer delay element structure. + * \param time_buffer Pointer to signal to delay. + * \param frame_length Frame length of input/output signal (needs to be >= + * delay). + * \param channel Index of current channel (0 <= channel < num_channels). + * + * \return void + */ +void FDK_Delay_Apply(FDK_SignalDelay* data, FIXP_PCM* time_buffer, + const UINT frame_length, const UCHAR channel); + +/** + * \brief Destroy delay element. + * + * \param data Pointer delay element structure. + * + * \return void + */ +void FDK_Delay_Destroy(FDK_SignalDelay* data); + +#endif /* #ifndef FDK_DELAY_H */ diff --git a/fdk-aac/libAACdec/src/aac_ram.cpp b/fdk-aac/libAACdec/src/aac_ram.cpp new file mode 100644 index 0000000..e13167d --- /dev/null +++ b/fdk-aac/libAACdec/src/aac_ram.cpp @@ -0,0 +1,185 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#include "aac_ram.h" +#include "aac_rom.h" + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER2_TAG 1 + +#define WORKBUFFER3_TAG 4 +#define WORKBUFFER4_TAG 5 + +#define WORKBUFFER5_TAG 6 + +#define WORKBUFFER6_TAG 7 + +/*! The structure AAC_DECODER_INSTANCE is the top level structure holding all + decoder configurations, handles and structs. + */ +C_ALLOC_MEM(AacDecoder, struct AAC_DECODER_INSTANCE, 1) + +/*! + \name StaticAacData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! The structure CAacDecoderStaticChannelInfo contains the static sideinfo + which is needed for the decoding of one aac channel.
Dimension: + #AacDecoderChannels */ +C_ALLOC_MEM2(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo, 1, (8)) + +/*! The structure CAacDecoderChannelInfo contains the dynamic sideinfo which is + needed for the decoding of one aac channel.
Dimension: + #AacDecoderChannels */ +C_AALLOC_MEM2(AacDecoderChannelInfo, CAacDecoderChannelInfo, 1, (8)) + +/*! Overlap buffer */ +C_AALLOC_MEM2(OverlapBuffer, FIXP_DBL, OverlapBufferSize, (8)) + +C_ALLOC_MEM(DrcInfo, CDrcInfo, 1) + +/*! The structure CpePersistentData holds the persistent data shared by both + channels of a CPE.
It needs to be allocated for each CPE.
+ Dimension: 1 */ +C_ALLOC_MEM(CpePersistentData, CpePersistentData, 1) + +/*! The structure CCplxPredictionData holds data for complex stereo prediction. +
Dimension: 1 + */ +C_ALLOC_MEM(CplxPredictionData, CCplxPredictionData, 1) + +/*! The buffer holds time samples for the crossfade in case of an USAC DASH IPF + config change Dimension: (8) + */ +C_ALLOC_MEM2(TimeDataFlush, INT_PCM, TIME_DATA_FLUSH_SIZE, (8)) + +/* @} */ + +/*! + \name DynamicAacData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the sbr decoder +*/ + +/* Take into consideration to make use of the WorkBufferCore[3/4] for decoder + * configurations with more than 2 channels */ +C_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL, ((8) * 1024), SECT_DATA_L2, + WORKBUFFER2_TAG) + +C_ALLOC_MEM_OVERLAY(WorkBufferCore3, FIXP_DBL, WB_SECTION_SIZE, SECT_DATA_L2, + WORKBUFFER3_TAG) +C_AALLOC_MEM(WorkBufferCore4, FIXP_DBL, WB_SECTION_SIZE) +C_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR, + fMax((INT)(sizeof(FIXP_DBL) * WB_SECTION_SIZE), + (INT)sizeof(CAacDecoderCommonData)), + SECT_DATA_L2, WORKBUFFER6_TAG) + +C_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1, 1, SECT_DATA_L1, + WORKBUFFER1_TAG) + +/* double buffer size needed for de-/interleaving */ +C_ALLOC_MEM_OVERLAY(WorkBufferCore5, PCM_DEC, (8) * (1024 * 4) * 2, + SECT_DATA_EXTERN, WORKBUFFER5_TAG) diff --git a/fdk-aac/libAACdec/src/aac_ram.h b/fdk-aac/libAACdec/src/aac_ram.h new file mode 100644 index 0000000..a861e25 --- /dev/null +++ b/fdk-aac/libAACdec/src/aac_ram.h @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef AAC_RAM_H +#define AAC_RAM_H + +#include "common_fix.h" + +#include "aacdecoder.h" + +#include "channel.h" + +#include "ac_arith_coder.h" + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr.h" + +/* End of formal fix.h */ + +#define MAX_SYNCHS 10 +#define SAMPL_FREQS 12 + +H_ALLOC_MEM(AacDecoder, AAC_DECODER_INSTANCE) + +H_ALLOC_MEM(DrcInfo, CDrcInfo) + +H_ALLOC_MEM(AacDecoderStaticChannelInfo, CAacDecoderStaticChannelInfo) +H_ALLOC_MEM(AacDecoderChannelInfo, CAacDecoderChannelInfo) +H_ALLOC_MEM(OverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(CpePersistentData, CpePersistentData) +H_ALLOC_MEM(CplxPredictionData, CCplxPredictionData) +H_ALLOC_MEM(SpectralCoeffs, FIXP_DBL) +H_ALLOC_MEM(SpecScale, SHORT) + +H_ALLOC_MEM(TimeDataFlush, INT_PCM) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore1, CWorkBufferCore1) +H_ALLOC_MEM_OVERLAY(WorkBufferCore2, FIXP_DBL) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore3, FIXP_DBL) +H_ALLOC_MEM(WorkBufferCore4, FIXP_DBL) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore5, PCM_DEC) + +H_ALLOC_MEM_OVERLAY(WorkBufferCore6, SCHAR) + +#endif /* #ifndef AAC_RAM_H */ diff --git a/fdk-aac/libAACdec/src/aac_rom.cpp b/fdk-aac/libAACdec/src/aac_rom.cpp new file mode 100644 index 0000000..cbdffc4 --- /dev/null +++ b/fdk-aac/libAACdec/src/aac_rom.cpp @@ -0,0 +1,3428 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl, Tobias Chalupka + + Description: Definition of constant tables + +*******************************************************************************/ + +#include "aac_rom.h" + +/* Prescale InverseQuantTable by 4 to save + redundant shifts in invers quantization + */ +#define SCL_TAB(a) (a >> 4) +const FIXP_DBL InverseQuantTable[INV_QUANT_TABLESIZE + 1] = { + SCL_TAB(0x32CBFD40), SCL_TAB(0x330FC340), SCL_TAB(0x33539FC0), + SCL_TAB(0x33979280), SCL_TAB(0x33DB9BC0), SCL_TAB(0x341FBB80), + SCL_TAB(0x3463F180), SCL_TAB(0x34A83DC0), SCL_TAB(0x34ECA000), + SCL_TAB(0x35311880), SCL_TAB(0x3575A700), SCL_TAB(0x35BA4B80), + SCL_TAB(0x35FF0600), SCL_TAB(0x3643D680), SCL_TAB(0x3688BCC0), + SCL_TAB(0x36CDB880), SCL_TAB(0x3712CA40), SCL_TAB(0x3757F1C0), + SCL_TAB(0x379D2F00), SCL_TAB(0x37E28180), SCL_TAB(0x3827E9C0), + SCL_TAB(0x386D6740), SCL_TAB(0x38B2FA40), SCL_TAB(0x38F8A2C0), + SCL_TAB(0x393E6080), SCL_TAB(0x39843380), SCL_TAB(0x39CA1BC0), + SCL_TAB(0x3A101940), SCL_TAB(0x3A562BC0), SCL_TAB(0x3A9C5340), + SCL_TAB(0x3AE28FC0), SCL_TAB(0x3B28E180), SCL_TAB(0x3B6F4800), + SCL_TAB(0x3BB5C340), SCL_TAB(0x3BFC5380), SCL_TAB(0x3C42F880), + SCL_TAB(0x3C89B200), SCL_TAB(0x3CD08080), SCL_TAB(0x3D176340), + SCL_TAB(0x3D5E5B00), SCL_TAB(0x3DA56700), SCL_TAB(0x3DEC87C0), + SCL_TAB(0x3E33BCC0), SCL_TAB(0x3E7B0640), SCL_TAB(0x3EC26400), + SCL_TAB(0x3F09D640), SCL_TAB(0x3F515C80), SCL_TAB(0x3F98F740), + SCL_TAB(0x3FE0A600), SCL_TAB(0x40286900), SCL_TAB(0x40704000), + SCL_TAB(0x40B82B00), SCL_TAB(0x41002A00), SCL_TAB(0x41483D00), + SCL_TAB(0x41906400), SCL_TAB(0x41D89F00), SCL_TAB(0x4220ED80), + SCL_TAB(0x42695000), SCL_TAB(0x42B1C600), SCL_TAB(0x42FA5000), + SCL_TAB(0x4342ED80), SCL_TAB(0x438B9E80), SCL_TAB(0x43D46380), + SCL_TAB(0x441D3B80), SCL_TAB(0x44662780), SCL_TAB(0x44AF2680), + SCL_TAB(0x44F83900), SCL_TAB(0x45415F00), SCL_TAB(0x458A9880), + SCL_TAB(0x45D3E500), SCL_TAB(0x461D4500), SCL_TAB(0x4666B800), + SCL_TAB(0x46B03E80), SCL_TAB(0x46F9D800), SCL_TAB(0x47438480), + SCL_TAB(0x478D4400), SCL_TAB(0x47D71680), SCL_TAB(0x4820FC00), + SCL_TAB(0x486AF500), SCL_TAB(0x48B50000), SCL_TAB(0x48FF1E80), + SCL_TAB(0x49494F80), SCL_TAB(0x49939380), SCL_TAB(0x49DDEA80), + SCL_TAB(0x4A285400), SCL_TAB(0x4A72D000), SCL_TAB(0x4ABD5E80), + SCL_TAB(0x4B080000), SCL_TAB(0x4B52B400), SCL_TAB(0x4B9D7A80), + SCL_TAB(0x4BE85380), SCL_TAB(0x4C333F00), SCL_TAB(0x4C7E3D00), + SCL_TAB(0x4CC94D00), SCL_TAB(0x4D146F80), SCL_TAB(0x4D5FA500), + SCL_TAB(0x4DAAEC00), SCL_TAB(0x4DF64580), SCL_TAB(0x4E41B180), + SCL_TAB(0x4E8D2F00), SCL_TAB(0x4ED8BF80), SCL_TAB(0x4F246180), + SCL_TAB(0x4F701600), SCL_TAB(0x4FBBDC00), SCL_TAB(0x5007B480), + SCL_TAB(0x50539F00), SCL_TAB(0x509F9B80), SCL_TAB(0x50EBA980), + SCL_TAB(0x5137C980), SCL_TAB(0x5183FB80), SCL_TAB(0x51D03F80), + SCL_TAB(0x521C9500), SCL_TAB(0x5268FC80), SCL_TAB(0x52B57580), + SCL_TAB(0x53020000), SCL_TAB(0x534E9C80), SCL_TAB(0x539B4A80), + SCL_TAB(0x53E80A80), SCL_TAB(0x5434DB80), SCL_TAB(0x5481BE80), + SCL_TAB(0x54CEB280), SCL_TAB(0x551BB880), SCL_TAB(0x5568CF80), + SCL_TAB(0x55B5F800), SCL_TAB(0x56033200), SCL_TAB(0x56507D80), + SCL_TAB(0x569DDA00), SCL_TAB(0x56EB4800), SCL_TAB(0x5738C700), + SCL_TAB(0x57865780), SCL_TAB(0x57D3F900), SCL_TAB(0x5821AC00), + SCL_TAB(0x586F7000), SCL_TAB(0x58BD4500), SCL_TAB(0x590B2B00), + SCL_TAB(0x59592200), SCL_TAB(0x59A72A80), SCL_TAB(0x59F54380), + SCL_TAB(0x5A436D80), SCL_TAB(0x5A91A900), SCL_TAB(0x5ADFF500), + SCL_TAB(0x5B2E5180), SCL_TAB(0x5B7CBF80), SCL_TAB(0x5BCB3E00), + SCL_TAB(0x5C19CD00), SCL_TAB(0x5C686D80), SCL_TAB(0x5CB71E00), + SCL_TAB(0x5D05DF80), SCL_TAB(0x5D54B200), SCL_TAB(0x5DA39500), + SCL_TAB(0x5DF28880), SCL_TAB(0x5E418C80), SCL_TAB(0x5E90A100), + SCL_TAB(0x5EDFC680), SCL_TAB(0x5F2EFC00), SCL_TAB(0x5F7E4280), + SCL_TAB(0x5FCD9900), SCL_TAB(0x601D0080), SCL_TAB(0x606C7800), + SCL_TAB(0x60BC0000), SCL_TAB(0x610B9800), SCL_TAB(0x615B4100), + SCL_TAB(0x61AAF980), SCL_TAB(0x61FAC300), SCL_TAB(0x624A9C80), + SCL_TAB(0x629A8600), SCL_TAB(0x62EA8000), SCL_TAB(0x633A8A00), + SCL_TAB(0x638AA480), SCL_TAB(0x63DACF00), SCL_TAB(0x642B0980), + SCL_TAB(0x647B5400), SCL_TAB(0x64CBAE80), SCL_TAB(0x651C1900), + SCL_TAB(0x656C9400), SCL_TAB(0x65BD1E80), SCL_TAB(0x660DB900), + SCL_TAB(0x665E6380), SCL_TAB(0x66AF1E00), SCL_TAB(0x66FFE880), + SCL_TAB(0x6750C280), SCL_TAB(0x67A1AC80), SCL_TAB(0x67F2A600), + SCL_TAB(0x6843B000), SCL_TAB(0x6894C900), SCL_TAB(0x68E5F200), + SCL_TAB(0x69372B00), SCL_TAB(0x69887380), SCL_TAB(0x69D9CB80), + SCL_TAB(0x6A2B3300), SCL_TAB(0x6A7CAA80), SCL_TAB(0x6ACE3180), + SCL_TAB(0x6B1FC800), SCL_TAB(0x6B716E00), SCL_TAB(0x6BC32400), + SCL_TAB(0x6C14E900), SCL_TAB(0x6C66BD80), SCL_TAB(0x6CB8A180), + SCL_TAB(0x6D0A9500), SCL_TAB(0x6D5C9800), SCL_TAB(0x6DAEAA00), + SCL_TAB(0x6E00CB80), SCL_TAB(0x6E52FC80), SCL_TAB(0x6EA53D00), + SCL_TAB(0x6EF78C80), SCL_TAB(0x6F49EB80), SCL_TAB(0x6F9C5980), + SCL_TAB(0x6FEED700), SCL_TAB(0x70416380), SCL_TAB(0x7093FF00), + SCL_TAB(0x70E6AA00), SCL_TAB(0x71396400), SCL_TAB(0x718C2D00), + SCL_TAB(0x71DF0580), SCL_TAB(0x7231ED00), SCL_TAB(0x7284E300), + SCL_TAB(0x72D7E880), SCL_TAB(0x732AFD00), SCL_TAB(0x737E2080), + SCL_TAB(0x73D15300), SCL_TAB(0x74249480), SCL_TAB(0x7477E480), + SCL_TAB(0x74CB4400), SCL_TAB(0x751EB200), SCL_TAB(0x75722F00), + SCL_TAB(0x75C5BB00), SCL_TAB(0x76195580), SCL_TAB(0x766CFF00), + SCL_TAB(0x76C0B700), SCL_TAB(0x77147E00), SCL_TAB(0x77685400), + SCL_TAB(0x77BC3880), SCL_TAB(0x78102B80), SCL_TAB(0x78642D80), + SCL_TAB(0x78B83E00), SCL_TAB(0x790C5D00), SCL_TAB(0x79608B00), + SCL_TAB(0x79B4C780), SCL_TAB(0x7A091280), SCL_TAB(0x7A5D6C00), + SCL_TAB(0x7AB1D400), SCL_TAB(0x7B064A80), SCL_TAB(0x7B5ACF80), + SCL_TAB(0x7BAF6380), SCL_TAB(0x7C040580), SCL_TAB(0x7C58B600), + SCL_TAB(0x7CAD7500), SCL_TAB(0x7D024200), SCL_TAB(0x7D571E00), + SCL_TAB(0x7DAC0800), SCL_TAB(0x7E010080), SCL_TAB(0x7E560780), + SCL_TAB(0x7EAB1C80), SCL_TAB(0x7F004000), SCL_TAB(0x7F557200), + SCL_TAB(0x7FAAB200), SCL_TAB(0x7FFFFFFF)}; + +/** + * \brief Table representing scale factor gains. Given a scale factor sf, and a + * value pSpec[i] the gain is given by: MantissaTable[sf % 4][msb] = 2^(sf % 4) + * / (1<> 2)) The corresponding + * exponents for the values in this tables are stored in ExponentTable[sf % + * 4][msb] below. + */ +const FIXP_DBL MantissaTable[4][14] = { + {0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, + 0x40000000, 0x50A28C00, 0x6597FA80, 0x40000000, 0x50A28C00, 0x6597FA80, + 0x40000000, 0x50A28C00}, + {0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, + 0x4C1BF800, 0x5FE44380, 0x78D0DF80, 0x4C1BF800, 0x5FE44380, 0x78D0DF80, + 0x4C1BF800, 0x5FE44380}, + {0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, + 0x5A827980, 0x7208F800, 0x47D66B00, 0x5A827980, 0x7208F800, 0x47D66B00, + 0x5A827980, 0x7208F800}, + {0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, + 0x6BA27E80, 0x43CE3E80, 0x556E0400, 0x6BA27E80, 0x43CE3E80, 0x556E0400, + 0x6BA27E80, 0x43CE3E80}}; + +const SCHAR ExponentTable[4][14] = { + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}}; + +/* 41 scfbands */ +static const SHORT sfb_96_1024[42] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, 188, 212, + 240, 276, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024}; +/* 12 scfbands */ +static const SHORT sfb_96_128[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128}; + +/* 47 scfbands*/ +static const SHORT sfb_64_1024[48] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, + 172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544, + 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 984, 1024}; + +/* 12 scfbands */ +static const SHORT sfb_64_128[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 128}; + +/* 49 scfbands */ +static const SHORT sfb_48_1024[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 1024}; +/* 14 scfbands */ +static const SHORT sfb_48_128[15] = {0, 4, 8, 12, 16, 20, 28, 36, + 44, 56, 68, 80, 96, 112, 128}; + +/* 51 scfbands */ +static const SHORT sfb_32_1024[52] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960, 992, 1024}; + +/* 47 scfbands */ +static const SHORT sfb_24_1024[48] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_24_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 108, 128}; + +/* 43 scfbands */ +static const SHORT sfb_16_1024[44] = { + 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 100, 112, 124, + 136, 148, 160, 172, 184, 196, 212, 228, 244, 260, 280, 300, 320, 344, 368, + 396, 424, 456, 492, 532, 572, 616, 664, 716, 772, 832, 896, 960, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_16_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 108, 128}; + +/* 40 scfbands */ +static const SHORT sfb_8_1024[41] = { + 0, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 156, + 172, 188, 204, 220, 236, 252, 268, 288, 308, 328, 348, 372, 396, 420, + 448, 476, 508, 544, 580, 620, 664, 712, 764, 820, 880, 944, 1024}; + +/* 15 scfbands */ +static const SHORT sfb_8_128[16] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 108, 128}; + +static const SHORT + sfb_96_960[42] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 48, 52, 56, 64, 72, 80, 88, 96, 108, 120, + 132, 144, 156, 172, 188, 212, 240, 276, 320, 384, 448, + 512, 576, 640, 704, 768, 832, 896, 960}; /* 40 scfbands */ + +static const SHORT sfb_96_120[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 120}; /* 12 scfbands */ + +static const SHORT sfb_64_960[47] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, 140, 156, + 172, 192, 216, 240, 268, 304, 344, 384, 424, 464, 504, 544, + 584, 624, 664, 704, 744, 784, 824, 864, 904, 944, 960}; /* 46 scfbands */ + +static const SHORT sfb_64_120[13] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 120}; /* 12 scfbands */ + +static const SHORT sfb_48_960[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960}; /* 49 scfbands */ +static const SHORT sfb_48_120[15] = { + 0, 4, 8, 12, 16, 20, 28, 36, + 44, 56, 68, 80, 96, 112, 120}; /* 14 scfbands */ + +static const SHORT sfb_32_960[50] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, 56, + 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, 196, 216, + 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, 544, 576, 608, + 640, 672, 704, 736, 768, 800, 832, 864, 896, 928, 960}; /* 49 scfbands */ + +static const SHORT sfb_24_960[47] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768, 832, 896, 960}; /* 46 scfbands */ + +static const SHORT sfb_24_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 108, 120}; /* 15 scfbands */ + +static const SHORT sfb_16_960[43] = {0, 8, 16, 24, 32, 40, 48, 56, + 64, 72, 80, 88, 100, 112, 124, 136, + 148, 160, 172, 184, 196, 212, 228, 244, + 260, 280, 300, 320, 344, 368, 396, 424, + 456, 492, 532, 572, 616, 664, 716, 772, + 832, 896, 960}; /* 42 scfbands */ + +static const SHORT sfb_16_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 108, 120}; /* 15 scfbands */ + +static const SHORT sfb_8_960[41] = {0, 12, 24, 36, 48, 60, 72, 84, 96, + 108, 120, 132, 144, 156, 172, 188, 204, 220, + 236, 252, 268, 288, 308, 328, 348, 372, 396, + 420, 448, 476, 508, 544, 580, 620, 664, 712, + 764, 820, 880, 944, 960}; /* 40 scfbands */ + +static const SHORT sfb_8_120[16] = { + 0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 108, 120}; /* 15 scfbands */ + +static const SHORT + sfb_96_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 156, 172, 188, 212, 240, 276, + 320, 384, 448, 512, 576, 640, 704, 768}; /* 37 scfbands */ +static const SHORT sfb_96_96[] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 96}; /* 12 scfbands */ + +static const SHORT sfb_64_768[] = + { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 48, 52, 56, 64, 72, 80, 88, 100, 112, 124, + 140, 156, 172, 192, 216, 240, 268, 304, 344, 384, 424, + 464, 504, 544, 584, 624, 664, 704, 744, 768}; /* 41 scfbands */ + +static const SHORT sfb_64_96[] = {0, 4, 8, 12, 16, 20, 24, + 32, 40, 48, 64, 92, 96}; /* 12 scfbands */ + +static const SHORT + sfb_48_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, + 544, 576, 608, 640, 672, 704, 736, 768}; /* 43 scfbands */ + +static const SHORT sfb_48_96[] = {0, 4, 8, 12, 16, 20, 28, + 36, 44, 56, 68, 80, 96}; /* 12 scfbands */ + +static const SHORT + sfb_32_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 48, + 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 160, 176, + 196, 216, 240, 264, 292, 320, 352, 384, 416, 448, 480, 512, + 544, 576, 608, 640, 672, 704, 736, 768}; /* 43 scfbands */ + +static const SHORT + sfb_24_768[] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, + 52, 60, 68, 76, 84, 92, 100, 108, 116, 124, 136, 148, + 160, 172, 188, 204, 220, 240, 260, 284, 308, 336, 364, 396, + 432, 468, 508, 552, 600, 652, 704, 768}; /* 43 scfbands */ + +static const SHORT sfb_24_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 64, 76, 92, 96}; /* 14 scfbands */ + +static const SHORT sfb_16_768[] = {0, 8, 16, 24, 32, 40, 48, 56, 64, + 72, 80, 88, 100, 112, 124, 136, 148, 160, + 172, 184, 196, 212, 228, 244, 260, 280, 300, + 320, 344, 368, 396, 424, 456, 492, 532, 572, + 616, 664, 716, 768}; /* 39 scfbands */ + +static const SHORT sfb_16_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 32, 40, 48, 60, 72, 88, 96}; /* 14 scfbands */ + +static const SHORT + sfb_8_768[] = {0, 12, 24, 36, 48, 60, 72, 84, 96, 108, + 120, 132, 144, 156, 172, 188, 204, 220, 236, 252, + 268, 288, 308, 328, 348, 372, 396, 420, 448, 476, + 508, 544, 580, 620, 664, 712, 764, 768}; /* 37 scfbands */ + +static const SHORT sfb_8_96[] = {0, 4, 8, 12, 16, 20, 24, 28, + 36, 44, 52, 60, 72, 88, 96}; /* 14 scfbands */ + +static const SHORT sfb_48_512[37] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, + 52, 56, 60, 68, 76, 84, 92, 100, 112, 124, 136, 148, 164, + 184, 208, 236, 268, 300, 332, 364, 396, 428, 460, 512}; /* 36 scfbands */ +static const SHORT + sfb_32_512[38] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, + 108, 120, 132, 144, 160, 176, 192, 212, 236, 260, + 288, 320, 352, 384, 416, 448, 480, 512}; /* 37 scfbands */ +static const SHORT sfb_24_512[32] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 52, 60, 68, 80, 92, 104, 120, 140, 164, 192, + 224, 256, 288, 320, 352, 384, 416, 448, 480, 512}; /* 31 scfbands */ + +static const SHORT sfb_48_480[36] = { + 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, + 52, 56, 64, 72, 80, 88, 96, 108, 120, 132, 144, 156, 172, + 188, 212, 240, 272, 304, 336, 368, 400, 432, 480}; /* 35 scfbands */ +static const SHORT + sfb_32_480[38] = {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, + 40, 44, 48, 52, 56, 60, 64, 72, 80, 88, + 96, 104, 112, 124, 136, 148, 164, 180, 200, 224, + 256, 288, 320, 352, 384, 416, 448, 480}; /* 37 scfbands */ +static const SHORT sfb_24_480[31] = + {0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, + 44, 52, 60, 68, 80, 92, 104, 120, 140, 164, 192, + 224, 256, 288, 320, 352, 384, 416, 448, 480}; /* 30 scfbands */ + +const SFB_INFO sfbOffsetTables[5][16] = {{ + {sfb_96_1024, sfb_96_128, 41, 12}, + {sfb_96_1024, sfb_96_128, 41, 12}, + {sfb_64_1024, sfb_64_128, 47, 12}, + {sfb_48_1024, sfb_48_128, 49, 14}, + {sfb_48_1024, sfb_48_128, 49, 14}, + {sfb_32_1024, sfb_48_128, 51, 14}, + {sfb_24_1024, sfb_24_128, 47, 15}, + {sfb_24_1024, sfb_24_128, 47, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_16_1024, sfb_16_128, 43, 15}, + {sfb_8_1024, sfb_8_128, 40, 15}, + {sfb_8_1024, sfb_8_128, 40, 15}, + }, + { + {sfb_96_960, sfb_96_120, 40, 12}, + {sfb_96_960, sfb_96_120, 40, 12}, + {sfb_64_960, sfb_64_120, 46, 12}, + {sfb_48_960, sfb_48_120, 49, 14}, + {sfb_48_960, sfb_48_120, 49, 14}, + {sfb_32_960, sfb_48_120, 49, 14}, + {sfb_24_960, sfb_24_120, 46, 15}, + {sfb_24_960, sfb_24_120, 46, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_16_960, sfb_16_120, 42, 15}, + {sfb_8_960, sfb_8_120, 40, 15}, + {sfb_8_960, sfb_8_120, 40, 15}, + }, + { + {sfb_96_768, sfb_96_96, 37, 12}, + {sfb_96_768, sfb_96_96, 37, 12}, + {sfb_64_768, sfb_64_96, 41, 12}, + {sfb_48_768, sfb_48_96, 43, 12}, + {sfb_48_768, sfb_48_96, 43, 12}, + {sfb_32_768, sfb_48_96, 43, 12}, + {sfb_24_768, sfb_24_96, 43, 14}, + {sfb_24_768, sfb_24_96, 43, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_16_768, sfb_16_96, 39, 14}, + {sfb_8_768, sfb_8_96, 37, 14}, + {sfb_8_768, sfb_8_96, 37, 14}, + }, + { + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_48_512, NULL, 36, 0}, + {sfb_32_512, NULL, 37, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + {sfb_24_512, NULL, 31, 0}, + }, + { + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_48_480, NULL, 35, 0}, + {sfb_32_480, NULL, 37, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + {sfb_24_480, NULL, 30, 0}, + }}; + +/*# don't use 1 bit hufman tables */ +/* + MPEG-2 AAC 2 BITS parallel Hufman Tables + + Bit 0: = 1=ENDNODE, 0=INDEX + Bit 1: = CODEWORD LEN MOD 2 + Bit 2..9: = VALUE/REF Tables 1..10,SCL + Bit 2..11: = VALUE/REF Table 11 +*/ +const USHORT HuffmanCodeBook_1[51][4] = { + {0x0157, 0x0157, 0x0004, 0x0018}, {0x0008, 0x000c, 0x0010, 0x0014}, + {0x015b, 0x015b, 0x0153, 0x0153}, {0x0057, 0x0057, 0x0167, 0x0167}, + {0x0257, 0x0257, 0x0117, 0x0117}, {0x0197, 0x0197, 0x0147, 0x0147}, + {0x001c, 0x0030, 0x0044, 0x0058}, {0x0020, 0x0024, 0x0028, 0x002c}, + {0x014b, 0x014b, 0x0163, 0x0163}, {0x0217, 0x0217, 0x0127, 0x0127}, + {0x0187, 0x0187, 0x0097, 0x0097}, {0x016b, 0x016b, 0x0017, 0x0017}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x0143, 0x0143, 0x0107, 0x0107}, + {0x011b, 0x011b, 0x0067, 0x0067}, {0x0193, 0x0193, 0x0297, 0x0297}, + {0x019b, 0x019b, 0x0247, 0x0247}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x01a7, 0x01a7, 0x0267, 0x0267}, {0x0113, 0x0113, 0x025b, 0x025b}, + {0x0053, 0x0053, 0x005b, 0x005b}, {0x0253, 0x0253, 0x0047, 0x0047}, + {0x005c, 0x0070, 0x0084, 0x0098}, {0x0060, 0x0064, 0x0068, 0x006c}, + {0x012b, 0x012b, 0x0123, 0x0123}, {0x018b, 0x018b, 0x00a7, 0x00a7}, + {0x0227, 0x0227, 0x0287, 0x0287}, {0x0087, 0x0087, 0x010b, 0x010b}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x021b, 0x021b, 0x0027, 0x0027}, + {0x01a3, 0x01a3, 0x0093, 0x0093}, {0x0183, 0x0183, 0x0207, 0x0207}, + {0x024b, 0x024b, 0x004b, 0x004b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0063, 0x0063, 0x0103, 0x0103}, {0x0007, 0x0007, 0x02a7, 0x02a7}, + {0x009b, 0x009b, 0x026b, 0x026b}, {0x0263, 0x0263, 0x01ab, 0x01ab}, + {0x009c, 0x00a0, 0x00a4, 0x00b8}, {0x0241, 0x0011, 0x0069, 0x0019}, + {0x0211, 0x0041, 0x0291, 0x0299}, {0x00a8, 0x00ac, 0x00b0, 0x00b4}, + {0x008b, 0x008b, 0x0223, 0x0223}, {0x00a3, 0x00a3, 0x020b, 0x020b}, + {0x02ab, 0x02ab, 0x0283, 0x0283}, {0x002b, 0x002b, 0x0083, 0x0083}, + {0x00bc, 0x00c0, 0x00c4, 0x00c8}, {0x0003, 0x0003, 0x022b, 0x022b}, + {0x028b, 0x028b, 0x02a3, 0x02a3}, {0x0023, 0x0023, 0x0203, 0x0203}, + {0x000b, 0x000b, 0x00ab, 0x00ab}}; + +const USHORT HuffmanCodeBook_2[39][4] = { + {0x0004, 0x000c, 0x0020, 0x0034}, {0x0157, 0x0157, 0x0159, 0x0008}, + {0x0153, 0x0153, 0x0257, 0x0257}, {0x0010, 0x0014, 0x0018, 0x001c}, + {0x0117, 0x0117, 0x0057, 0x0057}, {0x0147, 0x0147, 0x0197, 0x0197}, + {0x0167, 0x0167, 0x0185, 0x0161}, {0x0125, 0x0095, 0x0065, 0x0215}, + {0x0024, 0x0028, 0x002c, 0x0030}, {0x0051, 0x0149, 0x0119, 0x0141}, + {0x0015, 0x0199, 0x0259, 0x0245}, {0x0191, 0x0265, 0x0105, 0x0251}, + {0x0045, 0x0111, 0x0169, 0x01a5}, {0x0038, 0x0044, 0x0058, 0x006c}, + {0x0295, 0x0059, 0x003c, 0x0040}, {0x0227, 0x0227, 0x021b, 0x021b}, + {0x0123, 0x0123, 0x0087, 0x0087}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x018b, 0x018b, 0x006b, 0x006b}, {0x029b, 0x029b, 0x01a3, 0x01a3}, + {0x0207, 0x0207, 0x01ab, 0x01ab}, {0x0093, 0x0093, 0x0103, 0x0103}, + {0x005c, 0x0060, 0x0064, 0x0068}, {0x0213, 0x0213, 0x010b, 0x010b}, + {0x012b, 0x012b, 0x0249, 0x0061}, {0x0181, 0x0291, 0x0241, 0x0041}, + {0x0005, 0x0099, 0x0019, 0x0025}, {0x0070, 0x0074, 0x0078, 0x0088}, + {0x02a5, 0x0261, 0x0011, 0x00a5}, {0x0049, 0x0285, 0x0269, 0x0089}, + {0x0221, 0x007c, 0x0080, 0x0084}, {0x020b, 0x020b, 0x0003, 0x0003}, + {0x00a3, 0x00a3, 0x02a3, 0x02a3}, {0x02ab, 0x02ab, 0x0083, 0x0083}, + {0x008c, 0x0090, 0x0094, 0x0098}, {0x028b, 0x028b, 0x0023, 0x0023}, + {0x0283, 0x0283, 0x002b, 0x002b}, {0x000b, 0x000b, 0x0203, 0x0203}, + {0x022b, 0x022b, 0x00ab, 0x00ab}}; + +const USHORT HuffmanCodeBook_3[39][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0005, 0x0101, 0x0011, 0x0041}, + {0x000c, 0x0010, 0x0014, 0x0020}, {0x0017, 0x0017, 0x0143, 0x0143}, + {0x0051, 0x0111, 0x0045, 0x0151}, {0x0105, 0x0055, 0x0018, 0x001c}, + {0x0157, 0x0157, 0x0147, 0x0147}, {0x0117, 0x0117, 0x0009, 0x0201}, + {0x0024, 0x002c, 0x0040, 0x0054}, {0x0241, 0x0019, 0x0065, 0x0028}, + {0x0183, 0x0183, 0x0193, 0x0193}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0027, 0x0027, 0x0253, 0x0253}, {0x005b, 0x005b, 0x0083, 0x0083}, + {0x0063, 0x0063, 0x0093, 0x0093}, {0x0023, 0x0023, 0x0213, 0x0213}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x004b, 0x004b, 0x0167, 0x0167}, + {0x0163, 0x0163, 0x0097, 0x0097}, {0x0197, 0x0197, 0x0125, 0x0085}, + {0x0185, 0x0121, 0x0159, 0x0255}, {0x0058, 0x005c, 0x0060, 0x0070}, + {0x0119, 0x0245, 0x0281, 0x0291}, {0x0069, 0x00a5, 0x0205, 0x0109}, + {0x01a1, 0x0064, 0x0068, 0x006c}, {0x002b, 0x002b, 0x01a7, 0x01a7}, + {0x0217, 0x0217, 0x014b, 0x014b}, {0x0297, 0x0297, 0x016b, 0x016b}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x00a3, 0x00a3, 0x0263, 0x0263}, + {0x0285, 0x0129, 0x0099, 0x00a9}, {0x02a1, 0x01a9, 0x0199, 0x0265}, + {0x02a5, 0x0084, 0x0088, 0x008c}, {0x0223, 0x0223, 0x008b, 0x008b}, + {0x0227, 0x0227, 0x0189, 0x0259}, {0x0219, 0x0090, 0x0094, 0x0098}, + {0x02ab, 0x02ab, 0x026b, 0x026b}, {0x029b, 0x029b, 0x024b, 0x024b}, + {0x020b, 0x020b, 0x0229, 0x0289}}; + +const USHORT HuffmanCodeBook_4[38][4] = { + {0x0004, 0x0008, 0x000c, 0x0018}, {0x0155, 0x0151, 0x0115, 0x0055}, + {0x0145, 0x0005, 0x0015, 0x0001}, {0x0141, 0x0045, 0x0010, 0x0014}, + {0x0107, 0x0107, 0x0053, 0x0053}, {0x0103, 0x0103, 0x0113, 0x0113}, + {0x001c, 0x0020, 0x0034, 0x0048}, {0x0043, 0x0043, 0x0013, 0x0013}, + {0x0024, 0x0028, 0x002c, 0x0030}, {0x015b, 0x015b, 0x0197, 0x0197}, + {0x0167, 0x0167, 0x0257, 0x0257}, {0x005b, 0x005b, 0x011b, 0x011b}, + {0x0067, 0x0067, 0x014b, 0x014b}, {0x0038, 0x003c, 0x0040, 0x0044}, + {0x0193, 0x0193, 0x0251, 0x0095}, {0x0161, 0x0245, 0x0125, 0x0215}, + {0x0185, 0x0019, 0x0049, 0x0025}, {0x0109, 0x0211, 0x0061, 0x0241}, + {0x004c, 0x0050, 0x0058, 0x006c}, {0x0091, 0x0121, 0x0205, 0x0181}, + {0x0085, 0x0009, 0x0201, 0x0054}, {0x0023, 0x0023, 0x0083, 0x0083}, + {0x005c, 0x0060, 0x0064, 0x0068}, {0x01a7, 0x01a7, 0x016b, 0x016b}, + {0x019b, 0x019b, 0x0297, 0x0297}, {0x0267, 0x0267, 0x025b, 0x025b}, + {0x00a5, 0x0069, 0x0099, 0x01a1}, {0x0070, 0x0074, 0x0078, 0x0084}, + {0x0291, 0x0129, 0x0261, 0x0189}, {0x0285, 0x01a9, 0x0225, 0x0249}, + {0x0219, 0x02a5, 0x007c, 0x0080}, {0x029b, 0x029b, 0x026b, 0x026b}, + {0x00a3, 0x00a3, 0x002b, 0x002b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0283, 0x0283, 0x008b, 0x008b}, {0x0223, 0x0223, 0x020b, 0x020b}, + {0x02ab, 0x02ab, 0x02a3, 0x02a3}, {0x00ab, 0x00ab, 0x0229, 0x0289}}; + +const USHORT HuffmanCodeBook_5[41][4] = { + {0x0113, 0x0113, 0x0004, 0x0008}, {0x010d, 0x0115, 0x0151, 0x00d1}, + {0x000c, 0x0010, 0x0014, 0x0028}, {0x00d7, 0x00d7, 0x014f, 0x014f}, + {0x00cf, 0x00cf, 0x0157, 0x0157}, {0x0018, 0x001c, 0x0020, 0x0024}, + {0x010b, 0x010b, 0x0193, 0x0193}, {0x011b, 0x011b, 0x0093, 0x0093}, + {0x00c9, 0x0159, 0x008d, 0x0195}, {0x0149, 0x00d9, 0x018d, 0x0095}, + {0x002c, 0x0030, 0x0044, 0x0058}, {0x0105, 0x011d, 0x0051, 0x01d1}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x00c7, 0x00c7, 0x01d7, 0x01d7}, + {0x015f, 0x015f, 0x004f, 0x004f}, {0x0147, 0x0147, 0x00df, 0x00df}, + {0x0057, 0x0057, 0x01cf, 0x01cf}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x018b, 0x018b, 0x019b, 0x019b}, {0x008b, 0x008b, 0x009b, 0x009b}, + {0x0085, 0x009d, 0x01c9, 0x0059}, {0x019d, 0x01d9, 0x0185, 0x0049}, + {0x005c, 0x0060, 0x0074, 0x0088}, {0x0011, 0x0101, 0x0161, 0x0121}, + {0x0064, 0x0068, 0x006c, 0x0070}, {0x00c3, 0x00c3, 0x0213, 0x0213}, + {0x00e3, 0x00e3, 0x000f, 0x000f}, {0x0217, 0x0217, 0x020f, 0x020f}, + {0x0143, 0x0143, 0x0017, 0x0017}, {0x0078, 0x007c, 0x0080, 0x0084}, + {0x005f, 0x005f, 0x0047, 0x0047}, {0x01c7, 0x01c7, 0x020b, 0x020b}, + {0x0083, 0x0083, 0x01a3, 0x01a3}, {0x001b, 0x001b, 0x021b, 0x021b}, + {0x008c, 0x0090, 0x0094, 0x0098}, {0x01df, 0x01df, 0x0183, 0x0183}, + {0x0009, 0x00a1, 0x001d, 0x0041}, {0x01c1, 0x021d, 0x0205, 0x01e1}, + {0x0061, 0x0005, 0x009c, 0x00a0}, {0x0023, 0x0023, 0x0203, 0x0203}, + {0x0223, 0x0223, 0x0003, 0x0003}}; + +const USHORT HuffmanCodeBook_6[40][4] = { + {0x0004, 0x0008, 0x000c, 0x001c}, {0x0111, 0x0115, 0x00d1, 0x0151}, + {0x010d, 0x0155, 0x014d, 0x00d5}, {0x00cd, 0x0010, 0x0014, 0x0018}, + {0x00d9, 0x0159, 0x0149, 0x00c9}, {0x0109, 0x018d, 0x0119, 0x0095}, + {0x0195, 0x0091, 0x008d, 0x0191}, {0x0020, 0x0024, 0x0038, 0x004c}, + {0x0099, 0x0189, 0x0089, 0x0199}, {0x0028, 0x002c, 0x0030, 0x0034}, + {0x0147, 0x0147, 0x015f, 0x015f}, {0x00df, 0x00df, 0x01cf, 0x01cf}, + {0x00c7, 0x00c7, 0x01d7, 0x01d7}, {0x0057, 0x0057, 0x004f, 0x004f}, + {0x003c, 0x0040, 0x0044, 0x0048}, {0x011f, 0x011f, 0x0107, 0x0107}, + {0x0053, 0x0053, 0x01d3, 0x01d3}, {0x019f, 0x019f, 0x0085, 0x01c9}, + {0x01d9, 0x009d, 0x0059, 0x0049}, {0x0050, 0x005c, 0x0070, 0x0084}, + {0x0185, 0x01dd, 0x0054, 0x0058}, {0x005f, 0x005f, 0x0047, 0x0047}, + {0x01c7, 0x01c7, 0x0017, 0x0017}, {0x0060, 0x0064, 0x0068, 0x006c}, + {0x000f, 0x000f, 0x0163, 0x0163}, {0x0143, 0x0143, 0x00c3, 0x00c3}, + {0x0217, 0x0217, 0x00e3, 0x00e3}, {0x020f, 0x020f, 0x0013, 0x0013}, + {0x0074, 0x0078, 0x007c, 0x0080}, {0x0183, 0x0183, 0x0083, 0x0083}, + {0x021b, 0x021b, 0x000b, 0x000b}, {0x0103, 0x0103, 0x01a3, 0x01a3}, + {0x00a3, 0x00a3, 0x020b, 0x020b}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x0123, 0x0123, 0x001b, 0x001b}, {0x0213, 0x0213, 0x0005, 0x0205}, + {0x001d, 0x0061, 0x021d, 0x01e1}, {0x01c1, 0x0041, 0x0098, 0x009c}, + {0x0223, 0x0223, 0x0203, 0x0203}, {0x0003, 0x0003, 0x0023, 0x0023}}; + +const USHORT HuffmanCodeBook_7[31][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0007, 0x0007, 0x0043, 0x0043}, + {0x0045, 0x000c, 0x0010, 0x0024}, {0x0049, 0x0085, 0x0009, 0x0081}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x004f, 0x004f, 0x00c7, 0x00c7}, + {0x008b, 0x008b, 0x000f, 0x000f}, {0x00c3, 0x00c3, 0x00c9, 0x008d}, + {0x0105, 0x0051, 0x0145, 0x0055}, {0x0028, 0x002c, 0x0040, 0x0054}, + {0x00cd, 0x0109, 0x0101, 0x0011}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0093, 0x0093, 0x014b, 0x014b}, {0x0097, 0x0097, 0x0143, 0x0143}, + {0x005b, 0x005b, 0x0017, 0x0017}, {0x0187, 0x0187, 0x00d3, 0x00d3}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x014f, 0x014f, 0x010f, 0x010f}, + {0x00d7, 0x00d7, 0x018b, 0x018b}, {0x009b, 0x009b, 0x01c7, 0x01c7}, + {0x018d, 0x0181, 0x0019, 0x0111}, {0x0058, 0x005c, 0x0060, 0x0068}, + {0x005d, 0x0151, 0x009d, 0x0115}, {0x00d9, 0x01c9, 0x00dd, 0x0119}, + {0x0155, 0x0191, 0x01cd, 0x0064}, {0x001f, 0x001f, 0x01c3, 0x01c3}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x015b, 0x015b, 0x0197, 0x0197}, + {0x011f, 0x011f, 0x01d3, 0x01d3}, {0x01d7, 0x01d7, 0x015f, 0x015f}, + {0x019d, 0x0199, 0x01d9, 0x01dd}}; + +const USHORT HuffmanCodeBook_8[31][4] = { + {0x0004, 0x0008, 0x0010, 0x0024}, {0x0047, 0x0047, 0x0049, 0x0005}, + {0x0085, 0x0041, 0x0089, 0x000c}, {0x0003, 0x0003, 0x000b, 0x000b}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x0083, 0x0083, 0x004f, 0x004f}, + {0x00c7, 0x00c7, 0x008f, 0x008f}, {0x00cb, 0x00cb, 0x00cd, 0x0051}, + {0x0105, 0x0091, 0x0109, 0x000d}, {0x0028, 0x002c, 0x0040, 0x0054}, + {0x00c1, 0x00d1, 0x010d, 0x0095}, {0x0030, 0x0034, 0x0038, 0x003c}, + {0x0057, 0x0057, 0x014b, 0x014b}, {0x0147, 0x0147, 0x00d7, 0x00d7}, + {0x014f, 0x014f, 0x0113, 0x0113}, {0x0117, 0x0117, 0x0103, 0x0103}, + {0x0044, 0x0048, 0x004c, 0x0050}, {0x0153, 0x0153, 0x0013, 0x0013}, + {0x018b, 0x018b, 0x009b, 0x009b}, {0x005b, 0x005b, 0x0187, 0x0187}, + {0x018d, 0x00d9, 0x0155, 0x0015}, {0x0058, 0x005c, 0x0060, 0x0068}, + {0x0119, 0x0141, 0x0191, 0x005d}, {0x009d, 0x01c9, 0x0159, 0x00dd}, + {0x01c5, 0x0195, 0x01cd, 0x0064}, {0x019b, 0x019b, 0x011f, 0x011f}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x001b, 0x001b, 0x01d3, 0x01d3}, + {0x0183, 0x0183, 0x015f, 0x015f}, {0x019f, 0x019f, 0x01db, 0x01db}, + {0x01d5, 0x001d, 0x01c1, 0x01dd}}; + +const USHORT HuffmanCodeBook_9[84][4] = { + {0x0003, 0x0003, 0x0004, 0x0008}, {0x0007, 0x0007, 0x0043, 0x0043}, + {0x0045, 0x000c, 0x0010, 0x002c}, {0x0049, 0x0085, 0x0009, 0x0081}, + {0x0014, 0x0018, 0x001c, 0x0020}, {0x004f, 0x004f, 0x008b, 0x008b}, + {0x00c7, 0x00c7, 0x000d, 0x00c1}, {0x00c9, 0x008d, 0x0105, 0x0051}, + {0x0109, 0x0145, 0x0024, 0x0028}, {0x0093, 0x0093, 0x00cf, 0x00cf}, + {0x0103, 0x0103, 0x0013, 0x0013}, {0x0030, 0x0044, 0x0058, 0x00a4}, + {0x0034, 0x0038, 0x003c, 0x0040}, {0x0057, 0x0057, 0x014b, 0x014b}, + {0x0187, 0x0187, 0x010f, 0x010f}, {0x0097, 0x0097, 0x005b, 0x005b}, + {0x00d3, 0x00d3, 0x0141, 0x0189}, {0x0048, 0x004c, 0x0050, 0x0054}, + {0x0015, 0x01c5, 0x014d, 0x0205}, {0x0061, 0x0111, 0x00d5, 0x0099}, + {0x005d, 0x0181, 0x00a1, 0x0209}, {0x018d, 0x01c9, 0x0151, 0x0065}, + {0x005c, 0x0068, 0x007c, 0x0090}, {0x0245, 0x009d, 0x0060, 0x0064}, + {0x001b, 0x001b, 0x0117, 0x0117}, {0x00db, 0x00db, 0x00e3, 0x00e3}, + {0x006c, 0x0070, 0x0074, 0x0078}, {0x01c3, 0x01c3, 0x00a7, 0x00a7}, + {0x020f, 0x020f, 0x0193, 0x0193}, {0x01cf, 0x01cf, 0x0203, 0x0203}, + {0x006b, 0x006b, 0x011b, 0x011b}, {0x0080, 0x0084, 0x0088, 0x008c}, + {0x024b, 0x024b, 0x0157, 0x0157}, {0x0023, 0x0023, 0x001f, 0x001f}, + {0x00df, 0x00df, 0x00ab, 0x00ab}, {0x00e7, 0x00e7, 0x0123, 0x0123}, + {0x0094, 0x0098, 0x009c, 0x00a0}, {0x0287, 0x0287, 0x011f, 0x011f}, + {0x015b, 0x015b, 0x0197, 0x0197}, {0x0213, 0x0213, 0x01d3, 0x01d3}, + {0x024f, 0x024f, 0x006f, 0x006f}, {0x00a8, 0x00bc, 0x00d0, 0x00f4}, + {0x00ac, 0x00b0, 0x00b4, 0x00b8}, {0x0217, 0x0217, 0x0027, 0x0027}, + {0x0163, 0x0163, 0x00e9, 0x0289}, {0x0241, 0x00ad, 0x0125, 0x0199}, + {0x0071, 0x0251, 0x01a1, 0x02c5}, {0x00c0, 0x00c4, 0x00c8, 0x00cc}, + {0x0165, 0x0129, 0x01d5, 0x015d}, {0x02c9, 0x0305, 0x00b1, 0x00ed}, + {0x028d, 0x0255, 0x01d9, 0x01e1}, {0x012d, 0x0281, 0x019d, 0x00f1}, + {0x00d4, 0x00d8, 0x00dc, 0x00e0}, {0x0029, 0x0169, 0x0291, 0x0219}, + {0x0309, 0x01a5, 0x01e5, 0x02d1}, {0x002d, 0x0259, 0x02cd, 0x0295}, + {0x00e4, 0x00e8, 0x00ec, 0x00f0}, {0x0223, 0x0223, 0x021f, 0x021f}, + {0x0173, 0x0173, 0x030f, 0x030f}, {0x016f, 0x016f, 0x01df, 0x01df}, + {0x0133, 0x0133, 0x01af, 0x01af}, {0x00f8, 0x010c, 0x0120, 0x0134}, + {0x00fc, 0x0100, 0x0104, 0x0108}, {0x01ab, 0x01ab, 0x0313, 0x0313}, + {0x025f, 0x025f, 0x02d7, 0x02d7}, {0x02c3, 0x02c3, 0x01b3, 0x01b3}, + {0x029b, 0x029b, 0x0033, 0x0033}, {0x0110, 0x0114, 0x0118, 0x011c}, + {0x01eb, 0x01eb, 0x0317, 0x0317}, {0x029f, 0x029f, 0x0227, 0x0227}, + {0x0303, 0x0303, 0x01ef, 0x01ef}, {0x0263, 0x0263, 0x0267, 0x0267}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x022b, 0x022b, 0x02df, 0x02df}, + {0x01f3, 0x01f3, 0x02db, 0x02db}, {0x02e3, 0x02e3, 0x022f, 0x022f}, + {0x031f, 0x031f, 0x031b, 0x031b}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x02a1, 0x0269, 0x0321, 0x02a5}, {0x02e5, 0x0325, 0x02e9, 0x0271}, + {0x02a9, 0x026d, 0x0231, 0x02ad}, {0x02b1, 0x02f1, 0x0148, 0x014c}, + {0x032b, 0x032b, 0x02ef, 0x02ef}, {0x032f, 0x032f, 0x0333, 0x0333}}; + +const USHORT HuffmanCodeBook_10[82][4] = { + {0x0004, 0x000c, 0x0020, 0x004c}, {0x0045, 0x0085, 0x0049, 0x0008}, + {0x008b, 0x008b, 0x0007, 0x0007}, {0x0010, 0x0014, 0x0018, 0x001c}, + {0x0043, 0x0043, 0x00c7, 0x00c7}, {0x008f, 0x008f, 0x004f, 0x004f}, + {0x00cb, 0x00cb, 0x00cf, 0x00cf}, {0x0009, 0x0081, 0x0109, 0x0091}, + {0x0024, 0x0028, 0x002c, 0x0038}, {0x0105, 0x0051, 0x0001, 0x00d1}, + {0x010d, 0x000d, 0x00c1, 0x0111}, {0x0149, 0x0095, 0x0030, 0x0034}, + {0x0147, 0x0147, 0x0057, 0x0057}, {0x00d7, 0x00d7, 0x014f, 0x014f}, + {0x003c, 0x0040, 0x0044, 0x0048}, {0x0117, 0x0117, 0x0153, 0x0153}, + {0x009b, 0x009b, 0x018b, 0x018b}, {0x00db, 0x00db, 0x0013, 0x0013}, + {0x005b, 0x005b, 0x0103, 0x0103}, {0x0050, 0x0064, 0x0078, 0x00c0}, + {0x0054, 0x0058, 0x005c, 0x0060}, {0x0187, 0x0187, 0x018f, 0x018f}, + {0x0157, 0x0157, 0x011b, 0x011b}, {0x0193, 0x0193, 0x0159, 0x009d}, + {0x01cd, 0x01c9, 0x0195, 0x00a1}, {0x0068, 0x006c, 0x0070, 0x0074}, + {0x00dd, 0x0015, 0x005d, 0x0141}, {0x0061, 0x01c5, 0x00e1, 0x011d}, + {0x01d1, 0x0209, 0x0199, 0x015d}, {0x0205, 0x020d, 0x0121, 0x0211}, + {0x007c, 0x0084, 0x0098, 0x00ac}, {0x01d5, 0x0161, 0x0215, 0x0080}, + {0x019f, 0x019f, 0x01db, 0x01db}, {0x0088, 0x008c, 0x0090, 0x0094}, + {0x00a7, 0x00a7, 0x001b, 0x001b}, {0x021b, 0x021b, 0x00e7, 0x00e7}, + {0x024f, 0x024f, 0x0067, 0x0067}, {0x024b, 0x024b, 0x0183, 0x0183}, + {0x009c, 0x00a0, 0x00a4, 0x00a8}, {0x01a3, 0x01a3, 0x0127, 0x0127}, + {0x0253, 0x0253, 0x00ab, 0x00ab}, {0x0247, 0x0247, 0x01df, 0x01df}, + {0x01e3, 0x01e3, 0x0167, 0x0167}, {0x00b0, 0x00b4, 0x00b8, 0x00bc}, + {0x021f, 0x021f, 0x00eb, 0x00eb}, {0x0257, 0x0257, 0x012b, 0x012b}, + {0x028b, 0x028b, 0x006b, 0x006b}, {0x028f, 0x028f, 0x01a7, 0x01a7}, + {0x00c4, 0x00d8, 0x00ec, 0x0100}, {0x00c8, 0x00cc, 0x00d0, 0x00d4}, + {0x025b, 0x025b, 0x0023, 0x0023}, {0x0293, 0x0293, 0x001f, 0x001f}, + {0x00af, 0x00af, 0x025d, 0x00ed}, {0x01a9, 0x0285, 0x006d, 0x01e5}, + {0x00dc, 0x00e0, 0x00e4, 0x00e8}, {0x01c1, 0x0221, 0x0169, 0x02cd}, + {0x0295, 0x0261, 0x016d, 0x0201}, {0x012d, 0x02c9, 0x029d, 0x0299}, + {0x01e9, 0x02d1, 0x02c5, 0x00b1}, {0x00f0, 0x00f4, 0x00f8, 0x00fc}, + {0x0225, 0x00f1, 0x01ad, 0x02d5}, {0x0131, 0x01ed, 0x0171, 0x030d}, + {0x02d9, 0x0025, 0x0229, 0x0029}, {0x0071, 0x0241, 0x0311, 0x0265}, + {0x0104, 0x010c, 0x0120, 0x0134}, {0x01b1, 0x0309, 0x02a1, 0x0108}, + {0x02a7, 0x02a7, 0x0307, 0x0307}, {0x0110, 0x0114, 0x0118, 0x011c}, + {0x022f, 0x022f, 0x01f3, 0x01f3}, {0x02df, 0x02df, 0x0317, 0x0317}, + {0x031b, 0x031b, 0x026b, 0x026b}, {0x02e3, 0x02e3, 0x0233, 0x0233}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x0283, 0x0283, 0x031f, 0x031f}, + {0x002f, 0x002f, 0x02ab, 0x02ab}, {0x026f, 0x026f, 0x02af, 0x02af}, + {0x02c3, 0x02c3, 0x02ef, 0x02ef}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x02e7, 0x02e7, 0x02eb, 0x02eb}, {0x0033, 0x0033, 0x0323, 0x0323}, + {0x0271, 0x0329, 0x0325, 0x032d}, {0x02f1, 0x0301, 0x02b1, 0x0331}}; + +const USHORT HuffmanCodeBook_11[152][4] = { + {0x0004, 0x0010, 0x0038, 0x008c}, {0x0001, 0x0085, 0x0008, 0x000c}, + {0x0843, 0x0843, 0x0007, 0x0007}, {0x0083, 0x0083, 0x008b, 0x008b}, + {0x0014, 0x0018, 0x001c, 0x0024}, {0x0107, 0x0107, 0x010b, 0x010b}, + {0x0185, 0x008d, 0x010d, 0x0009}, {0x0189, 0x0101, 0x018d, 0x0020}, + {0x0093, 0x0093, 0x0207, 0x0207}, {0x0028, 0x002c, 0x0030, 0x0034}, + {0x0113, 0x0113, 0x020b, 0x020b}, {0x0193, 0x0193, 0x020f, 0x020f}, + {0x000f, 0x000f, 0x0183, 0x0183}, {0x0097, 0x0097, 0x0117, 0x0117}, + {0x003c, 0x0050, 0x0064, 0x0078}, {0x0040, 0x0044, 0x0048, 0x004c}, + {0x028b, 0x028b, 0x0213, 0x0213}, {0x0287, 0x0287, 0x0197, 0x0197}, + {0x028f, 0x028f, 0x0217, 0x0217}, {0x0291, 0x0119, 0x0309, 0x0099}, + {0x0054, 0x0058, 0x005c, 0x0060}, {0x0199, 0x030d, 0x0305, 0x0811}, + {0x080d, 0x02c1, 0x01c1, 0x0241}, {0x0219, 0x0341, 0x0011, 0x0311}, + {0x0201, 0x0809, 0x0295, 0x0815}, {0x0068, 0x006c, 0x0070, 0x0074}, + {0x03c1, 0x0141, 0x0441, 0x0389}, {0x011d, 0x038d, 0x0299, 0x0315}, + {0x0819, 0x0541, 0x019d, 0x009d}, {0x04c1, 0x081d, 0x0805, 0x0385}, + {0x007c, 0x0080, 0x0084, 0x0088}, {0x0391, 0x05c1, 0x021d, 0x0641}, + {0x0821, 0x00c1, 0x0319, 0x0825}, {0x0409, 0x0395, 0x0829, 0x06c1}, + {0x01a1, 0x0121, 0x040d, 0x0015}, {0x0090, 0x00c8, 0x011c, 0x0170}, + {0x0094, 0x0098, 0x00a0, 0x00b4}, {0x0741, 0x082d, 0x029d, 0x0411}, + {0x0399, 0x031d, 0x0281, 0x009c}, {0x0223, 0x0223, 0x07c3, 0x07c3}, + {0x00a4, 0x00a8, 0x00ac, 0x00b0}, {0x0833, 0x0833, 0x0407, 0x0407}, + {0x00a3, 0x00a3, 0x083b, 0x083b}, {0x0417, 0x0417, 0x0837, 0x0837}, + {0x048f, 0x048f, 0x02a3, 0x02a3}, {0x00b8, 0x00bc, 0x00c0, 0x00c4}, + {0x039f, 0x039f, 0x048b, 0x048b}, {0x0323, 0x0323, 0x0127, 0x0127}, + {0x01a7, 0x01a7, 0x083f, 0x083f}, {0x0493, 0x0493, 0x041b, 0x041b}, + {0x00cc, 0x00e0, 0x00f4, 0x0108}, {0x00d0, 0x00d4, 0x00d8, 0x00dc}, + {0x001b, 0x001b, 0x0227, 0x0227}, {0x0497, 0x0497, 0x03a3, 0x03a3}, + {0x041f, 0x041f, 0x0487, 0x0487}, {0x01ab, 0x01ab, 0x0303, 0x0303}, + {0x00e4, 0x00e8, 0x00ec, 0x00f0}, {0x012b, 0x012b, 0x00a7, 0x00a7}, + {0x02a7, 0x02a7, 0x0513, 0x0513}, {0x050b, 0x050b, 0x0327, 0x0327}, + {0x050f, 0x050f, 0x049b, 0x049b}, {0x00f8, 0x00fc, 0x0100, 0x0104}, + {0x022b, 0x022b, 0x0423, 0x0423}, {0x02ab, 0x02ab, 0x03a7, 0x03a7}, + {0x01af, 0x01af, 0x0507, 0x0507}, {0x001f, 0x001f, 0x032b, 0x032b}, + {0x010c, 0x0110, 0x0114, 0x0118}, {0x049f, 0x049f, 0x058f, 0x058f}, + {0x0517, 0x0517, 0x00ab, 0x00ab}, {0x0593, 0x0593, 0x012f, 0x012f}, + {0x0137, 0x0137, 0x051b, 0x051b}, {0x0120, 0x0134, 0x0148, 0x015c}, + {0x0124, 0x0128, 0x012c, 0x0130}, {0x01b7, 0x01b7, 0x058b, 0x058b}, + {0x0043, 0x0043, 0x0597, 0x0597}, {0x02af, 0x02af, 0x022d, 0x0425}, + {0x051d, 0x04a1, 0x0801, 0x0691}, {0x0138, 0x013c, 0x0140, 0x0144}, + {0x0381, 0x068d, 0x032d, 0x00b5}, {0x0235, 0x01b1, 0x0689, 0x02b5}, + {0x0521, 0x0599, 0x0429, 0x03a9}, {0x0139, 0x0231, 0x0585, 0x0611}, + {0x014c, 0x0150, 0x0154, 0x0158}, {0x00ad, 0x060d, 0x0685, 0x0131}, + {0x059d, 0x070d, 0x0615, 0x0695}, {0x0239, 0x0711, 0x03ad, 0x01b9}, + {0x02b1, 0x0335, 0x0331, 0x0021}, {0x0160, 0x0164, 0x0168, 0x016c}, + {0x042d, 0x0609, 0x04a5, 0x02b9}, {0x0699, 0x0529, 0x013d, 0x05a1}, + {0x0525, 0x0339, 0x04a9, 0x0715}, {0x04ad, 0x00b9, 0x0709, 0x0619}, + {0x0174, 0x0188, 0x019c, 0x01cc}, {0x0178, 0x017c, 0x0180, 0x0184}, + {0x0605, 0x0435, 0x0401, 0x03b5}, {0x061d, 0x03b1, 0x069d, 0x01bd}, + {0x00b1, 0x0719, 0x0789, 0x02bd}, {0x023d, 0x0705, 0x05a5, 0x0791}, + {0x018c, 0x0190, 0x0194, 0x0198}, {0x03b9, 0x06a1, 0x04b5, 0x0621}, + {0x0795, 0x078d, 0x05a9, 0x052d}, {0x0431, 0x033d, 0x03bd, 0x0721}, + {0x00bd, 0x071d, 0x0025, 0x0481}, {0x01a0, 0x01a4, 0x01a8, 0x01b8}, + {0x06a5, 0x0625, 0x04b1, 0x0439}, {0x06a9, 0x04b9, 0x0531, 0x0799}, + {0x079d, 0x01ac, 0x01b0, 0x01b4}, {0x0727, 0x0727, 0x043f, 0x043f}, + {0x05af, 0x05af, 0x072f, 0x072f}, {0x0787, 0x0787, 0x062b, 0x062b}, + {0x01bc, 0x01c0, 0x01c4, 0x01c8}, {0x072b, 0x072b, 0x05b7, 0x05b7}, + {0x0537, 0x0537, 0x06af, 0x06af}, {0x062f, 0x062f, 0x07a3, 0x07a3}, + {0x05bb, 0x05bb, 0x0637, 0x0637}, {0x01d0, 0x01e4, 0x01f8, 0x020c}, + {0x01d4, 0x01d8, 0x01dc, 0x01e0}, {0x06b3, 0x06b3, 0x04bf, 0x04bf}, + {0x053b, 0x053b, 0x002b, 0x002b}, {0x05b3, 0x05b3, 0x07a7, 0x07a7}, + {0x0503, 0x0503, 0x0633, 0x0633}, {0x01e8, 0x01ec, 0x01f0, 0x01f4}, + {0x002f, 0x002f, 0x0733, 0x0733}, {0x07ab, 0x07ab, 0x06b7, 0x06b7}, + {0x0683, 0x0683, 0x063b, 0x063b}, {0x053f, 0x053f, 0x05bf, 0x05bf}, + {0x01fc, 0x0200, 0x0204, 0x0208}, {0x07af, 0x07af, 0x06bb, 0x06bb}, + {0x0037, 0x0037, 0x0583, 0x0583}, {0x0737, 0x0737, 0x063f, 0x063f}, + {0x06bf, 0x06bf, 0x07b3, 0x07b3}, {0x0210, 0x0214, 0x0218, 0x021c}, + {0x003b, 0x003b, 0x073b, 0x073b}, {0x07b7, 0x07b7, 0x0033, 0x0033}, + {0x07bb, 0x07bb, 0x0701, 0x0601}, {0x073d, 0x003d, 0x0781, 0x07bd}, + {0x0118, 0x0117, 0x0100, 0x0109}, {0x05a5, 0x05a1, 0x05b7, 0x0513}, + {0x08f9, 0x08ff, 0x0821, 0x08ff}, {0x084f, 0x08ff, 0x08bc, 0x08ff}, + {0x0815, 0x08ff, 0x0837, 0x08ff}, {0x080d, 0x08ff, 0x085f, 0x08ff}, + {0x084a, 0x08ff, 0x087d, 0x08ff}, {0x08ff, 0x08ff, 0x08a8, 0x08ff}, + {0x0815, 0x08ff, 0x083f, 0x08ff}, {0x0830, 0x08ff, 0x0894, 0x08ff}, + {0x08d4, 0x08ff, 0x0825, 0x08ff}, {0x08ef, 0x08ff, 0x083f, 0x08ff}, + {0x0809, 0x08ff, 0x08fc, 0x08ff}, {0x0842, 0x08ff, 0x08b3, 0x08ff}, + {0x070d, 0x07a9, 0x060e, 0x06e2}, {0x06c7, 0x06d0, 0x04b2, 0x0407}}; + +const USHORT HuffmanCodeBook_SCL[65][4] = { + {0x00f3, 0x00f3, 0x0004, 0x0008}, {0x00ef, 0x00ef, 0x00f5, 0x00e9}, + {0x00f9, 0x000c, 0x0010, 0x0014}, {0x00e7, 0x00e7, 0x00ff, 0x00ff}, + {0x00e1, 0x0101, 0x00dd, 0x0105}, {0x0018, 0x001c, 0x0020, 0x0028}, + {0x010b, 0x010b, 0x00db, 0x00db}, {0x010f, 0x010f, 0x00d5, 0x0111}, + {0x00d1, 0x0115, 0x00cd, 0x0024}, {0x011b, 0x011b, 0x00cb, 0x00cb}, + {0x002c, 0x0030, 0x0034, 0x0040}, {0x00c7, 0x00c7, 0x011f, 0x011f}, + {0x0121, 0x00c1, 0x0125, 0x00bd}, {0x0129, 0x00b9, 0x0038, 0x003c}, + {0x0133, 0x0133, 0x012f, 0x012f}, {0x0137, 0x0137, 0x013b, 0x013b}, + {0x0044, 0x0048, 0x004c, 0x0058}, {0x00b7, 0x00b7, 0x00af, 0x00af}, + {0x00b1, 0x013d, 0x00a9, 0x00a5}, {0x0141, 0x00a1, 0x0050, 0x0054}, + {0x0147, 0x0147, 0x009f, 0x009f}, {0x014b, 0x014b, 0x009b, 0x009b}, + {0x005c, 0x0060, 0x0064, 0x0070}, {0x014f, 0x014f, 0x0095, 0x008d}, + {0x0155, 0x0085, 0x0091, 0x0089}, {0x0151, 0x0081, 0x0068, 0x006c}, + {0x015f, 0x015f, 0x0167, 0x0167}, {0x007b, 0x007b, 0x007f, 0x007f}, + {0x0074, 0x0078, 0x0080, 0x00b0}, {0x0159, 0x0075, 0x0069, 0x006d}, + {0x0071, 0x0061, 0x0161, 0x007c}, {0x0067, 0x0067, 0x005b, 0x005b}, + {0x0084, 0x0088, 0x008c, 0x009c}, {0x005f, 0x005f, 0x0169, 0x0055}, + {0x004d, 0x000d, 0x0005, 0x0009}, {0x0001, 0x0090, 0x0094, 0x0098}, + {0x018b, 0x018b, 0x018f, 0x018f}, {0x0193, 0x0193, 0x0197, 0x0197}, + {0x019b, 0x019b, 0x01d7, 0x01d7}, {0x00a0, 0x00a4, 0x00a8, 0x00ac}, + {0x0187, 0x0187, 0x016f, 0x016f}, {0x0173, 0x0173, 0x0177, 0x0177}, + {0x017b, 0x017b, 0x017f, 0x017f}, {0x0183, 0x0183, 0x01a3, 0x01a3}, + {0x00b4, 0x00c8, 0x00dc, 0x00f0}, {0x00b8, 0x00bc, 0x00c0, 0x00c4}, + {0x01bf, 0x01bf, 0x01c3, 0x01c3}, {0x01c7, 0x01c7, 0x01cb, 0x01cb}, + {0x01cf, 0x01cf, 0x01d3, 0x01d3}, {0x01bb, 0x01bb, 0x01a7, 0x01a7}, + {0x00cc, 0x00d0, 0x00d4, 0x00d8}, {0x01ab, 0x01ab, 0x01af, 0x01af}, + {0x01b3, 0x01b3, 0x01b7, 0x01b7}, {0x01db, 0x01db, 0x001b, 0x001b}, + {0x0023, 0x0023, 0x0027, 0x0027}, {0x00e0, 0x00e4, 0x00e8, 0x00ec}, + {0x002b, 0x002b, 0x0017, 0x0017}, {0x019f, 0x019f, 0x01e3, 0x01e3}, + {0x01df, 0x01df, 0x0013, 0x0013}, {0x001f, 0x001f, 0x003f, 0x003f}, + {0x00f4, 0x00f8, 0x00fc, 0x0100}, {0x0043, 0x0043, 0x004b, 0x004b}, + {0x0053, 0x0053, 0x0047, 0x0047}, {0x002f, 0x002f, 0x0033, 0x0033}, + {0x003b, 0x003b, 0x0037, 0x0037}}; + +/* .CodeBook = HuffmanCodeBook_x, .Dimension = 4, .numBits = 2, .Offset = 0 */ +const CodeBookDescription AACcodeBookDescriptionTable[13] = { + {NULL, 0, 0, 0}, + {HuffmanCodeBook_1, 4, 2, 1}, + {HuffmanCodeBook_2, 4, 2, 1}, + {HuffmanCodeBook_3, 4, 2, 0}, + {HuffmanCodeBook_4, 4, 2, 0}, + {HuffmanCodeBook_5, 2, 4, 4}, + {HuffmanCodeBook_6, 2, 4, 4}, + {HuffmanCodeBook_7, 2, 4, 0}, + {HuffmanCodeBook_8, 2, 4, 0}, + {HuffmanCodeBook_9, 2, 4, 0}, + {HuffmanCodeBook_10, 2, 4, 0}, + {HuffmanCodeBook_11, 2, 5, 0}, + {HuffmanCodeBook_SCL, 1, 8, 60}}; + +const CodeBookDescription AACcodeBookDescriptionSCL = {HuffmanCodeBook_SCL, 1, + 8, 60}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree41 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 1). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +/* HuffTree */ +const UINT aHuffTree41[80] = { + 0x4a0001, 0x026002, 0x013003, 0x021004, 0x01c005, 0x00b006, 0x010007, + 0x019008, 0x00900e, 0x00a03a, 0x400528, 0x00c037, 0x00d03b, 0x454404, + 0x00f04c, 0x448408, 0x017011, 0x01202e, 0x42c40c, 0x034014, 0x01502c, + 0x016049, 0x410470, 0x01804e, 0x414424, 0x03201a, 0x02001b, 0x520418, + 0x02f01d, 0x02a01e, 0x01f04d, 0x41c474, 0x540420, 0x022024, 0x04a023, + 0x428510, 0x025029, 0x430508, 0x02703c, 0x028047, 0x50c434, 0x438478, + 0x04802b, 0x46443c, 0x02d03e, 0x4404b0, 0x44451c, 0x03003f, 0x03104b, + 0x52444c, 0x033039, 0x4f0450, 0x035041, 0x036046, 0x4e8458, 0x04f038, + 0x45c53c, 0x4604e0, 0x4f8468, 0x46c4d4, 0x04503d, 0x4ac47c, 0x518480, + 0x043040, 0x4844dc, 0x042044, 0x4884a8, 0x4bc48c, 0x530490, 0x4a4494, + 0x4984b8, 0x49c4c4, 0x5044b4, 0x5004c0, 0x4d04c8, 0x4f44cc, 0x4d8538, + 0x4ec4e4, 0x52c4fc, 0x514534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree42 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 2). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree42[80] = { + 0x026001, 0x014002, 0x009003, 0x010004, 0x01d005, 0x00600d, 0x007018, + 0x450008, 0x4e0400, 0x02e00a, 0x03900b, 0x03d00c, 0x43c404, 0x01b00e, + 0x00f04f, 0x4d8408, 0x023011, 0x01203b, 0x01a013, 0x41440c, 0x015020, + 0x016040, 0x025017, 0x500410, 0x038019, 0x540418, 0x41c444, 0x02d01c, + 0x420520, 0x01e042, 0x03701f, 0x4244cc, 0x02a021, 0x02204c, 0x478428, + 0x024031, 0x42c4dc, 0x4304e8, 0x027033, 0x4a0028, 0x50c029, 0x4344a4, + 0x02c02b, 0x470438, 0x4404c8, 0x4f8448, 0x04902f, 0x04b030, 0x44c484, + 0x524032, 0x4ec454, 0x03e034, 0x035046, 0x4c4036, 0x488458, 0x4d445c, + 0x460468, 0x04e03a, 0x51c464, 0x03c04a, 0x46c514, 0x47453c, 0x04503f, + 0x47c4ac, 0x044041, 0x510480, 0x04304d, 0x4e448c, 0x490518, 0x49449c, + 0x048047, 0x4c0498, 0x4b84a8, 0x4b0508, 0x4fc4b4, 0x4bc504, 0x5304d0, + 0x5344f0, 0x4f452c, 0x528538}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree43 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 3). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree43[80] = { + 0x400001, 0x002004, 0x00300a, 0x46c404, 0x00b005, 0x00600d, 0x034007, + 0x037008, 0x494009, 0x4d8408, 0x42440c, 0x00c01b, 0x490410, 0x00e016, + 0x00f011, 0x010014, 0x4144fc, 0x01201d, 0x020013, 0x508418, 0x4c0015, + 0x41c440, 0x022017, 0x018026, 0x019035, 0x03801a, 0x420444, 0x01c01f, + 0x430428, 0x02101e, 0x44842c, 0x478434, 0x4b4438, 0x45443c, 0x02c023, + 0x039024, 0x02503f, 0x48844c, 0x030027, 0x02e028, 0x032029, 0x02a041, + 0x4d402b, 0x4504f0, 0x04302d, 0x4584a8, 0x02f03b, 0x46045c, 0x03103d, + 0x464046, 0x033044, 0x46853c, 0x47049c, 0x045036, 0x4744dc, 0x4a047c, + 0x500480, 0x4ac03a, 0x4b8484, 0x03c04e, 0x48c524, 0x03e040, 0x4984e8, + 0x50c4a4, 0x4b0530, 0x042047, 0x4bc04b, 0x4e44c4, 0x5184c8, 0x52c4cc, + 0x5204d0, 0x04d048, 0x04a049, 0x4e004c, 0x51c4ec, 0x4f4510, 0x5284f8, + 0x50404f, 0x514538, 0x540534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree44 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 4). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 4) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 4 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree44[80] = { + 0x001004, 0x020002, 0x036003, 0x490400, 0x005008, 0x010006, 0x01f007, + 0x404428, 0x00e009, 0x01100a, 0x00b018, 0x01600c, 0x03700d, 0x408015, + 0x00f03e, 0x40c424, 0x410478, 0x022012, 0x038013, 0x01e014, 0x454414, + 0x448418, 0x025017, 0x47441c, 0x030019, 0x02601a, 0x02d01b, 0x01c034, + 0x01d029, 0x4204f0, 0x4dc42c, 0x470430, 0x02103c, 0x4a0434, 0x02302a, + 0x440024, 0x4384a8, 0x43c44c, 0x02703a, 0x02802c, 0x444524, 0x4504e0, + 0x02b03d, 0x458480, 0x45c4f4, 0x04b02e, 0x04f02f, 0x460520, 0x042031, + 0x048032, 0x049033, 0x514464, 0x03504c, 0x540468, 0x47c46c, 0x4844d8, + 0x039044, 0x4884fc, 0x03b045, 0x48c53c, 0x49449c, 0x4b8498, 0x03f046, + 0x041040, 0x4c44a4, 0x50c4ac, 0x04a043, 0x5184b0, 0x4e44b4, 0x4bc4ec, + 0x04e047, 0x4c04e8, 0x4c8510, 0x4cc52c, 0x4d0530, 0x5044d4, 0x53804d, + 0x5284f8, 0x508500, 0x51c534}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree21 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 5). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree21[80] = { + 0x450001, 0x044002, 0x042003, 0x035004, 0x026005, 0x022006, 0x013007, + 0x010008, 0x00d009, 0x01c00a, 0x01f00b, 0x01e00c, 0x4a0400, 0x01b00e, + 0x03200f, 0x47e402, 0x020011, 0x01204d, 0x40449c, 0x017014, 0x015019, + 0x01603f, 0x406458, 0x01804f, 0x448408, 0x04901a, 0x40a45a, 0x48c40c, + 0x01d031, 0x40e48e, 0x490410, 0x492412, 0x021030, 0x480414, 0x033023, + 0x02402e, 0x02503e, 0x416482, 0x02a027, 0x02802c, 0x029040, 0x418468, + 0x02b04a, 0x41a486, 0x02d048, 0x41c484, 0x04e02f, 0x41e426, 0x420434, + 0x42249e, 0x424494, 0x03d034, 0x428470, 0x039036, 0x03703b, 0x038041, + 0x42a476, 0x03a04b, 0x42c454, 0x03c047, 0x42e472, 0x430478, 0x43246e, + 0x496436, 0x488438, 0x43a466, 0x046043, 0x43c464, 0x04504c, 0x43e462, + 0x460440, 0x44245e, 0x45c444, 0x46a446, 0x44a456, 0x47444c, 0x45244e, + 0x46c47c, 0x48a47a, 0x49a498}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree22 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 6). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree22[80] = { + 0x03c001, 0x02f002, 0x020003, 0x01c004, 0x00f005, 0x00c006, 0x016007, + 0x04d008, 0x00b009, 0x01500a, 0x400490, 0x40e402, 0x00d013, 0x00e02a, + 0x40c404, 0x019010, 0x011041, 0x038012, 0x40a406, 0x014037, 0x40849c, + 0x4a0410, 0x04a017, 0x458018, 0x412422, 0x02801a, 0x01b029, 0x480414, + 0x02401d, 0x01e02b, 0x48a01f, 0x416432, 0x02d021, 0x026022, 0x023039, + 0x418468, 0x025043, 0x48641a, 0x027040, 0x41c488, 0x41e48c, 0x42045a, + 0x47c424, 0x04c02c, 0x46e426, 0x03602e, 0x428478, 0x030033, 0x43c031, + 0x04b032, 0x42e42a, 0x03403a, 0x035048, 0x42c442, 0x470430, 0x494434, + 0x43649a, 0x45c438, 0x04403b, 0x43a454, 0x04503d, 0x03e03f, 0x43e464, + 0x440460, 0x484444, 0x049042, 0x446448, 0x44a456, 0x46644c, 0x047046, + 0x44e452, 0x450462, 0x47445e, 0x46a496, 0x49846c, 0x472476, 0x47a482, + 0x04e04f, 0x47e492, 0x48e49e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree23 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 7). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree23[63] = { + 0x400001, 0x002003, 0x410402, 0x004007, 0x412005, 0x01c006, 0x420404, + 0x00800b, 0x01d009, 0x00a01f, 0x406026, 0x00c012, 0x00d00f, 0x02700e, + 0x408440, 0x010022, 0x028011, 0x45440a, 0x013017, 0x029014, 0x024015, + 0x01602f, 0x43c40c, 0x02b018, 0x019033, 0x03201a, 0x43e01b, 0x47040e, + 0x422414, 0x01e025, 0x432416, 0x020021, 0x418442, 0x41a452, 0x036023, + 0x41c446, 0x46441e, 0x424430, 0x426434, 0x436428, 0x44442a, 0x02e02a, + 0x45642c, 0x03002c, 0x02d03b, 0x46642e, 0x43a438, 0x460448, 0x031037, + 0x47244a, 0x45a44c, 0x034039, 0x038035, 0x47844e, 0x462450, 0x474458, + 0x46a45c, 0x03a03c, 0x45e47a, 0x476468, 0x03d03e, 0x47c46c, 0x46e47e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree24 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 8). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree24[63] = { + 0x001006, 0x01d002, 0x005003, 0x424004, 0x400420, 0x414402, 0x00700a, + 0x008020, 0x00901f, 0x404432, 0x00b011, 0x00c00e, 0x00d032, 0x406446, + 0x02300f, 0x033010, 0x458408, 0x025012, 0x013016, 0x01402f, 0x015038, + 0x46840a, 0x028017, 0x01801a, 0x039019, 0x40c47a, 0x03e01b, 0x03b01c, + 0x40e47e, 0x41201e, 0x422410, 0x416434, 0x02a021, 0x02202b, 0x418444, + 0x02c024, 0x41a456, 0x02d026, 0x027034, 0x46241c, 0x029036, 0x41e45c, + 0x426031, 0x428430, 0x45242a, 0x03702e, 0x42c464, 0x03003c, 0x47442e, + 0x436442, 0x438454, 0x43a448, 0x03503a, 0x43c466, 0x43e03d, 0x44a440, + 0x44c472, 0x46044e, 0x45a450, 0x45e470, 0x46a476, 0x46c478, 0x47c46e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree25 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 9). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree25[168] = { + 0x400001, 0x002003, 0x41a402, 0x004007, 0x41c005, 0x035006, 0x434404, + 0x008010, 0x00900c, 0x04a00a, 0x42000b, 0x44e406, 0x03600d, 0x03800e, + 0x05a00f, 0x408468, 0x01101a, 0x012016, 0x039013, 0x070014, 0x46e015, + 0x40a440, 0x03b017, 0x01804d, 0x01904f, 0x4b840c, 0x01b022, 0x01c041, + 0x03f01d, 0x01e020, 0x01f05b, 0x40e4ee, 0x02107c, 0x45c410, 0x02302c, + 0x024028, 0x053025, 0x026045, 0x02707d, 0x412522, 0x047029, 0x05e02a, + 0x02b08a, 0x526414, 0x05602d, 0x02e081, 0x02f032, 0x06e030, 0x031080, + 0x416544, 0x079033, 0x034091, 0x41852c, 0x43641e, 0x04b037, 0x42246a, + 0x43c424, 0x04c03a, 0x426456, 0x03c066, 0x03d03e, 0x482428, 0x45842a, + 0x040072, 0x42c4ba, 0x050042, 0x04305c, 0x044074, 0x42e4be, 0x06a046, + 0x4dc430, 0x075048, 0x0490a3, 0x44a432, 0x450438, 0x43a452, 0x48443e, + 0x04e068, 0x45a442, 0x4d4444, 0x051088, 0x052087, 0x44648c, 0x077054, + 0x4da055, 0x50a448, 0x057060, 0x06b058, 0x05906d, 0x44c4f6, 0x46c454, + 0x45e474, 0x06905d, 0x460520, 0x05f07e, 0x462494, 0x061063, 0x07f062, + 0x464496, 0x06408b, 0x08d065, 0x542466, 0x067071, 0x4d2470, 0x4724ec, + 0x478476, 0x53a47a, 0x09b06c, 0x47c4ac, 0x4f847e, 0x06f078, 0x510480, + 0x48649e, 0x4884a0, 0x07307b, 0x49c48a, 0x4a648e, 0x098076, 0x4904c0, + 0x4924ea, 0x4c8498, 0x07a08e, 0x51249a, 0x4a24d6, 0x5064a4, 0x4f24a8, + 0x4aa4de, 0x51e4ae, 0x4b0538, 0x082092, 0x083085, 0x08f084, 0x5464b2, + 0x096086, 0x4ce4b4, 0x4d04b6, 0x089090, 0x4bc508, 0x4c253e, 0x08c0a4, + 0x5284c4, 0x4e04c6, 0x4ca4fa, 0x5144cc, 0x4f04d8, 0x4e24fc, 0x09309c, + 0x094099, 0x095097, 0x4e4516, 0x4e652e, 0x4e84fe, 0x4f450c, 0x09a09f, + 0x500502, 0x50450e, 0x09d0a0, 0x09e0a5, 0x518530, 0x51a54a, 0x0a70a1, + 0x0a20a6, 0x51c534, 0x53c524, 0x54052a, 0x548532, 0x536550, 0x54c54e}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree26 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 10). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree26[168] = { + 0x006001, 0x002013, 0x00300f, 0x00400d, 0x03b005, 0x40046e, 0x037007, + 0x00800a, 0x009067, 0x402420, 0x05600b, 0x00c057, 0x434404, 0x06600e, + 0x406470, 0x03c010, 0x059011, 0x06f012, 0x49e408, 0x014019, 0x03f015, + 0x016044, 0x017042, 0x079018, 0x4b840a, 0x01a01f, 0x01b047, 0x07c01c, + 0x08701d, 0x06901e, 0x44640c, 0x020027, 0x04b021, 0x02204f, 0x023025, + 0x02406b, 0x40e4e0, 0x081026, 0x528410, 0x02802c, 0x06c029, 0x08f02a, + 0x02b078, 0x53a412, 0x05202d, 0x02e033, 0x02f031, 0x0300a2, 0x4144ce, + 0x0a6032, 0x416534, 0x09a034, 0x09f035, 0x0360a7, 0x54e418, 0x03a038, + 0x436039, 0x43841a, 0x41c41e, 0x42246a, 0x05803d, 0x03e068, 0x424484, + 0x04005b, 0x04107a, 0x42645a, 0x043093, 0x4d2428, 0x05e045, 0x046072, + 0x42a45e, 0x048060, 0x073049, 0x04a098, 0x42c4c4, 0x07504c, 0x09504d, + 0x04e09c, 0x51042e, 0x063050, 0x077051, 0x43053c, 0x053084, 0x065054, + 0x4e4055, 0x4fe432, 0x43a454, 0x43c46c, 0x43e486, 0x07005a, 0x4a0440, + 0x07105c, 0x05d07b, 0x45c442, 0x05f08a, 0x476444, 0x07f061, 0x06206a, + 0x448506, 0x06408e, 0x52644a, 0x54444c, 0x45644e, 0x452450, 0x488458, + 0x4604ec, 0x4624f6, 0x50e464, 0x08206d, 0x0a406e, 0x542466, 0x4a2468, + 0x48a472, 0x474089, 0x4d8478, 0x097074, 0x47a508, 0x08d076, 0x47c4b6, + 0x51247e, 0x4804fc, 0x4bc482, 0x48c4a4, 0x48e4d4, 0x07d07e, 0x4904da, + 0x49208b, 0x094080, 0x49450c, 0x4964e2, 0x09d083, 0x52a498, 0x085091, + 0x0a5086, 0x4cc49a, 0x08808c, 0x4ee49c, 0x4a64ba, 0x4a84c0, 0x4c24aa, + 0x4ac4f0, 0x4ae4d0, 0x4ca4b0, 0x0900a1, 0x4b24ea, 0x092099, 0x4b4516, + 0x4d64be, 0x4c650a, 0x522096, 0x4c8524, 0x4dc4f2, 0x4de4f4, 0x4e6548, + 0x09e09b, 0x5384e8, 0x5204f8, 0x4fa53e, 0x50051a, 0x0a30a0, 0x502536, + 0x514504, 0x51e518, 0x54a51c, 0x54052c, 0x52e546, 0x530532, 0x54c550}; + +/* ********************************************************************************************* + */ +/* Table: HuffTree27 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the decode tree for spectral data + * (Codebook 11). */ +/* bit 23 and 11 not used */ +/* bit 22 and 10 determine end value */ +/* bit 21-12 and 9-0 (offset to next node) or (index value * + * 2) */ +/* --------------------------------------------------------------------------------------------- + */ +/* input: codeword */ +/* --------------------------------------------------------------------------------------------- + */ +/* output: index * 2 */ +/* --------------------------------------------------------------------------------------------- + */ +const UINT aHuffTree27[288] = { + 0x00100d, 0x002006, 0x003004, 0x400424, 0x047005, 0x402446, 0x048007, + 0x00800a, 0x00904c, 0x44a404, 0x07400b, 0x00c0bb, 0x466406, 0x00e014, + 0x00f054, 0x04e010, 0x051011, 0x0a9012, 0x0130bc, 0x408464, 0x01501f, + 0x01601a, 0x017059, 0x0af018, 0x0ca019, 0x40a0e4, 0x01b05e, 0x01c084, + 0x0bf01d, 0x05d01e, 0x55a40c, 0x020026, 0x021066, 0x043022, 0x023062, + 0x02408d, 0x025108, 0x40e480, 0x027030, 0x02802c, 0x02906b, 0x02a0da, + 0x06502b, 0x4105c8, 0x0a402d, 0x0ec02e, 0x0dd02f, 0x532412, 0x06e031, + 0x032036, 0x03303e, 0x0fd034, 0x0fc035, 0x4145b0, 0x03703a, 0x038117, + 0x10d039, 0x5ba416, 0x10f03b, 0x03c041, 0x5fa03d, 0x41c418, 0x10403f, + 0x04011d, 0x41a5f4, 0x11c042, 0x41e61c, 0x087044, 0x0f5045, 0x0d9046, + 0x4204a2, 0x640422, 0x04904a, 0x426448, 0x04b073, 0x428468, 0x46c04d, + 0x48a42a, 0x04f077, 0x076050, 0x42c4b0, 0x0520a7, 0x096053, 0x42e4a8, + 0x05507d, 0x07a056, 0x0d4057, 0x0df058, 0x442430, 0x05a081, 0x05b09b, + 0x05c0e2, 0x5b8432, 0x4fe434, 0x05f09e, 0x0e6060, 0x0610d6, 0x57c436, + 0x0cc063, 0x112064, 0x4384a0, 0x43a5ca, 0x067089, 0x0680b7, 0x0690a2, + 0x0a106a, 0x43c59c, 0x09206c, 0x06d0ba, 0x60643e, 0x0d106f, 0x0700ee, + 0x0de071, 0x10b072, 0x44056c, 0x46a444, 0x075094, 0x48c44c, 0x44e490, + 0x095078, 0x0ab079, 0x4504ce, 0x07b097, 0x11e07c, 0x630452, 0x0ac07e, + 0x07f099, 0x080106, 0x4544b8, 0x0820b1, 0x0830e5, 0x4fc456, 0x0b3085, + 0x08609d, 0x45853e, 0x0880c2, 0x5c045a, 0x08a08f, 0x08b0ce, 0x08c0f7, + 0x58645c, 0x11108e, 0x45e5c4, 0x0c4090, 0x10a091, 0x4604e4, 0x0d0093, + 0x462608, 0x48e46e, 0x4704b2, 0x4d2472, 0x0980bd, 0x4f2474, 0x0e309a, + 0x4764aa, 0x0be09c, 0x47851a, 0x47a4de, 0x09f0b5, 0x0a00c1, 0x50047c, + 0x57847e, 0x0a30c3, 0x504482, 0x0e90a5, 0x0a6100, 0x4c8484, 0x0a811f, + 0x48662a, 0x0c70aa, 0x488494, 0x4924d0, 0x0ad0c8, 0x0ae0d8, 0x496636, + 0x10e0b0, 0x4f8498, 0x0f30b2, 0x49a4dc, 0x0f20b4, 0x53c49c, 0x0b60cb, + 0x49e57a, 0x0b80e0, 0x0b9109, 0x5e44a4, 0x5484a6, 0x4ac4ae, 0x4b44ca, + 0x4d64b6, 0x4ba5da, 0x0c60c0, 0x4bc51e, 0x4be556, 0x6204c0, 0x4c24c4, + 0x0f80c5, 0x5664c6, 0x4cc53a, 0x4d462c, 0x0f10c9, 0x4d8552, 0x4da4fa, + 0x5be4e0, 0x0cd0ff, 0x5244e2, 0x0cf0e8, 0x4e6568, 0x59a4e8, 0x0f90d2, + 0x1010d3, 0x5ac4ea, 0x0d50d7, 0x4ec634, 0x4ee560, 0x4f44f0, 0x4f6638, + 0x502522, 0x0db0dc, 0x5065a6, 0x508604, 0x60050a, 0x50c0fb, 0x63250e, + 0x1130e1, 0x5a4510, 0x5125fc, 0x516514, 0x51863e, 0x51c536, 0x0e70f4, + 0x55c520, 0x602526, 0x0eb0ea, 0x5cc528, 0x5ea52a, 0x1140ed, 0x60c52c, + 0x1020ef, 0x0f0119, 0x58e52e, 0x530622, 0x558534, 0x53861e, 0x55e540, + 0x5800f6, 0x57e542, 0x5445e6, 0x5465e8, 0x0fa115, 0x54c54a, 0x54e60e, + 0x5ae550, 0x1160fe, 0x5f0554, 0x564562, 0x56a58a, 0x56e5ee, 0x10310c, + 0x5705d0, 0x107105, 0x5725d4, 0x57463a, 0x5765b4, 0x5825bc, 0x5845e2, + 0x5885de, 0x58c592, 0x5ce590, 0x5945f6, 0x63c596, 0x11b110, 0x5d8598, + 0x5c259e, 0x5e05a0, 0x5a25c6, 0x5a860a, 0x5aa5ec, 0x5b2610, 0x11a118, + 0x6185b6, 0x5f25d2, 0x5d6616, 0x5dc5f8, 0x61a5fe, 0x612614, 0x62e624, + 0x626628}; + +/* get starting addresses of huffman tables into an array [convert codebook into + * starting address] */ +/* cb tree */ +const UINT *aHuffTable[MAX_CB] = { + aHuffTree41, + /* 0 - */ /* use tree 1 as dummy here */ + aHuffTree41, /* 1 1 */ + aHuffTree42, /* 2 2 */ + aHuffTree43, /* 3 3 */ + aHuffTree44, /* 4 4 */ + aHuffTree21, /* 5 5 */ + aHuffTree22, /* 6 6 */ + aHuffTree23, /* 7 7 */ + aHuffTree24, /* 8 8 */ + aHuffTree25, /* 9 9 */ + aHuffTree26, /* 10 10 */ + aHuffTree27, /* 11 11 */ + aHuffTree41, + /* 12 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 13 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 14 - */ /* use tree 1 as dummy here */ + aHuffTree41, + /* 15 - */ /* use tree 1 as dummy here */ + aHuffTree27, /* 16 11 */ + aHuffTree27, /* 17 11 */ + aHuffTree27, /* 18 11 */ + aHuffTree27, /* 19 11 */ + aHuffTree27, /* 20 11 */ + aHuffTree27, /* 21 11 */ + aHuffTree27, /* 22 11 */ + aHuffTree27, /* 23 11 */ + aHuffTree27, /* 24 11 */ + aHuffTree27, /* 25 11 */ + aHuffTree27, /* 26 11 */ + aHuffTree27, /* 27 11 */ + aHuffTree27, /* 28 11 */ + aHuffTree27, /* 29 11 */ + aHuffTree27, /* 30 11 */ + aHuffTree27}; /* 31 11 */ + +/*--------------------------------------------------------------------------------------------- + data-description: + The following tables contain the quantized values. Two or four of the + quantized values are indexed by the result of the decoding in the decoding tree + (see tables above). + -------------------------------------------------------------------------------------------- + */ + +/* ********************************************************************************************* + */ +/* Table: ValTab41 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 1-2. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab41[324] = { + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, 1, -1, -1, 0, -1, -1, -1, + 0, 0, -1, -1, 0, 1, -1, -1, 1, -1, -1, -1, 1, 0, -1, -1, 1, 1, + -1, 0, -1, -1, -1, 0, -1, 0, -1, 0, -1, 1, -1, 0, 0, -1, -1, 0, + 0, 0, -1, 0, 0, 1, -1, 0, 1, -1, -1, 0, 1, 0, -1, 0, 1, 1, + -1, 1, -1, -1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, 0, -1, -1, 1, + 0, 0, -1, 1, 0, 1, -1, 1, 1, -1, -1, 1, 1, 0, -1, 1, 1, 1, + 0, -1, -1, -1, 0, -1, -1, 0, 0, -1, -1, 1, 0, -1, 0, -1, 0, -1, + 0, 0, 0, -1, 0, 1, 0, -1, 1, -1, 0, -1, 1, 0, 0, -1, 1, 1, + 0, 0, -1, -1, 0, 0, -1, 0, 0, 0, -1, 1, 0, 0, 0, -1, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 1, -1, 0, 0, 1, 0, 0, 0, 1, 1, + 0, 1, -1, -1, 0, 1, -1, 0, 0, 1, -1, 1, 0, 1, 0, -1, 0, 1, + 0, 0, 0, 1, 0, 1, 0, 1, 1, -1, 0, 1, 1, 0, 0, 1, 1, 1, + 1, -1, -1, -1, 1, -1, -1, 0, 1, -1, -1, 1, 1, -1, 0, -1, 1, -1, + 0, 0, 1, -1, 0, 1, 1, -1, 1, -1, 1, -1, 1, 0, 1, -1, 1, 1, + 1, 0, -1, -1, 1, 0, -1, 0, 1, 0, -1, 1, 1, 0, 0, -1, 1, 0, + 0, 0, 1, 0, 0, 1, 1, 0, 1, -1, 1, 0, 1, 0, 1, 0, 1, 1, + 1, 1, -1, -1, 1, 1, -1, 0, 1, 1, -1, 1, 1, 1, 0, -1, 1, 1, + 0, 0, 1, 1, 0, 1, 1, 1, 1, -1, 1, 1, 1, 0, 1, 1, 1, 1}; + +/* ********************************************************************************************* + */ +/* Table: ValTab42 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 3-4. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab42[324] = { + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 2, 0, + 0, 2, 0, 0, 0, 2, 1, 0, 0, 2, 2, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 2, 0, 1, + 1, 0, 0, 1, 1, 1, 0, 1, 1, 2, 0, 1, 2, 0, 0, 1, 2, 1, 0, 1, 2, 2, 0, 2, 0, + 0, 0, 2, 0, 1, 0, 2, 0, 2, 0, 2, 1, 0, 0, 2, 1, 1, 0, 2, 1, 2, 0, 2, 2, 0, + 0, 2, 2, 1, 0, 2, 2, 2, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 2, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 2, 1, 0, 2, 0, 1, 0, 2, 1, 1, 0, 2, 2, 1, 1, 0, 0, 1, 1, + 0, 1, 1, 1, 0, 2, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 2, 0, 1, 1, 2, + 1, 1, 1, 2, 2, 1, 2, 0, 0, 1, 2, 0, 1, 1, 2, 0, 2, 1, 2, 1, 0, 1, 2, 1, 1, + 1, 2, 1, 2, 1, 2, 2, 0, 1, 2, 2, 1, 1, 2, 2, 2, 2, 0, 0, 0, 2, 0, 0, 1, 2, + 0, 0, 2, 2, 0, 1, 0, 2, 0, 1, 1, 2, 0, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 2, 0, + 2, 2, 2, 1, 0, 0, 2, 1, 0, 1, 2, 1, 0, 2, 2, 1, 1, 0, 2, 1, 1, 1, 2, 1, 1, + 2, 2, 1, 2, 0, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 0, 0, 2, 2, 0, 1, 2, 2, 0, 2, + 2, 2, 1, 0, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 2, 0, 2, 2, 2, 1, 2, 2, 2, 2}; + +/* ********************************************************************************************* + */ +/* Table: ValTab21 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 5-6. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab21[162] = { + -4, -4, -4, -3, -4, -2, -4, -1, -4, 0, -4, 1, -4, 2, -4, 3, -4, 4, + -3, -4, -3, -3, -3, -2, -3, -1, -3, 0, -3, 1, -3, 2, -3, 3, -3, 4, + -2, -4, -2, -3, -2, -2, -2, -1, -2, 0, -2, 1, -2, 2, -2, 3, -2, 4, + -1, -4, -1, -3, -1, -2, -1, -1, -1, 0, -1, 1, -1, 2, -1, 3, -1, 4, + 0, -4, 0, -3, 0, -2, 0, -1, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, + 1, -4, 1, -3, 1, -2, 1, -1, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, + 2, -4, 2, -3, 2, -2, 2, -1, 2, 0, 2, 1, 2, 2, 2, 3, 2, 4, + 3, -4, 3, -3, 3, -2, 3, -1, 3, 0, 3, 1, 3, 2, 3, 3, 3, 4, + 4, -4, 4, -3, 4, -2, 4, -1, 4, 0, 4, 1, 4, 2, 4, 3, 4, 4}; + +/* ********************************************************************************************* + */ +/* Table: ValTab22 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 7-8. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab22[128] = { + 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}; + +/* ********************************************************************************************* + */ +/* Table: ValTab23 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks + * 9-10. */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab23[338] = { + 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}; + +/* ********************************************************************************************* + */ +/* Table: ValTab24 */ +/* --------------------------------------------------------------------------------------------- + */ +/* description: This table contains the quantized values for codebooks 11. + */ +/* --------------------------------------------------------------------------------------------- + */ +const SCHAR aValTab24[578] = { + 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}; + +/* cb quant. val table */ +const SCHAR *aQuantTable[] = { + aValTab41, + /* 0 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, /* 1 1 */ + aValTab41, /* 2 1 */ + aValTab42, /* 3 2 */ + aValTab42, /* 4 2 */ + aValTab21, /* 5 3 */ + aValTab21, /* 6 3 */ + aValTab22, /* 7 4 */ + aValTab22, /* 8 4 */ + aValTab23, /* 9 5 */ + aValTab23, /* 10 5 */ + aValTab24, /* 11 6 */ + aValTab41, + /* 12 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 13 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 14 - */ /* use quant. val talble 1 as dummy here */ + aValTab41, + /* 15 - */ /* use quant. val talble 1 as dummy here */ + aValTab24, /* 16 6 */ + aValTab24, /* 17 6 */ + aValTab24, /* 18 6 */ + aValTab24, /* 19 6 */ + aValTab24, /* 20 6 */ + aValTab24, /* 21 6 */ + aValTab24, /* 22 6 */ + aValTab24, /* 23 6 */ + aValTab24, /* 24 6 */ + aValTab24, /* 25 6 */ + aValTab24, /* 26 6 */ + aValTab24, /* 27 6 */ + aValTab24, /* 28 6 */ + aValTab24, /* 29 6 */ + aValTab24, /* 30 6 */ + aValTab24}; /* 31 6 */ + +/* arrays for HCR_TABLE_INFO structures */ +/* maximum length of codeword in each codebook */ +/* codebook: 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 */ +const UCHAR aMaxCwLen[MAX_CB] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, + 49, 0, 0, 0, 0, 14, 17, 21, 21, 25, 25, + 29, 29, 29, 29, 33, 33, 33, 37, 37, 41}; + +/* 11 13 15 17 19 + * 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 + * 22 24 26 28 30 */ +const UCHAR aDimCb[MAX_CB] = { + 2, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; /* codebook dimension - + zero cb got a + dimension of 2 */ + +/* 11 13 15 17 19 + * 21 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 + * 22 24 26 28 30 */ +const UCHAR aDimCbShift[MAX_CB] = { + 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; /* codebook dimension */ + +/* 1 -> decode sign bits */ +/* 0 -> decode no sign bits 11 13 15 17 19 21 + * 23 25 27 39 31 */ +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 14 16 18 20 22 + * 24 26 28 30 */ +const UCHAR aSignCb[MAX_CB] = {0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}; + +/* arrays for HCR_CB_PAIRS structures */ +const UCHAR aMinOfCbPair[MAX_CB_PAIRS] = {0, 1, 3, 5, 7, 9, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 11}; +const UCHAR aMaxOfCbPair[MAX_CB_PAIRS] = {0, 2, 4, 6, 8, 10, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 11}; + +/* priorities of codebooks */ +const UCHAR aCbPriority[MAX_CB] = {0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, + 22, 0, 0, 0, 0, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; + +const SCHAR aCodebook2StartInt[] = {STOP_THIS_STATE, /* cb 0 */ + BODY_ONLY, /* cb 1 */ + BODY_ONLY, /* cb 2 */ + BODY_SIGN__BODY, /* cb 3 */ + BODY_SIGN__BODY, /* cb 4 */ + BODY_ONLY, /* cb 5 */ + BODY_ONLY, /* cb 6 */ + BODY_SIGN__BODY, /* cb 7 */ + BODY_SIGN__BODY, /* cb 8 */ + BODY_SIGN__BODY, /* cb 9 */ + BODY_SIGN__BODY, /* cb 10 */ + BODY_SIGN_ESC__BODY, /* cb 11 */ + STOP_THIS_STATE, /* cb 12 */ + STOP_THIS_STATE, /* cb 13 */ + STOP_THIS_STATE, /* cb 14 */ + STOP_THIS_STATE, /* cb 15 */ + BODY_SIGN_ESC__BODY, /* cb 16 */ + BODY_SIGN_ESC__BODY, /* cb 17 */ + BODY_SIGN_ESC__BODY, /* cb 18 */ + BODY_SIGN_ESC__BODY, /* cb 19 */ + BODY_SIGN_ESC__BODY, /* cb 20 */ + BODY_SIGN_ESC__BODY, /* cb 21 */ + BODY_SIGN_ESC__BODY, /* cb 22 */ + BODY_SIGN_ESC__BODY, /* cb 23 */ + BODY_SIGN_ESC__BODY, /* cb 24 */ + BODY_SIGN_ESC__BODY, /* cb 25 */ + BODY_SIGN_ESC__BODY, /* cb 26 */ + BODY_SIGN_ESC__BODY, /* cb 27 */ + BODY_SIGN_ESC__BODY, /* cb 28 */ + BODY_SIGN_ESC__BODY, /* cb 29 */ + BODY_SIGN_ESC__BODY, /* cb 30 */ + BODY_SIGN_ESC__BODY}; /* cb 31 */ + +const STATEFUNC aStateConstant2State[] = { + NULL, /* 0 = STOP_THIS_STATE */ + Hcr_State_BODY_ONLY, /* 1 = BODY_ONLY */ + Hcr_State_BODY_SIGN__BODY, /* 2 = BODY_SIGN__BODY */ + Hcr_State_BODY_SIGN__SIGN, /* 3 = BODY_SIGN__SIGN */ + Hcr_State_BODY_SIGN_ESC__BODY, /* 4 = BODY_SIGN_ESC__BODY */ + Hcr_State_BODY_SIGN_ESC__SIGN, /* 5 = BODY_SIGN_ESC__SIGN */ + Hcr_State_BODY_SIGN_ESC__ESC_PREFIX, /* 6 = BODY_SIGN_ESC__ESC_PREFIX */ + Hcr_State_BODY_SIGN_ESC__ESC_WORD}; /* 7 = BODY_SIGN_ESC__ESC_WORD */ + +/* CB: 0 1 2 3 4 5 6 7 8 9 10 12 + * 14 16 18 20 22 24 26 28 30 */ +const USHORT aLargestAbsoluteValue[MAX_CB] = { + 0, 1, 1, 2, 2, 4, 4, 7, 7, 12, 12, + 8191, 0, 0, 0, 0, 15, 31, 47, 63, 95, 127, + 159, 191, 223, 255, 319, 383, 511, 767, 1023, 2047}; /* lav */ +/* CB: 11 13 + * 15 17 19 21 23 25 27 39 31 */ + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlcEscape' contains the decode tree for +the rvlc escape sequences. bit 23 and 11 not used bit 22 and 10 determine end +value --> if set codeword is decoded bit 21-12 and 9-0 (offset to next node) +or (index value) The escape sequence is the index value. + + input: codeword + output: index +------------------------------------------------------------------------------------------ +*/ +const UINT aHuffTreeRvlcEscape[53] = { + 0x002001, 0x400003, 0x401004, 0x402005, 0x403007, 0x404006, 0x00a405, + 0x009008, 0x00b406, 0x00c407, 0x00d408, 0x00e409, 0x40b40a, 0x40c00f, + 0x40d010, 0x40e011, 0x40f012, 0x410013, 0x411014, 0x412015, 0x016413, + 0x414415, 0x017416, 0x417018, 0x419019, 0x01a418, 0x01b41a, 0x01c023, + 0x03201d, 0x01e020, 0x43501f, 0x41b41c, 0x021022, 0x41d41e, 0x41f420, + 0x02402b, 0x025028, 0x026027, 0x421422, 0x423424, 0x02902a, 0x425426, + 0x427428, 0x02c02f, 0x02d02e, 0x42942a, 0x42b42c, 0x030031, 0x42d42e, + 0x42f430, 0x033034, 0x431432, 0x433434}; + +/* ------------------------------------------------------------------------------------------ + description: The table 'HuffTreeRvlc' contains the huffman decoding tree +for the RVLC scale factors. The table contains 15 allowed, symmetric codewords +and 8 forbidden codewords, which are used for error detection. + + usage of bits: bit 23 and 11 not used + bit 22 and 10 determine end value --> if set codeword is +decoded bit 21-12 and 9-0 (offset to next node within the table) or (index+7). + The decoded (index+7) is in the range from 0,1,..,22. If the +(index+7) is in the range 15,16,..,22, then a forbidden codeword is decoded. + + input: A single bit from a RVLC scalefactor codeword + output: [if codeword is not completely decoded:] offset to next node +within table or [if codeword is decoded:] A dpcm value i.e. (index+7) in range +from 0,1,..,22. The differential scalefactor (DPCM value) named 'index' is +calculated by subtracting 7 from the decoded value (index+7). +------------------------------------------------------------------------------------------ +*/ +const UINT aHuffTreeRvlCodewds[22] = { + 0x407001, 0x002009, 0x003406, 0x004405, 0x005404, 0x006403, + 0x007400, 0x008402, 0x411401, 0x00a408, 0x00c00b, 0x00e409, + 0x01000d, 0x40f40a, 0x41400f, 0x01340b, 0x011015, 0x410012, + 0x41240c, 0x416014, 0x41540d, 0x41340e}; + +const FIXP_WTB LowDelaySynthesis256[768] = { + WTC(0xdaecb88a), WTC(0xdb7a5230), WTC(0xdc093961), WTC(0xdc9977b5), + WTC(0xdd2b11b4), WTC(0xddbe06c1), WTC(0xde525277), WTC(0xdee7f167), + WTC(0xdf7ee2f9), WTC(0xe0173207), WTC(0xe0b0e70e), WTC(0xe14beb4d), + WTC(0xe1e82002), WTC(0xe285693d), WTC(0xe323ba3c), WTC(0xe3c33cdb), + WTC(0xe4640c93), WTC(0xe5060b3f), WTC(0xe5a915ce), WTC(0xe64cffc2), + WTC(0xe6f19868), WTC(0xe796b4d7), WTC(0xe83c2ebf), WTC(0xe8e1eea1), + WTC(0xe987f784), WTC(0xea2e8014), WTC(0xead5a2b6), WTC(0xeb7d3476), + WTC(0xec24ebfb), WTC(0xeccc4e9a), WTC(0xed72f723), WTC(0xee18b585), + WTC(0xeebd6902), WTC(0xef610661), WTC(0xf0037f41), WTC(0xf0a4c139), + WTC(0xf144c5bc), WTC(0xf1e395c4), WTC(0xf2812c5d), WTC(0xf31d6db4), + WTC(0xf3b83ed0), WTC(0xf4517963), WTC(0xf4e8d672), WTC(0xf57de495), + WTC(0xf610395e), WTC(0xf69f7e84), WTC(0xf72b9152), WTC(0xf7b495b5), + WTC(0xf83af453), WTC(0xf8bf7118), WTC(0xf9429a33), WTC(0xf9c4c183), + WTC(0xfa466592), WTC(0xfac80867), WTC(0xfb49d2bd), WTC(0xfbcb7294), + WTC(0xfc4d0e35), WTC(0xfccf7e7b), WTC(0xfd53af97), WTC(0xfddab5ca), + WTC(0xfe629a56), WTC(0xfee5c7c9), WTC(0xff5b6311), WTC(0xffb6bd45), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff6c845), WTC(0xbfe461ee), WTC(0xbfd1f586), WTC(0xbfbf85b2), + WTC(0xbfad1518), WTC(0xbf9aa640), WTC(0xbf883911), WTC(0xbf75caf0), + WTC(0xbf635c4b), WTC(0xbf50f09b), WTC(0xbf3e886d), WTC(0xbf2c2167), + WTC(0xbf19bc2c), WTC(0xbf075c64), WTC(0xbef502db), WTC(0xbee2ad83), + WTC(0xbed05d67), WTC(0xbebe16a7), WTC(0xbeabda46), WTC(0xbe99a62e), + WTC(0xbe877b90), WTC(0xbe755ee8), WTC(0xbe63517d), WTC(0xbe51515b), + WTC(0xbe3f5fc9), WTC(0xbe2d8141), WTC(0xbe1bb721), WTC(0xbe09ffa3), + WTC(0xbdf85c17), WTC(0xbde6d0e3), WTC(0xbdd55f47), WTC(0xbdc4055d), + WTC(0xbdb2c438), WTC(0xbda19fe0), WTC(0xbd909942), WTC(0xbd7fae2f), + WTC(0xbd6edf8d), WTC(0xbd5e3153), WTC(0xbd4da45b), WTC(0xbd3d365a), + WTC(0xbd2ce7eb), WTC(0xbd1cbc87), WTC(0xbd0cb466), WTC(0xbcfccc80), + WTC(0xbced04c5), WTC(0xbcdd6022), WTC(0xbccdde49), WTC(0xbcbe7bb4), + WTC(0xbcaf37ec), WTC(0xbca01594), WTC(0xbc91149b), WTC(0xbc823234), + WTC(0xbc736d81), WTC(0xbc64c7a4), WTC(0xbc564085), WTC(0xbc47d6a9), + WTC(0xbc398617), WTC(0xbc2b4915), WTC(0xbc1d2a92), WTC(0xbc0f4370), + WTC(0xbc016785), WTC(0xbbf32f6c), WTC(0xbbe53648), WTC(0xbbd91eb5), + WTC(0xbbd02f7c), WTC(0xbbcb58db), WTC(0xbbca5ac2), WTC(0xbbcbdea2), + WTC(0xbbcee192), WTC(0xbbd2c7c2), WTC(0xbbd7a648), WTC(0xbbde3c5a), + WTC(0xbbe7079f), WTC(0xbbf238bf), WTC(0xbbff8eec), WTC(0xbc0e5d22), + WTC(0xbc1e2c8b), WTC(0xbc2ec3a4), WTC(0xbc402f19), WTC(0xbc52c1ac), + WTC(0xbc6709aa), WTC(0xbc7dcbce), WTC(0xbc979383), WTC(0xbcb4ae30), + WTC(0xbcd52aeb), WTC(0xbcf8db63), WTC(0xbd1f6993), WTC(0xbd485b46), + WTC(0xbd735007), WTC(0xbda003fc), WTC(0xbdce556c), WTC(0xbdfe453b), + WTC(0xbe2ffd4e), WTC(0xbe63ceb7), WTC(0xbe9a006f), WTC(0xbed2ce2b), + WTC(0xbf0e7d8e), WTC(0xbf4d5cfc), WTC(0xbf8f92bd), WTC(0xbfd5160c), + WTC(0xc01d3b27), WTC(0xc066b8f5), WTC(0xc0b0a3b8), WTC(0xc0fa7cdd), + WTC(0xc144b0e8), WTC(0xc1908d71), WTC(0xc1ded403), WTC(0xc22fae49), + WTC(0xc2830092), WTC(0xc2d86ca8), WTC(0xc32f4341), WTC(0xc38687e5), + WTC(0xc3dd5c55), WTC(0xc43310e4), WTC(0xc4883eca), WTC(0xc4deba3d), + WTC(0xc5372c82), WTC(0xc59102fb), WTC(0xc5eb416a), WTC(0xc644986f), + WTC(0xc69cabb2), WTC(0xc6f41290), WTC(0xc74b22bf), WTC(0xc7a1e4b9), + WTC(0xc7f83500), WTC(0xc84dc737), WTC(0xc8a24e07), WTC(0xc8f5776f), + WTC(0xb4db4a8b), WTC(0xb3c58a32), WTC(0xb2b2acb4), WTC(0xb1a2afc0), + WTC(0xb0959107), WTC(0xaf8b4e0a), WTC(0xae83dfef), WTC(0xad7f3ba6), + WTC(0xac7d5a57), WTC(0xab7e397d), WTC(0xaa81d5a7), WTC(0xa9882a64), + WTC(0xa89135bc), WTC(0xa79cf84e), WTC(0xa6ab74fc), WTC(0xa5bcb0d0), + WTC(0xa4d0b1b8), WTC(0xa3e77e6d), WTC(0xa3011e16), WTC(0xa21d986c), + WTC(0xa13cf921), WTC(0xa05f4fb9), WTC(0x9f84a850), WTC(0x9ead0baf), + WTC(0x9dd8888c), WTC(0x9d073385), WTC(0x9c391db5), WTC(0x9b6e5484), + WTC(0x9aa6e656), WTC(0x99e2e2c5), WTC(0x99225ac4), WTC(0x9865608a), + WTC(0x97ac0564), WTC(0x96f65984), WTC(0x96446a25), WTC(0x95964196), + WTC(0x94ebe9ec), WTC(0x94456d19), WTC(0x93a2d46a), WTC(0x93042864), + WTC(0x92696dea), WTC(0x91d2a637), WTC(0x913fd120), WTC(0x90b0ecfe), + WTC(0x9025f239), WTC(0x8f9ed33e), WTC(0x8f1b804b), WTC(0x8e9be72b), + WTC(0x8e1fe984), WTC(0x8da75ce4), WTC(0x8d321511), WTC(0x8cbfe381), + WTC(0x8c508090), WTC(0x8be38b7b), WTC(0x8b78a10a), WTC(0x8b0f5bb4), + WTC(0x8aa740f3), WTC(0x8a3fc439), WTC(0x89d8a093), WTC(0x8971e7bf), + WTC(0x890d0fa8), WTC(0x88acfc32), WTC(0x8855e07a), WTC(0x880d5010), + WTC(0x87cc444c), WTC(0x87b6e84e), WTC(0x879e3713), WTC(0x87850a87), + WTC(0x876c76ee), WTC(0x8753c55a), WTC(0x873aa70d), WTC(0x872147e7), + WTC(0x8707bb23), WTC(0x86edf64f), WTC(0x86d3f20d), WTC(0x86b9ab68), + WTC(0x869f21e7), WTC(0x86845744), WTC(0x8669499e), WTC(0x864df395), + WTC(0x863254b2), WTC(0x8616715e), WTC(0x85fa4870), WTC(0x85ddd324), + WTC(0x85c1108b), WTC(0x85a40597), WTC(0x8586b1d1), WTC(0x85690f48), + WTC(0x854b1dfb), WTC(0x852ce3e7), WTC(0x850e61c8), WTC(0x84ef9303), + WTC(0x84d078c2), WTC(0x84b119fa), WTC(0x849177fa), WTC(0x84718e56), + WTC(0x84515e65), WTC(0x8430ef53), WTC(0x841042cb), WTC(0x83ef54e8), + WTC(0x83ce27ab), WTC(0x83acc30a), WTC(0x838b2934), WTC(0x83695686), + WTC(0x83474d47), WTC(0x832515b6), WTC(0x8302b202), WTC(0x82e01e3b), + WTC(0x82bd5c8e), WTC(0x829a755a), WTC(0x82776abf), WTC(0x8254388a), + WTC(0x8230e07e), WTC(0x820d6a69), WTC(0x81e9d82d), WTC(0x81c625ae), + WTC(0x81a25455), WTC(0x817e6b1f), WTC(0x815a6b39), WTC(0x81364fec), + WTC(0x81121a34), WTC(0x80edd0c9), WTC(0x80c97479), WTC(0x80a5000a), + WTC(0x80807332), WTC(0x805bd2e6), WTC(0x80372460), WTC(0x80126cc4), + WTC(0x0a8a8431), WTC(0x0ae3c329), WTC(0x0b3fdab2), WTC(0x0b9e6e44), + WTC(0x0bff2161), WTC(0x0c619a72), WTC(0x0cc5c66d), WTC(0x0d2bd6df), + WTC(0x0d93cf64), WTC(0x0dfd8545), WTC(0x0e69093a), WTC(0x0ed6a636), + WTC(0x0f465aea), WTC(0x0fb7d810), WTC(0x102ade99), WTC(0x109f4245), + WTC(0x1114c9e8), WTC(0x118b31bc), WTC(0x120282b8), WTC(0x127b0be1), + WTC(0x12f46b9a), WTC(0x136d8dde), WTC(0x13e57912), WTC(0x145b55cb), + WTC(0x14ce5b18), WTC(0x153dccd0), WTC(0x15a8e724), WTC(0x160edefe), + WTC(0x166f004f), WTC(0x16c8aff4), WTC(0x171b7afc), WTC(0x17673db3), + WTC(0x17afb798), WTC(0x17fc62a2), WTC(0x185114c1), WTC(0x18add722), + WTC(0x1912798d), WTC(0x197eb9a2), WTC(0x19f25657), WTC(0x1a6d113e), + WTC(0x1aeeb824), WTC(0x1b7723ab), WTC(0x1c060b77), WTC(0x1c9b09a1), + WTC(0x1d361822), WTC(0x1dd7933f), WTC(0x1e7ff592), WTC(0x1f2fd0b5), + WTC(0x1fe762a9), WTC(0x20a68700), WTC(0x216bbf5e), WTC(0x22344798), + WTC(0x22feebdb), WTC(0x23cc22a6), WTC(0x249da10b), WTC(0x25762e41), + WTC(0x2655ebc8), WTC(0x273a4e66), WTC(0x28212eaa), WTC(0x2908ff30), + WTC(0x29f2ca00), WTC(0x2ae221c4), WTC(0x2bd9c6fc), WTC(0x2cdb967e), + WTC(0x2de64c86), WTC(0x2ef61340), WTC(0x3006852b), WTC(0x31131a1b), + WTC(0x321aec79), WTC(0x3320d4ed), WTC(0x342a2cb3), WTC(0x353e77f7), + WTC(0x3660aaba), WTC(0x378ef057), WTC(0x38c42495), WTC(0x39f81cec), + WTC(0x3b250148), WTC(0x3c47960e), WTC(0x3d60c625), WTC(0x3e75864a), + WTC(0x3f8a9ef7), WTC(0x40a46d36), WTC(0x41c537d7), WTC(0x42ed2889), + WTC(0x441b52d1), WTC(0x454dc37f), WTC(0x4681e9fa), WTC(0x47b4a9fe), + WTC(0x48e39960), WTC(0x4a0d10fd), WTC(0x4b30824b), WTC(0x4c4e759e), + WTC(0x4d680b1c), WTC(0x4e7eecaa), WTC(0x4f947d1e), WTC(0x50a9d1f4), + WTC(0x51bfee19), WTC(0x52d7be4d), WTC(0x53f187eb), WTC(0x550cd3c8), + WTC(0x56270706), WTC(0x573b7c75), WTC(0x58474819), WTC(0x59496ae2), + WTC(0x5a43dfa0), WTC(0x5b3b721f), WTC(0x5c32e266), WTC(0x5d2abea1), + WTC(0x5e22b479), WTC(0x5f199f8b), WTC(0x600d9194), WTC(0x60fbe188), + WTC(0x61e289de), WTC(0x62c0520c), WTC(0x63974d1e), WTC(0x646cb022), + WTC(0x6542745a), WTC(0x66172e2f), WTC(0x66e897d0), WTC(0x67b3cc52), + WTC(0x68783ebd), WTC(0x6937b9ed), WTC(0x69f365dd), WTC(0x6aabab1a), + WTC(0x6b60849c), WTC(0x6c11876e), WTC(0x6cbe46f0), WTC(0x6d6645bc), + WTC(0xae238366), WTC(0xb047d99a), WTC(0xb26207ba), WTC(0xb4733ab5), + WTC(0xb67c9f5f), WTC(0xb87f5bce), WTC(0xba7bf18d), WTC(0xbc723dd6), + WTC(0xbe621be8), WTC(0xc04b6b3d), WTC(0xc22e00ff), WTC(0xc409a8ad), + WTC(0xc5de425b), WTC(0xc7abc2a7), WTC(0xc9721421), WTC(0xcb31173c), + WTC(0xcce8c08d), WTC(0xce991894), WTC(0xd04218cd), WTC(0xd1e3aba9), + WTC(0xd37dcf0c), WTC(0xd510942f), WTC(0xd69bfa86), WTC(0xd81fefcc), + WTC(0xd99c766d), WTC(0xdb11a570), WTC(0xdc7f806e), WTC(0xdde5f79d), + WTC(0xdf451092), WTC(0xe09ce645), WTC(0xe1ed7fff), WTC(0xe336d16a), + WTC(0xe478e4f4), WTC(0xe5b3dbbb), WTC(0xe6e7c1ac), WTC(0xe8148d53), + WTC(0xe93a4835), WTC(0xea590eb0), WTC(0xeb70e4f8), WTC(0xec81b75d), + WTC(0xed8b8b6c), WTC(0xee8e8068), WTC(0xef8aa970), WTC(0xf0800dfd), + WTC(0xf16edc4d), WTC(0xf2576853), WTC(0xf339e058), WTC(0xf4164a51), + WTC(0xf4ec8fb8), WTC(0xf5bc7cef), WTC(0xf685a697), WTC(0xf74771c9), + WTC(0xf801f31b), WTC(0xf8b5eeb1), WTC(0xf963fadb), WTC(0xfa0c7427), + WTC(0xfaaf3e0f), WTC(0xfb4bcb6d), WTC(0xfbe2276f), WTC(0xfc72f578), + WTC(0xfcfe65d9), WTC(0xfd842e5b), WTC(0xfe03e14e), WTC(0xfe7ce07d), + WTC(0xfeef932b), WTC(0xff5d0236), WTC(0xffc68fee), WTC(0x002dbccc), + WTC(0x00927c78), WTC(0x00f32cbd), WTC(0x014d7209), WTC(0x019e5f51), + WTC(0x01e550aa), WTC(0x0223fc07), WTC(0x025d2618), WTC(0x02947b12), + WTC(0x02cc33db), WTC(0x0304fa92), WTC(0x033db713), WTC(0x0373a431), + WTC(0x03a47d96), WTC(0x03ce9b0f), WTC(0x03f14dc9), WTC(0x040ce0bc), + WTC(0x042245a9), WTC(0x043309a5), WTC(0x0440981a), WTC(0x044c30f1), + WTC(0x0456bb74), WTC(0x0460c1b4), WTC(0x046a2fdd), WTC(0x0472573f), + WTC(0x047877b6), WTC(0x047bc673), WTC(0x047b8615), WTC(0x04770be2), + WTC(0x046e23fc), WTC(0x04611460), WTC(0x04507fbd), WTC(0x043d6170), + WTC(0x0428ca31), WTC(0x0413d39a), WTC(0x03feb9c3), WTC(0x03e8d946), + WTC(0x03d16667), WTC(0x03b77aba), WTC(0x039aa384), WTC(0x037ae75c), + WTC(0x0358be80), WTC(0x03350af6), WTC(0x031064fa), WTC(0x02eb13f6), + WTC(0x02c51a7b), WTC(0x029e38b0), WTC(0x027619ef), WTC(0x024c5c09), + WTC(0x02210ea3), WTC(0x01f4b19e), WTC(0x01c78f79), WTC(0x0199b8ad), + WTC(0x016b3aef), WTC(0x013c2366), WTC(0x010c7be8), WTC(0x00dc4bb5), + WTC(0x00abab29), WTC(0x007ac3e1), WTC(0x0049c02f), WTC(0x0018ca71), + WTC(0xd6208221), WTC(0xd54e9f5b), WTC(0xd47fa35f), WTC(0xd3b35bdb), + WTC(0xd2e99693), WTC(0xd2222685), WTC(0xd15d5e4c), WTC(0xd09c06ff), + WTC(0xcfde0c24), WTC(0xcf2281d2), WTC(0xce698b2a), WTC(0xcdb455e0), + WTC(0xcd02c9b7), WTC(0xcc5381e5), WTC(0xcba580c3), WTC(0xcaf839ea), + WTC(0xca4ad0b7), WTC(0xc99c2153), WTC(0xc8ec5a61), WTC(0xc83ce258), + WTC(0xc78c42cd), WTC(0xc6d6213b), WTC(0xc616a6e0), WTC(0xc54a9f27), + WTC(0xc46ee44d), WTC(0xc38058a2), WTC(0xc27bd88d), WTC(0xc15e3d07), + WTC(0xc024a4d9), WTC(0xbecc7ca2), WTC(0xbd53f2b9), WTC(0xbbba98b4), + WTC(0xba0ffbc3), WTC(0xb872fb24), WTC(0xb6f36547), WTC(0xb5915345), + WTC(0xb44c3975), WTC(0xb3238942), WTC(0xb216b3fb), WTC(0xb1252b0b), + WTC(0xb04e5fc8), WTC(0xaf91c370), WTC(0xaeeec760), WTC(0xae64dd0b), + WTC(0xadf375ce), WTC(0xad9a02f0), WTC(0xad57f5bc), WTC(0xad2cbf87), + WTC(0xad17d19d), WTC(0xad189d42), WTC(0xad2e93d6), WTC(0xad5926d3), + WTC(0xad97c78a), WTC(0xade9e726), WTC(0xae4ef6fc), WTC(0xaec6688c), + WTC(0xaf4fad2c), WTC(0xafea3605), WTC(0xb0957469), WTC(0xb150d9d2), + WTC(0xb21bd793), WTC(0xb2f5de5d), WTC(0xb3de573d), WTC(0xb4d4de47), + WTC(0xb5d89c80), WTC(0xb6e937c2), WTC(0xb8061354), WTC(0xb92ea07c), + WTC(0xba62508e), WTC(0xbba094e4), WTC(0xbce8dee0), WTC(0xbe3a9fe3), + WTC(0xbf954939), WTC(0xc0f84c11), WTC(0xc26319c2), WTC(0xc3d523c5), + WTC(0xc54ddb77), WTC(0xc6ccb217), WTC(0xc85118f8), WTC(0xc9da8182), + WTC(0xcb685d07), WTC(0xccfa1cc7), WTC(0xce8f3211), WTC(0xd0270e48), + WTC(0xd1c122c7), WTC(0xd35ce0de), WTC(0xd4f9b9e1), WTC(0xd6971f23), + WTC(0xd83481f8), WTC(0xd9d153bb), WTC(0xdb6d05c0), WTC(0xdd070956), + WTC(0xde9ecfd2), WTC(0xe033ca91), WTC(0xe1c56ae7), WTC(0xe3532223), + WTC(0xe4dc6199), WTC(0xe6609aa5), WTC(0xe7df3e9a), WTC(0xe957bec9), + WTC(0xeac98c84), WTC(0xec341927), WTC(0xed96d607), WTC(0xeef13474), + WTC(0xf042a5c5), WTC(0xf18a9b4e), WTC(0xf2c88667), WTC(0xf3fbd863), + WTC(0xf5240296), WTC(0xf6407658), WTC(0xf750a4fe), WTC(0xf853ffda), + WTC(0xf949f840), WTC(0xfa31ff83), WTC(0xfb0b86fb), WTC(0xfbd5fffe), + WTC(0xfc90dbe1), WTC(0xfd3b8bf8), WTC(0xfdd58197), WTC(0xfe5e2e14), + WTC(0xfed502c4), WTC(0xff3970fc), WTC(0xff8aea0f), WTC(0xffc8df55), + WTC(0xfff2c233), WTC(0x000804e6), WTC(0x0008256a), WTC(0xfff25358), +}; + +const FIXP_WTB LowDelaySynthesis240[720] = { + WTC(0xdaf16ba1), WTC(0xdb888d4d), WTC(0xdc212bc1), WTC(0xdcbb51d0), + WTC(0xdd5703be), WTC(0xddf43f3b), WTC(0xde92fee5), WTC(0xdf333f92), + WTC(0xdfd505d1), WTC(0xe078624a), WTC(0xe11d48ff), WTC(0xe1c39358), + WTC(0xe26b2066), WTC(0xe313d8a9), WTC(0xe3bde63c), WTC(0xe4696e45), + WTC(0xe5164d95), WTC(0xe5c4597d), WTC(0xe673596f), WTC(0xe723153c), + WTC(0xe7d35813), WTC(0xe883fa49), WTC(0xe934e7a3), WTC(0xe9e64205), + WTC(0xea984aa8), WTC(0xeb4ae6ef), WTC(0xebfdcbf6), WTC(0xecb0744b), + WTC(0xed625671), WTC(0xee133361), WTC(0xeec2e1b4), WTC(0xef715334), + WTC(0xf01e7588), WTC(0xf0ca33ec), WTC(0xf1748a4e), WTC(0xf21d83ed), + WTC(0xf2c50dbe), WTC(0xf36b0639), WTC(0xf40f4892), WTC(0xf4b1944d), + WTC(0xf5517289), WTC(0xf5ee573d), WTC(0xf687d70d), WTC(0xf71db368), + WTC(0xf7b01057), WTC(0xf83f6570), WTC(0xf8cc9d0a), WTC(0xf9585a73), + WTC(0xf9e307f8), WTC(0xfa6d44d2), WTC(0xfaf79d75), WTC(0xfb8208e8), + WTC(0xfc0c33c8), WTC(0xfc96d00c), WTC(0xfd22f257), WTC(0xfdb1e623), + WTC(0xfe4318a3), WTC(0xfed08c1d), WTC(0xff5091f1), WTC(0xffb4390a), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff62b62), WTC(0xbfe28a84), WTC(0xbfcee30d), WTC(0xbfbb3832), + WTC(0xbfa78d29), WTC(0xbf93e490), WTC(0xbf803cc6), WTC(0xbf6c9376), + WTC(0xbf58eb89), WTC(0xbf4547f8), WTC(0xbf31a6aa), WTC(0xbf1e06a3), + WTC(0xbf0a6bdf), WTC(0xbef6d863), WTC(0xbee349e5), WTC(0xbecfc145), + WTC(0xbebc4362), WTC(0xbea8d111), WTC(0xbe956806), WTC(0xbe820aeb), + WTC(0xbe6ebeb9), WTC(0xbe5b8313), WTC(0xbe485678), WTC(0xbe353cfb), + WTC(0xbe223ab8), WTC(0xbe0f4e5f), WTC(0xbdfc77b4), WTC(0xbde9bb99), + WTC(0xbdd71cbe), WTC(0xbdc4990d), WTC(0xbdb23175), WTC(0xbd9feab6), + WTC(0xbd8dc58d), WTC(0xbd7bbf8c), WTC(0xbd69daec), WTC(0xbd581c07), + WTC(0xbd46820c), WTC(0xbd350af8), WTC(0xbd23b9cc), WTC(0xbd129158), + WTC(0xbd018ece), WTC(0xbcf0b057), WTC(0xbcdff912), WTC(0xbccf69cf), + WTC(0xbcbefe81), WTC(0xbcaeb63a), WTC(0xbc9e9406), WTC(0xbc8e977c), + WTC(0xbc7ebd58), WTC(0xbc6f0544), WTC(0xbc5f7077), WTC(0xbc4ffe1d), + WTC(0xbc40ab99), WTC(0xbc317239), WTC(0xbc2252ad), WTC(0xbc136963), + WTC(0xbc04a822), WTC(0xbbf5941e), WTC(0xbbe68dab), WTC(0xbbd97a36), + WTC(0xbbcff44f), WTC(0xbbcb1891), WTC(0xbbca7818), WTC(0xbbcc765f), + WTC(0xbbcffaa5), WTC(0xbbd46a0f), WTC(0xbbda4060), WTC(0xbbe257f1), + WTC(0xbbed131c), WTC(0xbbfa7628), WTC(0xbc09cdd6), WTC(0xbc1a685b), + WTC(0xbc2bf2fd), WTC(0xbc3e6557), WTC(0xbc521d37), WTC(0xbc67c093), + WTC(0xbc803b98), WTC(0xbc9c3060), WTC(0xbcbbf6da), WTC(0xbcdf8c51), + WTC(0xbd06afb5), WTC(0xbd30e36d), WTC(0xbd5d99a0), WTC(0xbd8c71a6), + WTC(0xbdbd29c3), WTC(0xbdefb72a), WTC(0xbe243660), WTC(0xbe5b0335), + WTC(0xbe9477fd), WTC(0xbed0de00), WTC(0xbf108881), WTC(0xbf53d585), + WTC(0xbf9aeeba), WTC(0xbfe5bb38), WTC(0xc033318c), WTC(0xc081cdf2), + WTC(0xc0d0a9ee), WTC(0xc11f76d5), WTC(0xc16f66c3), WTC(0xc1c1d5c1), + WTC(0xc21726d4), WTC(0xc26f5bba), WTC(0xc2ca1036), WTC(0xc3268b0f), + WTC(0xc3839ff3), WTC(0xc3e03d22), WTC(0xc43b93ef), WTC(0xc4968594), + WTC(0xc4f3353c), WTC(0xc55202ab), WTC(0xc5b21fcf), WTC(0xc61224e6), + WTC(0xc670c168), WTC(0xc6ce3f1e), WTC(0xc72b3fbb), WTC(0xc787e688), + WTC(0xc7e41f56), WTC(0xc83f94a9), WTC(0xc899e833), WTC(0xc8f2b832), + WTC(0xb4d1fc78), WTC(0xb3a9ec70), WTC(0xb28524ca), WTC(0xb163a2ba), + WTC(0xb0456373), WTC(0xaf2a6327), WTC(0xae129708), WTC(0xacfdf2ca), + WTC(0xabec7168), WTC(0xaade0f8c), WTC(0xa9d2c80a), WTC(0xa8ca9711), + WTC(0xa7c57cdc), WTC(0xa6c37c29), WTC(0xa5c49ae6), WTC(0xa4c8e02c), + WTC(0xa3d05422), WTC(0xa2daff83), WTC(0xa1e8ec04), WTC(0xa0fa293f), + WTC(0xa00ec98a), WTC(0x9f26d990), WTC(0x9e4265a5), WTC(0x9d618437), + WTC(0x9c844ce0), WTC(0x9baad0fa), WTC(0x9ad52154), WTC(0x9a03509b), + WTC(0x993572ed), WTC(0x986b9e4d), WTC(0x97a5e7d8), WTC(0x96e46329), + WTC(0x96271ff8), WTC(0x956e2ab8), WTC(0x94b98f9c), WTC(0x94095a97), + WTC(0x935d969b), WTC(0x92b64cdf), WTC(0x9213809b), WTC(0x9175328a), + WTC(0x90db6153), WTC(0x90460712), WTC(0x8fb5146f), WTC(0x8f2876f4), + WTC(0x8ea018e5), WTC(0x8e1bd6df), WTC(0x8d9b7d9b), WTC(0x8d1ed745), + WTC(0x8ca5a942), WTC(0x8c2f93ce), WTC(0x8bbc204c), WTC(0x8b4ad58d), + WTC(0x8adb31e4), WTC(0x8a6c909b), WTC(0x89fe673d), WTC(0x8990a478), + WTC(0x89244670), WTC(0x88bc84cb), WTC(0x885e0963), WTC(0x880f73f5), + WTC(0x87cba2c0), WTC(0x87b48a6f), WTC(0x8799fb25), WTC(0x877f46f2), + WTC(0x876519cd), WTC(0x874a9a11), WTC(0x872fae01), WTC(0x871487d2), + WTC(0x86f9287b), WTC(0x86dd83b5), WTC(0x86c1947c), WTC(0x86a558f1), + WTC(0x8688d2e3), WTC(0x866c015b), WTC(0x864ede0c), WTC(0x863167cc), + WTC(0x8613a3b8), WTC(0x85f58fb2), WTC(0x85d723f0), WTC(0x85b86176), + WTC(0x85994d82), WTC(0x8579e443), WTC(0x855a201b), WTC(0x853a05b7), + WTC(0x85199a26), WTC(0x84f8d93f), WTC(0x84d7c100), WTC(0x84b65901), + WTC(0x8494a4ee), WTC(0x84729fd4), WTC(0x84504a9b), WTC(0x842dadb3), + WTC(0x840aca71), WTC(0x83e79c87), WTC(0x83c42892), WTC(0x83a07767), + WTC(0x837c883a), WTC(0x83585835), WTC(0x8333eeca), WTC(0x830f5368), + WTC(0x82ea82ec), WTC(0x82c57c57), WTC(0x82a048ea), WTC(0x827aed86), + WTC(0x82556588), WTC(0x822fb255), WTC(0x8209dd1e), WTC(0x81e3e76f), + WTC(0x81bdccac), WTC(0x81979098), WTC(0x81713ad7), WTC(0x814ac95d), + WTC(0x812437f2), WTC(0x80fd8c4b), WTC(0x80d6cc0a), WTC(0x80aff283), + WTC(0x8088fc64), WTC(0x8061eebe), WTC(0x803acfe9), WTC(0x8013a62d), + WTC(0x0a8d710a), WTC(0x0aecd974), WTC(0x0b4f7449), WTC(0x0bb4d13b), + WTC(0x0c1c7fee), WTC(0x0c86202a), WTC(0x0cf1c2e7), WTC(0x0d5f98d1), + WTC(0x0dcf816a), WTC(0x0e4162ae), WTC(0x0eb588ad), WTC(0x0f2c1e88), + WTC(0x0fa4d14f), WTC(0x101f4d80), WTC(0x109b5bfd), WTC(0x1118b908), + WTC(0x11971466), WTC(0x12168249), WTC(0x129754ab), WTC(0x1318d5c0), + WTC(0x1399b5d7), WTC(0x1418d8ec), WTC(0x14953f24), WTC(0x150dfe8a), + WTC(0x15822faa), WTC(0x15f0dd70), WTC(0x16592014), WTC(0x16ba35b2), + WTC(0x171384e7), WTC(0x1764cf1f), WTC(0x17b22a28), WTC(0x18047d40), + WTC(0x185ffc05), WTC(0x18c4a075), WTC(0x19322980), WTC(0x19a84643), + WTC(0x1a26a8f4), WTC(0x1aad099d), WTC(0x1b3b3493), WTC(0x1bd0eb32), + WTC(0x1c6db754), WTC(0x1d115a8c), WTC(0x1dbc329b), WTC(0x1e6ecb33), + WTC(0x1f29d42a), WTC(0x1feda2e4), WTC(0x20ba056e), WTC(0x218d02a2), + WTC(0x22635c75), WTC(0x233c2e7f), WTC(0x24184da1), WTC(0x24fa799d), + WTC(0x25e54e95), WTC(0x26d6edd8), WTC(0x27cc57a5), WTC(0x28c36349), + WTC(0x29bbdfdf), WTC(0x2ab9b7c2), WTC(0x2bc09790), WTC(0x2cd2d465), + WTC(0x2def4cb9), WTC(0x2f115dcc), WTC(0x3033a99c), WTC(0x3150fd8d), + WTC(0x32698a94), WTC(0x338152e6), WTC(0x34a02dcd), WTC(0x35cdedd1), + WTC(0x370aa9fa), WTC(0x38527a79), WTC(0x399c4a4f), WTC(0x3adf9c27), + WTC(0x3c17edc7), WTC(0x3d44f05d), WTC(0x3e6c519e), WTC(0x3f93ea5b), + WTC(0x40c0fc6d), WTC(0x41f60bdd), WTC(0x43332d15), WTC(0x4476e6ea), + WTC(0x45beb7e1), WTC(0x47072f2b), WTC(0x484cb71a), WTC(0x498ceafd), + WTC(0x4ac650c3), WTC(0x4bf93458), WTC(0x4d26a4c7), WTC(0x4e5090eb), + WTC(0x4f78c2ac), WTC(0x50a0918a), WTC(0x51c93995), WTC(0x52f3d6c7), + WTC(0x5420a9a2), WTC(0x554ef122), WTC(0x567ac4a9), WTC(0x579ebeb9), + WTC(0x58b8569c), WTC(0x59c74ea4), WTC(0x5ad03f31), WTC(0x5bd821c8), + WTC(0x5ce05502), WTC(0x5de8e582), WTC(0x5ef09b49), WTC(0x5ff56247), + WTC(0x60f40d81), WTC(0x61ea1450), WTC(0x62d60a2d), WTC(0x63bad7f1), + WTC(0x649e942e), WTC(0x65827556), WTC(0x66648178), WTC(0x67418c31), + WTC(0x6816c1ee), WTC(0x68e5411d), WTC(0x69aeffdb), WTC(0x6a74bb0e), + WTC(0x6b36a5ae), WTC(0x6bf44fd1), WTC(0x6cad341f), WTC(0x6d60c0ca), + WTC(0xae35f79b), WTC(0xb07e1b0d), WTC(0xb2bad26d), WTC(0xb4ed8af7), + WTC(0xb717b207), WTC(0xb93a8f5b), WTC(0xbb56631e), WTC(0xbd6afcab), + WTC(0xbf7832db), WTC(0xc17dd996), WTC(0xc37bb355), WTC(0xc5718d72), + WTC(0xc75f56cc), WTC(0xc944f93d), WTC(0xcb224f17), WTC(0xccf74805), + WTC(0xcec3ed8c), WTC(0xd08835d9), WTC(0xd2440837), WTC(0xd3f7692d), + WTC(0xd5a26b17), WTC(0xd74502b6), WTC(0xd8df1f82), WTC(0xda70d495), + WTC(0xdbfa35a1), WTC(0xdd7b3498), WTC(0xdef3cba3), WTC(0xe064184e), + WTC(0xe1cc2ab9), WTC(0xe32bf548), WTC(0xe48381cd), WTC(0xe5d2f779), + WTC(0xe71a6218), WTC(0xe859b789), WTC(0xe9910a60), WTC(0xeac07956), + WTC(0xebe7fb55), WTC(0xed077f41), WTC(0xee1f1f9d), WTC(0xef2efd99), + WTC(0xf0372472), WTC(0xf137b605), WTC(0xf23112b3), WTC(0xf323808a), + WTC(0xf40f0a86), WTC(0xf4f39883), WTC(0xf5d0eb3c), WTC(0xf6a679c6), + WTC(0xf7739640), WTC(0xf8389849), WTC(0xf8f66b2a), WTC(0xf9ada7d6), + WTC(0xfa5e97ed), WTC(0xfb08becd), WTC(0xfbabb380), WTC(0xfc48125f), + WTC(0xfcde5b40), WTC(0xfd6e4aac), WTC(0xfdf76560), WTC(0xfe78f3ab), + WTC(0xfef34cf0), WTC(0xff67b689), WTC(0xffd7e342), WTC(0x004584ef), + WTC(0x00b00074), WTC(0x01152d47), WTC(0x0171ccea), WTC(0x01c2fdbe), + WTC(0x0209b563), WTC(0x02489832), WTC(0x0283e2cd), WTC(0x02bf2050), + WTC(0x02fb72fb), WTC(0x03381f29), WTC(0x0371ea7c), WTC(0x03a602f3), + WTC(0x03d267e0), WTC(0x03f6621b), WTC(0x04125dc8), WTC(0x0427b7a5), + WTC(0x04385062), WTC(0x0445caca), WTC(0x04518ee3), WTC(0x045c745e), + WTC(0x0466d714), WTC(0x0470125c), WTC(0x047742d7), WTC(0x047b73cf), + WTC(0x047bba82), WTC(0x047744aa), WTC(0x046dc536), WTC(0x045f9068), + WTC(0x044d7632), WTC(0x0438aa92), WTC(0x04227f39), WTC(0x040c2331), + WTC(0x03f561d8), WTC(0x03dd60b4), WTC(0x03c31064), WTC(0x03a58d7d), + WTC(0x0384b74f), WTC(0x0360e29a), WTC(0x033b1151), WTC(0x031417f0), + WTC(0x02ec54ca), WTC(0x02c3d2ce), WTC(0x029a458d), WTC(0x026f4411), + WTC(0x02426093), WTC(0x0213d67f), WTC(0x01e43b01), WTC(0x01b3c7c1), + WTC(0x01828dd8), WTC(0x01509d92), WTC(0x011e0556), WTC(0x00eace1d), + WTC(0x00b70bb3), WTC(0x0082ed8b), WTC(0x004ea707), WTC(0x001a6b8f), + WTC(0xd619769b), WTC(0xd539cbf6), WTC(0xd45d68b9), WTC(0xd3840fce), + WTC(0xd2ad840b), WTC(0xd1d9a580), WTC(0xd1092160), WTC(0xd03cacdc), + WTC(0xcf7383ba), WTC(0xceacfd46), WTC(0xcdea429a), WTC(0xcd2bf5ec), + WTC(0xcc709dc1), WTC(0xcbb6dc91), WTC(0xcafdff71), WTC(0xca4504cd), + WTC(0xc98a93f4), WTC(0xc8cf0eb0), WTC(0xc813ee7f), WTC(0xc75665f3), + WTC(0xc6912d63), WTC(0xc5bff74a), WTC(0xc4dee9fa), WTC(0xc3ea39ef), + WTC(0xc2de1c94), WTC(0xc1b6bd08), WTC(0xc07074da), WTC(0xbf081038), + WTC(0xbd7b166b), WTC(0xbbc8afd7), WTC(0xba01d47c), WTC(0xb84b481f), + WTC(0xb6b65953), WTC(0xb542e5d2), WTC(0xb3f04291), WTC(0xb2bdc25a), + WTC(0xb1aab810), WTC(0xb0b676a0), WTC(0xafe050d5), WTC(0xaf27997d), + WTC(0xae8ba390), WTC(0xae0bc202), WTC(0xada7479d), WTC(0xad5d872f), + WTC(0xad2dd392), WTC(0xad177f97), WTC(0xad19de04), WTC(0xad3441c5), + WTC(0xad65fddc), WTC(0xadae6514), WTC(0xae0cca18), WTC(0xae807fde), + WTC(0xaf08d967), WTC(0xafa5296f), WTC(0xb054c2ac), WTC(0xb116f81b), + WTC(0xb1eb1cb1), WTC(0xb2d082fe), WTC(0xb3c677e5), WTC(0xb4cc6e9c), + WTC(0xb5e17eb4), WTC(0xb7052956), WTC(0xb836b427), WTC(0xb97571f3), + WTC(0xbac0b594), WTC(0xbc17d1ee), WTC(0xbd7a19eb), WTC(0xbee6e071), + WTC(0xc05d7837), WTC(0xc1dd33fe), WTC(0xc36566c2), WTC(0xc4f56377), + WTC(0xc68c7ce5), WTC(0xc82a05db), WTC(0xc9cd5148), WTC(0xcb75b207), + WTC(0xcd227ad9), WTC(0xced2fe95), WTC(0xd0869026), WTC(0xd23c8268), + WTC(0xd3f42834), WTC(0xd5acd460), WTC(0xd765d9c5), WTC(0xd91e8b42), + WTC(0xdad63bb5), WTC(0xdc8c3df2), WTC(0xde3fe4d1), WTC(0xdff08333), + WTC(0xe19d6bf6), WTC(0xe345f1ee), WTC(0xe4e967f3), WTC(0xe68720e7), + WTC(0xe81e6fa3), WTC(0xe9aea6fb), WTC(0xeb3719cb), WTC(0xecb71af3), + WTC(0xee2dfd4b), WTC(0xef9b13ab), WTC(0xf0fdb0ee), WTC(0xf25527f1), + WTC(0xf3a0cb8e), WTC(0xf4dfee9f), WTC(0xf611e3ff), WTC(0xf735fe8b), + WTC(0xf84b911a), WTC(0xf951ee85), WTC(0xfa4869a5), WTC(0xfb2e5557), + WTC(0xfc030477), WTC(0xfcc5c9e0), WTC(0xfd75f86b), WTC(0xfe12e2f2), + WTC(0xfe9bdc51), WTC(0xff103761), WTC(0xff6f46fc), WTC(0xffb85dfe), + WTC(0xffeacf42), WTC(0x0005ee03), WTC(0x0009162b), WTC(0xfff368d1), +}; + +const FIXP_WTB LowDelaySynthesis160[480] = { + WTC(0xdb171130), WTC(0xdbfadfbd), WTC(0xdce2192a), WTC(0xddcccbc8), + WTC(0xdebaeb0c), WTC(0xdfac6ebd), WTC(0xe0a17875), WTC(0xe199e10c), + WTC(0xe29531fd), WTC(0xe3933ef6), WTC(0xe49487be), WTC(0xe598bcf5), + WTC(0xe69f38b0), WTC(0xe7a73d45), WTC(0xe8b02e94), WTC(0xe9b9dc97), + WTC(0xeac4e62c), WTC(0xebd111fc), WTC(0xecdd0242), WTC(0xede7178d), + WTC(0xeeee9c24), WTC(0xeff34dba), WTC(0xf0f4eaf5), WTC(0xf1f36695), + WTC(0xf2eeb2b2), WTC(0xf3e663cb), WTC(0xf4d9cbfe), WTC(0xf5c76b3c), + WTC(0xf6ada4cb), WTC(0xf78bc92d), WTC(0xf862dc57), WTC(0xf93589ca), + WTC(0xfa059b44), WTC(0xfad501fc), WTC(0xfba49819), WTC(0xfc740f58), + WTC(0xfd465b6d), WTC(0xfe1ee06f), WTC(0xfef2581b), WTC(0xff9ec7d9), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff143f6), WTC(0xbfd3cd5c), WTC(0xbfb64d54), WTC(0xbf98ce80), + WTC(0xbf7b5291), WTC(0xbf5dd523), WTC(0xbf405f8e), WTC(0xbf22ee55), + WTC(0xbf058664), WTC(0xbee82d22), WTC(0xbecae0a1), WTC(0xbeadacb5), + WTC(0xbe908f68), WTC(0xbe73901d), WTC(0xbe56b673), WTC(0xbe3a013e), + WTC(0xbe1d7dad), WTC(0xbe012b19), WTC(0xbde51134), WTC(0xbdc93781), + WTC(0xbdad9c88), WTC(0xbd924bd8), WTC(0xbd774311), WTC(0xbd5c882b), + WTC(0xbd4220fa), WTC(0xbd280a49), WTC(0xbd0e4d50), WTC(0xbcf4e46e), + WTC(0xbcdbd1a4), WTC(0xbcc31624), WTC(0xbcaaaa02), WTC(0xbc929348), + WTC(0xbc7acc12), WTC(0xbc63525e), WTC(0xbc4c26b1), WTC(0xbc353ea9), + WTC(0xbc1e91e2), WTC(0xbc085aea), WTC(0xbbf1c04a), WTC(0xbbdc7521), + WTC(0xbbce4740), WTC(0xbbca5187), WTC(0xbbcd3a7c), WTC(0xbbd33634), + WTC(0xbbdc0a34), WTC(0xbbea218a), WTC(0xbbfe25b7), WTC(0xbc162887), + WTC(0xbc3076c5), WTC(0xbc4d09f6), WTC(0xbc6d925c), WTC(0xbc94da6e), + WTC(0xbcc48300), WTC(0xbcfc9763), WTC(0xbd3bd94f), WTC(0xbd808d05), + WTC(0xbdc9a11b), WTC(0xbe16e339), WTC(0xbe691db9), WTC(0xbec179c1), + WTC(0xbf210140), WTC(0xbf88cd62), WTC(0xbff8e8d3), WTC(0xc06e1aaa), + WTC(0xc0e45951), WTC(0xc15b3820), WTC(0xc1d6e2ff), WTC(0xc2590e0a), + WTC(0xc2e10f83), WTC(0xc36c5c9a), WTC(0xc3f735f3), WTC(0xc47fb2d1), + WTC(0xc50abce5), WTC(0xc59a0a25), WTC(0xc629f21c), WTC(0xc6b6ef89), + WTC(0xc7427180), WTC(0xc7cd1fc4), WTC(0xc856485f), WTC(0xc8dcae93), + WTC(0xb487a986), WTC(0xb2ce0812), WTC(0xb11bc4c2), WTC(0xaf70d5cb), + WTC(0xadcd228e), WTC(0xac3086a2), WTC(0xaa9af36b), WTC(0xa90c5935), + WTC(0xa784b214), WTC(0xa60407e9), WTC(0xa48a7076), WTC(0xa31806f9), + WTC(0xa1aceb03), WTC(0xa0494f63), WTC(0x9eed6840), WTC(0x9d996570), + WTC(0x9c4d93b4), WTC(0x9b0a3114), WTC(0x99cf798d), WTC(0x989db16a), + WTC(0x97752146), WTC(0x965609f1), WTC(0x95409b05), WTC(0x9434fda9), + WTC(0x9333587b), WTC(0x923bc7d6), WTC(0x914e5299), WTC(0x906af345), + WTC(0x8f9185e6), WTC(0x8ec1cbe9), WTC(0x8dfb64c9), WTC(0x8d3dab18), + WTC(0x8c87de34), WTC(0x8bd8c494), WTC(0x8b2ecacc), WTC(0x8a882a5f), + WTC(0x89e2ecd1), WTC(0x893f12b2), WTC(0x88a3c878), WTC(0x882141c7), + WTC(0x87c65dcd), WTC(0x87a0c07b), WTC(0x8778b859), WTC(0x87514698), + WTC(0x8728e900), WTC(0x87000679), WTC(0x86d68f05), WTC(0x86ac6ee7), + WTC(0x8681a5ce), WTC(0x86562ed0), WTC(0x8629fdeb), WTC(0x85fd1ca8), + WTC(0x85cf7b32), WTC(0x85a11a2f), WTC(0x8571fbbe), WTC(0x854213f5), + WTC(0x8511722b), WTC(0x84e00ee3), WTC(0x84adf346), WTC(0x847b28e5), + WTC(0x8447a9d0), WTC(0x84138a20), WTC(0x83dec5b6), WTC(0x83a9694f), + WTC(0x83738231), WTC(0x833d0def), WTC(0x8306247b), WTC(0x82cec29b), + WTC(0x8296f5f3), WTC(0x825ecbe4), WTC(0x82263fe8), WTC(0x81ed682f), + WTC(0x81b4406d), WTC(0x817ad2a1), WTC(0x814127f4), WTC(0x8107392d), + WTC(0x80cd184d), WTC(0x8092bc5f), WTC(0x80582866), WTC(0x801d714f), + WTC(0x0aa4f846), WTC(0x0b3686fe), WTC(0x0bce899e), WTC(0x0c6b8a7e), + WTC(0x0d0d036f), WTC(0x0db358b8), WTC(0x0e5e31dd), WTC(0x0f0e4270), + WTC(0x0fc347c1), WTC(0x107c35cc), WTC(0x11383a63), WTC(0x11f68759), + WTC(0x12b7b1e3), WTC(0x13799d61), WTC(0x14383db4), WTC(0x14f032c0), + WTC(0x159e6920), WTC(0x163fb449), WTC(0x16d14820), WTC(0x17512c3f), + WTC(0x17c5f622), WTC(0x18483f2a), WTC(0x18df3074), WTC(0x1989f589), + WTC(0x1a4783af), WTC(0x1b16f152), WTC(0x1bf7795a), WTC(0x1ce7c950), + WTC(0x1de817ec), WTC(0x1efa3f4a), WTC(0x201ff37a), WTC(0x2157d4e1), + WTC(0x22995036), WTC(0x23e0d882), WTC(0x25345db2), WTC(0x269a10c3), + WTC(0x280a0798), WTC(0x297d6cf9), WTC(0x2afa7e1b), WTC(0x2c8d210a), + WTC(0x2e377db2), WTC(0x2feb60cc), WTC(0x31977111), WTC(0x333b1637), + WTC(0x34ea14df), WTC(0x36ba32d4), WTC(0x38a524c8), WTC(0x3a8fa891), + WTC(0x3c640cb3), WTC(0x3e22ab11), WTC(0x3fde7cc9), WTC(0x41a80486), + WTC(0x438394e4), WTC(0x456c8d8f), WTC(0x4758f4da), WTC(0x493d7a7b), + WTC(0x4b139f32), WTC(0x4cdbb199), WTC(0x4e9ab8d1), WTC(0x50569530), + WTC(0x5213a89e), WTC(0x53d5462c), WTC(0x559a5aa7), WTC(0x5756acf5), + WTC(0x58fcfb38), WTC(0x5a8e3e07), WTC(0x5c1a20e8), WTC(0x5da6c7da), + WTC(0x5f3231f3), WTC(0x60b51fb6), WTC(0x62260848), WTC(0x6381f5a9), + WTC(0x64d79ac7), WTC(0x662c51c0), WTC(0x67779c07), WTC(0x68b22184), + WTC(0x69e0ca28), WTC(0x6b068bcf), WTC(0x6c23008e), WTC(0x6d346856), + WTC(0xaec92693), WTC(0xb22ca2bd), WTC(0xb578d421), WTC(0xb8b27edb), + WTC(0xbbdc38b5), WTC(0xbef598bb), WTC(0xc1fe0dcd), WTC(0xc4f4d7ff), + WTC(0xc7d98479), WTC(0xcaabc289), WTC(0xcd6b38f6), WTC(0xd017edff), + WTC(0xd2b1aa37), WTC(0xd538739f), WTC(0xd7ac554d), WTC(0xda0d2f5e), + WTC(0xdc5b3f69), WTC(0xde966e30), WTC(0xe0bee2c8), WTC(0xe2d4c9cd), + WTC(0xe4d82000), WTC(0xe6c94926), WTC(0xe8a84b14), WTC(0xea755ac3), + WTC(0xec309bdc), WTC(0xedd9f2a8), WTC(0xef71c040), WTC(0xf0f842ad), + WTC(0xf26e53cb), WTC(0xf3d4cd9f), WTC(0xf52b9ddf), WTC(0xf671db4d), + WTC(0xf7a58faa), WTC(0xf8c79907), WTC(0xf9da7c73), WTC(0xfadee240), + WTC(0xfbd360e6), WTC(0xfcb95db4), WTC(0xfd913bb1), WTC(0xfe594e2e), + WTC(0xff10e67c), WTC(0xffbc2326), WTC(0x00608350), WTC(0x00fc8a2d), + WTC(0x01873313), WTC(0x01f8e4fe), WTC(0x02579318), WTC(0x02b03ec3), + WTC(0x030ab2da), WTC(0x0363ea2a), WTC(0x03b1e60d), WTC(0x03ee2920), + WTC(0x0418405c), WTC(0x04348449), WTC(0x0448d9f7), WTC(0x0459c65f), + WTC(0x04694a29), WTC(0x0475b506), WTC(0x047bebeb), WTC(0x0478dcd2), + WTC(0x046aa475), WTC(0x045249a9), WTC(0x043332f0), WTC(0x0411bb77), + WTC(0x03ef893b), WTC(0x03c9ebb8), WTC(0x039da778), WTC(0x036a1273), + WTC(0x03316a60), WTC(0x02f6553a), WTC(0x02b98be9), WTC(0x027a2e2c), + WTC(0x0236df64), WTC(0x01f036bf), WTC(0x01a78b41), WTC(0x015d29da), + WTC(0x01114624), WTC(0x00c406e9), WTC(0x0075ddb1), WTC(0x00277692), + WTC(0xd5e139e9), WTC(0xd494362e), WTC(0xd34e2bff), WTC(0xd20e56f8), + WTC(0xd0d5a3dc), WTC(0xcfa5904f), WTC(0xce7be3cb), WTC(0xcd5b3086), + WTC(0xcc420f0f), WTC(0xcb2c2bf6), WTC(0xca1695c3), WTC(0xc8fdf020), + WTC(0xc7e4fc07), WTC(0xc6c374c6), WTC(0xc5895653), WTC(0xc4297218), + WTC(0xc296f958), WTC(0xc0c51a3c), WTC(0xbea84ee5), WTC(0xbc38842f), + WTC(0xb9915966), WTC(0xb7186ae5), WTC(0xb4eb3040), WTC(0xb3076897), + WTC(0xb16acba3), WTC(0xb013112a), WTC(0xaefdf0a2), WTC(0xae2921f5), + WTC(0xad925cd6), WTC(0xad3758be), WTC(0xad15cd3d), WTC(0xad2b71ca), + WTC(0xad75fe65), WTC(0xadf32a84), WTC(0xaea0ada9), WTC(0xaf7c3fcd), + WTC(0xb0839825), WTC(0xb1b46e9c), WTC(0xb30c7a20), WTC(0xb48970be), + WTC(0xb62912e0), WTC(0xb7e90de7), WTC(0xb9c71d12), WTC(0xbbc0f7fd), + WTC(0xbdd45674), WTC(0xbffef022), WTC(0xc23e7c49), WTC(0xc490b2d4), + WTC(0xc6f34b70), WTC(0xc963fda9), WTC(0xcbe0813e), WTC(0xce668d98), + WTC(0xd0f3da69), WTC(0xd3861f64), WTC(0xd61b141f), WTC(0xd8b07038), + WTC(0xdb43eb5d), WTC(0xddd33d22), WTC(0xe05c1d2e), WTC(0xe2dc432c), + WTC(0xe55166ad), WTC(0xe7b93f62), WTC(0xea1184df), WTC(0xec57eec9), + WTC(0xee8a34c6), WTC(0xf0a60e70), WTC(0xf2a9336e), WTC(0xf4915b60), + WTC(0xf65c3dea), WTC(0xf80792ae), WTC(0xf9911147), WTC(0xfaf67154), + WTC(0xfc356a7e), WTC(0xfd4bb465), WTC(0xfe3706a9), WTC(0xfef518ec), + WTC(0xff83a2cf), WTC(0xffe05bed), WTC(0x0008fd26), WTC(0xfffb4037), +}; + +const FIXP_WTB LowDelaySynthesis128[384] = { + WTC(0xdb335c78), WTC(0xdc512d40), WTC(0xdd746116), WTC(0xde9cf7ae), + WTC(0xdfcadda8), WTC(0xe0fe4196), WTC(0xe236a409), WTC(0xe373518f), + WTC(0xe4b4e870), WTC(0xe5faf25e), WTC(0xe744190a), WTC(0xe88f06f4), + WTC(0xe9db2796), WTC(0xeb29613f), WTC(0xec78b08e), WTC(0xedc5f65d), + WTC(0xef0f5af4), WTC(0xf05447dd), WTC(0xf1945392), WTC(0xf2cf795a), + WTC(0xf405123d), WTC(0xf533af3d), WTC(0xf65842dd), WTC(0xf77071ae), + WTC(0xf87d623f), WTC(0xf983c711), WTC(0xfa8730ce), WTC(0xfb8aad4b), + WTC(0xfc8e1dc6), WTC(0xfd96d19a), WTC(0xfea5325a), WTC(0xff8d21da), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbfed9606), WTC(0xbfc8bddf), WTC(0xbfa3dd57), WTC(0xbf7f023c), + WTC(0xbf5a25e8), WTC(0xbf3554df), WTC(0xbf108b6b), WTC(0xbeebd7bd), + WTC(0xbec738a6), WTC(0xbea2bf45), WTC(0xbe7e6b42), WTC(0xbe5a4fd5), + WTC(0xbe366de8), WTC(0xbe12d91e), WTC(0xbdef9338), WTC(0xbdccaf6e), + WTC(0xbdaa2e3f), WTC(0xbd88205e), WTC(0xbd668430), WTC(0xbd456994), + WTC(0xbd24cdad), WTC(0xbd04bc91), WTC(0xbce52def), WTC(0xbcc62942), + WTC(0xbca7a273), WTC(0xbc899fba), WTC(0xbc6c16ab), WTC(0xbc4f0812), + WTC(0xbc326537), WTC(0xbc162fb3), WTC(0xbbfa5915), WTC(0xbbded462), + WTC(0xbbcd3956), WTC(0xbbcae0f5), WTC(0xbbd0beb7), WTC(0xbbdaaf42), + WTC(0xbbec5289), WTC(0xbc06d115), WTC(0xbc266162), WTC(0xbc494d27), + WTC(0xbc721013), WTC(0xbca5b2d9), WTC(0xbce6a063), WTC(0xbd339d3d), + WTC(0xbd8975b2), WTC(0xbde618b1), WTC(0xbe499de1), WTC(0xbeb60feb), + WTC(0xbf2d830e), WTC(0xbfb1ee2e), WTC(0xc041e22f), WTC(0xc0d59618), + WTC(0xc16a574d), WTC(0xc206ed94), WTC(0xc2ad7ad1), WTC(0xc35ae733), + WTC(0xc4085fbf), WTC(0xc4b33a35), WTC(0xc563f6ce), WTC(0xc6181ab7), + WTC(0xc6c86beb), WTC(0xc7768de4), WTC(0xc8231ab3), WTC(0xc8cc145a), + WTC(0xb4500dde), WTC(0xb22a524e), WTC(0xb010144c), WTC(0xae013530), + WTC(0xabfd7206), WTC(0xaa04a92f), WTC(0xa816c008), WTC(0xa633baab), + WTC(0xa45bbe2b), WTC(0xa28eff5e), WTC(0xa0cdc4c6), WTC(0x9f187801), + WTC(0x9d6f7708), WTC(0x9bd34eb0), WTC(0x9a44763a), WTC(0x98c36ace), + WTC(0x9750b896), WTC(0x95ecdc61), WTC(0x94982f8c), WTC(0x9353005a), + WTC(0x921d8bac), WTC(0x90f7e126), WTC(0x8fe1e828), WTC(0x8edb3ddc), + WTC(0x8de337c8), WTC(0x8cf89cdb), WTC(0x8c19be6d), WTC(0x8b43d072), + WTC(0x8a737663), WTC(0x89a52f4d), WTC(0x88dc38e8), WTC(0x882f6f3f), + WTC(0x87c22c55), WTC(0x87918a21), WTC(0x87602c61), WTC(0x872dfd0a), + WTC(0x86fae063), WTC(0x86c6d729), WTC(0x8691c4ad), WTC(0x865ba7e8), + WTC(0x86246b66), WTC(0x85ec17ab), WTC(0x85b293e2), WTC(0x8577eaac), + WTC(0x853c09be), WTC(0x84ff042d), WTC(0x84c0d195), WTC(0x84818c4c), + WTC(0x84412e63), WTC(0x83ffd42c), WTC(0x83bd7bdf), WTC(0x837a471b), + WTC(0x833636dc), WTC(0x82f16e48), WTC(0x82abed37), WTC(0x8265d6c4), + WTC(0x821f28cf), WTC(0x81d80322), WTC(0x8190625c), WTC(0x81486134), + WTC(0x80fff7a0), WTC(0x80b73d86), WTC(0x806e2527), WTC(0x8024c969), + WTC(0x0ab6c2d2), WTC(0x0b6edac2), WTC(0x0c302988), WTC(0x0cf88fab), + WTC(0x0dc87461), WTC(0x0e9f9122), WTC(0x0f7ee53f), WTC(0x1064e7bf), + WTC(0x114fe4b7), WTC(0x123e9e4c), WTC(0x13311589), WTC(0x1420b664), + WTC(0x15069245), WTC(0x15dc93ad), WTC(0x169caf41), WTC(0x17422e16), + WTC(0x17d51de4), WTC(0x187e7622), WTC(0x1947aa0b), WTC(0x1a2ed3b4), + WTC(0x1b321858), WTC(0x1c4fcc7f), WTC(0x1d8601a3), WTC(0x1ed6ec5e), + WTC(0x20460b07), WTC(0x21cfbf59), WTC(0x23652732), WTC(0x2508e4b1), + WTC(0x26c7b0a6), WTC(0x289505da), WTC(0x2a698dd8), WTC(0x2c5954d2), + WTC(0x2e6dd135), WTC(0x308d838f), WTC(0x329de377), WTC(0x34b28f13), + WTC(0x36f67988), WTC(0x395ec1e5), WTC(0x3bb7b587), WTC(0x3deb63cc), + WTC(0x4016b320), WTC(0x42584eb2), WTC(0x44b424ca), WTC(0x471ba5b2), + WTC(0x49791954), WTC(0x4bc02004), WTC(0x4df3b8c0), WTC(0x501f1e1e), + WTC(0x524b93e2), WTC(0x547f0eef), WTC(0x56b23d03), WTC(0x58c99052), + WTC(0x5abfc042), WTC(0x5caebf1a), WTC(0x5e9e618b), WTC(0x608595d7), + WTC(0x62528e67), WTC(0x6401eb53), WTC(0x65ad0eb1), WTC(0x674f1cd2), + WTC(0x68d8804e), WTC(0x6a4ff10e), WTC(0x6bb987a5), WTC(0x6d12e937), + WTC(0xaf370652), WTC(0xb36badcf), WTC(0xb77ec321), WTC(0xbb77e364), + WTC(0xbf57979e), WTC(0xc31cb589), WTC(0xc6c5e686), WTC(0xca52811d), + WTC(0xcdc1d66b), WTC(0xd113d0f0), WTC(0xd4481c98), WTC(0xd75ee41b), + WTC(0xda57f7bf), WTC(0xdd33a926), WTC(0xdff1e272), WTC(0xe2931227), + WTC(0xe5174232), WTC(0xe77f0b15), WTC(0xe9ca889d), WTC(0xebfa2f7c), + WTC(0xee0de002), WTC(0xf0063326), WTC(0xf1e3e5f1), WTC(0xf3a8d749), + WTC(0xf5555599), WTC(0xf6e77eb2), WTC(0xf85cb5d6), WTC(0xf9b8e64d), + WTC(0xfafe52ad), WTC(0xfc2b37b8), WTC(0xfd420467), WTC(0xfe41412c), + WTC(0xff26ded5), WTC(0xfffa6150), WTC(0x00c374a4), WTC(0x01773884), + WTC(0x02058de3), WTC(0x0278d689), WTC(0x02e87372), WTC(0x03593268), + WTC(0x03ba79ab), WTC(0x03fff32b), WTC(0x042b2341), WTC(0x044690de), + WTC(0x045bc96a), WTC(0x046e77e9), WTC(0x047a85c1), WTC(0x0479d8c4), + WTC(0x04681aec), WTC(0x0447318f), WTC(0x041e4d13), WTC(0x03f3edad), + WTC(0x03c4cc17), WTC(0x038b1f6f), WTC(0x03470909), WTC(0x02fdcebd), + WTC(0x02b1cb18), WTC(0x0261730d), WTC(0x020afad0), WTC(0x01b0b9c8), + WTC(0x0153c1a0), WTC(0x00f47426), WTC(0x00933db7), WTC(0x003140e9), + WTC(0xd5b730bf), WTC(0xd4192c32), WTC(0xd2859479), WTC(0xd0fc3b9d), + WTC(0xcf800352), WTC(0xce0e6ab3), WTC(0xccaaf25f), WTC(0xcb4ed003), + WTC(0xc9f3ae44), WTC(0xc8948a56), WTC(0xc73226fd), WTC(0xc5b2676a), + WTC(0xc3fa2a82), WTC(0xc1f05f70), WTC(0xbf7c884b), WTC(0xbc8b1e86), + WTC(0xb93e1633), WTC(0xb63eb483), WTC(0xb3b45d14), WTC(0xb19a8ee2), + WTC(0xafecd4aa), WTC(0xaea6b8e7), WTC(0xadc3c6bf), WTC(0xad3f88ac), + WTC(0xad158929), WTC(0xad4152b1), WTC(0xadbe7068), WTC(0xae886c76), + WTC(0xaf9ad1fe), WTC(0xb0f12b26), WTC(0xb2870347), WTC(0xb457d633), + WTC(0xb65f592c), WTC(0xb898eca0), WTC(0xbb00291b), WTC(0xbd90996b), + WTC(0xc045c861), WTC(0xc31b4022), WTC(0xc60c8bd5), WTC(0xc91535f2), + WTC(0xcc30c94c), WTC(0xcf5ad039), WTC(0xd28ed58a), WTC(0xd5c863e5), + WTC(0xd90305e6), WTC(0xdc3a4644), WTC(0xdf69af93), WTC(0xe28ccc93), + WTC(0xe59f27d7), WTC(0xe89c4c15), WTC(0xeb7fc3e3), WTC(0xee4519f7), + WTC(0xf0e7d8ed), WTC(0xf3638b73), WTC(0xf5b3bc30), WTC(0xf7d3f5d0), + WTC(0xf9bfc2f0), WTC(0xfb72ae35), WTC(0xfce84251), WTC(0xfe1c09e5), + WTC(0xff098f9a), WTC(0xffac5e15), WTC(0xffffffb2), WTC(0x0000159b), +}; + +const FIXP_WTB LowDelaySynthesis120[360] = { + WTC(0xdb3ccdcd), WTC(0xdc6e0d69), WTC(0xdda570a7), WTC(0xdee2ef33), + WTC(0xe02680f4), WTC(0xe1704397), WTC(0xe2bf5626), WTC(0xe4137c80), + WTC(0xe56d30cd), WTC(0xe6cb22fe), WTC(0xe82b9f14), WTC(0xe98d8220), + WTC(0xeaf18a17), WTC(0xec57328f), WTC(0xedbae901), WTC(0xef1a42b9), + WTC(0xf07481f7), WTC(0xf1c932d4), WTC(0xf3183e19), WTC(0xf460b35f), + WTC(0xf5a04ac7), WTC(0xf6d33845), WTC(0xf7f80ec0), WTC(0xf912a5cd), + WTC(0xfa282a2e), WTC(0xfb3cd81c), WTC(0xfc51629b), WTC(0xfd69f81f), + WTC(0xfe8abdeb), WTC(0xff86f173), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbfec5bfa), WTC(0xbfc50dd8), WTC(0xbf9db88b), WTC(0xbf76683c), + WTC(0xbf4f1944), WTC(0xbf27d649), WTC(0xbf00a158), WTC(0xbed9848c), + WTC(0xbeb288f1), WTC(0xbe8bb79f), WTC(0xbe651f00), WTC(0xbe3ec6f8), + WTC(0xbe18c1f6), WTC(0xbdf315fe), WTC(0xbdcdd79d), WTC(0xbda909c1), + WTC(0xbd84beae), WTC(0xbd60f6ab), WTC(0xbd3dc210), WTC(0xbd1b2093), + WTC(0xbcf91ae9), WTC(0xbcd7acab), WTC(0xbcb6d5cc), WTC(0xbc969143), + WTC(0xbc76dcf4), WTC(0xbc57b317), WTC(0xbc390c4d), WTC(0xbc1ad514), + WTC(0xbbfd2fdb), WTC(0xbbdfa548), WTC(0xbbcce946), WTC(0xbbcb39d9), + WTC(0xbbd214cf), WTC(0xbbddfb60), WTC(0xbbf3783e), WTC(0xbc11f8d2), + WTC(0xbc3509f8), WTC(0xbc5ca2b0), WTC(0xbc8dc0b0), WTC(0xbccd4b2f), + WTC(0xbd1b7107), WTC(0xbd74c6a4), WTC(0xbdd635c0), WTC(0xbe3f4cd7), + WTC(0xbeb24836), WTC(0xbf31b5df), WTC(0xbfbfe6e2), WTC(0xc05a6dbf), + WTC(0xc0f80700), WTC(0xc198449c), WTC(0xc242ea15), WTC(0xc2f8270d), + WTC(0xc3b20bd2), WTC(0xc468f554), WTC(0xc522637e), WTC(0xc5e2403b), + WTC(0xc69f9771), WTC(0xc7599dd5), WTC(0xc811f85a), WTC(0xc8c687db), + WTC(0xb43d8b3b), WTC(0xb1f3fb3c), WTC(0xafb77be9), WTC(0xad87e063), + WTC(0xab64dcd5), WTC(0xa94e4cc2), WTC(0xa74418f8), WTC(0xa5465837), + WTC(0xa3554252), WTC(0xa1711f59), WTC(0x9f9a62f5), WTC(0x9dd18104), + WTC(0x9c17167e), WTC(0x9a6bbbe9), WTC(0x98d0061c), WTC(0x97449e23), + WTC(0x95ca1ad6), WTC(0x9460e7a1), WTC(0x93096222), WTC(0x91c3c9da), + WTC(0x90902633), WTC(0x8f6e3c5f), WTC(0x8e5d7788), WTC(0x8d5cb789), + WTC(0x8c6a42d5), WTC(0x8b833d6f), WTC(0x8aa3cc10), WTC(0x89c7789a), + WTC(0x88ef9802), WTC(0x883452c3), WTC(0x87c0bb9a), WTC(0x878c8326), + WTC(0x8757eb4c), WTC(0x87222119), WTC(0x86eb5f31), WTC(0x86b3802c), + WTC(0x867a73ee), WTC(0x86402cf8), WTC(0x8604a439), WTC(0x85c7cd22), + WTC(0x8589a40b), WTC(0x854a1d2f), WTC(0x850944c1), WTC(0x84c71670), + WTC(0x8483acc8), WTC(0x843f04b6), WTC(0x83f93cd9), WTC(0x83b2576c), + WTC(0x836a7812), WTC(0x8321a764), WTC(0x82d805e8), WTC(0x828da076), + WTC(0x824290c3), WTC(0x81f6e6a8), WTC(0x81aab23c), WTC(0x815e05f8), + WTC(0x8110e4d6), WTC(0x80c362df), WTC(0x8075781d), WTC(0x80273c0c), + WTC(0x0abcb7ed), WTC(0x0b81d183), WTC(0x0c5113e3), WTC(0x0d2867d5), + WTC(0x0e082fa5), WTC(0x0ef089ad), WTC(0x0fe1d9cd), WTC(0x10d9e5f4), + WTC(0x11d6a2a0), WTC(0x12d814b1), WTC(0x13d98f52), WTC(0x14d221e1), + WTC(0x15ba467a), WTC(0x168a9c18), WTC(0x173d1fef), WTC(0x17da3bff), + WTC(0x18912cac), WTC(0x196c2a5e), WTC(0x1a68dd2e), WTC(0x1b85250c), + WTC(0x1cbea9a1), WTC(0x1e147be7), WTC(0x1f8aa446), WTC(0x2122e73a), + WTC(0x22cf6de3), WTC(0x248867f3), WTC(0x265d7937), WTC(0x2847c91b), + WTC(0x2a39d98e), WTC(0x2c482abf), WTC(0x2e7ff439), WTC(0x30c31f46), + WTC(0x32f5245d), WTC(0x3535070e), WTC(0x37adae38), WTC(0x3a3f151a), + WTC(0x3caf861b), WTC(0x3effc08b), WTC(0x415a803b), WTC(0x43d45ca9), + WTC(0x46631c69), WTC(0x48ed9c7e), WTC(0x4b608807), WTC(0x4dbbead3), + WTC(0x500ca1df), WTC(0x525e3c5d), WTC(0x54b7c199), WTC(0x570df9a2), + WTC(0x5940f661), WTC(0x5b542f13), WTC(0x5d64a202), WTC(0x5f738e39), + WTC(0x61704027), WTC(0x6348ef5e), WTC(0x65109c5f), WTC(0x66d3e29d), + WTC(0x687eb29a), WTC(0x6a125643), WTC(0x6b960b3a), WTC(0x6d07b283), + WTC(0xaf5b8daa), WTC(0xb3d557ba), WTC(0xb829feb2), WTC(0xbc6199e7), + WTC(0xc07bfbc1), WTC(0xc477a1b6), WTC(0xc8532f30), WTC(0xcc0dd698), + WTC(0xcfa71f06), WTC(0xd31ec578), WTC(0xd674c5b9), WTC(0xd9a90516), + WTC(0xdcbbc2b6), WTC(0xdfacf934), WTC(0xe27d19ab), WTC(0xe52c3d89), + WTC(0xe7bb0f52), WTC(0xea29bdd0), WTC(0xec78bc4a), WTC(0xeea805e6), + WTC(0xf0b85a68), WTC(0xf2ab266e), WTC(0xf48234a7), WTC(0xf63cb733), + WTC(0xf7d70b3f), WTC(0xf952d4d3), WTC(0xfab4906d), WTC(0xfbfaa858), + WTC(0xfd272437), WTC(0xfe392bea), WTC(0xff2e26f1), WTC(0x000efac0), + WTC(0x00e36d26), WTC(0x019bd803), WTC(0x0229e357), WTC(0x02a16b25), + WTC(0x0319ee5e), WTC(0x038ccea0), WTC(0x03e56d3d), WTC(0x041dc072), + WTC(0x043f58cc), WTC(0x04571273), WTC(0x046ba761), WTC(0x0479caa5), + WTC(0x047a2279), WTC(0x04673950), WTC(0x04435263), WTC(0x041750da), + WTC(0x03e99926), WTC(0x03b4ba1f), WTC(0x03731e2b), WTC(0x0327b303), + WTC(0x02d8301b), WTC(0x0284fb11), WTC(0x022b464a), WTC(0x01cc1b40), + WTC(0x0169ab7d), WTC(0x01047d1e), WTC(0x009d04e0), WTC(0x003484b0), + WTC(0xd5a9348a), WTC(0xd3f05eca), WTC(0xd24339e7), WTC(0xd0a269b7), + WTC(0xcf0fe026), WTC(0xcd8aa14b), WTC(0xcc13963e), WTC(0xcaa19c5a), + WTC(0xc92cd701), WTC(0xc7b5cd7b), WTC(0xc62a4fe3), WTC(0xc46742be), + WTC(0xc24e128c), WTC(0xbfc0b758), WTC(0xbca661e3), WTC(0xb922924b), + WTC(0xb5f87ac2), WTC(0xb35308e7), WTC(0xb12cc90f), WTC(0xaf80522c), + WTC(0xae483b10), WTC(0xad7f1af9), WTC(0xad1f8874), WTC(0xad241a09), + WTC(0xad8766ea), WTC(0xae4405b1), WTC(0xaf548d72), WTC(0xb0b394ad), + WTC(0xb25bb297), WTC(0xb4476fa1), WTC(0xb6718d2c), WTC(0xb8d47781), + WTC(0xbb6ad37b), WTC(0xbe2f3831), WTC(0xc11c3c6c), WTC(0xc42c76b1), + WTC(0xc75a7e40), WTC(0xcaa0e9d1), WTC(0xcdfa502b), WTC(0xd1614803), + WTC(0xd4d06850), WTC(0xd84247d3), WTC(0xdbb17d6d), WTC(0xdf189fe3), + WTC(0xe272461e), WTC(0xe5b906e1), WTC(0xe8e7790e), WTC(0xebf83366), + WTC(0xeee5cccc), WTC(0xf1aadc0a), WTC(0xf441f7fa), WTC(0xf6a5b772), + WTC(0xf8d0b146), WTC(0xfabd7c3e), WTC(0xfc66af35), WTC(0xfdc6e101), + WTC(0xfed8a875), WTC(0xff969c63), WTC(0xfffb5390), WTC(0x00017ad8), +}; + +const FIXP_WTB LowDelaySynthesis512[1536] = { + /* part 0 */ + WTC(0xdac984c0), WTC(0xdb100080), WTC(0xdb56cd00), WTC(0xdb9dec40), + WTC(0xdbe55fc0), WTC(0xdc2d2880), WTC(0xdc754780), WTC(0xdcbdbd80), + WTC(0xdd068a80), WTC(0xdd4fae80), WTC(0xdd992940), WTC(0xdde2f9c0), + WTC(0xde2d1fc0), WTC(0xde779a80), WTC(0xdec26a00), WTC(0xdf0d8e00), + WTC(0xdf590680), WTC(0xdfa4d540), WTC(0xdff0fc80), WTC(0xe03d7e20), + WTC(0xe08a5900), WTC(0xe0d78a20), WTC(0xe1250cc0), WTC(0xe172dcc0), + WTC(0xe1c0f7a0), WTC(0xe20f59a0), WTC(0xe25dfea0), WTC(0xe2ace400), + WTC(0xe2fc0be0), WTC(0xe34b7bc0), WTC(0xe39b3c80), WTC(0xe3eb5260), + WTC(0xe43bbac0), WTC(0xe48c7160), WTC(0xe4dd7140), WTC(0xe52eb600), + WTC(0xe5803c00), WTC(0xe5d1fda0), WTC(0xe623f360), WTC(0xe6761700), + WTC(0xe6c86400), WTC(0xe71ad500), WTC(0xe76d63e0), WTC(0xe7c00ba0), + WTC(0xe812c8e0), WTC(0xe86598e0), WTC(0xe8b878e0), WTC(0xe90b68a0), + WTC(0xe95e6c40), WTC(0xe9b18ae0), WTC(0xea04ce80), WTC(0xea583ba0), + WTC(0xeaabcda0), WTC(0xeaff7ee0), WTC(0xeb5348e0), WTC(0xeba722c0), + WTC(0xebfb0060), WTC(0xec4ed240), WTC(0xeca28540), WTC(0xecf60c20), + WTC(0xed496120), WTC(0xed9c7e80), WTC(0xedef5e40), WTC(0xee41fc00), + WTC(0xee945600), WTC(0xeee66ac0), WTC(0xef3839a0), WTC(0xef89c0e0), + WTC(0xefdafda0), WTC(0xf02bed60), WTC(0xf07c8e80), WTC(0xf0cce000), + WTC(0xf11ce220), WTC(0xf16c9620), WTC(0xf1bbfe30), WTC(0xf20b19e0), + WTC(0xf259e5a0), WTC(0xf2a85dc0), WTC(0xf2f67ed0), WTC(0xf34445b0), + WTC(0xf391aed0), WTC(0xf3deb590), WTC(0xf42b53e0), WTC(0xf4778140), + WTC(0xf4c33190), WTC(0xf50e5660), WTC(0xf558df30), WTC(0xf5a2be50), + WTC(0xf5ebea10), WTC(0xf6345780), WTC(0xf67bfab0), WTC(0xf6c2cee0), + WTC(0xf708d7b0), WTC(0xf74e19c0), WTC(0xf7929a70), WTC(0xf7d66630), + WTC(0xf8199268), WTC(0xf85c3860), WTC(0xf89e7480), WTC(0xf8e058c0), + WTC(0xf921ec08), WTC(0xf9633800), WTC(0xf9a44980), WTC(0xf9e53158), + WTC(0xfa260158), WTC(0xfa66ca18), WTC(0xfaa79ac0), WTC(0xfae87920), + WTC(0xfb295fa0), WTC(0xfb6a42b8), WTC(0xfbab1240), WTC(0xfbebd1c0), + WTC(0xfc2c9c24), WTC(0xfc6d8d90), WTC(0xfcaec240), WTC(0xfcf05684), + WTC(0xfd326a98), WTC(0xfd75254c), WTC(0xfdb8afd4), WTC(0xfdfccdfc), + WTC(0xfe40d694), WTC(0xfe84161c), WTC(0xfec5cf5a), WTC(0xff04e7fc), + WTC(0xff3fdfe3), WTC(0xff751ddf), WTC(0xffa2fb0f), WTC(0xffc87c42), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbffb6081), WTC(0xbff22f81), WTC(0xbfe8fc01), WTC(0xbfdfc781), + WTC(0xbfd69101), WTC(0xbfcd5a01), WTC(0xbfc42201), WTC(0xbfbae981), + WTC(0xbfb1b101), WTC(0xbfa87901), WTC(0xbf9f4181), WTC(0xbf960b01), + WTC(0xbf8cd481), WTC(0xbf839d81), WTC(0xbf7a6681), WTC(0xbf712f01), + WTC(0xbf67f801), WTC(0xbf5ec101), WTC(0xbf558b01), WTC(0xbf4c5681), + WTC(0xbf432281), WTC(0xbf39ee81), WTC(0xbf30bb01), WTC(0xbf278801), + WTC(0xbf1e5501), WTC(0xbf152381), WTC(0xbf0bf381), WTC(0xbf02c581), + WTC(0xbef99901), WTC(0xbef06d01), WTC(0xbee74281), WTC(0xbede1901), + WTC(0xbed4f081), WTC(0xbecbca81), WTC(0xbec2a781), WTC(0xbeb98681), + WTC(0xbeb06881), WTC(0xbea74c81), WTC(0xbe9e3281), WTC(0xbe951a81), + WTC(0xbe8c0501), WTC(0xbe82f301), WTC(0xbe79e481), WTC(0xbe70da01), + WTC(0xbe67d381), WTC(0xbe5ed081), WTC(0xbe55d001), WTC(0xbe4cd381), + WTC(0xbe43da81), WTC(0xbe3ae601), WTC(0xbe31f701), WTC(0xbe290d01), + WTC(0xbe202801), WTC(0xbe174781), WTC(0xbe0e6c01), WTC(0xbe059481), + WTC(0xbdfcc301), WTC(0xbdf3f701), WTC(0xbdeb3101), WTC(0xbde27201), + WTC(0xbdd9b981), WTC(0xbdd10681), WTC(0xbdc85981), WTC(0xbdbfb281), + WTC(0xbdb71201), WTC(0xbdae7881), WTC(0xbda5e601), WTC(0xbd9d5b81), + WTC(0xbd94d801), WTC(0xbd8c5c01), WTC(0xbd83e681), WTC(0xbd7b7781), + WTC(0xbd731081), WTC(0xbd6ab101), WTC(0xbd625981), WTC(0xbd5a0b01), + WTC(0xbd51c481), WTC(0xbd498601), WTC(0xbd414f01), WTC(0xbd391f81), + WTC(0xbd30f881), WTC(0xbd28d981), WTC(0xbd20c401), WTC(0xbd18b781), + WTC(0xbd10b381), WTC(0xbd08b781), WTC(0xbd00c381), WTC(0xbcf8d781), + WTC(0xbcf0f381), WTC(0xbce91801), WTC(0xbce14601), WTC(0xbcd97c81), + WTC(0xbcd1bb81), WTC(0xbcca0301), WTC(0xbcc25181), WTC(0xbcbaa801), + WTC(0xbcb30601), WTC(0xbcab6c01), WTC(0xbca3db01), WTC(0xbc9c5281), + WTC(0xbc94d201), WTC(0xbc8d5901), WTC(0xbc85e801), WTC(0xbc7e7e01), + WTC(0xbc771c01), WTC(0xbc6fc101), WTC(0xbc686e01), WTC(0xbc612301), + WTC(0xbc59df81), WTC(0xbc52a381), WTC(0xbc4b6e81), WTC(0xbc444081), + WTC(0xbc3d1801), WTC(0xbc35f501), WTC(0xbc2ed681), WTC(0xbc27bd81), + WTC(0xbc20ae01), WTC(0xbc19ab01), WTC(0xbc12b801), WTC(0xbc0bcf81), + WTC(0xbc04e381), WTC(0xbbfde481), WTC(0xbbf6c601), WTC(0xbbef9b81), + WTC(0xbbe89901), WTC(0xbbe1f401), WTC(0xbbdbe201), WTC(0xbbd68c81), + WTC(0xbbd21281), WTC(0xbbce9181), WTC(0xbbcc2681), WTC(0xbbcaca01), + WTC(0xbbca5081), WTC(0xbbca8d01), WTC(0xbbcb5301), WTC(0xbbcc8201), + WTC(0xbbce0601), WTC(0xbbcfca81), WTC(0xbbd1bd81), WTC(0xbbd3e101), + WTC(0xbbd64d01), WTC(0xbbd91b81), WTC(0xbbdc6481), WTC(0xbbe03801), + WTC(0xbbe49d01), WTC(0xbbe99981), WTC(0xbbef3301), WTC(0xbbf56181), + WTC(0xbbfc0f81), WTC(0xbc032601), WTC(0xbc0a8f01), WTC(0xbc123b81), + WTC(0xbc1a2401), WTC(0xbc224181), WTC(0xbc2a8c81), WTC(0xbc330781), + WTC(0xbc3bbc01), WTC(0xbc44b481), WTC(0xbc4dfb81), WTC(0xbc57a301), + WTC(0xbc61c401), WTC(0xbc6c7781), WTC(0xbc77d601), WTC(0xbc83f201), + WTC(0xbc90d481), WTC(0xbc9e8801), WTC(0xbcad1501), WTC(0xbcbc7e01), + WTC(0xbcccbd01), WTC(0xbcddcc81), WTC(0xbcefa601), WTC(0xbd023f01), + WTC(0xbd158801), WTC(0xbd297181), WTC(0xbd3deb81), WTC(0xbd52eb01), + WTC(0xbd686681), WTC(0xbd7e5581), WTC(0xbd94b001), WTC(0xbdab7181), + WTC(0xbdc29a81), WTC(0xbdda2a01), WTC(0xbdf22181), WTC(0xbe0a8581), + WTC(0xbe236001), WTC(0xbe3cbc01), WTC(0xbe56a381), WTC(0xbe712001), + WTC(0xbe8c3781), WTC(0xbea7f301), WTC(0xbec45881), WTC(0xbee17201), + WTC(0xbeff4801), WTC(0xbf1de601), WTC(0xbf3d5501), WTC(0xbf5d9a81), + WTC(0xbf7eb581), WTC(0xbfa0a581), WTC(0xbfc36a01), WTC(0xbfe6ed01), + WTC(0xc00b04c0), WTC(0xc02f86c0), WTC(0xc0544940), WTC(0xc0792ec0), + WTC(0xc09e2640), WTC(0xc0c31f00), WTC(0xc0e80a00), WTC(0xc10cf480), + WTC(0xc1320940), WTC(0xc15773c0), WTC(0xc17d5f00), WTC(0xc1a3e340), + WTC(0xc1cb05c0), WTC(0xc1f2cbc0), WTC(0xc21b3940), WTC(0xc2444b00), + WTC(0xc26df5c0), WTC(0xc2982d80), WTC(0xc2c2e640), WTC(0xc2ee0a00), + WTC(0xc3197940), WTC(0xc34513c0), WTC(0xc370b9c0), WTC(0xc39c4f00), + WTC(0xc3c7bc00), WTC(0xc3f2e940), WTC(0xc41dc140), WTC(0xc44856c0), + WTC(0xc472e640), WTC(0xc49dad80), WTC(0xc4c8e880), WTC(0xc4f4acc0), + WTC(0xc520e840), WTC(0xc54d8780), WTC(0xc57a76c0), WTC(0xc5a79640), + WTC(0xc5d4bac0), WTC(0xc601b880), WTC(0xc62e6580), WTC(0xc65ab600), + WTC(0xc686bd40), WTC(0xc6b28fc0), WTC(0xc6de41c0), WTC(0xc709de40), + WTC(0xc7356640), WTC(0xc760da80), WTC(0xc78c3c40), WTC(0xc7b78640), + WTC(0xc7e2afc0), WTC(0xc80dae80), WTC(0xc83878c0), WTC(0xc86304c0), + WTC(0xc88d4900), WTC(0xc8b73b80), WTC(0xc8e0d280), WTC(0xc90a0440), + /* part 1 */ + WTC(0xb5212e81), WTC(0xb4959501), WTC(0xb40ab501), WTC(0xb3808d81), + WTC(0xb2f71f01), WTC(0xb26e6881), WTC(0xb1e66a01), WTC(0xb15f2381), + WTC(0xb0d89401), WTC(0xb052bc01), WTC(0xafcd9a81), WTC(0xaf492f01), + WTC(0xaec57801), WTC(0xae427481), WTC(0xadc02281), WTC(0xad3e8101), + WTC(0xacbd9081), WTC(0xac3d5001), WTC(0xabbdc001), WTC(0xab3edf01), + WTC(0xaac0ad01), WTC(0xaa432981), WTC(0xa9c65401), WTC(0xa94a2c01), + WTC(0xa8ceb201), WTC(0xa853e501), WTC(0xa7d9c681), WTC(0xa7605601), + WTC(0xa6e79401), WTC(0xa66f8201), WTC(0xa5f81f81), WTC(0xa5816e81), + WTC(0xa50b6e81), WTC(0xa4962181), WTC(0xa4218801), WTC(0xa3ada281), + WTC(0xa33a7201), WTC(0xa2c7f801), WTC(0xa2563501), WTC(0xa1e52a81), + WTC(0xa174da81), WTC(0xa1054701), WTC(0xa0967201), WTC(0xa0285d81), + WTC(0x9fbb0981), WTC(0x9f4e7801), WTC(0x9ee2a901), WTC(0x9e779f81), + WTC(0x9e0d5e01), WTC(0x9da3e601), WTC(0x9d3b3b81), WTC(0x9cd35f81), + WTC(0x9c6c5481), WTC(0x9c061b81), WTC(0x9ba0b701), WTC(0x9b3c2801), + WTC(0x9ad87081), WTC(0x9a759301), WTC(0x9a139101), WTC(0x99b26c81), + WTC(0x99522801), WTC(0x98f2c601), WTC(0x98944901), WTC(0x9836b201), + WTC(0x97da0481), WTC(0x977e4181), WTC(0x97236b01), WTC(0x96c98381), + WTC(0x96708b81), WTC(0x96188501), WTC(0x95c17081), WTC(0x956b4f81), + WTC(0x95162381), WTC(0x94c1ee01), WTC(0x946eaf81), WTC(0x941c6901), + WTC(0x93cb1c81), WTC(0x937acb01), WTC(0x932b7501), WTC(0x92dd1b01), + WTC(0x928fbe01), WTC(0x92435d01), WTC(0x91f7f981), WTC(0x91ad9281), + WTC(0x91642781), WTC(0x911bb981), WTC(0x90d44781), WTC(0x908dd101), + WTC(0x90485401), WTC(0x9003ce81), WTC(0x8fc03f01), WTC(0x8f7da401), + WTC(0x8f3bfb01), WTC(0x8efb4181), WTC(0x8ebb7581), WTC(0x8e7c9301), + WTC(0x8e3e9481), WTC(0x8e017581), WTC(0x8dc53001), WTC(0x8d89be81), + WTC(0x8d4f1b01), WTC(0x8d154081), WTC(0x8cdc2901), WTC(0x8ca3cb01), + WTC(0x8c6c1b01), WTC(0x8c350d01), WTC(0x8bfe9401), WTC(0x8bc8a401), + WTC(0x8b933001), WTC(0x8b5e2c81), WTC(0x8b298b81), WTC(0x8af53e81), + WTC(0x8ac13381), WTC(0x8a8d5801), WTC(0x8a599a81), WTC(0x8a25f301), + WTC(0x89f26101), WTC(0x89bee581), WTC(0x898b8301), WTC(0x89586901), + WTC(0x8925f101), WTC(0x88f47901), WTC(0x88c45e81), WTC(0x88962981), + WTC(0x886a8a81), WTC(0x88423301), WTC(0x881dd301), WTC(0x87fdd781), + WTC(0x87d0ca81), WTC(0x87c76201), WTC(0x87bcab81), WTC(0x87b0ef01), + WTC(0x87a48b01), WTC(0x8797dd81), WTC(0x878b4301), WTC(0x877ede01), + WTC(0x87729701), WTC(0x87665481), WTC(0x8759fd01), WTC(0x874d8681), + WTC(0x8740f681), WTC(0x87345381), WTC(0x8727a381), WTC(0x871ae981), + WTC(0x870e2301), WTC(0x87014f81), WTC(0x86f46d81), WTC(0x86e77b81), + WTC(0x86da7901), WTC(0x86cd6681), WTC(0x86c04381), WTC(0x86b30f01), + WTC(0x86a5ca81), WTC(0x86987581), WTC(0x868b1001), WTC(0x867d9a81), + WTC(0x86701381), WTC(0x86627b01), WTC(0x8654d001), WTC(0x86471281), + WTC(0x86394301), WTC(0x862b6201), WTC(0x861d7081), WTC(0x860f6e01), + WTC(0x86015981), WTC(0x85f33281), WTC(0x85e4f801), WTC(0x85d6a981), + WTC(0x85c84801), WTC(0x85b9d481), WTC(0x85ab4f01), WTC(0x859cb781), + WTC(0x858e0e01), WTC(0x857f5101), WTC(0x85707f81), WTC(0x85619a01), + WTC(0x8552a181), WTC(0x85439601), WTC(0x85347901), WTC(0x85254a81), + WTC(0x85160981), WTC(0x8506b581), WTC(0x84f74e01), WTC(0x84e7d381), + WTC(0x84d84601), WTC(0x84c8a701), WTC(0x84b8f801), WTC(0x84a93801), + WTC(0x84996701), WTC(0x84898481), WTC(0x84798f81), WTC(0x84698881), + WTC(0x84597081), WTC(0x84494881), WTC(0x84391081), WTC(0x8428ca01), + WTC(0x84187401), WTC(0x84080d81), WTC(0x83f79681), WTC(0x83e70f01), + WTC(0x83d67881), WTC(0x83c5d381), WTC(0x83b52101), WTC(0x83a46181), + WTC(0x83939501), WTC(0x8382ba01), WTC(0x8371d081), WTC(0x8360d901), + WTC(0x834fd481), WTC(0x833ec381), WTC(0x832da781), WTC(0x831c8101), + WTC(0x830b4f81), WTC(0x82fa1181), WTC(0x82e8c801), WTC(0x82d77201), + WTC(0x82c61101), WTC(0x82b4a601), WTC(0x82a33281), WTC(0x8291b601), + WTC(0x82803101), WTC(0x826ea201), WTC(0x825d0901), WTC(0x824b6601), + WTC(0x8239b981), WTC(0x82280581), WTC(0x82164a81), WTC(0x82048881), + WTC(0x81f2bf81), WTC(0x81e0ee81), WTC(0x81cf1581), WTC(0x81bd3401), + WTC(0x81ab4b01), WTC(0x81995c01), WTC(0x81876781), WTC(0x81756d81), + WTC(0x81636d81), WTC(0x81516701), WTC(0x813f5981), WTC(0x812d4481), + WTC(0x811b2981), WTC(0x81090981), WTC(0x80f6e481), WTC(0x80e4bb81), + WTC(0x80d28d81), WTC(0x80c05a01), WTC(0x80ae1f81), WTC(0x809bdf01), + WTC(0x80899881), WTC(0x80774c81), WTC(0x8064fc81), WTC(0x8052a881), + WTC(0x80405101), WTC(0x802df701), WTC(0x801b9b01), WTC(0x80093e01), + WTC(0x0a74b120), WTC(0x0aa08a90), WTC(0x0acd2b80), WTC(0x0afa8860), + WTC(0x0b289590), WTC(0x0b574790), WTC(0x0b8692d0), WTC(0x0bb66bb0), + WTC(0x0be6c6b0), WTC(0x0c179830), WTC(0x0c48d500), WTC(0x0c7a7ad0), + WTC(0x0cac9000), WTC(0x0cdf1b60), WTC(0x0d122390), WTC(0x0d45a8f0), + WTC(0x0d79a5e0), WTC(0x0dae1480), WTC(0x0de2ef30), WTC(0x0e183800), + WTC(0x0e4df8c0), WTC(0x0e843b90), WTC(0x0ebb0a20), WTC(0x0ef26430), + WTC(0x0f2a3fc0), WTC(0x0f629280), WTC(0x0f9b5210), WTC(0x0fd47690), + WTC(0x100dfa80), WTC(0x1047d8a0), WTC(0x10820b40), WTC(0x10bc8b80), + WTC(0x10f75080), WTC(0x11325100), WTC(0x116d84e0), WTC(0x11a8ece0), + WTC(0x11e49420), WTC(0x122085a0), WTC(0x125ccbc0), WTC(0x12995a40), + WTC(0x12d60e80), WTC(0x1312c4c0), WTC(0x134f59e0), WTC(0x138bae60), + WTC(0x13c7a740), WTC(0x140329e0), WTC(0x143e1b60), WTC(0x147862a0), + WTC(0x14b1e840), WTC(0x14ea94c0), WTC(0x152250a0), WTC(0x15590380), + WTC(0x158e93e0), WTC(0x15c2e820), WTC(0x15f5e6e0), WTC(0x162779a0), + WTC(0x16578ca0), WTC(0x16860ca0), WTC(0x16b2e640), WTC(0x16de0b00), + WTC(0x17077140), WTC(0x172f0fa0), WTC(0x1754e200), WTC(0x17796080), + WTC(0x179d7f20), WTC(0x17c23760), WTC(0x17e87da0), WTC(0x1810cc80), + WTC(0x183b25a0), WTC(0x18678520), WTC(0x1895e700), WTC(0x18c64540), + WTC(0x18f89780), WTC(0x192cd560), WTC(0x1962f680), WTC(0x199af2a0), + WTC(0x19d4c1e0), WTC(0x1a105ca0), WTC(0x1a4dbae0), WTC(0x1a8cd660), + WTC(0x1acdaa60), WTC(0x1b103260), WTC(0x1b546940), WTC(0x1b9a4600), + WTC(0x1be1bb80), WTC(0x1c2abc60), WTC(0x1c753b80), WTC(0x1cc13860), + WTC(0x1d0ebe20), WTC(0x1d5dd8c0), WTC(0x1dae9480), WTC(0x1e010060), + WTC(0x1e552f40), WTC(0x1eab33e0), WTC(0x1f032060), WTC(0x1f5cfce0), + WTC(0x1fb8c660), WTC(0x201679c0), WTC(0x207611c0), WTC(0x20d75f00), + WTC(0x213a0640), WTC(0x219dab80), WTC(0x2201f480), WTC(0x2266ba80), + WTC(0x22cc0ac0), WTC(0x2331f4c0), WTC(0x23988940), WTC(0x23ffff40), + WTC(0x2468b340), WTC(0x24d30300), WTC(0x253f4900), WTC(0x25ad8980), + WTC(0x261d72c0), WTC(0x268eaec0), WTC(0x2700e880), WTC(0x2773db40), + WTC(0x27e751c0), WTC(0x285b1780), WTC(0x28cefbc0), WTC(0x29431f80), + WTC(0x29b7f680), WTC(0x2a2df780), WTC(0x2aa59880), WTC(0x2b1f3280), + WTC(0x2b9b0140), WTC(0x2c194000), WTC(0x2c9a2540), WTC(0x2d1d8dc0), + WTC(0x2da2fc40), WTC(0x2e29ee80), WTC(0x2eb1e340), WTC(0x2f3a4e40), + WTC(0x2fc29980), WTC(0x304a2ec0), WTC(0x30d07cc0), WTC(0x315566c0), + WTC(0x31d94480), WTC(0x325c72c0), WTC(0x32df51c0), WTC(0x33628c80), + WTC(0x33e71a00), WTC(0x346df400), WTC(0x34f80dc0), WTC(0x3585c640), + WTC(0x3616e700), WTC(0x36ab3380), WTC(0x37426ac0), WTC(0x37dbe840), + WTC(0x3876a340), WTC(0x39118f40), WTC(0x39aba2c0), WTC(0x3a4422c0), + WTC(0x3adaa200), WTC(0x3b6eb6c0), WTC(0x3bfffd80), WTC(0x3c8e9380), + WTC(0x3d1b1780), WTC(0x3da62e00), WTC(0x3e307b00), WTC(0x3eba97c0), + WTC(0x3f451280), WTC(0x3fd07940), WTC(0x405d577f), WTC(0x40ebf57f), + WTC(0x417c59ff), WTC(0x420e897f), WTC(0x42a2857f), WTC(0x4338307f), + WTC(0x43cf4d7f), WTC(0x44679cff), WTC(0x4500dfff), WTC(0x459ac2ff), + WTC(0x4634e2ff), WTC(0x46ced9ff), WTC(0x4768437f), WTC(0x4800d27f), + WTC(0x489850ff), WTC(0x492e88ff), WTC(0x49c346ff), WTC(0x4a5678ff), + WTC(0x4ae82f7f), WTC(0x4b787c7f), WTC(0x4c07717f), WTC(0x4c95337f), + WTC(0x4d21f77f), WTC(0x4dadf3ff), WTC(0x4e395eff), WTC(0x4ec4657f), + WTC(0x4f4f297f), WTC(0x4fd9cd7f), WTC(0x5064737f), WTC(0x50ef3cff), + WTC(0x517a46ff), WTC(0x5205b0ff), WTC(0x529197ff), WTC(0x531e04ff), + WTC(0x53aaeb7f), WTC(0x54383eff), WTC(0x54c5ef7f), WTC(0x5553a8ff), + WTC(0x55e0d57f), WTC(0x566cda7f), WTC(0x56f720ff), WTC(0x577f4aff), + WTC(0x580534ff), WTC(0x5888bd7f), WTC(0x5909c6ff), WTC(0x598890ff), + WTC(0x5a05b7ff), WTC(0x5a81db7f), WTC(0x5afd99ff), WTC(0x5b794a7f), + WTC(0x5bf5007f), WTC(0x5c70cbff), WTC(0x5cecbb7f), WTC(0x5d68c47f), + WTC(0x5de4c3ff), WTC(0x5e6094ff), WTC(0x5edc127f), WTC(0x5f56fdff), + WTC(0x5fd1017f), WTC(0x6049c67f), WTC(0x60c0f67f), WTC(0x613650ff), + WTC(0x61a9a9ff), WTC(0x621ad77f), WTC(0x6289b37f), WTC(0x62f67fff), + WTC(0x6361e87f), WTC(0x63cc9bff), WTC(0x6437457f), WTC(0x64a2247f), + WTC(0x650d0c7f), WTC(0x6577cc7f), WTC(0x65e2327f), WTC(0x664bf57f), + WTC(0x66b4b5ff), WTC(0x671c137f), WTC(0x6781afff), WTC(0x67e579ff), + WTC(0x6847abff), WTC(0x68a882ff), WTC(0x69083bff), WTC(0x6966fbff), + WTC(0x69c4cfff), WTC(0x6a21c57f), WTC(0x6a7de87f), WTC(0x6ad9377f), + WTC(0x6b33a5ff), WTC(0x6b8d257f), WTC(0x6be5a8ff), WTC(0x6c3d20ff), + WTC(0x6c9380ff), WTC(0x6ce8ba7f), WTC(0x6d3cbfff), WTC(0x6d8f827f), + /* part 2 */ + WTC(0xad98b481), WTC(0xaead9d01), WTC(0xafbfc381), WTC(0xb0cf4d01), + WTC(0xb1dc5f81), WTC(0xb2e72081), WTC(0xb3efb501), WTC(0xb4f64381), + WTC(0xb5faf101), WTC(0xb6fde401), WTC(0xb7ff4001), WTC(0xb8ff1601), + WTC(0xb9fd6181), WTC(0xbafa1d01), WTC(0xbbf54401), WTC(0xbceed101), + WTC(0xbde6c081), WTC(0xbedd0e81), WTC(0xbfd1b701), WTC(0xc0c4b440), + WTC(0xc1b5ffc0), WTC(0xc2a59340), WTC(0xc3936780), WTC(0xc47f78c0), + WTC(0xc569c600), WTC(0xc6524d40), WTC(0xc7390dc0), WTC(0xc81e04c0), + WTC(0xc9012e00), WTC(0xc9e28540), WTC(0xcac20700), WTC(0xcb9fb1c0), + WTC(0xcc7b8640), WTC(0xcd558600), WTC(0xce2db200), WTC(0xcf0409c0), + WTC(0xcfd88a40), WTC(0xd0ab3080), WTC(0xd17bfa00), WTC(0xd24ae640), + WTC(0xd317f7c0), WTC(0xd3e33080), WTC(0xd4ac9340), WTC(0xd5741f40), + WTC(0xd639d2c0), WTC(0xd6fdab00), WTC(0xd7bfa5c0), WTC(0xd87fc300), + WTC(0xd93e0600), WTC(0xd9fa7180), WTC(0xdab50900), WTC(0xdb6dccc0), + WTC(0xdc24ba80), WTC(0xdcd9d000), WTC(0xdd8d0b80), WTC(0xde3e6dc0), + WTC(0xdeedf9c0), WTC(0xdf9bb340), WTC(0xe0479e20), WTC(0xe0f1bac0), + WTC(0xe19a07e0), WTC(0xe2408380), WTC(0xe2e52c00), WTC(0xe38802e0), + WTC(0xe4290c00), WTC(0xe4c84c20), WTC(0xe565c760), WTC(0xe6017f20), + WTC(0xe69b7240), WTC(0xe7339f60), WTC(0xe7ca0500), WTC(0xe85ea480), + WTC(0xe8f18180), WTC(0xe9829fc0), WTC(0xea1202e0), WTC(0xea9fab80), + WTC(0xeb2b9700), WTC(0xebb5c2a0), WTC(0xec3e2bc0), WTC(0xecc4d300), + WTC(0xed49bc80), WTC(0xedccec60), WTC(0xee4e66a0), WTC(0xeece2d80), + WTC(0xef4c41e0), WTC(0xefc8a480), WTC(0xf0435610), WTC(0xf0bc5c60), + WTC(0xf133c230), WTC(0xf1a99270), WTC(0xf21dd7b0), WTC(0xf29097e0), + WTC(0xf301d3d0), WTC(0xf3718c20), WTC(0xf3dfc180), WTC(0xf44c7100), + WTC(0xf4b79480), WTC(0xf52125b0), WTC(0xf5891df0), WTC(0xf5ef6fe0), + WTC(0xf6540730), WTC(0xf6b6cf50), WTC(0xf717b490), WTC(0xf776b9a0), + WTC(0xf7d3f720), WTC(0xf82f86e8), WTC(0xf8898260), WTC(0xf8e1fc50), + WTC(0xf93900f0), WTC(0xf98e9c28), WTC(0xf9e2d940), WTC(0xfa35b4a0), + WTC(0xfa871bd8), WTC(0xfad6fbd0), WTC(0xfb254250), WTC(0xfb71f0c0), + WTC(0xfbbd1c28), WTC(0xfc06da60), WTC(0xfc4f40a4), WTC(0xfc965500), + WTC(0xfcdc0e5c), WTC(0xfd2062f4), WTC(0xfd6348d0), WTC(0xfda4b1b8), + WTC(0xfde48b2c), WTC(0xfe22c280), WTC(0xfe5f462a), WTC(0xfe9a1f2e), + WTC(0xfed3711c), WTC(0xff0b60ac), WTC(0xff4212dd), WTC(0xff77b344), + WTC(0xffac7407), WTC(0xffe08796), WTC(0x00141e37), WTC(0x00473665), + WTC(0x00799cd0), WTC(0x00ab1bff), WTC(0x00db7d8b), WTC(0x010a75ea), + WTC(0x0137a46e), WTC(0x0162a77a), WTC(0x018b20ac), WTC(0x01b0fb7a), + WTC(0x01d46d3c), WTC(0x01f5ae7c), WTC(0x0214f91c), WTC(0x0232a5cc), + WTC(0x024f2c04), WTC(0x026b048c), WTC(0x0286a628), WTC(0x02a25808), + WTC(0x02be31c0), WTC(0x02da48e0), WTC(0x02f6b09c), WTC(0x031345dc), + WTC(0x032faf50), WTC(0x034b9148), WTC(0x036690e8), WTC(0x0380658c), + WTC(0x0398d8e4), WTC(0x03afb568), WTC(0x03c4c6e0), WTC(0x03d7f770), + WTC(0x03e94f9c), WTC(0x03f8d938), WTC(0x04069ee8), WTC(0x0412bef8), + WTC(0x041d6b30), WTC(0x0426d638), WTC(0x042f3288), WTC(0x0436ad98), + WTC(0x043d6fd0), WTC(0x0443a170), WTC(0x04496a40), WTC(0x044ee728), + WTC(0x04542a40), WTC(0x04594520), WTC(0x045e4890), WTC(0x04633210), + WTC(0x0467ebe8), WTC(0x046c5f80), WTC(0x04707630), WTC(0x047417f0), + WTC(0x04772b58), WTC(0x047996e8), WTC(0x047b4140), WTC(0x047c12a0), + WTC(0x047bf520), WTC(0x047ad2e0), WTC(0x04789690), WTC(0x047539c8), + WTC(0x0470c4b8), WTC(0x046b4058), WTC(0x0464b600), WTC(0x045d3a08), + WTC(0x0454ebc8), WTC(0x044beb00), WTC(0x04425798), WTC(0x043853b0), + WTC(0x042e0398), WTC(0x04238bd8), WTC(0x04190f98), WTC(0x040e9670), + WTC(0x04040c18), WTC(0x03f95b30), WTC(0x03ee6e20), WTC(0x03e32b64), + WTC(0x03d77598), WTC(0x03cb2f24), WTC(0x03be3b18), WTC(0x03b08b18), + WTC(0x03a21f64), WTC(0x0392f8d4), WTC(0x038318e0), WTC(0x03728e94), + WTC(0x03617694), WTC(0x034fee18), WTC(0x033e11f4), WTC(0x032bf530), + WTC(0x0319a114), WTC(0x03071e80), WTC(0x02f475f4), WTC(0x02e1a7c0), + WTC(0x02ceac04), WTC(0x02bb7a84), WTC(0x02a80af0), WTC(0x029452b0), + WTC(0x028044e0), WTC(0x026bd488), WTC(0x0256f558), WTC(0x0241a940), + WTC(0x022c0084), WTC(0x02160c08), WTC(0x01ffdc5a), WTC(0x01e97ad2), + WTC(0x01d2e982), WTC(0x01bc2a2a), WTC(0x01a53e8c), WTC(0x018e2860), + WTC(0x0176e94c), WTC(0x015f82fa), WTC(0x0147f70e), WTC(0x013046c2), + WTC(0x011872e8), WTC(0x01007c4a), WTC(0x00e863cf), WTC(0x00d02c81), + WTC(0x00b7db94), WTC(0x009f7651), WTC(0x00870204), WTC(0x006e83f8), + WTC(0x00560176), WTC(0x003d7fcb), WTC(0x0025043f), WTC(0x000c941f), + WTC(0xd65574c0), WTC(0xd5ebc100), WTC(0xd582d080), WTC(0xd51a9cc0), + WTC(0xd4b31f80), WTC(0xd44c5280), WTC(0xd3e62f80), WTC(0xd380b040), + WTC(0xd31bce40), WTC(0xd2b78380), WTC(0xd253ca40), WTC(0xd1f0acc0), + WTC(0xd18e4580), WTC(0xd12caf40), WTC(0xd0cc0400), WTC(0xd06c40c0), + WTC(0xd00d4740), WTC(0xcfaef6c0), WTC(0xcf513140), WTC(0xcef3fa80), + WTC(0xce977a40), WTC(0xce3bd980), WTC(0xcde13f40), WTC(0xcd87a880), + WTC(0xcd2ee800), WTC(0xccd6cf00), WTC(0xcc7f2f40), WTC(0xcc27e880), + WTC(0xcbd0ea00), WTC(0xcb7a2380), WTC(0xcb238380), WTC(0xcaccee80), + WTC(0xca763ec0), WTC(0xca1f4d00), WTC(0xc9c7f480), WTC(0xc9703b40), + WTC(0xc9185200), WTC(0xc8c06b00), WTC(0xc868b4c0), WTC(0xc81100c0), + WTC(0xc7b8c280), WTC(0xc75f6a40), WTC(0xc7046900), WTC(0xc6a74340), + WTC(0xc6479300), WTC(0xc5e4f200), WTC(0xc57efac0), WTC(0xc5154880), + WTC(0xc4a77780), WTC(0xc4352440), WTC(0xc3bdeac0), WTC(0xc3416740), + WTC(0xc2bf33c0), WTC(0xc236eb40), WTC(0xc1a82900), WTC(0xc11290c0), + WTC(0xc075cf00), WTC(0xbfd19081), WTC(0xbf258401), WTC(0xbe716d81), + WTC(0xbdb52b81), WTC(0xbcf09a81), WTC(0xbc23af81), WTC(0xbb505c01), + WTC(0xba7a9081), WTC(0xb9a65281), WTC(0xb8d79301), WTC(0xb8104c01), + WTC(0xb7508181), WTC(0xb6982201), WTC(0xb5e71b01), WTC(0xb53d5b01), + WTC(0xb49ad081), WTC(0xb3ff6901), WTC(0xb36b1301), WTC(0xb2ddbd01), + WTC(0xb2575481), WTC(0xb1d7c801), WTC(0xb15f0601), WTC(0xb0ecfc01), + WTC(0xb0819881), WTC(0xb01cca01), WTC(0xafbe7e01), WTC(0xaf66a301), + WTC(0xaf152701), WTC(0xaec9f881), WTC(0xae850601), WTC(0xae463c81), + WTC(0xae0d8b01), WTC(0xaddae001), WTC(0xadae2881), WTC(0xad875381), + WTC(0xad664f81), WTC(0xad4b0981), WTC(0xad357081), WTC(0xad257301), + WTC(0xad1afe01), WTC(0xad160081), WTC(0xad166901), WTC(0xad1c2481), + WTC(0xad272201), WTC(0xad374f81), WTC(0xad4c9b01), WTC(0xad66f381), + WTC(0xad864601), WTC(0xadaa8101), WTC(0xadd39301), WTC(0xae016a01), + WTC(0xae33f481), WTC(0xae6b2001), WTC(0xaea6db01), WTC(0xaee71381), + WTC(0xaf2bb801), WTC(0xaf74b681), WTC(0xafc1fd01), WTC(0xb0137a01), + WTC(0xb0691b81), WTC(0xb0c2cf81), WTC(0xb1208481), WTC(0xb1822881), + WTC(0xb1e7a981), WTC(0xb250f601), WTC(0xb2bdfc01), WTC(0xb32eaa01), + WTC(0xb3a2ed01), WTC(0xb41ab481), WTC(0xb495ee01), WTC(0xb5148801), + WTC(0xb5967081), WTC(0xb61b9581), WTC(0xb6a3e581), WTC(0xb72f4e01), + WTC(0xb7bdbe01), WTC(0xb84f2381), WTC(0xb8e36c81), WTC(0xb97a8701), + WTC(0xba146101), WTC(0xbab0e981), WTC(0xbb500d81), WTC(0xbbf1bc81), + WTC(0xbc95e381), WTC(0xbd3c7181), WTC(0xbde55481), WTC(0xbe907a01), + WTC(0xbf3dd101), WTC(0xbfed4701), WTC(0xc09ecac0), WTC(0xc1524a00), + WTC(0xc207b300), WTC(0xc2bef440), WTC(0xc377fb80), WTC(0xc432b700), + WTC(0xc4ef1500), WTC(0xc5ad03c0), WTC(0xc66c7140), WTC(0xc72d4bc0), + WTC(0xc7ef8180), WTC(0xc8b30080), WTC(0xc977b700), WTC(0xca3d9340), + WTC(0xcb048340), WTC(0xcbcc7540), WTC(0xcc955740), WTC(0xcd5f17c0), + WTC(0xce29a480), WTC(0xcef4ec00), WTC(0xcfc0dc80), WTC(0xd08d63c0), + WTC(0xd15a7040), WTC(0xd227f000), WTC(0xd2f5d140), WTC(0xd3c40240), + WTC(0xd4927100), WTC(0xd5610b80), WTC(0xd62fc080), WTC(0xd6fe7dc0), + WTC(0xd7cd3140), WTC(0xd89bc980), WTC(0xd96a34c0), WTC(0xda3860c0), + WTC(0xdb063c00), WTC(0xdbd3b480), WTC(0xdca0b880), WTC(0xdd6d3640), + WTC(0xde391bc0), WTC(0xdf045740), WTC(0xdfced6c0), WTC(0xe09888c0), + WTC(0xe1615b20), WTC(0xe2293c20), WTC(0xe2f01a00), WTC(0xe3b5e2c0), + WTC(0xe47a84c0), WTC(0xe53dee00), WTC(0xe6000cc0), WTC(0xe6c0cf20), + WTC(0xe7802360), WTC(0xe83df7a0), WTC(0xe8fa39e0), WTC(0xe9b4d880), + WTC(0xea6dc1a0), WTC(0xeb24e360), WTC(0xebda2be0), WTC(0xec8d8960), + WTC(0xed3eea20), WTC(0xedee3c00), WTC(0xee9b6d80), WTC(0xef466ca0), + WTC(0xefef2780), WTC(0xf0958c50), WTC(0xf1398950), WTC(0xf1db0ca0), + WTC(0xf27a0470), WTC(0xf3165ed0), WTC(0xf3b00a10), WTC(0xf446f440), + WTC(0xf4db0b90), WTC(0xf56c3e30), WTC(0xf5fa7a50), WTC(0xf685ae10), + WTC(0xf70dc7a0), WTC(0xf792b520), WTC(0xf81464c8), WTC(0xf892c4c0), + WTC(0xf90dc330), WTC(0xf9854e40), WTC(0xf9f95418), WTC(0xfa69c2f0), + WTC(0xfad688e8), WTC(0xfb3f9428), WTC(0xfba4d2e8), WTC(0xfc063344), + WTC(0xfc63a370), WTC(0xfcbd1194), WTC(0xfd126bdc), WTC(0xfd63a06c), + WTC(0xfdb09d78), WTC(0xfdf95124), WTC(0xfe3da99e), WTC(0xfe7d950e), + WTC(0xfeb901a2), WTC(0xfeefdd80), WTC(0xff2216d7), WTC(0xff4f9bcf), + WTC(0xff785a93), WTC(0xff9c414e), WTC(0xffbb3e2b), WTC(0xffd53f54), + WTC(0xffea32f4), WTC(0xfffa0735), WTC(0x0004aa43), WTC(0x000a0a47), + WTC(0x000a156c), WTC(0x0004b9de), WTC(0xfff9e5c5), WTC(0xffe9874e)}; + +const FIXP_WTB LowDelaySynthesis480[1440] = { + WTC(0xdad2e6c0), WTC(0xdb1da900), WTC(0xdb68ce40), WTC(0xdbb45840), + WTC(0xdc004940), WTC(0xdc4ca280), WTC(0xdc996500), WTC(0xdce69140), + WTC(0xdd342780), WTC(0xdd822700), WTC(0xddd08a80), WTC(0xde1f4d00), + WTC(0xde6e6ec0), WTC(0xdebdec40), WTC(0xdf0dba80), WTC(0xdf5dd540), + WTC(0xdfae3cc0), WTC(0xdfff0500), WTC(0xe0505140), WTC(0xe0a22980), + WTC(0xe0f488e0), WTC(0xe1476180), WTC(0xe19aa480), WTC(0xe1ee4d80), + WTC(0xe2425400), WTC(0xe29689a0), WTC(0xe2eacd60), WTC(0xe33f2420), + WTC(0xe393a300), WTC(0xe3e87f20), WTC(0xe43dcee0), WTC(0xe4938a80), + WTC(0xe4e9b0a0), WTC(0xe5404300), WTC(0xe5973e60), WTC(0xe5ee9b80), + WTC(0xe64649e0), WTC(0xe69e37e0), WTC(0xe6f65ec0), WTC(0xe74eb6c0), + WTC(0xe7a73000), WTC(0xe7ffbe40), WTC(0xe8585ee0), WTC(0xe8b10740), + WTC(0xe9099c40), WTC(0xe96214e0), WTC(0xe9ba79a0), WTC(0xea12e7c0), + WTC(0xea6b89c0), WTC(0xeac46580), WTC(0xeb1d7260), WTC(0xeb76b620), + WTC(0xebd036c0), WTC(0xec29e520), WTC(0xec83aa60), WTC(0xecdd5a00), + WTC(0xed36d500), WTC(0xed901540), WTC(0xede91160), WTC(0xee41bc20), + WTC(0xee9a0ee0), WTC(0xeef20860), WTC(0xef49a7e0), WTC(0xefa0ec00), + WTC(0xeff7d1c0), WTC(0xf04e56b0), WTC(0xf0a476e0), WTC(0xf0fa2f60), + WTC(0xf14f80e0), WTC(0xf1a46e10), WTC(0xf1f8fe80), WTC(0xf24d34a0), + WTC(0xf2a10bb0), WTC(0xf2f48210), WTC(0xf3479cc0), WTC(0xf39a5be0), + WTC(0xf3ecb8f0), WTC(0xf43eafa0), WTC(0xf4903b50), WTC(0xf4e14e80), + WTC(0xf531d6a0), WTC(0xf581bc10), WTC(0xf5d0e9c0), WTC(0xf61f5250), + WTC(0xf66ce6e0), WTC(0xf6b99330), WTC(0xf7054eb0), WTC(0xf7501f20), + WTC(0xf79a0750), WTC(0xf7e30700), WTC(0xf82b2fc0), WTC(0xf872a138), + WTC(0xf8b97f18), WTC(0xf8ffe668), WTC(0xf945e538), WTC(0xf98b8860), + WTC(0xf9d0f380), WTC(0xfa165148), WTC(0xfa5bb8a8), WTC(0xfaa13df8), + WTC(0xfae6fb00), WTC(0xfb2cf8c8), WTC(0xfb732a80), WTC(0xfbb97910), + WTC(0xfbffcd10), WTC(0xfc463478), WTC(0xfc8cd3fc), WTC(0xfcd3be5c), + WTC(0xfd1afa90), WTC(0xfd62aa84), WTC(0xfdab0288), WTC(0xfdf404b4), + WTC(0xfe3d3006), WTC(0xfe85b20e), WTC(0xfecca4cc), WTC(0xff10d559), + WTC(0xff50579b), WTC(0xff8a40d2), WTC(0xffb7d86e), WTC(0xffef6bbb), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xbff67a01), WTC(0xbfecaa81), WTC(0xbfe2d901), WTC(0xbfd90601), + WTC(0xbfcf3181), WTC(0xbfc55c81), WTC(0xbfbb8701), WTC(0xbfb1b101), + WTC(0xbfa7dc01), WTC(0xbf9e0701), WTC(0xbf943301), WTC(0xbf8a5f81), + WTC(0xbf808b81), WTC(0xbf76b701), WTC(0xbf6ce201), WTC(0xbf630d81), + WTC(0xbf593a01), WTC(0xbf4f6801), WTC(0xbf459681), WTC(0xbf3bc601), + WTC(0xbf31f501), WTC(0xbf282501), WTC(0xbf1e5501), WTC(0xbf148681), + WTC(0xbf0aba01), WTC(0xbf00ef81), WTC(0xbef72681), WTC(0xbeed5f01), + WTC(0xbee39801), WTC(0xbed9d281), WTC(0xbed00f81), WTC(0xbec64e81), + WTC(0xbebc9181), WTC(0xbeb2d681), WTC(0xbea91f01), WTC(0xbe9f6901), + WTC(0xbe95b581), WTC(0xbe8c0501), WTC(0xbe825801), WTC(0xbe78b001), + WTC(0xbe6f0c01), WTC(0xbe656c01), WTC(0xbe5bd001), WTC(0xbe523781), + WTC(0xbe48a301), WTC(0xbe3f1381), WTC(0xbe358901), WTC(0xbe2c0501), + WTC(0xbe228681), WTC(0xbe190d81), WTC(0xbe0f9a01), WTC(0xbe062b81), + WTC(0xbdfcc301), WTC(0xbdf36101), WTC(0xbdea0681), WTC(0xbde0b301), + WTC(0xbdd76701), WTC(0xbdce2181), WTC(0xbdc4e301), WTC(0xbdbbab01), + WTC(0xbdb27b01), WTC(0xbda95301), WTC(0xbda03381), WTC(0xbd971c81), + WTC(0xbd8e0e01), WTC(0xbd850701), WTC(0xbd7c0781), WTC(0xbd731081), + WTC(0xbd6a2201), WTC(0xbd613d81), WTC(0xbd586281), WTC(0xbd4f9101), + WTC(0xbd46c801), WTC(0xbd3e0801), WTC(0xbd355081), WTC(0xbd2ca281), + WTC(0xbd23ff01), WTC(0xbd1b6501), WTC(0xbd12d581), WTC(0xbd0a4f81), + WTC(0xbd01d281), WTC(0xbcf95e81), WTC(0xbcf0f381), WTC(0xbce89281), + WTC(0xbce03b81), WTC(0xbcd7ef01), WTC(0xbccfac01), WTC(0xbcc77181), + WTC(0xbcbf4001), WTC(0xbcb71701), WTC(0xbcaef701), WTC(0xbca6e101), + WTC(0xbc9ed481), WTC(0xbc96d101), WTC(0xbc8ed701), WTC(0xbc86e581), + WTC(0xbc7efc81), WTC(0xbc771c01), WTC(0xbc6f4401), WTC(0xbc677501), + WTC(0xbc5fae81), WTC(0xbc57f101), WTC(0xbc503b81), WTC(0xbc488e81), + WTC(0xbc40e881), WTC(0xbc394901), WTC(0xbc31af01), WTC(0xbc2a1a81), + WTC(0xbc228f01), WTC(0xbc1b1081), WTC(0xbc13a481), WTC(0xbc0c4581), + WTC(0xbc04e381), WTC(0xbbfd6c01), WTC(0xbbf5d181), WTC(0xbbee2f81), + WTC(0xbbe6c801), WTC(0xbbdfdb81), WTC(0xbbd9a781), WTC(0xbbd45881), + WTC(0xbbd01301), WTC(0xbbccfc81), WTC(0xbbcb2281), WTC(0xbbca5d01), + WTC(0xbbca7481), WTC(0xbbcb3201), WTC(0xbbcc6b01), WTC(0xbbce0601), + WTC(0xbbcfea81), WTC(0xbbd20301), WTC(0xbbd45601), WTC(0xbbd70201), + WTC(0xbbda2501), WTC(0xbbdddb01), WTC(0xbbe23281), WTC(0xbbe73201), + WTC(0xbbece281), WTC(0xbbf34281), WTC(0xbbfa3c01), WTC(0xbc01b381), + WTC(0xbc098d81), WTC(0xbc11b681), WTC(0xbc1a2401), WTC(0xbc22cd81), + WTC(0xbc2bab01), WTC(0xbc34c081), WTC(0xbc3e1981), WTC(0xbc47c281), + WTC(0xbc51cb01), WTC(0xbc5c4c81), WTC(0xbc676501), WTC(0xbc733401), + WTC(0xbc7fd301), WTC(0xbc8d5101), WTC(0xbc9bb901), WTC(0xbcab1781), + WTC(0xbcbb7001), WTC(0xbcccbd01), WTC(0xbcdef701), WTC(0xbcf21601), + WTC(0xbd060c81), WTC(0xbd1ac801), WTC(0xbd303581), WTC(0xbd464281), + WTC(0xbd5ce281), WTC(0xbd740b81), WTC(0xbd8bb281), WTC(0xbda3d081), + WTC(0xbdbc6381), WTC(0xbdd56b81), WTC(0xbdeee981), WTC(0xbe08e181), + WTC(0xbe236001), WTC(0xbe3e7201), WTC(0xbe5a2301), WTC(0xbe767e81), + WTC(0xbe938c81), WTC(0xbeb15701), WTC(0xbecfe601), WTC(0xbeef4601), + WTC(0xbf0f8301), WTC(0xbf30a901), WTC(0xbf52c101), WTC(0xbf75cc81), + WTC(0xbf99cb01), WTC(0xbfbebb81), WTC(0xbfe48981), WTC(0xc00b04c0), + WTC(0xc031f880), WTC(0xc0593340), WTC(0xc0809280), WTC(0xc0a802c0), + WTC(0xc0cf6ec0), WTC(0xc0f6cc00), WTC(0xc11e3a80), WTC(0xc145f040), + WTC(0xc16e22c0), WTC(0xc196fb00), WTC(0xc1c08680), WTC(0xc1eaca00), + WTC(0xc215cbc0), WTC(0xc2418940), WTC(0xc26df5c0), WTC(0xc29b02c0), + WTC(0xc2c8a140), WTC(0xc2f6b500), WTC(0xc3251740), WTC(0xc353a0c0), + WTC(0xc3822c00), WTC(0xc3b09940), WTC(0xc3deccc0), WTC(0xc40ca800), + WTC(0xc43a28c0), WTC(0xc4678a00), WTC(0xc4951780), WTC(0xc4c31d00), + WTC(0xc4f1bdc0), WTC(0xc520e840), WTC(0xc5508440), WTC(0xc5807900), + WTC(0xc5b09e80), WTC(0xc5e0bfc0), WTC(0xc610a740), WTC(0xc64029c0), + WTC(0xc66f49c0), WTC(0xc69e2180), WTC(0xc6ccca40), WTC(0xc6fb5700), + WTC(0xc729cc80), WTC(0xc7582b40), WTC(0xc7867480), WTC(0xc7b4a480), + WTC(0xc7e2afc0), WTC(0xc8108a80), WTC(0xc83e28c0), WTC(0xc86b7f00), + WTC(0xc8988100), WTC(0xc8c52340), WTC(0xc8f15980), WTC(0xc91d1840), + WTC(0xb4d6a381), WTC(0xb4422b81), WTC(0xb3ae8601), WTC(0xb31bb301), + WTC(0xb289b181), WTC(0xb1f88181), WTC(0xb1682281), WTC(0xb0d89401), + WTC(0xb049d601), WTC(0xafbbe801), WTC(0xaf2ec901), WTC(0xaea27681), + WTC(0xae16f001), WTC(0xad8c3301), WTC(0xad023f01), WTC(0xac791401), + WTC(0xabf0b181), WTC(0xab691681), WTC(0xaae24301), WTC(0xaa5c3601), + WTC(0xa9d6ef01), WTC(0xa9526d81), WTC(0xa8ceb201), WTC(0xa84bbb81), + WTC(0xa7c98b01), WTC(0xa7482101), WTC(0xa6c77e01), WTC(0xa647a301), + WTC(0xa5c89001), WTC(0xa54a4701), WTC(0xa4ccc901), WTC(0xa4501601), + WTC(0xa3d43001), WTC(0xa3591801), WTC(0xa2dece81), WTC(0xa2655581), + WTC(0xa1ecae01), WTC(0xa174da81), WTC(0xa0fddd81), WTC(0xa087b981), + WTC(0xa0127081), WTC(0x9f9e0301), WTC(0x9f2a7281), WTC(0x9eb7c101), + WTC(0x9e45f081), WTC(0x9dd50481), WTC(0x9d650081), WTC(0x9cf5e701), + WTC(0x9c87ba81), WTC(0x9c1a7c81), WTC(0x9bae2f81), WTC(0x9b42d581), + WTC(0x9ad87081), WTC(0x9a6f0381), WTC(0x9a069001), WTC(0x999f1981), + WTC(0x9938a281), WTC(0x98d32d81), WTC(0x986ebd81), WTC(0x980b5501), + WTC(0x97a8f681), WTC(0x9747a481), WTC(0x96e76101), WTC(0x96882e01), + WTC(0x962a0c81), WTC(0x95ccff01), WTC(0x95710601), WTC(0x95162381), + WTC(0x94bc5981), WTC(0x9463a881), WTC(0x940c1281), WTC(0x93b59901), + WTC(0x93603d01), WTC(0x930bff81), WTC(0x92b8e101), WTC(0x9266e281), + WTC(0x92160301), WTC(0x91c64301), WTC(0x9177a301), WTC(0x912a2201), + WTC(0x90ddc001), WTC(0x90927b81), WTC(0x90485401), WTC(0x8fff4601), + WTC(0x8fb74f81), WTC(0x8f706f01), WTC(0x8f2aa101), WTC(0x8ee5e301), + WTC(0x8ea23201), WTC(0x8e5f8881), WTC(0x8e1de001), WTC(0x8ddd3201), + WTC(0x8d9d7781), WTC(0x8d5eaa01), WTC(0x8d20c301), WTC(0x8ce3ba81), + WTC(0x8ca78781), WTC(0x8c6c1b01), WTC(0x8c316681), WTC(0x8bf75b01), + WTC(0x8bbde981), WTC(0x8b850281), WTC(0x8b4c9701), WTC(0x8b149701), + WTC(0x8adcee01), WTC(0x8aa58681), WTC(0x8a6e4a01), WTC(0x8a372881), + WTC(0x8a001f01), WTC(0x89c92f81), WTC(0x89925a81), WTC(0x895bcd01), + WTC(0x8925f101), WTC(0x88f13801), WTC(0x88be1681), WTC(0x888d3181), + WTC(0x885f8481), WTC(0x88353501), WTC(0x88124281), WTC(0x87e73d81), + WTC(0x87d4ac81), WTC(0x87cb5101), WTC(0x87c05e81), WTC(0x87b42481), + WTC(0x87a70e81), WTC(0x87998f01), WTC(0x878c1881), WTC(0x877ede01), + WTC(0x8771c601), WTC(0x8764b101), WTC(0x87578181), WTC(0x874a2f01), + WTC(0x873cc201), WTC(0x872f4201), WTC(0x8721b481), WTC(0x87141b01), + WTC(0x87067281), WTC(0x86f8ba81), WTC(0x86eaf081), WTC(0x86dd1481), + WTC(0x86cf2601), WTC(0x86c12401), WTC(0x86b30f01), WTC(0x86a4e781), + WTC(0x8696ad01), WTC(0x86886001), WTC(0x867a0081), WTC(0x866b8d81), + WTC(0x865d0581), WTC(0x864e6901), WTC(0x863fb701), WTC(0x8630f181), + WTC(0x86221801), WTC(0x86132c01), WTC(0x86042c01), WTC(0x85f51681), + WTC(0x85e5eb81), WTC(0x85d6a981), WTC(0x85c75201), WTC(0x85b7e601), + WTC(0x85a86581), WTC(0x8598d081), WTC(0x85892681), WTC(0x85796601), + WTC(0x85698e81), WTC(0x8559a081), WTC(0x85499d01), WTC(0x85398481), + WTC(0x85295881), WTC(0x85191801), WTC(0x8508c181), WTC(0x84f85581), + WTC(0x84e7d381), WTC(0x84d73c01), WTC(0x84c69101), WTC(0x84b5d301), + WTC(0x84a50201), WTC(0x84941d81), WTC(0x84832481), WTC(0x84721701), + WTC(0x8460f581), WTC(0x844fc081), WTC(0x843e7a81), WTC(0x842d2281), + WTC(0x841bb981), WTC(0x840a3e81), WTC(0x83f8b001), WTC(0x83e70f01), + WTC(0x83d55d01), WTC(0x83c39a81), WTC(0x83b1c881), WTC(0x839fe801), + WTC(0x838df801), WTC(0x837bf801), WTC(0x8369e781), WTC(0x8357c701), + WTC(0x83459881), WTC(0x83335c81), WTC(0x83211501), WTC(0x830ec081), + WTC(0x82fc5f01), WTC(0x82e9ef01), WTC(0x82d77201), WTC(0x82c4e801), + WTC(0x82b25301), WTC(0x829fb401), WTC(0x828d0b01), WTC(0x827a5801), + WTC(0x82679901), WTC(0x8254cf01), WTC(0x8241fa01), WTC(0x822f1b01), + WTC(0x821c3401), WTC(0x82094581), WTC(0x81f64f01), WTC(0x81e34f81), + WTC(0x81d04681), WTC(0x81bd3401), WTC(0x81aa1981), WTC(0x8196f781), + WTC(0x8183cf81), WTC(0x8170a181), WTC(0x815d6c01), WTC(0x814a2f81), + WTC(0x8136ea01), WTC(0x81239d81), WTC(0x81104a01), WTC(0x80fcf181), + WTC(0x80e99401), WTC(0x80d63101), WTC(0x80c2c781), WTC(0x80af5701), + WTC(0x809bdf01), WTC(0x80886081), WTC(0x8074dc01), WTC(0x80615281), + WTC(0x804dc481), WTC(0x803a3381), WTC(0x80269f81), WTC(0x80130981), + WTC(0x0a608220), WTC(0x0a8ee7d0), WTC(0x0abe35c0), WTC(0x0aee5de0), + WTC(0x0b1f5230), WTC(0x0b5104a0), WTC(0x0b836720), WTC(0x0bb66bb0), + WTC(0x0bea0440), WTC(0x0c1e22c0), WTC(0x0c52ba70), WTC(0x0c87ca90), + WTC(0x0cbd5ba0), WTC(0x0cf375e0), WTC(0x0d2a1f50), WTC(0x0d615480), + WTC(0x0d990e40), WTC(0x0dd14500), WTC(0x0e09f730), WTC(0x0e432e90), + WTC(0x0e7cf790), WTC(0x0eb75e50), WTC(0x0ef26430), WTC(0x0f2dfd70), + WTC(0x0f6a1d70), WTC(0x0fa6b7e0), WTC(0x0fe3c3d0), WTC(0x10213ac0), + WTC(0x105f1640), WTC(0x109d4f20), WTC(0x10dbdb80), WTC(0x111ab0c0), + WTC(0x1159c360), WTC(0x11990fc0), WTC(0x11d8a060), WTC(0x121882c0), + WTC(0x1258c480), WTC(0x12995a40), WTC(0x12da1b00), WTC(0x131adb60), + WTC(0x135b70c0), WTC(0x139bb680), WTC(0x13db8c00), WTC(0x141ad080), + WTC(0x14596460), WTC(0x149729e0), WTC(0x14d404e0), WTC(0x150fd8e0), + WTC(0x154a88c0), WTC(0x1583f5e0), WTC(0x15bc0120), WTC(0x15f28ba0), + WTC(0x162779a0), WTC(0x165ab300), WTC(0x168c2040), WTC(0x16bbaa80), + WTC(0x16e94120), WTC(0x1714d9e0), WTC(0x173e6440), WTC(0x17660680), + WTC(0x178ca020), WTC(0x17b36400), WTC(0x17db84e0), WTC(0x1805d920), + WTC(0x18328400), WTC(0x18617cc0), WTC(0x1892bfa0), WTC(0x18c64540), + WTC(0x18fc0400), WTC(0x1933f140), WTC(0x196e0320), WTC(0x19aa2fc0), + WTC(0x19e86d80), WTC(0x1a28b2e0), WTC(0x1a6af700), WTC(0x1aaf3320), + WTC(0x1af56180), WTC(0x1b3d7ce0), WTC(0x1b877c40), WTC(0x1bd350c0), + WTC(0x1c20ea40), WTC(0x1c703840), WTC(0x1cc13860), WTC(0x1d13f760), + WTC(0x1d688420), WTC(0x1dbeed40), WTC(0x1e174660), WTC(0x1e71a640), + WTC(0x1ece2400), WTC(0x1f2cd220), WTC(0x1f8db3c0), WTC(0x1ff0c3e0), + WTC(0x20560080), WTC(0x20bd46c0), WTC(0x21263400), WTC(0x21905740), + WTC(0x21fb4100), WTC(0x2266ba80), WTC(0x22d2d140), WTC(0x233f9780), + WTC(0x23ad25c0), WTC(0x241bc800), WTC(0x248bf040), WTC(0x24fe1380), + WTC(0x25728180), WTC(0x25e90a00), WTC(0x26614080), WTC(0x26dabdc0), + WTC(0x27552540), WTC(0x27d03200), WTC(0x284ba580), WTC(0x28c740c0), + WTC(0x29431f80), WTC(0x29bfc9c0), WTC(0x2a3dd080), WTC(0x2abdc000), + WTC(0x2b3ffd00), WTC(0x2bc4cd80), WTC(0x2c4c7d40), WTC(0x2cd72ec0), + WTC(0x2d647f80), WTC(0x2df3cd80), WTC(0x2e847d80), WTC(0x2f15ea40), + WTC(0x2fa760c0), WTC(0x30382b80), WTC(0x30c79440), WTC(0x315566c0), + WTC(0x31e20800), WTC(0x326de7c0), WTC(0x32f98200), WTC(0x3385ba00), + WTC(0x3413bec0), WTC(0x34a4c480), WTC(0x3539bf00), WTC(0x35d2c4c0), + WTC(0x366f8340), WTC(0x370fb800), WTC(0x37b2cf80), WTC(0x3857a480), + WTC(0x38fcee80), WTC(0x39a16840), WTC(0x3a4422c0), WTC(0x3ae495c0), + WTC(0x3b824000), WTC(0x3c1cb500), WTC(0x3cb438c0), WTC(0x3d4994c0), + WTC(0x3ddd8f40), WTC(0x3e70ec00), WTC(0x3f045e40), WTC(0x3f989080), + WTC(0x402e32ff), WTC(0x40c5c07f), WTC(0x415f547f), WTC(0x41faf07f), + WTC(0x4298997f), WTC(0x4338307f), WTC(0x43d96bff), WTC(0x447bffff), + WTC(0x451f9cff), WTC(0x45c3daff), WTC(0x46683eff), WTC(0x470c4cff), + WTC(0x47af93ff), WTC(0x4851c3ff), WTC(0x48f29d7f), WTC(0x4991de7f), + WTC(0x4a2f5e7f), WTC(0x4acb287f), WTC(0x4b65537f), WTC(0x4bfdf37f), + WTC(0x4c95337f), WTC(0x4d2b51ff), WTC(0x4dc091ff), WTC(0x4e5533ff), + WTC(0x4ee96b7f), WTC(0x4f7d61ff), WTC(0x501140ff), WTC(0x50a5317f), + WTC(0x51395a7f), WTC(0x51cddf7f), WTC(0x5262e6ff), WTC(0x52f885ff), + WTC(0x538eb47f), WTC(0x542560ff), WTC(0x54bc7b7f), WTC(0x5553a8ff), + WTC(0x55ea35ff), WTC(0x567f66ff), WTC(0x5712897f), WTC(0x57a33a7f), + WTC(0x583152ff), WTC(0x58bca5ff), WTC(0x594530ff), WTC(0x59cb79ff), + WTC(0x5a5047ff), WTC(0x5ad45eff), WTC(0x5b584e7f), WTC(0x5bdc417f), + WTC(0x5c60487f), WTC(0x5ce476ff), WTC(0x5d68c47f), WTC(0x5ded06ff), + WTC(0x5e7111ff), WTC(0x5ef4b5ff), WTC(0x5f77a17f), WTC(0x5ff96aff), + WTC(0x6079a7ff), WTC(0x60f7f7ff), WTC(0x617417ff), WTC(0x61edd87f), + WTC(0x6264ffff), WTC(0x62d9a6ff), WTC(0x634c817f), WTC(0x63be657f), + WTC(0x6430277f), WTC(0x64a2247f), WTC(0x65142bff), WTC(0x6586027f), + WTC(0x65f7697f), WTC(0x666801ff), WTC(0x66d756ff), WTC(0x6744f0ff), + WTC(0x67b0787f), WTC(0x681a077f), WTC(0x6881ebff), WTC(0x68e8707f), + WTC(0x694dceff), WTC(0x69b21e7f), WTC(0x6a156cff), WTC(0x6a77ca7f), + WTC(0x6ad9377f), WTC(0x6b39a4ff), WTC(0x6b9901ff), WTC(0x6bf73cff), + WTC(0x6c54457f), WTC(0x6cb00aff), WTC(0x6d0a7bff), WTC(0x6d6387ff), + WTC(0xae2cbe01), WTC(0xaf526d01), WTC(0xb0751201), WTC(0xb194da81), + WTC(0xb2b1f401), WTC(0xb3cc8d01), WTC(0xb4e4d201), WTC(0xb5faf101), + WTC(0xb70f1881), WTC(0xb8217301), WTC(0xb9321181), WTC(0xba40ee01), + WTC(0xbb4e0201), WTC(0xbc594781), WTC(0xbd62b881), WTC(0xbe6a5181), + WTC(0xbf700d01), WTC(0xc073e4c0), WTC(0xc175d240), WTC(0xc275cc80), + WTC(0xc373cb80), WTC(0xc46fca00), WTC(0xc569c600), WTC(0xc661bdc0), + WTC(0xc757af80), WTC(0xc84b9840), WTC(0xc93d7300), WTC(0xca2d3a40), + WTC(0xcb1aea40), WTC(0xcc068280), WTC(0xccf00480), WTC(0xcdd77200), + WTC(0xcebccb40), WTC(0xcfa00d80), WTC(0xd0813540), WTC(0xd1603f00), + WTC(0xd23d2980), WTC(0xd317f7c0), WTC(0xd3f0ac40), WTC(0xd4c74980), + WTC(0xd59bcf80), WTC(0xd66e3b00), WTC(0xd73e8900), WTC(0xd80cb740), + WTC(0xd8d8c7c0), WTC(0xd9a2be00), WTC(0xda6a9e40), WTC(0xdb306a40), + WTC(0xdbf42080), WTC(0xdcb5be80), WTC(0xdd754140), WTC(0xde32a900), + WTC(0xdeedf9c0), WTC(0xdfa737c0), WTC(0xe05e6740), WTC(0xe1138900), + WTC(0xe1c69ac0), WTC(0xe2779a40), WTC(0xe3268680), WTC(0xe3d36260), + WTC(0xe47e33a0), WTC(0xe526ff80), WTC(0xe5cdc960), WTC(0xe6729100), + WTC(0xe7155460), WTC(0xe7b611c0), WTC(0xe854ca20), WTC(0xe8f18180), + WTC(0xe98c3ca0), WTC(0xea24ffe0), WTC(0xeabbcb20), WTC(0xeb509b60), + WTC(0xebe36d00), WTC(0xec743e00), WTC(0xed0310e0), WTC(0xed8feaa0), + WTC(0xee1ad060), WTC(0xeea3c640), WTC(0xef2acd60), WTC(0xefafe6a0), + WTC(0xf03312f0), WTC(0xf0b45800), WTC(0xf133c230), WTC(0xf1b15ef0), + WTC(0xf22d3af0), WTC(0xf2a75c80), WTC(0xf31fc460), WTC(0xf39673b0), + WTC(0xf40b6a00), WTC(0xf47ea230), WTC(0xf4f01450), WTC(0xf55fb930), + WTC(0xf5cd84c0), WTC(0xf6396090), WTC(0xf6a333e0), WTC(0xf70ae540), + WTC(0xf7707260), WTC(0xf7d3f720), WTC(0xf83592f0), WTC(0xf8956450), + WTC(0xf8f38120), WTC(0xf94ff7c8), WTC(0xf9aad740), WTC(0xfa042920), + WTC(0xfa5be110), WTC(0xfab1e778), WTC(0xfb062478), WTC(0xfb588d78), + WTC(0xfba93530), WTC(0xfbf836c8), WTC(0xfc45ace0), WTC(0xfc91a294), + WTC(0xfcdc0e5c), WTC(0xfd24e438), WTC(0xfd6c17dc), WTC(0xfdb19758), + WTC(0xfdf54c3c), WTC(0xfe371ef8), WTC(0xfe7701aa), WTC(0xfeb50d62), + WTC(0xfef1700a), WTC(0xff2c5574), WTC(0xff65ee7b), WTC(0xff9e75de), + WTC(0xffd62863), WTC(0x000d4401), WTC(0x0043d345), WTC(0x00799cd0), + WTC(0x00ae5f49), WTC(0x00e1d7a4), WTC(0x0113a6f2), WTC(0x0143575c), + WTC(0x01707024), WTC(0x019a9346), WTC(0x01c1cf08), WTC(0x01e66c12), + WTC(0x0208ac48), WTC(0x0228e868), WTC(0x0247a6c8), WTC(0x02657aa0), + WTC(0x0282f710), WTC(0x02a07e50), WTC(0x02be31c0), WTC(0x02dc2b30), + WTC(0x02fa7f34), WTC(0x0318fb10), WTC(0x03372fdc), WTC(0x0354ae54), + WTC(0x03710d18), WTC(0x038bfdb4), WTC(0x03a54084), WTC(0x03bc92b8), + WTC(0x03d1c710), WTC(0x03e4dd20), WTC(0x03f5e25c), WTC(0x0404e218), + WTC(0x0411fc30), WTC(0x041d6b30), WTC(0x04276cd0), WTC(0x04303e00), + WTC(0x04381528), WTC(0x043f2310), WTC(0x04459908), WTC(0x044ba430), + WTC(0x045161f8), WTC(0x0456e6f8), WTC(0x045c49a8), WTC(0x046192f8), + WTC(0x0466af40), WTC(0x046b8240), WTC(0x046ff0d8), WTC(0x0473de18), + WTC(0x04772b58), WTC(0x0479b9a0), WTC(0x047b6a30), WTC(0x047c2088), + WTC(0x047bc230), WTC(0x047a3418), WTC(0x04776098), WTC(0x04734790), + WTC(0x046df4c0), WTC(0x04677220), WTC(0x045fd1b0), WTC(0x04573588), + WTC(0x044dc4b8), WTC(0x0443a5b8), WTC(0x04390160), WTC(0x042e0398), + WTC(0x0422d8c0), WTC(0x0417aa30), WTC(0x040c7ce0), WTC(0x040136e0), + WTC(0x03f5beb0), WTC(0x03e9f8ec), WTC(0x03ddc484), WTC(0x03d0fd9c), + WTC(0x03c37fa0), WTC(0x03b53014), WTC(0x03a60a18), WTC(0x03960f88), + WTC(0x03854110), WTC(0x0373ad9c), WTC(0x03617694), WTC(0x034ebf9c), + WTC(0x033bab30), WTC(0x03284ef0), WTC(0x0314b598), WTC(0x0300ea54), + WTC(0x02ecf524), WTC(0x02d8d210), WTC(0x02c476ac), WTC(0x02afd940), + WTC(0x029aee4c), WTC(0x0285a6f4), WTC(0x026ff398), WTC(0x0259c448), + WTC(0x024317cc), WTC(0x022c0084), WTC(0x02149310), WTC(0x01fce334), + WTC(0x01e4fb24), WTC(0x01ccdd0a), WTC(0x01b48b20), WTC(0x019c077e), + WTC(0x01835432), WTC(0x016a733c), WTC(0x015166a6), WTC(0x0138302e), + WTC(0x011ed0f6), WTC(0x010549f8), WTC(0x00eb9c25), WTC(0x00d1caa6), + WTC(0x00b7db94), WTC(0x009dd560), WTC(0x0083be75), WTC(0x00699d41), + WTC(0x004f782f), WTC(0x003555ab), WTC(0x001b3c21), WTC(0x000131fe), + WTC(0xd61cfc40), WTC(0xd5acb340), WTC(0xd53d4400), WTC(0xd4cea6c0), + WTC(0xd460d440), WTC(0xd3f3c440), WTC(0xd3876f80), WTC(0xd31bce40), + WTC(0xd2b0d900), WTC(0xd2468980), WTC(0xd1dcef00), WTC(0xd17429c0), + WTC(0xd10c5b80), WTC(0xd0a59b80), WTC(0xd03fd780), WTC(0xcfdae780), + WTC(0xcf76a380), WTC(0xcf12fac0), WTC(0xceb01100), WTC(0xce4e18c0), + WTC(0xcded4440), WTC(0xcd8d9a40), WTC(0xcd2ee800), WTC(0xccd0f440), + WTC(0xcc738780), WTC(0xcc167d40), WTC(0xcbb9c180), WTC(0xcb5d4040), + WTC(0xcb00e240), WTC(0xcaa48000), WTC(0xca47eac0), WTC(0xc9eaf1c0), + WTC(0xc98d8100), WTC(0xc92fc580), WTC(0xc8d1fc80), WTC(0xc8746480), + WTC(0xc816dc40), WTC(0xc7b8c280), WTC(0xc7596800), WTC(0xc6f81f80), + WTC(0xc6945740), WTC(0xc62d93c0), WTC(0xc5c358c0), WTC(0xc5552b80), + WTC(0xc4e29240), WTC(0xc46b1440), WTC(0xc3ee3840), WTC(0xc36b8500), + WTC(0xc2e28040), WTC(0xc252ae80), WTC(0xc1bb9540), WTC(0xc11cc200), + WTC(0xc075cf00), WTC(0xbfc65781), WTC(0xbf0df881), WTC(0xbe4c6f01), + WTC(0xbd819401), WTC(0xbcad2d01), WTC(0xbbcfb981), WTC(0xbaeca681), + WTC(0xba08e781), WTC(0xb9297081), WTC(0xb851e081), WTC(0xb782ed01), + WTC(0xb6bc6a81), WTC(0xb5fe4981), WTC(0xb5487281), WTC(0xb49ad081), + WTC(0xb3f54d81), WTC(0xb357d401), WTC(0xb2c24e01), WTC(0xb234a681), + WTC(0xb1aec701), WTC(0xb1309b01), WTC(0xb0ba0c01), WTC(0xb04b0481), + WTC(0xafe36f01), WTC(0xaf833601), WTC(0xaf2a4381), WTC(0xaed88201), + WTC(0xae8ddb81), WTC(0xae4a3b81), WTC(0xae0d8b01), WTC(0xadd7b581), + WTC(0xada8a481), WTC(0xad804281), WTC(0xad5e7a81), WTC(0xad433601), + WTC(0xad2e6001), WTC(0xad1fe281), WTC(0xad17a801), WTC(0xad159a81), + WTC(0xad19a501), WTC(0xad23b101), WTC(0xad33aa01), WTC(0xad497981), + WTC(0xad650a01), WTC(0xad864601), WTC(0xadad1781), WTC(0xadd96981), + WTC(0xae0b2601), WTC(0xae423781), WTC(0xae7e8801), WTC(0xaec00201), + WTC(0xaf069081), WTC(0xaf521c81), WTC(0xafa29201), WTC(0xaff7da01), + WTC(0xb051df01), WTC(0xb0b08c81), WTC(0xb113cb81), WTC(0xb17b8701), + WTC(0xb1e7a981), WTC(0xb2581d81), WTC(0xb2cccc81), WTC(0xb345a181), + WTC(0xb3c28701), WTC(0xb4436681), WTC(0xb4c82b81), WTC(0xb550bf81), + WTC(0xb5dd0d01), WTC(0xb66cff01), WTC(0xb7007f01), WTC(0xb7977781), + WTC(0xb831d381), WTC(0xb8cf7d01), WTC(0xb9705e01), WTC(0xba146101), + WTC(0xbabb7081), WTC(0xbb657781), WTC(0xbc125f01), WTC(0xbcc21281), + WTC(0xbd747b81), WTC(0xbe298581), WTC(0xbee11981), WTC(0xbf9b2301), + WTC(0xc0578b80), WTC(0xc1163dc0), WTC(0xc1d72400), WTC(0xc29a28c0), + WTC(0xc35f3640), WTC(0xc42636c0), WTC(0xc4ef1500), WTC(0xc5b9bb00), + WTC(0xc6861340), WTC(0xc7540840), WTC(0xc8238400), WTC(0xc8f47100), + WTC(0xc9c6b9c0), WTC(0xca9a4840), WTC(0xcb6f0780), WTC(0xcc44e140), + WTC(0xcd1bc000), WTC(0xcdf38e00), WTC(0xcecc3600), WTC(0xcfa5a240), + WTC(0xd07fbcc0), WTC(0xd15a7040), WTC(0xd235a6c0), WTC(0xd3114b00), + WTC(0xd3ed4740), WTC(0xd4c98580), WTC(0xd5a5f080), WTC(0xd6827280), + WTC(0xd75ef600), WTC(0xd83b6500), WTC(0xd917aa00), WTC(0xd9f3af80), + WTC(0xdacf5fc0), WTC(0xdbaaa540), WTC(0xdc856a00), WTC(0xdd5f98c0), + WTC(0xde391bc0), WTC(0xdf11dd40), WTC(0xdfe9c780), WTC(0xe0c0c540), + WTC(0xe196c080), WTC(0xe26ba3c0), WTC(0xe33f5960), WTC(0xe411cba0), + WTC(0xe4e2e500), WTC(0xe5b28fc0), WTC(0xe680b640), WTC(0xe74d42e0), + WTC(0xe8181fe0), WTC(0xe8e137e0), WTC(0xe9a87500), WTC(0xea6dc1a0), + WTC(0xeb310820), WTC(0xebf23300), WTC(0xecb12c60), WTC(0xed6ddee0), + WTC(0xee2834a0), WTC(0xeee01800), WTC(0xef957380), WTC(0xf0483160), + WTC(0xf0f83c00), WTC(0xf1a57db0), WTC(0xf24fe0f0), WTC(0xf2f74ff0), + WTC(0xf39bb530), WTC(0xf43cfaf0), WTC(0xf4db0b90), WTC(0xf575d180), + WTC(0xf60d3700), WTC(0xf6a12680), WTC(0xf7318a50), WTC(0xf7be4cc0), + WTC(0xf8475850), WTC(0xf8cc9738), WTC(0xf94df3e0), WTC(0xf9cb58a8), + WTC(0xfa44afe0), WTC(0xfab9e3e8), WTC(0xfb2adf20), WTC(0xfb978be8), + WTC(0xfbffd488), WTC(0xfc63a370), WTC(0xfcc2e2f0), WTC(0xfd1d7d64), + WTC(0xfd735d2c), WTC(0xfdc46c9c), WTC(0xfe109618), WTC(0xfe57c3f4), + WTC(0xfe99e090), WTC(0xfed6d644), WTC(0xff0e8f6e), WTC(0xff40f667), + WTC(0xff6df58c), WTC(0xff957738), WTC(0xffb765c5), WTC(0xffd3ab90), + WTC(0xffea32f4), WTC(0xfffae64c), WTC(0x0005aff3), WTC(0x000a7a44), + WTC(0x00092f9c), WTC(0x0001ba54), WTC(0xfff404ca), WTC(0xffdff957)}; + +/* + * TNS_MAX_BANDS + * entry for each sampling rate + * 1 long window + * 2 SHORT window + */ +const UCHAR tns_max_bands_tbl[13][2] = { + {31, 9}, /* 96000 */ + {31, 9}, /* 88200 */ + {34, 10}, /* 64000 */ + {40, 14}, /* 48000 */ + {42, 14}, /* 44100 */ + {51, 14}, /* 32000 */ + {46, 14}, /* 24000 */ + {46, 14}, /* 22050 */ + {42, 14}, /* 16000 */ + {42, 14}, /* 12000 */ + {42, 14}, /* 11025 */ + {39, 14}, /* 8000 */ + {39, 14}, /* 7350 */ +}; + +/* TNS_MAX_BANDS for low delay. The array index is the sampleRateIndex */ +const UCHAR tns_max_bands_tbl_480[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 30, /* 24000 */ + 30, /* 22050 */ + 30, /* 16000 */ + 30, /* 12000 */ + 30, /* 11025 */ + 30, /* 8000 */ + 30 /* 7350 */ +}; +const UCHAR tns_max_bands_tbl_512[13] = { + 31, /* 96000 */ + 31, /* 88200 */ + 31, /* 64000 */ + 31, /* 48000 */ + 32, /* 44100 */ + 37, /* 32000 */ + 31, /* 24000 */ + 31, /* 22050 */ + 31, /* 16000 */ + 31, /* 12000 */ + 31, /* 11025 */ + 31, /* 8000 */ + 31 /* 7350 */ +}; + +#define TCC(x) (FIXP_DBL(x)) + +const FIXP_TCC FDKaacDec_tnsCoeff3[8] = { + TCC(0x81f1d1d4), TCC(0x9126146c), TCC(0xadb922c4), TCC(0xd438af1f), + TCC(0x00000000), TCC(0x3789809b), TCC(0x64130dd4), TCC(0x7cca7016)}; +const FIXP_TCC FDKaacDec_tnsCoeff4[16] = { + TCC(0x808bc842), TCC(0x84e2e58c), TCC(0x8d6b49d1), TCC(0x99da920a), + TCC(0xa9c45713), TCC(0xbc9ddeb9), TCC(0xd1c2d51b), TCC(0xe87ae53d), + TCC(0x00000000), TCC(0x1a9cd9b6), TCC(0x340ff254), TCC(0x4b3c8c29), + TCC(0x5f1f5ebb), TCC(0x6ed9ebba), TCC(0x79bc385f), TCC(0x7f4c7e5b)}; + +const UCHAR FDKaacDec_tnsCoeff3_gain_ld[] = { + 3, 1, 1, 1, 0, 1, 1, 3, +}; +const UCHAR FDKaacDec_tnsCoeff4_gain_ld[] = { + 4, 2, 2, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 4, +}; + +/* Lookup tables for elements in ER bitstream */ +const MP4_ELEMENT_ID + elementsTab[AACDEC_MAX_CH_CONF][AACDEC_CH_ELEMENTS_TAB_SIZE] = { + /* 1 */ {ID_SCE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* 1 channel */ + /* 2 */ + {ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, ID_NONE, + ID_NONE} /* 2 channels */ +#if (AACDEC_MAX_CH_CONF > 2) + /* 3 */, + {ID_SCE, ID_CPE, ID_EXT, ID_END, ID_NONE, ID_NONE, + ID_NONE}, /* 3 channels */ + /* 4 */ + {ID_SCE, ID_CPE, ID_SCE, ID_EXT, ID_END, ID_NONE, + ID_NONE}, /* 4 channels */ + /* 5 */ + {ID_SCE, ID_CPE, ID_CPE, ID_EXT, ID_END, ID_NONE, + ID_NONE}, /* 5 channels */ + /* 6 */ + {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, ID_END, + ID_NONE} /* 6 channels */ +#endif +#if (AACDEC_MAX_CH_CONF > 6) + /* 7 */, + {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, + ID_END}, /* 8 channels */ + /* 8 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 9 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 10 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* reserved */ + /* 11 */ + {ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_EXT, + ID_END}, /* 7 channels */ + /* 12 */ + {ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_EXT, + ID_END}, /* 8 channels */ + /* 13 */ + {ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, ID_NONE, + ID_NONE}, /* see elementsChCfg13 */ + /* 14 */ + {ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_EXT, + ID_END} /* 8 channels */ +#endif +}; + +/*! Random sign bit used for concealment + */ +const USHORT AacDec_randomSign[AAC_NF_NO_RANDOM_VAL / 16] = { + /* + sign bits of FDK_sbrDecoder_sbr_randomPhase[] entries: + LSB ........... MSB -> MSB ... LSB + */ + /* 1001 0111 0011 1100 -> */ 0x3ce9, + /* 0100 0111 0111 1011 -> */ 0xdee2, + /* 0001 1100 1110 1011 -> */ 0xd738, + /* 0001 0011 0110 1001 -> */ 0x96c8, + /* 0101 0011 1101 0000 -> */ 0x0bca, + /* 0001 0001 1111 0100 -> */ 0x2f88, + /* 1110 1100 1110 1101 -> */ 0xb737, + /* 0010 1010 1011 1001 -> */ 0x9d54, + /* 0111 1100 0110 1010 -> */ 0x563e, + /* 1101 0111 0010 0101 -> */ 0xa4eb, + /* 0001 0101 1011 1100 -> */ 0x3da8, + /* 0101 0111 1001 1011 -> */ 0xd9ea, + /* 1101 0100 0101 0101 -> */ 0xaa2b, + /* 1000 1001 0100 0011 -> */ 0xc291, + /* 1100 1111 1010 1100 -> */ 0x35f3, + /* 1100 1010 1110 0010 -> */ 0x4753, + /* 0110 0001 1010 1000 -> */ 0x1586, + /* 0011 0101 1111 1100 -> */ 0x3fac, + /* 0001 0110 1010 0001 -> */ 0x8568, + /* 0010 1101 0111 0010 -> */ 0x4eb4, + /* 1101 1010 0100 1001 -> */ 0x925b, + /* 1100 1001 0000 1110 -> */ 0x7093, + /* 1000 1100 0110 1010 -> */ 0x5631, + /* 0000 1000 0110 1101 -> */ 0xb610, + /* 1000 0001 1111 1011 -> */ 0xdf81, + /* 1111 0011 0100 0111 -> */ 0xe2cf, + /* 1000 0001 0010 1010 -> */ 0x5481, + /* 1101 0101 1100 1111 -> */ 0xf3ab, + /* 0110 0001 0110 1000 -> */ 0x1686, + /* 0011 0011 1100 0110 -> */ 0x63cc, + /* 0011 0111 0101 0110 -> */ 0x6aec, + /* 1011 0001 1010 0010 -> */ 0x458d}; + +/* MDST filter coefficients for current window + * max: 0.635722 => 20 bits (unsigned) necessary for representation + * min: = -max */ +const FIXP_FILT mdst_filt_coef_curr[20][3] = { + {FILT(0.000000f), FILT(0.000000f), FILT(0.500000f)}, + /*, FILT( 0.000000f), FILT(-0.500000f), FILT( 0.000000f), FILT( 0.000000f) }, */ /* only long / eight short l:sine r:sine */ + {FILT(0.091497f), FILT(0.000000f), FILT(0.581427f)}, + /*, FILT( 0.000000f), FILT(-0.581427f), FILT( 0.000000f), FILT(-0.091497f) }, */ /* l:kbd r:kbd */ + {FILT(0.045748f), FILT(0.057238f), FILT(0.540714f)}, + /*, FILT( 0.000000f), FILT(-0.540714f), FILT(-0.057238f), FILT(-0.045748f) }, */ /* l:sine r:kbd */ + {FILT(0.045748f), FILT(-0.057238f), FILT(0.540714f)}, + /*, FILT( 0.000000f), FILT(-0.540714f), FILT( 0.057238f), FILT(-0.045748f) }, */ /* l:kbd r:sine */ + + {FILT(0.102658f), FILT(0.103791f), FILT(0.567149f)}, + /*, FILT( 0.000000f), FILT(-0.567149f), FILT(-0.103791f), FILT(-0.102658f) }, */ /* long start */ + {FILT(0.150512f), FILT(0.047969f), + FILT(0.608574f)}, /*, FILT( 0.000000f), FILT(-0.608574f), + FILT(-0.047969f), FILT(-0.150512f) }, */ + {FILT(0.104763f), FILT(0.105207f), + FILT(0.567861f)}, /*, FILT( 0.000000f), FILT(-0.567861f), + FILT(-0.105207f), FILT(-0.104763f) }, */ + {FILT(0.148406f), FILT(0.046553f), + FILT(0.607863f)}, /*, FILT( 0.000000f), FILT(-0.607863f), + FILT(-0.046553f), FILT(-0.148406f) }, */ + + {FILT(0.102658f), FILT(-0.103791f), FILT(0.567149f)}, + /*, FILT( 0.000000f), FILT(-0.567149f), FILT( 0.103791f), FILT(-0.102658f) }, */ /* long stop */ + {FILT(0.150512f), FILT(-0.047969f), + FILT(0.608574f)}, /*, FILT( 0.000000f), FILT(-0.608574f), FILT( + 0.047969f), FILT(-0.150512f) }, */ + {FILT(0.148406f), FILT(-0.046553f), + FILT(0.607863f)}, /*, FILT( 0.000000f), FILT(-0.607863f), FILT( + 0.046553f), FILT(-0.148406f) }, */ + {FILT(0.104763f), FILT(-0.105207f), + FILT(0.567861f)}, /*, FILT( 0.000000f), FILT(-0.567861f), FILT( + 0.105207f), FILT(-0.104763f) }, */ + + {FILT(0.205316f), FILT(0.000000f), FILT(0.634298f)}, + /*, FILT( 0.000000f), FILT(-0.634298f), FILT( 0.000000f), FILT(-0.205316f) }, */ /* stop start */ + {FILT(0.209526f), FILT(0.000000f), + FILT(0.635722f)}, /*, FILT( 0.000000f), FILT(-0.635722f), FILT( + 0.000000f), FILT(-0.209526f) }, */ + {FILT(0.207421f), FILT(0.001416f), + FILT(0.635010f)}, /*, FILT( 0.000000f), FILT(-0.635010f), + FILT(-0.001416f), FILT(-0.207421f) }, */ + {FILT(0.207421f), FILT(-0.001416f), + FILT(0.635010f)}, /*, FILT( 0.000000f), FILT(-0.635010f), FILT( + 0.001416f), FILT(-0.207421f) } */ + + {FILT(0.185618f), FILT(0.000000f), FILT(0.627371f)}, + /*, FILT( 0.000000f), FILT(-0.634298f), FILT( 0.000000f), FILT(-0.205316f) }, */ /* stop start Transform Splitting */ + {FILT(0.204932f), FILT(0.000000f), + FILT(0.634159f)}, /*, FILT( 0.000000f), FILT(-0.635722f), FILT( + 0.000000f), FILT(-0.209526f) }, */ + {FILT(0.194609f), FILT(0.006202f), + FILT(0.630536f)}, /*, FILT( 0.000000f), FILT(-0.635010f), + FILT(-0.001416f), FILT(-0.207421f) }, */ + {FILT(0.194609f), FILT(-0.006202f), + FILT(0.630536f)}, /*, FILT( 0.000000f), FILT(-0.635010f), FILT( + 0.001416f), FILT(-0.207421f) } */ +}; + +/* MDST filter coefficients for previous window + * max: 0.31831 => 15 bits (unsigned) necessary for representation + * min: 0.0 */ +const FIXP_FILT mdst_filt_coef_prev[6][4] = { + {FILT(0.000000f), FILT(0.106103f), FILT(0.250000f), FILT(0.318310f)}, + /*, FILT( 0.250000f), FILT( 0.106103f), FILT( 0.000000f) }, */ /* only long + / long + start / + eight + short + l:sine */ + {FILT(0.059509f), FILT(0.123714f), FILT(0.186579f), FILT(0.213077f)}, + /*, FILT( 0.186579f), FILT( 0.123714f), FILT( 0.059509f) }, */ /* l:kbd + */ + + {FILT(0.038498f), FILT(0.039212f), FILT(0.039645f), FILT(0.039790f)}, + /*, FILT( 0.039645f), FILT( 0.039212f), FILT( 0.038498f) }, */ /* long stop + / stop + start + l:sine */ + {FILT(0.026142f), FILT(0.026413f), FILT(0.026577f), FILT(0.026631f)}, + /*, FILT( 0.026577f), FILT( 0.026413f), FILT( 0.026142f) } */ /* l:kbd + */ + + {FILT(0.069608f), FILT(0.075028f), FILT(0.078423f), FILT(0.079580f)}, + /*, FILT( 0.039645f), FILT( 0.039212f), FILT( 0.038498f) }, */ /* Transform + splitting + l:sine */ + {FILT(0.042172f), FILT(0.043458f), FILT(0.044248f), FILT(0.044514f)}, + /*, FILT( 0.026577f), FILT( 0.026413f), FILT( 0.026142f) } */ /* l:kbd + */ +}; diff --git a/fdk-aac/libAACdec/src/aac_rom.h b/fdk-aac/libAACdec/src/aac_rom.h new file mode 100644 index 0000000..ffaf951 --- /dev/null +++ b/fdk-aac/libAACdec/src/aac_rom.h @@ -0,0 +1,237 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: Definition of constant tables + +*******************************************************************************/ + +#ifndef AAC_ROM_H +#define AAC_ROM_H + +#include "common_fix.h" +#include "FDK_audio.h" +#include "aacdec_hcr_types.h" +#include "aacdec_hcrs.h" + +#define PCM_DEC FIXP_DBL +#define MAXVAL_PCM_DEC MAXVAL_DBL +#define MINVAL_PCM_DEC MINVAL_DBL +#define FIXP_DBL2PCM_DEC(x) (x) +#define PCM_DEC2FIXP_DBL(x) (x) +#define PCM_DEC_BITS DFRACT_BITS +#define PCM_DEC2FX_PCM(x) FX_DBL2FX_PCM(x) +#define FX_PCM2PCM_DEC(x) FX_PCM2FX_DBL(x) + +#define AACDEC_MAX_CH_CONF 14 +#define AACDEC_CH_ELEMENTS_TAB_SIZE 7 /*!< Size of element tables */ + +#define AAC_NF_NO_RANDOM_VAL \ + 512 /*!< Size of random number array for noise floor */ + +#define INV_QUANT_TABLESIZE 256 + +extern const FIXP_DBL InverseQuantTable[INV_QUANT_TABLESIZE + 1]; +extern const FIXP_DBL MantissaTable[4][14]; +extern const SCHAR ExponentTable[4][14]; + +#define NUM_LD_COEF_512 1536 +#define NUM_LD_COEF_480 1440 +/* Window table partition exponents. */ +#define WTS0 (1) +#define WTS1 (0) +#define WTS2 (-2) +extern const FIXP_WTB LowDelaySynthesis512[1536]; +extern const FIXP_WTB LowDelaySynthesis480[1440]; +extern const FIXP_WTB LowDelaySynthesis256[768]; +extern const FIXP_WTB LowDelaySynthesis240[720]; +extern const FIXP_WTB LowDelaySynthesis160[480]; +extern const FIXP_WTB LowDelaySynthesis128[384]; +extern const FIXP_WTB LowDelaySynthesis120[360]; + +typedef struct { + const SHORT *sfbOffsetLong; + const SHORT *sfbOffsetShort; + UCHAR numberOfSfbLong; + UCHAR numberOfSfbShort; +} SFB_INFO; + +extern const SFB_INFO sfbOffsetTables[5][16]; + +/* Huffman tables */ +enum { HuffmanBits = 2, HuffmanEntries = (1 << HuffmanBits) }; + +typedef struct { + const USHORT (*CodeBook)[HuffmanEntries]; + UCHAR Dimension; + UCHAR numBits; + UCHAR Offset; +} CodeBookDescription; + +extern const CodeBookDescription AACcodeBookDescriptionTable[13]; +extern const CodeBookDescription AACcodeBookDescriptionSCL; + +extern const STATEFUNC aStateConstant2State[]; + +extern const SCHAR aCodebook2StartInt[]; + +extern const UCHAR aMinOfCbPair[]; +extern const UCHAR aMaxOfCbPair[]; + +extern const UCHAR aMaxCwLen[]; +extern const UCHAR aDimCb[]; +extern const UCHAR aDimCbShift[]; +extern const UCHAR aSignCb[]; +extern const UCHAR aCbPriority[]; + +extern const UINT *aHuffTable[]; +extern const SCHAR *aQuantTable[]; + +extern const USHORT aLargestAbsoluteValue[]; + +extern const UINT aHuffTreeRvlcEscape[]; +extern const UINT aHuffTreeRvlCodewds[]; + +extern const UCHAR tns_max_bands_tbl[13][2]; + +extern const UCHAR tns_max_bands_tbl_480[13]; +extern const UCHAR tns_max_bands_tbl_512[13]; + +#define FIXP_TCC FIXP_DBL + +extern const FIXP_TCC FDKaacDec_tnsCoeff3[8]; +extern const FIXP_TCC FDKaacDec_tnsCoeff4[16]; + +extern const UCHAR FDKaacDec_tnsCoeff3_gain_ld[]; +extern const UCHAR FDKaacDec_tnsCoeff4_gain_ld[]; + +extern const USHORT AacDec_randomSign[AAC_NF_NO_RANDOM_VAL / 16]; + +extern const FIXP_DBL pow2_div24minus1[47]; +extern const int offsetTab[2][16]; + +/* Channel mapping indices for time domain I/O. + The first dimension is the channel configuration index. */ +extern const UCHAR channelMappingTablePassthrough[15][8]; +extern const UCHAR channelMappingTableWAV[15][8]; + +/* Lookup tables for elements in ER bitstream */ +extern const MP4_ELEMENT_ID elementsTab[AACDEC_MAX_CH_CONF] + [AACDEC_CH_ELEMENTS_TAB_SIZE]; + +#define SF_FNA_COEFFS \ + 1 /* Compile-time prescaler for MDST-filter coefficients. */ +/* SF_FNA_COEFFS > 0 should only be considered for FIXP_DBL-coefficients */ +/* (i.e. if CPLX_PRED_FILTER_16BIT is not defined). */ +/* With FIXP_DBL loss of precision is possible for SF_FNA_COEFFS > 11. */ + +#ifdef CPLX_PRED_FILTER_16BIT +#define FIXP_FILT FIXP_SGL +#define FILT(a) ((FL2FXCONST_SGL(a)) >> SF_FNA_COEFFS) +#else +#define FIXP_FILT FIXP_DBL +#define FILT(a) ((FL2FXCONST_DBL(a)) >> SF_FNA_COEFFS) +#endif + +extern const FIXP_FILT mdst_filt_coef_curr[20][3]; /* MDST-filter coefficient + tables used for current + window */ +extern const FIXP_FILT mdst_filt_coef_prev[6][4]; /* MDST-filter coefficient + tables used for previous + window */ + +#endif /* #ifndef AAC_ROM_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_drc.cpp b/fdk-aac/libAACdec/src/aacdec_drc.cpp new file mode 100644 index 0000000..922a09e --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_drc.cpp @@ -0,0 +1,1355 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for AAC + +*******************************************************************************/ + +#include "aacdec_drc.h" + +#include "channelinfo.h" +#include "aac_rom.h" + +#include "sbrdecoder.h" + +/* + * Dynamic Range Control + */ + +/* For parameter conversion */ +#define DRC_PARAMETER_BITS (7) +#define DRC_MAX_QUANT_STEPS (1 << DRC_PARAMETER_BITS) +#define DRC_MAX_QUANT_FACTOR (DRC_MAX_QUANT_STEPS - 1) +#define DRC_PARAM_QUANT_STEP \ + (FL2FXCONST_DBL(1.0f / (float)DRC_MAX_QUANT_FACTOR)) +#define DRC_PARAM_SCALE (1) +#define DRC_SCALING_MAX \ + ((FIXP_DBL)((INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)127)) + +#define DRC_BLOCK_LEN (1024) +#define DRC_BAND_MULT (4) +#define DRC_BLOCK_LEN_DIV_BAND_MULT (DRC_BLOCK_LEN / DRC_BAND_MULT) + +#define MAX_REFERENCE_LEVEL (127) + +#define DRC_HEAVY_THRESHOLD_DB (10) + +#define DVB_ANC_DATA_SYNC_BYTE (0xBC) /* DVB ancillary data sync byte. */ + +#define OFF 0 +#define ON 1 + +static INT convert_drcParam(FIXP_DBL param_dbl) { + /* converts an internal DRC boost/cut scaling factor in FIXP_DBL + (which is downscaled by DRC_PARAM_SCALE) + back to an integer value between 0 and 127. */ + LONG param_long; + + param_long = (LONG)param_dbl >> 7; + param_long = param_long * (INT)DRC_MAX_QUANT_FACTOR; + param_long >>= 31 - 7 - DRC_PARAM_SCALE - 1; + param_long += 1; /* for rounding */ + param_long >>= 1; + + return (INT)param_long; +} + +/*! + \brief Initialize DRC information + + \self Handle of DRC info + + \return none +*/ +void aacDecoder_drcInit(HANDLE_AAC_DRC self) { + CDrcParams *pParams; + + if (self == NULL) { + return; + } + + /* init control fields */ + self->enable = OFF; + self->numThreads = 0; + + /* init params */ + pParams = &self->params; + pParams->bsDelayEnable = 0; + pParams->cut = FL2FXCONST_DBL(0.0f); + pParams->usrCut = FL2FXCONST_DBL(0.0f); + pParams->boost = FL2FXCONST_DBL(0.0f); + pParams->usrBoost = FL2FXCONST_DBL(0.0f); + pParams->targetRefLevel = -1; + pParams->expiryFrame = AACDEC_DRC_DFLT_EXPIRY_FRAMES; + pParams->applyDigitalNorm = OFF; + pParams->applyHeavyCompression = OFF; + pParams->usrApplyHeavyCompression = OFF; + + pParams->defaultPresentationMode = DISABLED_PARAMETER_HANDLING; + pParams->encoderTargetLevel = MAX_REFERENCE_LEVEL; /* worst case assumption */ + + self->update = 1; + self->numOutChannels = 0; + self->prevAacNumChannels = 0; + + /* initial program ref level = target ref level */ + self->progRefLevel = pParams->targetRefLevel; + self->progRefLevelPresent = 0; + self->presMode = -1; + self->uniDrcPrecedence = 0; +} + +/*! + \brief Initialize DRC control data for one channel + + \self Handle of DRC info + + \return none +*/ +void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChData) { + if (pDrcChData != NULL) { + pDrcChData->expiryCount = 0; + pDrcChData->numBands = 1; + pDrcChData->bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + pDrcChData->drcValue[0] = 0; + pDrcChData->drcInterpolationScheme = 0; + pDrcChData->drcDataType = UNKNOWN_PAYLOAD; + } +} + +/*! + \brief Set one single DRC parameter + + \self Handle of DRC info. + \param Parameter to be set. + \value Value to be set. + + \return an error code. +*/ +AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, INT value) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + switch (param) { + case DRC_CUT_SCALE: + /* set attenuation scale factor */ + if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrCut = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value); + self->update = 1; + break; + case DRC_BOOST_SCALE: + /* set boost factor */ + if ((value < 0) || (value > DRC_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.usrBoost = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * (INT)value); + self->update = 1; + break; + case TARGET_REF_LEVEL: + if (value > MAX_REFERENCE_LEVEL || value < -MAX_REFERENCE_LEVEL) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + if (value < 0) { + self->params.applyDigitalNorm = OFF; + self->params.targetRefLevel = -1; + } else { + /* ref_level must be between 0 and MAX_REFERENCE_LEVEL, inclusive */ + self->params.applyDigitalNorm = ON; + if (self->params.targetRefLevel != (SCHAR)value) { + self->params.targetRefLevel = (SCHAR)value; + self->progRefLevel = (SCHAR)value; /* Always set the program reference + level equal to the target level + according to 4.5.2.7.3 of + ISO/IEC 14496-3. */ + } + self->update = 1; + } + break; + case APPLY_NORMALIZATION: + if ((value != OFF) && (value != ON)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + /* Store new parameter value */ + self->params.applyDigitalNorm = (UCHAR)value; + break; + case APPLY_HEAVY_COMPRESSION: + if ((value != OFF) && (value != ON)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + /* Store new parameter value */ + self->params.usrApplyHeavyCompression = (UCHAR)value; + self->update = 1; + break; + case DEFAULT_PRESENTATION_MODE: + if (value < AAC_DRC_PARAMETER_HANDLING_DISABLED || + value > AAC_DRC_PRESENTATION_MODE_2_DEFAULT) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.defaultPresentationMode = + (AACDEC_DRC_PARAMETER_HANDLING)value; + self->update = 1; + break; + case ENCODER_TARGET_LEVEL: + if (value > MAX_REFERENCE_LEVEL || value < 0) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.encoderTargetLevel = (UCHAR)value; + self->update = 1; + break; + case DRC_BS_DELAY: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.bsDelayEnable = value; + break; + case DRC_DATA_EXPIRY_FRAME: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->params.expiryFrame = (value > 0) ? (UINT)value : 0; + break; + case MAX_OUTPUT_CHANNELS: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->numOutChannels = (INT)value; + self->update = 1; + break; + case UNIDRC_PRECEDENCE: + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + self->uniDrcPrecedence = (UCHAR)value; + break; + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + + return ErrorStatus; +} + +static int parseExcludedChannels(UINT *excludedChnsMask, + HANDLE_FDK_BITSTREAM bs) { + UINT excludeMask = 0; + UINT i, j; + int bitCnt = 9; + + for (i = 0, j = 1; i < 7; i++, j <<= 1) { + if (FDKreadBits(bs, 1)) { + excludeMask |= j; + } + } + + /* additional_excluded_chns */ + while (FDKreadBits(bs, 1)) { + for (i = 0; i < 7; i++, j <<= 1) { + if (FDKreadBits(bs, 1)) { + excludeMask |= j; + } + } + bitCnt += 9; + FDK_ASSERT(j < (UINT)-1); + } + + *excludedChnsMask = excludeMask; + + return (bitCnt); +} + +/*! + \brief Save DRC payload bitstream position + + \self Handle of DRC info + \bs Handle of FDK bitstream + + \return The number of DRC payload bits +*/ +int aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM bs, + AACDEC_DRC_PAYLOAD_TYPE type) { + UINT bsStartPos; + int i, numBands = 1, bitCnt = 0; + + if (self == NULL) { + return 0; + } + + bsStartPos = FDKgetValidBits(bs); + + switch (type) { + case MPEG_DRC_EXT_DATA: { + bitCnt = 4; + + if (FDKreadBits(bs, 1)) { /* pce_tag_present */ + FDKreadBits(bs, 8); /* pce_instance_tag + drc_tag_reserved_bits */ + bitCnt += 8; + } + + if (FDKreadBits(bs, 1)) { /* excluded_chns_present */ + FDKreadBits(bs, 7); /* exclude mask [0..7] */ + bitCnt += 8; + while (FDKreadBits(bs, 1)) { /* additional_excluded_chns */ + FDKreadBits(bs, 7); /* exclude mask [x..y] */ + bitCnt += 8; + } + } + + if (FDKreadBits(bs, 1)) { /* drc_bands_present */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + FDKreadBits(bs, 4); /* reserved */ + bitCnt += 8; + for (i = 0; i < numBands; i++) { + FDKreadBits(bs, 8); /* drc_band_top[i] */ + bitCnt += 8; + } + } + + if (FDKreadBits(bs, 1)) { /* prog_ref_level_present */ + FDKreadBits(bs, 8); /* prog_ref_level + prog_ref_level_reserved_bits */ + bitCnt += 8; + } + + for (i = 0; i < numBands; i++) { + FDKreadBits(bs, 8); /* dyn_rng_sgn[i] + dyn_rng_ctl[i] */ + bitCnt += 8; + } + + if ((self->numPayloads < MAX_DRC_THREADS) && + ((INT)FDKgetValidBits(bs) >= 0)) { + self->drcPayloadPosition[self->numPayloads++] = bsStartPos; + } + } break; + + case DVB_DRC_ANC_DATA: + bitCnt += 8; + /* check sync word */ + if (FDKreadBits(bs, 8) == DVB_ANC_DATA_SYNC_BYTE) { + int dmxLevelsPresent, compressionPresent; + int coarseGrainTcPresent, fineGrainTcPresent; + + /* bs_info field */ + FDKreadBits( + bs, + 8); /* mpeg_audio_type, dolby_surround_mode, presentation_mode */ + bitCnt += 8; + + /* Evaluate ancillary_data_status */ + FDKreadBits(bs, 3); /* reserved, set to 0 */ + dmxLevelsPresent = + FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + FDKreadBits(bs, 1); /* reserved, set to 0 */ + compressionPresent = + FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + coarseGrainTcPresent = + FDKreadBits(bs, 1); /* coarse_grain_timecode_status */ + fineGrainTcPresent = + FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + bitCnt += 8; + + /* MPEG4 downmixing levels */ + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + bitCnt += 8; + } + /* audio coding mode and compression status */ + if (compressionPresent) { + FDKreadBits(bs, 16); /* audio_coding_mode, Compression_value */ + bitCnt += 16; + } + /* coarse grain timecode */ + if (coarseGrainTcPresent) { + FDKreadBits(bs, 16); /* coarse_grain_timecode */ + bitCnt += 16; + } + /* fine grain timecode */ + if (fineGrainTcPresent) { + FDKreadBits(bs, 16); /* fine_grain_timecode */ + bitCnt += 16; + } + if (!self->dvbAncDataAvailable && ((INT)FDKgetValidBits(bs) >= 0)) { + self->dvbAncDataPosition = bsStartPos; + self->dvbAncDataAvailable = 1; + } + } + break; + + default: + break; + } + + return (bitCnt); +} + +/*! + \brief Parse DRC parameters from bitstream + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of MPEG DRC data chunk (in) + + \return Flag telling whether new DRC data has been found or not. +*/ +static int aacDecoder_drcParse(HANDLE_FDK_BITSTREAM bs, CDrcPayload *pDrcBs, + UINT payloadPosition) { + int i, numBands; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition); + + /* pce_tag_present */ + if (FDKreadBits(bs, 1)) { + pDrcBs->pceInstanceTag = FDKreadBits(bs, 4); /* pce_instance_tag */ + /* only one program supported */ + FDKreadBits(bs, 4); /* drc_tag_reserved_bits */ + } else { + pDrcBs->pceInstanceTag = -1; /* not present */ + } + + if (FDKreadBits(bs, 1)) { /* excluded_chns_present */ + /* get excluded_chn_mask */ + parseExcludedChannels(&pDrcBs->excludedChnsMask, bs); + } else { + pDrcBs->excludedChnsMask = 0; + } + + numBands = 1; + if (FDKreadBits(bs, 1)) /* drc_bands_present */ + { + /* get band_incr */ + numBands += FDKreadBits(bs, 4); /* drc_band_incr */ + pDrcBs->channelData.drcInterpolationScheme = + FDKreadBits(bs, 4); /* drc_interpolation_scheme */ + /* band_top */ + for (i = 0; i < numBands; i++) { + pDrcBs->channelData.bandTop[i] = FDKreadBits(bs, 8); /* drc_band_top[i] */ + } + } else { + pDrcBs->channelData.bandTop[0] = DRC_BLOCK_LEN_DIV_BAND_MULT - + 1; /* ... comprising the whole spectrum. */ + ; + } + + pDrcBs->channelData.numBands = numBands; + + if (FDKreadBits(bs, 1)) /* prog_ref_level_present */ + { + pDrcBs->progRefLevel = FDKreadBits(bs, 7); /* prog_ref_level */ + FDKreadBits(bs, 1); /* prog_ref_level_reserved_bits */ + } else { + pDrcBs->progRefLevel = -1; + } + + for (i = 0; i < numBands; i++) { + pDrcBs->channelData.drcValue[i] = FDKreadBits(bs, 1) + << 7; /* dyn_rng_sgn[i] */ + pDrcBs->channelData.drcValue[i] |= + FDKreadBits(bs, 7) & 0x7F; /* dyn_rng_ctl[i] */ + } + + /* Set DRC payload type */ + pDrcBs->channelData.drcDataType = MPEG_DRC_EXT_DATA; + + return (1); +} + +/*! + \brief Parse heavy compression value transported in DSEs of DVB streams with + MPEG-4 content. + + \bs Handle of FDK bitstream (in) + \pDrcBs Pointer to DRC payload data container (out) + \payloadPosition Bitstream position of DVB ancillary data chunk + + \return Flag telling whether new DRC data has been found or not. +*/ +#define DVB_COMPRESSION_SCALE (8) /* 48,164 dB */ + +static int aacDecoder_drcReadCompression(HANDLE_FDK_BITSTREAM bs, + CDrcPayload *pDrcBs, + UINT payloadPosition) { + int foundDrcData = 0; + int dmxLevelsPresent, compressionPresent; + + /* Move to the beginning of the DRC payload field */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - (INT)payloadPosition); + + /* Sanity checks */ + if (FDKgetValidBits(bs) < 24) { + return 0; + } + + /* Check sync word */ + if (FDKreadBits(bs, 8) != DVB_ANC_DATA_SYNC_BYTE) { + return 0; + } + + /* Evaluate bs_info field */ + if (FDKreadBits(bs, 2) != 3) { /* mpeg_audio_type */ + /* No MPEG-4 audio data */ + return 0; + } + FDKreadBits(bs, 2); /* dolby_surround_mode */ + pDrcBs->presMode = FDKreadBits(bs, 2); /* presentation_mode */ + FDKreadBits(bs, 1); /* stereo_downmix_mode */ + if (FDKreadBits(bs, 1) != 0) { /* reserved, set to 0 */ + return 0; + } + + /* Evaluate ancillary_data_status */ + if (FDKreadBits(bs, 3) != 0) { /* reserved, set to 0 */ + return 0; + } + dmxLevelsPresent = FDKreadBits(bs, 1); /* downmixing_levels_MPEG4_status */ + /*extensionPresent =*/FDKreadBits(bs, + 1); /* ancillary_data_extension_status; */ + compressionPresent = + FDKreadBits(bs, 1); /* audio_coding_mode_and_compression status */ + /*coarseGrainTcPresent =*/FDKreadBits(bs, + 1); /* coarse_grain_timecode_status */ + /*fineGrainTcPresent =*/FDKreadBits(bs, 1); /* fine_grain_timecode_status */ + + if (dmxLevelsPresent) { + FDKreadBits(bs, 8); /* downmixing_levels_MPEG4 */ + } + + /* audio_coding_mode_and_compression_status */ + if (compressionPresent) { + UCHAR compressionOn, compressionValue; + + /* audio_coding_mode */ + if (FDKreadBits(bs, 7) != 0) { /* The reserved bits shall be set to "0". */ + return 0; + } + compressionOn = (UCHAR)FDKreadBits(bs, 1); /* compression_on */ + compressionValue = (UCHAR)FDKreadBits(bs, 8); /* Compression_value */ + + if (compressionOn) { + /* A compression value is available so store the data just like MPEG DRC + * data */ + pDrcBs->channelData.numBands = 1; /* One band ... */ + pDrcBs->channelData.drcValue[0] = + compressionValue; /* ... with one value ... */ + pDrcBs->channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - + 1; /* ... comprising the whole spectrum. */ + ; + pDrcBs->pceInstanceTag = -1; /* Not present */ + pDrcBs->progRefLevel = -1; /* Not present */ + pDrcBs->channelData.drcDataType = + DVB_DRC_ANC_DATA; /* Set DRC payload type to DVB. */ + foundDrcData = 1; + } + } + + return (foundDrcData); +} + +/* + * Extract DRC payload from bitstream and map it to channels. + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +static int aacDecoder_drcExtractAndMap( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + CDrcPayload threadBs[MAX_DRC_THREADS]; + CDrcPayload *validThreadBs[MAX_DRC_THREADS]; + CDrcParams *pParams; + UINT backupBsPosition; + int result = 0; + int i, thread, validThreads = 0; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(hBs != NULL); + FDK_ASSERT(pAacDecoderStaticChannelInfo != NULL); + + pParams = &self->params; + + self->numThreads = 0; + backupBsPosition = FDKgetValidBits(hBs); + + for (i = 0; i < self->numPayloads && self->numThreads < MAX_DRC_THREADS; + i++) { + /* Init payload data chunk. The memclear is very important because it + initializes the most values. Without it the module wouldn't work properly + or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + + /* Extract payload */ + self->numThreads += aacDecoder_drcParse(hBs, &threadBs[self->numThreads], + self->drcPayloadPosition[i]); + } + self->numPayloads = 0; + + if (self->dvbAncDataAvailable && + self->numThreads < MAX_DRC_THREADS) { /* Append a DVB heavy compression + payload thread if available. */ + + /* Init payload data chunk. The memclear is very important because it + initializes the most values. Without it the module wouldn't work properly + or crash. */ + FDKmemclear(&threadBs[self->numThreads], sizeof(CDrcPayload)); + threadBs[self->numThreads].channelData.bandTop[0] = + DRC_BLOCK_LEN_DIV_BAND_MULT - 1; + + /* Extract payload */ + self->numThreads += aacDecoder_drcReadCompression( + hBs, &threadBs[self->numThreads], self->dvbAncDataPosition); + } + self->dvbAncDataAvailable = 0; + + /* Reset the bitbufffer */ + FDKpushBiDirectional(hBs, (INT)FDKgetValidBits(hBs) - (INT)backupBsPosition); + + /* calculate number of valid bits in excl_chn_mask */ + + /* coupling channels not supported */ + + /* check for valid threads */ + for (thread = 0; thread < self->numThreads; thread++) { + CDrcPayload *pThreadBs = &threadBs[thread]; + int numExclChns = 0; + + switch ((AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType) { + default: + continue; + case MPEG_DRC_EXT_DATA: + case DVB_DRC_ANC_DATA: + break; + } + + if (pThreadBs->pceInstanceTag >= 0) { /* if PCE tag present */ + if (pThreadBs->pceInstanceTag != pceInstanceTag) { + continue; /* don't accept */ + } + } + + /* calculate number of excluded channels */ + if (pThreadBs->excludedChnsMask > 0) { + INT exclMask = pThreadBs->excludedChnsMask; + int ch; + for (ch = 0; ch < validChannels; ch++) { + numExclChns += exclMask & 0x1; + exclMask >>= 1; + } + } + if (numExclChns < validChannels) { + validThreadBs[validThreads] = pThreadBs; + validThreads++; + } + } + + /* map DRC bitstream information onto DRC channel information */ + for (thread = 0; thread < validThreads; thread++) { + CDrcPayload *pThreadBs = validThreadBs[thread]; + INT exclMask = pThreadBs->excludedChnsMask; + AACDEC_DRC_PAYLOAD_TYPE drcPayloadType = + (AACDEC_DRC_PAYLOAD_TYPE)pThreadBs->channelData.drcDataType; + int ch; + + /* last progRefLevel transmitted is the one that is used + * (but it should really only be transmitted once per block!) + */ + if (pThreadBs->progRefLevel >= 0) { + self->progRefLevel = pThreadBs->progRefLevel; + self->progRefLevelPresent = 1; + self->prlExpiryCount = 0; /* Got a new value -> Reset counter */ + } + + if (drcPayloadType == DVB_DRC_ANC_DATA) { + /* Announce the presentation mode of this valid thread. */ + self->presMode = pThreadBs->presMode; + } + + /* SCE, CPE and LFE */ + for (ch = 0; ch < validChannels; ch++) { + AACDEC_DRC_PAYLOAD_TYPE prvPayloadType = UNKNOWN_PAYLOAD; + int mapedChannel = channelMapping[ch]; + + if ((mapedChannel >= validChannels) || + ((exclMask & (1 << mapedChannel)) != 0)) + continue; + + if ((pParams->expiryFrame <= 0) || + (pAacDecoderStaticChannelInfo[ch]->drcData.expiryCount < + pParams->expiryFrame)) { + prvPayloadType = + (AACDEC_DRC_PAYLOAD_TYPE)pAacDecoderStaticChannelInfo[ch] + ->drcData.drcDataType; + } + if (((drcPayloadType == MPEG_DRC_EXT_DATA) && + (prvPayloadType != DVB_DRC_ANC_DATA)) || + ((drcPayloadType == DVB_DRC_ANC_DATA) && + (pParams->applyHeavyCompression == + ON))) { /* copy thread to channel */ + pAacDecoderStaticChannelInfo[ch]->drcData = pThreadBs->channelData; + result = 1; + } + } + /* CCEs not supported by now */ + } + + /* Increment and check expiry counter for the program reference level: */ + if ((pParams->expiryFrame > 0) && + (self->prlExpiryCount++ > + pParams->expiryFrame)) { /* The program reference level is too old, so + set it back to the target level. */ + self->progRefLevelPresent = 0; + self->progRefLevel = pParams->targetRefLevel; + self->prlExpiryCount = 0; + } + + return result; +} + +void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcChData, FIXP_DBL *extGain, + int ch, /* needed only for SBR */ + int aacFrameSize, int bSbrPresent) { + int band, bin, numBands; + int bottom = 0; + int modifyBins = 0; + + FIXP_DBL max_mantissa; + INT max_exponent; + + FIXP_DBL norm_mantissa = FL2FXCONST_DBL(0.5f); + INT norm_exponent = 1; + + FIXP_DBL fact_mantissa[MAX_DRC_BANDS]; + INT fact_exponent[MAX_DRC_BANDS]; + + CDrcParams *pParams = &self->params; + + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + int winSeq = pIcsInfo->WindowSequence; + + /* Increment and check expiry counter */ + if ((pParams->expiryFrame > 0) && + (++pDrcChData->expiryCount > + pParams->expiryFrame)) { /* The DRC data is too old, so delete it. */ + aacDecoder_drcInitChannelData(pDrcChData); + } + + if (self->enable != ON) { + sbrDecoder_drcDisable((HANDLE_SBRDECODER)pSbrDec, ch); + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed + * on by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale); + } else { + FDK_ASSERT(0); + } + } + return; + } + + numBands = pDrcChData->numBands; + + /* If program reference normalization is done in the digital domain, + modify factor to perform normalization. prog_ref_level can + alternatively be passed to the system for modification of the level in + the analog domain. Analog level modification avoids problems with + reduced DAC SNR (if signal is attenuated) or clipping (if signal is + boosted) */ + + if (pParams->targetRefLevel >= 0) { + /* 0.5^((targetRefLevel - progRefLevel)/24) */ + norm_mantissa = + fLdPow(FL2FXCONST_DBL(-1.0), /* log2(0.5) */ + 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0f / 24.0) >> 3) * + (INT)(pParams->targetRefLevel - self->progRefLevel)), + 3, &norm_exponent); + } + /* Always export the normalization gain (if possible). */ + if (extGain != NULL) { + INT gainScale = (INT)*extGain; + /* The gain scaling must be passed to the function in the buffer pointed on + * by extGain. */ + if (gainScale >= 0 && gainScale <= DFRACT_BITS) { + *extGain = scaleValue(norm_mantissa, norm_exponent - gainScale); + } else { + FDK_ASSERT(0); + } + } + if (self->params.applyDigitalNorm == OFF) { + /* Reset normalization gain since this module must not apply it */ + norm_mantissa = FL2FXCONST_DBL(0.5f); + norm_exponent = 1; + } + + /* calc scale factors */ + for (band = 0; band < numBands; band++) { + UCHAR drcVal = pDrcChData->drcValue[band]; + + fact_mantissa[band] = FL2FXCONST_DBL(0.5f); + fact_exponent[band] = 1; + + if ((pParams->applyHeavyCompression == ON) && + ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == + DVB_DRC_ANC_DATA)) { + INT compressionFactorVal_e; + int valX, valY; + + valX = drcVal >> 4; + valY = drcVal & 0x0F; + + /* calculate the unscaled heavy compression factor. + compressionFactor = 48.164 - 6.0206*valX - 0.4014*valY dB + range: -48.166 dB to 48.164 dB */ + if (drcVal != 0x7F) { + fact_mantissa[band] = fPowInt( + FL2FXCONST_DBL(0.95483867181), /* -0.4014dB = 0.95483867181 */ + 0, valY, &compressionFactorVal_e); + + /* -0.0008dB (48.164 - 6.0206*8 = -0.0008) */ + fact_mantissa[band] = + fMult(FL2FXCONST_DBL(0.99990790084), fact_mantissa[band]); + + fact_exponent[band] = + DVB_COMPRESSION_SCALE - valX + compressionFactorVal_e; + } + } else if ((AACDEC_DRC_PAYLOAD_TYPE)pDrcChData->drcDataType == + MPEG_DRC_EXT_DATA) { + /* apply the scaled dynamic range control words to factor. + * if scaling drc_cut (or drc_boost), or control word drc_mantissa is 0 + * then there is no dynamic range compression + * + * if pDrcChData->drcSgn[band] is + * 1 then gain is < 1 : factor = 2^(-self->cut * + * pDrcChData->drcMag[band] / 24) 0 then gain is > 1 : factor = 2^( + * self->boost * pDrcChData->drcMag[band] / 24) + */ + + if ((drcVal & 0x7F) > 0) { + FIXP_DBL tParamVal = (drcVal & 0x80) ? -pParams->cut : pParams->boost; + + fact_mantissa[band] = f2Pow( + (FIXP_DBL)((INT)fMult(FL2FXCONST_DBL(1.0f / 192.0f), tParamVal) * + (drcVal & 0x7F)), + 3 + DRC_PARAM_SCALE, &fact_exponent[band]); + } + } + + fact_mantissa[band] = fMult(fact_mantissa[band], norm_mantissa); + fact_exponent[band] += norm_exponent; + + } /* end loop over bands */ + + /* normalizations */ + { + int res; + + max_mantissa = FL2FXCONST_DBL(0.0f); + max_exponent = 0; + for (band = 0; band < numBands; band++) { + max_mantissa = fixMax(max_mantissa, fact_mantissa[band]); + max_exponent = fixMax(max_exponent, fact_exponent[band]); + } + + /* left shift factors to gain accurancy */ + res = CntLeadingZeros(max_mantissa) - 1; + + /* above topmost DRC band gain factor is 1 */ + if (((pDrcChData->bandTop[fMax(0, numBands - 1)] + 1) << 2) < aacFrameSize) + res = 0; + + if (res > 0) { + res = fixMin(res, max_exponent); + max_exponent -= res; + + for (band = 0; band < numBands; band++) { + fact_mantissa[band] <<= res; + fact_exponent[band] -= res; + } + } + + /* normalize magnitudes to one scale factor */ + for (band = 0; band < numBands; band++) { + if (fact_exponent[band] < max_exponent) { + fact_mantissa[band] >>= max_exponent - fact_exponent[band]; + } + if (fact_mantissa[band] != FL2FXCONST_DBL(0.5f)) { + modifyBins = 1; + } + } + if (max_exponent != 1) { + modifyBins = 1; + } + } + + /* apply factor to spectral lines + * short blocks must take care that bands fall on + * block boundaries! + */ + if (!bSbrPresent) { + bottom = 0; + + if (!modifyBins) { + /* We don't have to modify the spectral bins because the fractional part + of all factors is 0.5. In order to keep accurancy we don't apply the + factor but decrease the exponent instead. */ + max_exponent -= 1; + } else { + for (band = 0; band < numBands; band++) { + int top = fixMin((int)((pDrcChData->bandTop[band] + 1) << 2), + aacFrameSize); /* ... * DRC_BAND_MULT; */ + + for (bin = bottom; bin < top; bin++) { + pSpectralCoefficient[bin] = + fMult(pSpectralCoefficient[bin], fact_mantissa[band]); + } + + bottom = top; + } + } + + /* above topmost DRC band gain factor is 1 */ + if (max_exponent > 0) { + for (bin = bottom; bin < aacFrameSize; bin += 1) { + pSpectralCoefficient[bin] >>= max_exponent; + } + } + + /* adjust scaling */ + pSpecScale[0] += max_exponent; + + if (winSeq == BLOCK_SHORT) { + int win; + for (win = 1; win < 8; win++) { + pSpecScale[win] += max_exponent; + } + } + } else { + HANDLE_SBRDECODER hSbrDecoder = (HANDLE_SBRDECODER)pSbrDec; + numBands = pDrcChData->numBands; + + /* feed factors into SBR decoder for application in QMF domain. */ + sbrDecoder_drcFeedChannel(hSbrDecoder, ch, numBands, fact_mantissa, + max_exponent, pDrcChData->drcInterpolationScheme, + winSeq, pDrcChData->bandTop); + } + + return; +} + +/* + * DRC parameter and presentation mode handling + */ +static void aacDecoder_drcParameterHandling(HANDLE_AAC_DRC self, + INT aacNumChannels, + SCHAR prevDrcProgRefLevel, + SCHAR prevDrcPresMode) { + int isDownmix, isMonoDownmix, isStereoDownmix; + int dDmx, dHr; + AACDEC_DRC_PARAMETER_HANDLING drcParameterHandling; + CDrcParams *p; + + FDK_ASSERT(self != NULL); + + p = &self->params; + + if (self->progRefLevel != prevDrcProgRefLevel) self->update = 1; + + if (self->presMode != prevDrcPresMode) self->update = 1; + + if (self->prevAacNumChannels != aacNumChannels) self->update = 1; + + /* return if no relevant parameter has changed */ + if (!self->update) { + return; + } + + /* derive downmix property. aacNumChannels: number of channels in aac stream, + * numOutChannels: number of output channels */ + isDownmix = (aacNumChannels > self->numOutChannels); + isDownmix = (isDownmix && (self->numOutChannels > 0)); + isMonoDownmix = (isDownmix && (self->numOutChannels == 1)); + isStereoDownmix = (isDownmix && (self->numOutChannels == 2)); + + if ((self->presMode == 1) || (self->presMode == 2)) { + drcParameterHandling = (AACDEC_DRC_PARAMETER_HANDLING)self->presMode; + } else { /* no presentation mode -> use parameter handling specified by + AAC_DRC_DEFAULT_PRESENTATION_MODE */ + drcParameterHandling = p->defaultPresentationMode; + } + + /* by default, do as desired */ + p->cut = p->usrCut; + p->boost = p->usrBoost; + p->applyHeavyCompression = p->usrApplyHeavyCompression; + + switch (drcParameterHandling) { + case DISABLED_PARAMETER_HANDLING: + default: + /* use drc parameters as requested */ + break; + + case ENABLED_PARAMETER_HANDLING: + /* dDmx: estimated headroom reduction due to downmix, format: -1/4*dB + dDmx = floor(-4*20*log10(aacNumChannels/numOutChannels)) */ + if (isDownmix) { + FIXP_DBL dmxTmp; + int e_log, e_mult; + dmxTmp = fDivNorm(self->numOutChannels, + aacNumChannels); /* inverse division -> + negative sign after + logarithm */ + dmxTmp = fLog2(dmxTmp, 0, &e_log); + dmxTmp = fMultNorm( + dmxTmp, FL2FXCONST_DBL(4.0f * 20.0f * 0.30103f / (float)(1 << 5)), + &e_mult); /* e = e_log + e_mult + 5 */ + dDmx = (int)scaleValue(dmxTmp, e_log + e_mult + 5 - (DFRACT_BITS - 1)); + } else { + dDmx = 0; + } + + /* dHr: Full estimated (decoder) headroom reduction due to loudness + * normalisation (DTL - PRL) and downmix. Format: -1/4*dB */ + if (p->targetRefLevel >= 0) { /* if target level is provided */ + dHr = p->targetRefLevel + dDmx - self->progRefLevel; + } else { + dHr = dDmx; + } + + if (dHr < 0) { /* if headroom is reduced */ + /* Use compression, but as little as possible. */ + /* eHr: Headroom provided by encoder, format: -1/4 dB */ + int eHr = fixMin(p->encoderTargetLevel - self->progRefLevel, 0); + if (eHr < + dHr) { /* if encoder provides more headroom than decoder needs */ + /* derive scaling of light DRC */ + FIXP_DBL calcFactor_norm; + INT calcFactor; /* fraction of DRC gains that is minimally needed for + clipping prevention */ + calcFactor_norm = + fDivNorm(-dHr, -eHr); /* 0.0 < calcFactor_norm < 1.0 */ + calcFactor_norm = calcFactor_norm >> DRC_PARAM_SCALE; + /* quantize to 128 steps */ + calcFactor = convert_drcParam( + calcFactor_norm); /* convert to integer value between 0 and 127 */ + calcFactor_norm = (FIXP_DBL)( + (INT)(DRC_PARAM_QUANT_STEP >> DRC_PARAM_SCALE) * calcFactor); + p->cut = (calcFactor_norm > p->cut) + ? calcFactor_norm + : p->cut; /* use calcFactor_norm as lower limit */ + } else { + /* encoder provides equal or less headroom than decoder needs */ + /* the time domain limiter must always be active in this case. It is + * assumed that the framework activates it by default */ + p->cut = DRC_SCALING_MAX; + if ((dHr - eHr) <= + -4 * DRC_HEAVY_THRESHOLD_DB) { /* use heavy compression if + headroom deficit is equal or + higher than + DRC_HEAVY_THRESHOLD_DB */ + p->applyHeavyCompression = ON; + } + } + } else { /* dHr >= 0 */ + /* no restrictions required, as headroom is not reduced. */ + /* p->cut = p->usrCut; */ + } + break; + + /* presentation mode 1 and 2 according to ETSI TS 101 154: + Digital Video Broadcasting (DVB); Specification for the use of Video + and Audio Coding in Broadcasting Applications based on the MPEG-2 + Transport Stream, section C.5.4., "Decoding", and Table C.33. Also + according to amendment 4 to ISO/IEC 14496-3, section 4.5.2.14.2.4, and + Table AMD4.11. ISO DRC -> applyHeavyCompression = OFF (Use + light compression, MPEG-style) Compression_value -> + applyHeavyCompression = ON (Use heavy compression, DVB-style) scaling + restricted -> p->cut = DRC_SCALING_MAX */ + + case DRC_PRESENTATION_MODE_1: /* presentation mode 1, Light:-31/Heavy:-23 */ + if ((p->targetRefLevel >= 0) && + (p->targetRefLevel < + 124)) { /* if target level is provided and > -31 dB */ + /* playback up to -23 dB */ + p->applyHeavyCompression = ON; + } else { /* target level <= -31 dB or not provided */ + /* playback -31 dB */ + if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */ + p->cut = DRC_SCALING_MAX; + } + } + break; + + case DRC_PRESENTATION_MODE_2: /* presentation mode 2, Light:-23/Heavy:-23 */ + if ((p->targetRefLevel >= 0) && + (p->targetRefLevel < + 124)) { /* if target level is provided and > -31 dB */ + /* playback up to -23 dB */ + if (isMonoDownmix) { /* if mono downmix */ + p->applyHeavyCompression = ON; + } else { + p->applyHeavyCompression = OFF; + p->cut = DRC_SCALING_MAX; + } + } else { /* target level <= -31 dB or not provided */ + /* playback -31 dB */ + p->applyHeavyCompression = OFF; + if (isMonoDownmix || isStereoDownmix) { /* stereo or mono downmixing */ + p->cut = DRC_SCALING_MAX; + } + } + break; + } /* switch (drcParameterHandling) */ + + /* With heavy compression, there is no scaling. + Scaling factors are set for notification only. */ + if (p->applyHeavyCompression == ON) { + p->boost = DRC_SCALING_MAX; + p->cut = DRC_SCALING_MAX; + } + + /* switch on/off processing */ + self->enable = ((p->boost > (FIXP_DBL)0) || (p->cut > (FIXP_DBL)0) || + (p->applyHeavyCompression == ON) || (p->targetRefLevel >= 0)); + self->enable = (self->enable && !self->uniDrcPrecedence); + + self->prevAacNumChannels = aacNumChannels; + self->update = 0; +} + +/* + * Prepare DRC processing + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +int aacDecoder_drcProlog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + int result = 0; + + if (self == NULL) { + return -1; + } + + if (!self->params.bsDelayEnable) { + /* keep previous progRefLevel and presMode for update flag in + * drcParameterHandling */ + INT prevPRL, prevPM = 0; + prevPRL = self->progRefLevel; + prevPM = self->presMode; + + result = aacDecoder_drcExtractAndMap( + self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping, + validChannels); + + if (result < 0) { + return result; + } + + /* Drc parameter handling */ + aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM); + } + + return result; +} + +/* + * Finalize DRC processing + * Valid return values are: + * -1 : An unexpected error occured. + * 0 : No error and no valid DRC data available. + * 1 : No error and valid DRC data has been mapped. + */ +int aacDecoder_drcEpilog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, + UCHAR channelMapping[], /* Channel mapping translating drcChannel index to + canonical channel index */ + int validChannels) { + int result = 0; + + if (self == NULL) { + return -1; + } + + if (self->params.bsDelayEnable) { + /* keep previous progRefLevel and presMode for update flag in + * drcParameterHandling */ + INT prevPRL, prevPM = 0; + prevPRL = self->progRefLevel; + prevPM = self->presMode; + + result = aacDecoder_drcExtractAndMap( + self, hBs, pAacDecoderStaticChannelInfo, pceInstanceTag, channelMapping, + validChannels); + + if (result < 0) { + return result; + } + + /* Drc parameter handling */ + aacDecoder_drcParameterHandling(self, validChannels, prevPRL, prevPM); + } + + return result; +} + +/* + * Export relevant metadata info from bitstream payload. + */ +void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode, + SCHAR *pProgRefLevel) { + if (self != NULL) { + if (pPresMode != NULL) { + *pPresMode = self->presMode; + } + if (pProgRefLevel != NULL) { + if (self->progRefLevelPresent) { + *pProgRefLevel = self->progRefLevel; + } else { + *pProgRefLevel = -1; + } + } + } +} diff --git a/fdk-aac/libAACdec/src/aacdec_drc.h b/fdk-aac/libAACdec/src/aacdec_drc.h new file mode 100644 index 0000000..924ec6f --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_drc.h @@ -0,0 +1,192 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for AAC + +*******************************************************************************/ + +#ifndef AACDEC_DRC_H +#define AACDEC_DRC_H + +#include "tp_data.h" /* for program config element support */ + +#include "aacdec_drc_types.h" +#include "channel.h" +#include "FDK_bitstream.h" + +#define AACDEC_DRC_DFLT_EXPIRY_FRAMES \ + (0) /* Default DRC data expiry time in AAC frames */ + +/* #define AACDEC_DRC_IGNORE_FRAMES_WITH_MULTIPLE_CH_THREADS */ /* The name says + it all. */ +/* #define AACDEC_DRC_DEBUG */ + +/** + * \brief DRC module setting parameters + */ +typedef enum { + DRC_CUT_SCALE = 0, + DRC_BOOST_SCALE, + TARGET_REF_LEVEL, + DRC_BS_DELAY, + DRC_DATA_EXPIRY_FRAME, + APPLY_NORMALIZATION, + APPLY_HEAVY_COMPRESSION, + DEFAULT_PRESENTATION_MODE, + ENCODER_TARGET_LEVEL, + MAX_OUTPUT_CHANNELS, + UNIDRC_PRECEDENCE +} AACDEC_DRC_PARAM; + +/** + * \brief DRC module interface functions + */ +void aacDecoder_drcInit(HANDLE_AAC_DRC self); + +void aacDecoder_drcInitChannelData(CDrcChannelData *pDrcChannel); + +AAC_DECODER_ERROR aacDecoder_drcSetParam(HANDLE_AAC_DRC self, + AACDEC_DRC_PARAM param, INT value); + +int aacDecoder_drcMarkPayload(HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + AACDEC_DRC_PAYLOAD_TYPE type); + +int aacDecoder_drcProlog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, UCHAR channelMapping[], int validChannels); + +/** + * \brief Apply DRC. If SBR is present, DRC data is handed over to the SBR + * decoder. + * \param self AAC decoder instance + * \param pSbrDec pointer to SBR decoder instance + * \param pAacDecoderChannelInfo AAC decoder channel instance to be processed + * \param pDrcDat DRC channel data + * \param extGain Pointer to a FIXP_DBL where a externally applyable gain will + * be stored into (independently on whether it will be apply internally or not). + * At function call the buffer must hold the scale (0 >= scale < + * DFRACT_BITS) to be applied on the gain value. + * \param ch channel index + * \param aacFrameSize AAC frame size + * \param bSbrPresent flag indicating that SBR is present, in which case DRC is + * handed over to the SBR instance pSbrDec + */ +void aacDecoder_drcApply(HANDLE_AAC_DRC self, void *pSbrDec, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CDrcChannelData *pDrcDat, FIXP_DBL *extGain, int ch, + int aacFrameSize, int bSbrPresent); + +int aacDecoder_drcEpilog( + HANDLE_AAC_DRC self, HANDLE_FDK_BITSTREAM hBs, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + UCHAR pceInstanceTag, UCHAR channelMapping[], int validChannels); + +/** + * \brief Get metadata information found in bitstream. + * \param self DRC module instance handle. + * \param pPresMode Pointer to field where the presentation mode will be written + * to. + * \param pProgRefLevel Pointer to field where the program reference level will + * be written to. + * \return Nothing. + */ +void aacDecoder_drcGetInfo(HANDLE_AAC_DRC self, SCHAR *pPresMode, + SCHAR *pProgRefLevel); + +#endif /* AACDEC_DRC_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_drc_types.h b/fdk-aac/libAACdec/src/aacdec_drc_types.h new file mode 100644 index 0000000..76c35d0 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_drc_types.h @@ -0,0 +1,220 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) global data types + +*******************************************************************************/ + +#ifndef AACDEC_DRC_TYPES_H +#define AACDEC_DRC_TYPES_H + +#include "common_fix.h" + +#define MAX_DRC_THREADS \ + ((8) + 1) /* Heavy compression value is handled just like MPEG DRC data */ +#define MAX_DRC_BANDS (16) /* 2^LEN_DRC_BAND_INCR (LEN_DRC_BAND_INCR = 4) */ + +/** + * \brief DRC module global data types + */ +typedef enum { + UNKNOWN_PAYLOAD = 0, + MPEG_DRC_EXT_DATA = 1, + DVB_DRC_ANC_DATA = 2 + +} AACDEC_DRC_PAYLOAD_TYPE; + +/** + * \brief Options for parameter handling / presentation mode + */ +typedef enum { + DISABLED_PARAMETER_HANDLING = -1, /*!< DRC parameter handling disabled, all + parameters are applied as requested. */ + ENABLED_PARAMETER_HANDLING = + 0, /*!< Apply changes to requested DRC parameters to prevent clipping */ + DRC_PRESENTATION_MODE_1 = 1, /*!< DRC Presentation mode 1*/ + DRC_PRESENTATION_MODE_2 = 2 /*!< DRC Presentation mode 2*/ + +} AACDEC_DRC_PARAMETER_HANDLING; + +typedef struct { + UINT expiryCount; + UINT numBands; + USHORT bandTop[MAX_DRC_BANDS]; + SHORT drcInterpolationScheme; + UCHAR drcValue[MAX_DRC_BANDS]; + SCHAR drcDataType; + +} CDrcChannelData; + +typedef struct { + UINT excludedChnsMask; + SCHAR progRefLevel; + SCHAR presMode; /* Presentation mode: 0 (not indicated), 1, 2, and 3 + (reserved). */ + SCHAR pceInstanceTag; + + CDrcChannelData channelData; + +} CDrcPayload; + +typedef struct { + /* DRC parameters: Latest user requests */ + FIXP_DBL usrCut; + FIXP_DBL usrBoost; + UCHAR usrApplyHeavyCompression; + + /* DRC parameters: Currently used, possibly changed by + * aacDecoder_drcParameterHandling */ + FIXP_DBL cut; /* attenuation scale factor */ + FIXP_DBL boost; /* boost scale factor */ + SCHAR targetRefLevel; /* target reference level for loudness normalization */ + UCHAR applyHeavyCompression; /* heavy compression (DVB) flag */ + + UINT expiryFrame; + UCHAR bsDelayEnable; + UCHAR applyDigitalNorm; + + AACDEC_DRC_PARAMETER_HANDLING defaultPresentationMode; + UCHAR encoderTargetLevel; + +} CDrcParams; + +typedef struct { + CDrcParams + params; /* Module parameters that can be set by user (via SetParam API + function) */ + + UCHAR enable; /* Switch that controls dynamic range processing */ + UCHAR digitalNorm; /* Switch to en-/disable reference level normalization in + digital domain */ + + UCHAR update; /* Flag indicating the change of a user or bitstream parameter + which affects aacDecoder_drcParameterHandling */ + INT numOutChannels; /* Number of output channels */ + INT prevAacNumChannels; /* Previous number of channels of aac bitstream, used + for update flag */ + + USHORT numPayloads; /* The number of DRC data payload elements found within + frame */ + USHORT + numThreads; /* The number of DRC data threads extracted from the found + payload elements */ + SCHAR progRefLevel; /* Program reference level for all channels */ + UCHAR progRefLevelPresent; /* Program reference level found in bitstream */ + + UINT prlExpiryCount; /* Counter that can be used to monitor the life time of + the program reference level. */ + + SCHAR presMode; /* Presentation mode as defined in ETSI TS 101 154 */ + UCHAR dvbAncDataAvailable; /* Flag that indicates whether DVB ancillary data + is present or not */ + UINT dvbAncDataPosition; /* Used to store the DVB ancillary data payload + position in the bitstream (only one per frame) */ + UINT drcPayloadPosition[MAX_DRC_THREADS]; /* Used to store the DRC payload + positions in the bitstream */ + + UCHAR + uniDrcPrecedence; /* Flag for signalling that uniDrc is active and takes + precedence over legacy DRC */ + +} CDrcInfo; + +typedef CDrcInfo *HANDLE_AAC_DRC; + +#endif /* AACDEC_DRC_TYPES_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_hcr.cpp b/fdk-aac/libAACdec/src/aacdec_hcr.cpp new file mode 100644 index 0000000..6114756 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcr.cpp @@ -0,0 +1,1498 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: HCR initialization, preprocess HCR sideinfo, + decode priority codewords (PCWs) + +*******************************************************************************/ + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_types.h" +#include "aacdec_hcr_bit.h" +#include "aacdec_hcrs.h" +#include "aac_ram.h" +#include "aac_rom.h" +#include "channel.h" +#include "block.h" + +#include "aacdecoder.h" /* for ID_CPE, ID_SCE ... */ +#include "FDK_bitstream.h" + +extern int mlFileChCurr; + +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine, + UINT *errorWord); + +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord); + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr); +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr); +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr); +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr); + +static void DeriveNumberOfExtendedSortedSectionsInSets( + UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx); + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT quantSpecCoef, INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits); + +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + UINT codebookDim, const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, int *pNumDecodedBits); + +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits); + +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr); + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo); + +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension); + +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr); + +/*--------------------------------------------------------------------------------------------- + description: Check if codebook and numSect are within allowed range +(short only) +-------------------------------------------------------------------------------------------- +*/ +static void errDetectorInHcrSideinfoShrt(SCHAR cb, SHORT numLine, + UINT *errorWord) { + if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) { + *errorWord |= CB_OUT_OF_RANGE_SHORT_BLOCK; + } + if (numLine < 0 || numLine > 1024) { + *errorWord |= LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Check both HCR lengths +-------------------------------------------------------------------------------------------- +*/ +static void errDetectorInHcrLengths(SCHAR lengthOfLongestCodeword, + SHORT lengthOfReorderedSpectralData, + UINT *errorWord) { + if (lengthOfReorderedSpectralData < lengthOfLongestCodeword) { + *errorWord |= HCR_SI_LENGTHS_FAILURE; + } +} + +/*--------------------------------------------------------------------------------------------- + description: Decode (and adapt if necessary) the two HCR sideinfo +components: 'reordered_spectral_data_length' and 'longest_codeword_length' +-------------------------------------------------------------------------------------------- +*/ + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const MP4_ELEMENT_ID globalHcrType) { + SHORT lengOfReorderedSpectralData; + SCHAR lengOfLongestCodeword; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfReorderedSpectralData = + 0; + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = 0; + + /* ------- SI-Value No 1 ------- */ + lengOfReorderedSpectralData = FDKreadBits(bs, 14) + ERROR_LORSD; + if (globalHcrType == ID_CPE) { + if ((lengOfReorderedSpectralData >= 0) && + (lengOfReorderedSpectralData <= CPE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + lengOfReorderedSpectralData; /* the decoded value is within range */ + } else { + if (lengOfReorderedSpectralData > CPE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + CPE_TOP_LENGTH; /* use valid maximum */ + } + } + } else if (globalHcrType == ID_SCE || globalHcrType == ID_LFE || + globalHcrType == ID_CCE) { + if ((lengOfReorderedSpectralData >= 0) && + (lengOfReorderedSpectralData <= SCE_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + lengOfReorderedSpectralData; /* the decoded value is within range */ + } else { + if (lengOfReorderedSpectralData > SCE_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData = + SCE_TOP_LENGTH; /* use valid maximum */ + } + } + } + + /* ------- SI-Value No 2 ------- */ + lengOfLongestCodeword = FDKreadBits(bs, 6) + ERROR_LOLC; + if ((lengOfLongestCodeword >= 0) && + (lengOfLongestCodeword <= LEN_OF_LONGEST_CW_TOP_LENGTH)) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = + lengOfLongestCodeword; /* the decoded value is within range */ + } else { + if (lengOfLongestCodeword > LEN_OF_LONGEST_CW_TOP_LENGTH) { + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword = + LEN_OF_LONGEST_CW_TOP_LENGTH; /* use valid maximum */ + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: Set up HCR - must be called before every call to +HcrDecoder(). For short block a sorting algorithm is applied to get the SI in +the order that HCR could assemble the qsc's as if it is a long block. +----------------------------------------------------------------------------------------------- + return: error log +-------------------------------------------------------------------------------------------- +*/ + +UINT HcrInit(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) { + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pNumLinesInSec; + UCHAR *pCodeBk; + SHORT numSection; + SCHAR cb; + int numLine; + int i; + + pHcr->decInOut.lengthOfReorderedSpectralData = + pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData; + pHcr->decInOut.lengthOfLongestCodeword = + pAacDecoderChannelInfo->pDynData->specificTo.aac.lenOfLongestCodeword; + pHcr->decInOut.pQuantizedSpectralCoefficientsBase = + pAacDecoderChannelInfo->pSpectralCoefficient; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = 0; + pHcr->decInOut.pCodebook = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + pHcr->decInOut.pNumLineInSect = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + pHcr->decInOut.numSection = + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection; + pHcr->decInOut.errorLog = 0; + pHcr->nonPcwSideinfo.pResultBase = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + + FDKsyncCache(bs); + pHcr->decInOut.bitstreamAnchor = (INT)FDKgetValidBits(bs); + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) /* short block */ + { + SHORT band; + SHORT maxBand; + SCHAR group; + SCHAR winGroupLen; + SCHAR window; + SCHAR numUnitInBand; + SCHAR cntUnitInBand; + SCHAR groupWin; + SCHAR cb_prev; + + UCHAR *pCodeBook; + const SHORT *BandOffsets; + SCHAR numOfGroups; + + pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; /* in */ + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; /* out */ + pCodeBk = pHcr->decInOut.pCodebook; /* out */ + BandOffsets = + GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); /* aux */ + numOfGroups = GetWindowGroups(pIcsInfo); + + numLine = 0; + numSection = 0; + cb = pCodeBook[0]; + cb_prev = pCodeBook[0]; + + /* convert HCR-sideinfo into a unitwise manner: When the cb changes, a new + * section starts */ + + *pCodeBk++ = cb_prev; + + maxBand = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (band = 0; band < maxBand; + band++) { /* from low to high sfbs i.e. from low to high frequencies */ + numUnitInBand = + ((BandOffsets[band + 1] - BandOffsets[band]) >> + FOUR_LOG_DIV_TWO_LOG); /* get the number of units in current sfb */ + for (cntUnitInBand = numUnitInBand; cntUnitInBand != 0; + cntUnitInBand--) { /* for every unit in the band */ + for (window = 0, group = 0; group < numOfGroups; group++) { + winGroupLen = (SCHAR)GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + for (groupWin = winGroupLen; groupWin != 0; groupWin--, window++) { + cb = pCodeBook[group * 16 + band]; + if (cb != cb_prev) { + errDetectorInHcrSideinfoShrt(cb, numLine, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + *pCodeBk++ = cb; + *pNumLinesInSec++ = numLine; + numSection++; + + cb_prev = cb; + numLine = LINES_PER_UNIT; + } else { + numLine += LINES_PER_UNIT; + } + } + } + } + } + + numSection++; + + errDetectorInHcrSideinfoShrt(cb, numLine, &pHcr->decInOut.errorLog); + if (numSection <= 0 || numSection > 1024 / 2) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK; + } + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + + *pCodeBk = cb; + *pNumLinesInSec = numLine; + pHcr->decInOut.numSection = numSection; + + } else /* end short block prepare SI */ + { /* long block */ + errDetectorInHcrLengths(pHcr->decInOut.lengthOfLongestCodeword, + pHcr->decInOut.lengthOfReorderedSpectralData, + &pHcr->decInOut.errorLog); + numSection = pHcr->decInOut.numSection; + pNumLinesInSec = pHcr->decInOut.pNumLineInSect; + pCodeBk = pHcr->decInOut.pCodebook; + if (numSection <= 0 || numSection > 64) { + pHcr->decInOut.errorLog |= NUM_SECT_OUT_OF_RANGE_LONG_BLOCK; + numSection = 0; + } + + for (i = numSection; i != 0; i--) { + cb = *pCodeBk++; + + if (cb < ZERO_HCB || cb >= MAX_CB_CHECK || cb == BOOKSCL) { + pHcr->decInOut.errorLog |= CB_OUT_OF_RANGE_LONG_BLOCK; + } + + numLine = *pNumLinesInSec++; + /* FDK_ASSERT(numLine > 0); */ + + if ((numLine <= 0) || (numLine > 1024)) { + pHcr->decInOut.errorLog |= LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK; + } + } + if (pHcr->decInOut.errorLog != 0) { + return (pHcr->decInOut.errorLog); + } + } + + pCodeBk = pHcr->decInOut.pCodebook; + for (i = 0; i < numSection; i++) { + if ((*pCodeBk == NOISE_HCB) || (*pCodeBk == INTENSITY_HCB2) || + (*pCodeBk == INTENSITY_HCB)) { + *pCodeBk = 0; + } + pCodeBk++; + } + + /* HCR-sideinfo-input is complete and seems to be valid */ + + return (pHcr->decInOut.errorLog); +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes the codewords of the spectral +coefficients from the bitstream according to the HCR algorithm and stores the +quantized spectral coefficients in correct order in the output buffer. +-------------------------------------------------------------------------------------------- +*/ + +UINT HcrDecoder(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs) { + int pTmp1, pTmp2, pTmp3, pTmp4; + int pTmp5; + + INT bitCntOffst; + INT saveBitCnt = (INT)FDKgetValidBits(bs); /* save bitstream position */ + + HcrCalcNumCodeword(pHcr); + + HcrSortCodebookAndNumCodewordInSection(pHcr); + + HcrPrepareSegmentationGrid(pHcr); + + HcrExtendedSectionInfo(pHcr); + + if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) != 0) { + return (pHcr->decInOut.errorLog); /* sideinfo is massively corrupt, return + from HCR without having decoded + anything */ + } + + DeriveNumberOfExtendedSortedSectionsInSets( + pHcr->segmentInfo.numSegment, + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection, + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx, + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets, + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx); + + /* store */ + pTmp1 = pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + pTmp2 = pHcr->sectionInfo.extendedSortedCodebookIdx; + pTmp3 = pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + pTmp4 = pHcr->decInOut.quantizedSpectralCoefficientsIdx; + pTmp5 = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + + /* ------- decode meaningful PCWs ------ */ + DecodePCWs(bs, pHcr); + + if ((pHcr->decInOut.errorLog & HCR_FATAL_PCW_ERROR_MASK) == 0) { + /* ------ decode the non-PCWs -------- */ + DecodeNonPCWs(bs, pHcr); + } + + errDetectWithinSegmentationFinal(pHcr); + + /* restore */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = pTmp1; + pHcr->sectionInfo.extendedSortedCodebookIdx = pTmp2; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = pTmp3; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = pTmp4; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = pTmp5; + + HcrReorderQuantizedSpectralCoefficients(pHcr, pAacDecoderChannelInfo, + pSamplingRateInfo); + + /* restore bitstream position */ + bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt; + if (bitCntOffst) { + FDKpushBiDirectional(bs, bitCntOffst); + } + + return (pHcr->decInOut.errorLog); +} + +/*--------------------------------------------------------------------------------------------- + description: This function reorders the quantized spectral coefficients +sectionwise for long- and short-blocks and compares to the LAV (Largest Absolute +Value of the current codebook) -- a counter is incremented if there is an error + detected. + Additional for short-blocks a unit-based-deinterleaving is +applied. Moreover (for short blocks) the scaling is derived (compare plain +huffman decoder). +-------------------------------------------------------------------------------------------- +*/ + +static void HcrReorderQuantizedSpectralCoefficients( + H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo) { + INT qsc; + UINT abs_qsc; + UINT i, j; + USHORT numSpectralValuesInSection; + FIXP_DBL *pTeVa; + USHORT lavErrorCnt = 0; + + UINT numSection = pHcr->decInOut.numSection; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase = + pHcr->decInOut.pQuantizedSpectralCoefficientsBase; + FIXP_DBL *pQuantizedSpectralCoefficients = + SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + const UCHAR *pCbDimShift = aDimCbShift; + const USHORT *pLargestAbsVal = aLargestAbsoluteValue; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + FIXP_DBL pTempValues[1024]; + FIXP_DBL *pBak = pTempValues; + + FDKmemclear(pTempValues, 1024 * sizeof(FIXP_DBL)); + + /* long and short: check if decoded huffman-values (quantized spectral + * coefficients) are within range */ + for (i = numSection; i != 0; i--) { + numSpectralValuesInSection = *pNumSortedCodewordInSection++ + << pCbDimShift[*pSortedCodebook]; + pTeVa = &pTempValues[*pReorderOffset++]; + for (j = numSpectralValuesInSection; j != 0; j--) { + qsc = *pQuantizedSpectralCoefficients++; + abs_qsc = fAbs(qsc); + if (abs_qsc <= pLargestAbsVal[*pSortedCodebook]) { + *pTeVa++ = (FIXP_DBL)qsc; /* the qsc value is within range */ + } else { /* line is too high .. */ + if (abs_qsc == + Q_VALUE_INVALID) { /* .. because of previous marking --> dont set + LAV flag (would be confusing), just copy out + the already marked value */ + *pTeVa++ = (FIXP_DBL)qsc; + } else { /* .. because a too high value was decoded for this cb --> set + LAV flag */ + *pTeVa++ = (FIXP_DBL)Q_VALUE_INVALID; + lavErrorCnt += 1; + } + } + } + pSortedCodebook++; + } + + if (!IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + FIXP_DBL *pOut; + FIXP_DBL locMax; + FIXP_DBL tmp; + SCHAR groupoffset; + SCHAR group; + SCHAR band; + SCHAR groupwin; + SCHAR window; + SCHAR numWinGroup; + SHORT interm; + SCHAR numSfbTransm; + SCHAR winGroupLen; + SHORT index; + INT msb; + INT lsb; + + SHORT *pScaleFacHcr = pAacDecoderChannelInfo->pDynData->aScaleFactor; + SHORT *pSfbSclHcr = pAacDecoderChannelInfo->pDynData->aSfbScale; + const SHORT *BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + pBak = pTempValues; + /* deinterleave unitwise for short blocks */ + for (window = 0; window < (8); window++) { + pOut = SPEC(pQuantizedSpectralCoefficientsBase, window, + pAacDecoderChannelInfo->granuleLength); + for (i = 0; i < (LINES_PER_UNIT_GROUP); i++) { + pTeVa = pBak + (window << FOUR_LOG_DIV_TWO_LOG) + + i * 32; /* distance of lines between unit groups has to be + constant for every framelength (32)! */ + for (j = (LINES_PER_UNIT); j != 0; j--) { + *pOut++ = *pTeVa++; + } + } + } + + /* short blocks only */ + /* derive global scaling-value for every sfb and every window (as it is done + * in plain-huffman-decoder at short blocks) */ + groupoffset = 0; + + numWinGroup = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + numSfbTransm = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < numWinGroup; group++) { + winGroupLen = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + for (band = 0; band < numSfbTransm; band++) { + interm = group * 16 + band; + msb = pScaleFacHcr[interm] >> 2; + lsb = pScaleFacHcr[interm] & 3; + for (groupwin = 0; groupwin < winGroupLen; groupwin++) { + window = groupoffset + groupwin; + pBak = SPEC(pQuantizedSpectralCoefficientsBase, window, + pAacDecoderChannelInfo->granuleLength); + locMax = FL2FXCONST_DBL(0.0f); + for (index = BandOffsets[band]; index < BandOffsets[band + 1]; + index += LINES_PER_UNIT) { + pTeVa = &pBak[index]; + for (i = LINES_PER_UNIT; i != 0; i--) { + tmp = (*pTeVa < FL2FXCONST_DBL(0.0f)) ? -*pTeVa++ : *pTeVa++; + locMax = fixMax(tmp, locMax); + } + } + if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) { + locMax = (FIXP_DBL)MAX_QUANTIZED_VALUE; + } + pSfbSclHcr[window * 16 + band] = + msb - GetScaleFromValue( + locMax, lsb); /* save global scale maxima in this sfb */ + } + } + groupoffset += + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + } + } else { + /* copy straight for long-blocks */ + pQuantizedSpectralCoefficients = + SPEC_LONG(pQuantizedSpectralCoefficientsBase); + for (i = 1024; i != 0; i--) { + *pQuantizedSpectralCoefficients++ = *pBak++; + } + } + + if (lavErrorCnt != 0) { + pHcr->decInOut.errorLog |= LAV_VIOLATION; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of codewords + for each section (numCodewordInSection) and the number of +codewords for all sections (numCodeword). For zero and intensity codebooks a +entry is also done in the variable numCodewordInSection. It is assumed that the +codebook is a two tuples codebook. This is needed later for the calculation of +the base addresses for the reordering of the quantize spectral coefficients at +the end of the hcr tool. The variable numCodeword contain the number of +codewords which are really in the bitstream. Zero or intensity codebooks does +not increase the variable numCodewords. +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void HcrCalcNumCodeword(H_HCR_INFO pHcr) { + int hcrSection; + UINT numCodeword; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + SHORT *pNumLineInSection = pHcr->decInOut.pNumLineInSect; + const UCHAR *pCbDimShift = aDimCbShift; + + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + + numCodeword = 0; + for (hcrSection = numSection; hcrSection != 0; hcrSection--) { + *pNumCodewordInSection = *pNumLineInSection++ >> pCbDimShift[*pCodebook]; + if (*pCodebook != 0) { + numCodeword += *pNumCodewordInSection; + } + pNumCodewordInSection++; + pCodebook++; + } + pHcr->sectionInfo.numCodeword = numCodeword; +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number + of sorted codebooks and sorts the codebooks and the +numCodewordInSection according to the priority. +-------------------------------------------------------------------------------------------- +*/ + +static void HcrSortCodebookAndNumCodewordInSection(H_HCR_INFO pHcr) { + UINT i, j, k; + UCHAR temp; + UINT counter; + UINT startOffset; + UINT numZeroSection; + UCHAR *pDest; + UINT numSectionDec; + + UINT numSection = pHcr->decInOut.numSection; + UCHAR *pCodebook = pHcr->decInOut.pCodebook; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumCodewordInSection = pHcr->sectionInfo.pNumCodewordInSection; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + USHORT *pReorderOffset = pHcr->sectionInfo.pReorderOffset; + const UCHAR *pCbPriority = aCbPriority; + const UCHAR *pMinOfCbPair = aMinOfCbPair; + const UCHAR *pMaxOfCbPair = aMaxOfCbPair; + const UCHAR *pCbDimShift = aDimCbShift; + + UINT searchStart = 0; + + /* calculate *pNumSortedSection and store the priorities in array + * pSortedCdebook */ + pDest = pSortedCodebook; + numZeroSection = 0; + for (i = numSection; i != 0; i--) { + if (pCbPriority[*pCodebook] == 0) { + numZeroSection += 1; + } + *pDest++ = pCbPriority[*pCodebook++]; + } + pHcr->sectionInfo.numSortedSection = + numSection - numZeroSection; /* numSortedSection contains no zero or + intensity section */ + pCodebook = pHcr->decInOut.pCodebook; + + /* sort priorities of the codebooks in array pSortedCdebook[] */ + numSectionDec = numSection - 1; + if (numSectionDec > 0) { + counter = numSectionDec; + for (j = numSectionDec; j != 0; j--) { + for (i = 0; i < counter; i++) { + /* swap priorities */ + if (pSortedCodebook[i + 1] > pSortedCodebook[i]) { + temp = pSortedCodebook[i]; + pSortedCodebook[i] = pSortedCodebook[i + 1]; + pSortedCodebook[i + 1] = temp; + } + } + counter -= 1; + } + } + + /* clear codebookSwitch array */ + for (i = numSection; i != 0; i--) { + *pCodebookSwitch++ = 0; + } + pCodebookSwitch = pHcr->sectionInfo.pCodebookSwitch; + + /* sort sectionCodebooks and numCodwordsInSection and calculate + * pReorderOffst[j] */ + for (j = 0; j < numSection; j++) { + for (i = searchStart; i < numSection; i++) { + if (pCodebookSwitch[i] == 0 && + (pMinOfCbPair[pSortedCodebook[j]] == pCodebook[i] || + pMaxOfCbPair[pSortedCodebook[j]] == pCodebook[i])) { + pCodebookSwitch[i] = 1; + pSortedCodebook[j] = pCodebook[i]; /* sort codebook */ + pNumSortedCodewordInSection[j] = + pNumCodewordInSection[i]; /* sort NumCodewordInSection */ + + startOffset = 0; + for (k = 0; k < i; k++) { /* make entry in pReorderOffst */ + startOffset += pNumCodewordInSection[k] << pCbDimShift[pCodebook[k]]; + } + pReorderOffset[j] = + startOffset; /* offset for reordering the codewords */ + + if (i == searchStart) { + k = i; + while (pCodebookSwitch[k++] == 1) searchStart++; + } + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the segmentation, which includes +numSegment, leftStartOfSegment, rightStartOfSegment and remainingBitsInSegment. + The segmentation could be visualized a as kind of +'overlay-grid' for the bitstream-block holding the HCR-encoded +quantized-spectral-coefficients. +-------------------------------------------------------------------------------------------- +*/ + +static void HcrPrepareSegmentationGrid(H_HCR_INFO pHcr) { + USHORT i, j; + USHORT numSegment = 0; + INT segmentStart = 0; + UCHAR segmentWidth; + UCHAR lastSegmentWidth; + UCHAR sortedCodebook; + UCHAR endFlag = 0; + INT intermediateResult; + + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + SHORT lengthOfReorderedSpectralData = + pHcr->decInOut.lengthOfReorderedSpectralData; + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + INT *pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + const UCHAR *pMaxCwLength = aMaxCwLen; + + for (i = numSortedSection; i != 0; i--) { + sortedCodebook = *pSortedCodebook++; + segmentWidth = + fMin((INT)pMaxCwLength[sortedCodebook], (INT)lengthOfLongestCodeword); + + for (j = *pNumSortedCodewordInSection; j != 0; j--) { + /* width allows a new segment */ + intermediateResult = segmentStart; + if ((segmentStart + segmentWidth) <= lengthOfReorderedSpectralData) { + /* store segment start, segment length and increment the number of + * segments */ + *pLeftStartOfSegment++ = intermediateResult; + *pRightStartOfSegment++ = intermediateResult + segmentWidth - 1; + *pRemainingBitsInSegment++ = segmentWidth; + segmentStart += segmentWidth; + numSegment += 1; + } + /* width does not allow a new segment */ + else { + /* correct the last segment length */ + pLeftStartOfSegment--; + pRightStartOfSegment--; + pRemainingBitsInSegment--; + segmentStart = *pLeftStartOfSegment; + + lastSegmentWidth = lengthOfReorderedSpectralData - segmentStart; + *pRemainingBitsInSegment = lastSegmentWidth; + *pRightStartOfSegment = segmentStart + lastSegmentWidth - 1; + endFlag = 1; + break; + } + } + pNumSortedCodewordInSection++; + if (endFlag != 0) { + break; + } + } + pHcr->segmentInfo.numSegment = numSegment; +} + +/*--------------------------------------------------------------------------------------------- + description: This function adapts the sorted section boundaries to the +boundaries of segmentation. If the section lengths does not fit completely into +the current segment, the section is spitted into two so called 'extended + sections'. The extended-section-info +(pNumExtendedSortedCodewordInSectin and pExtendedSortedCodebook) is updated in +this case. + +-------------------------------------------------------------------------------------------- +*/ + +static void HcrExtendedSectionInfo(H_HCR_INFO pHcr) { + UINT srtSecCnt = 0; /* counter for sorted sections */ + UINT xSrtScCnt = 0; /* counter for extended sorted sections */ + UINT remainNumCwInSortSec; + UINT inSegmentRemainNumCW; + + UINT numSortedSection = pHcr->sectionInfo.numSortedSection; + UCHAR *pSortedCodebook = pHcr->sectionInfo.pSortedCodebook; + USHORT *pNumSortedCodewordInSection = + pHcr->sectionInfo.pNumSortedCodewordInSection; + UCHAR *pExtendedSortedCoBo = pHcr->sectionInfo.pExtendedSortedCodebook; + USHORT *pNumExtSortCwInSect = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + UINT numSegment = pHcr->segmentInfo.numSegment; + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + SCHAR lengthOfLongestCodeword = pHcr->decInOut.lengthOfLongestCodeword; + const UCHAR *pMaxCwLength = aMaxCwLen; + + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + + while (srtSecCnt < numSortedSection) { + if (inSegmentRemainNumCW < remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + remainNumCwInSortSec -= inSegmentRemainNumCW; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was not integrated in extended sorted section + */ + } else if (inSegmentRemainNumCW == remainNumCwInSortSec) { + pNumExtSortCwInSect[xSrtScCnt] = inSegmentRemainNumCW; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + inSegmentRemainNumCW = numSegment; + /* data of a sorted section was integrated in extended sorted section */ + } else { /* inSegmentRemainNumCW > remainNumCwInSortSec */ + pNumExtSortCwInSect[xSrtScCnt] = remainNumCwInSortSec; + pExtendedSortedCoBo[xSrtScCnt] = pSortedCodebook[srtSecCnt]; + + inSegmentRemainNumCW -= remainNumCwInSortSec; + srtSecCnt++; + remainNumCwInSortSec = pNumSortedCodewordInSection[srtSecCnt]; + /* data of a sorted section was integrated in extended sorted section */ + } + pMaxLenOfCbInExtSrtSec[xSrtScCnt] = + fMin((INT)pMaxCwLength[pExtendedSortedCoBo[xSrtScCnt]], + (INT)lengthOfLongestCodeword); + + xSrtScCnt += 1; + + if (xSrtScCnt >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + pHcr->decInOut.errorLog |= EXTENDED_SORTED_COUNTER_OVERFLOW; + return; + } + } + pNumExtSortCwInSect[xSrtScCnt] = 0; +} + +/*--------------------------------------------------------------------------------------------- + description: This function calculates the number of extended sorted +sections which belong to the sets. Each set from set 0 (one and only set for the +PCWs) till to the last set gets a entry in the array to which + 'pNumExtendedSortedSectinsInSets' points to. + + Calculation: The entrys in +pNumExtendedSortedCodewordInSectin are added untill the value numSegment is +reached. Then the sum_variable is cleared and the calculation starts from the +beginning. As much extended sorted Sections are summed up to reach the value +numSegment, as much is the current entry in *pNumExtendedSortedCodewordInSectin. +-------------------------------------------------------------------------------------------- +*/ +static void DeriveNumberOfExtendedSortedSectionsInSets( + UINT numSegment, USHORT *pNumExtendedSortedCodewordInSection, + int numExtendedSortedCodewordInSectionIdx, + USHORT *pNumExtendedSortedSectionsInSets, + int numExtendedSortedSectionsInSetsIdx) { + USHORT counter = 0; + UINT cwSum = 0; + USHORT *pNumExSortCwInSec = pNumExtendedSortedCodewordInSection; + USHORT *pNumExSortSecInSets = pNumExtendedSortedSectionsInSets; + + while (pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx] != 0) { + cwSum += pNumExSortCwInSec[numExtendedSortedCodewordInSectionIdx]; + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + if (cwSum > numSegment) { + return; + } + counter++; + if (counter > 1024 / 4) { + return; + } + if (cwSum == numSegment) { + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = counter; + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + counter = 0; + cwSum = 0; + } + } + pNumExSortSecInSets[numExtendedSortedSectionsInSetsIdx] = + counter; /* save last entry for the last - probably shorter - set */ +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all priority codewords (PCWs) in a +spectrum (within set 0). The calculation of the PCWs is managed in two loops. +The loopcounter of the outer loop is set to the first value pointer + pNumExtendedSortedSectionsInSets points to. This value +represents the number of extended sorted sections within set 0. The loopcounter +of the inner loop is set to the first value pointer + pNumExtendedSortedCodewordInSectin points to. The value +represents the number of extended sorted codewords in sections (the original +sections have been splitted to go along with the borders of the sets). Each time +the number of the extended sorted codewords in sections are de- coded, the +pointer 'pNumExtendedSortedCodewordInSectin' is incremented by one. +-------------------------------------------------------------------------------------------- +*/ +static void DecodePCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { + UINT i; + USHORT extSortSec; + USHORT curExtSortCwInSec; + UCHAR codebook; + UCHAR dimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + USHORT *pNumExtendedSortedCodewordInSection = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + FIXP_DBL *pQuantizedSpectralCoefficients = + SPEC_LONG(pHcr->decInOut.pQuantizedSpectralCoefficientsBase); + int quantizedSpectralCoefficientsIdx = + pHcr->decInOut.quantizedSpectralCoefficientsIdx; + INT *pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UCHAR *pMaxLenOfCbInExtSrtSec = pHcr->sectionInfo.pMaxLenOfCbInExtSrtSec; + int maxLenOfCbInExtSrtSecIdx = pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx; + UCHAR maxAllowedCwLen; + int numDecodedBits; + const UCHAR *pCbDimension = aDimCb; + const UCHAR *pCbSign = aSignCb; + + /* clear result array */ + FDKmemclear(pQuantizedSpectralCoefficients + quantizedSpectralCoefficientsIdx, + 1024 * sizeof(FIXP_DBL)); + + /* decode all PCWs in the extended sorted section(s) belonging to set 0 */ + for (extSortSec = + pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; + extSortSec != 0; extSortSec--) { + codebook = + pExtendedSortedCodebook[extendedSortedCodebookIdx]; /* get codebook for + this extended + sorted section + and increment ptr + to cb of next + ext. sort sec */ + extendedSortedCodebookIdx++; + if (extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + dimension = pCbDimension[codebook]; /* get dimension of codebook of this + extended sort. sec. */ + pCurrentTree = + aHuffTable[codebook]; /* convert codebook to pointer to QSCs */ + pQuantValBase = + aQuantTable[codebook]; /* convert codebook to index to table of QSCs */ + maxAllowedCwLen = pMaxLenOfCbInExtSrtSec[maxLenOfCbInExtSrtSecIdx]; + maxLenOfCbInExtSrtSecIdx++; + if (maxLenOfCbInExtSrtSecIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + + /* switch for decoding with different codebooks: */ + if (pCbSign[codebook] == + 0) { /* no sign bits follow after the codeword-body */ + /* PCW_BodyONLY */ + /*==============*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + /* result is written out here because NO sign bits follow the body */ + for (i = dimension; i != 0; i--) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)*pQuantVal++; /* write quant. spec. coef. into + spectrum; sign is already valid */ + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_ONLY_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY, pHcr, PCW_BODY, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - dimension, + dimension)) { + return; + } + pLeftStartOfSegment++; /* update pointer for decoding the next PCW */ + pRemainingBitsInSegment++; /* update pointer for decoding the next PCW + */ + } + } else if ((codebook < 11) && (pCbSign[codebook] == + 1)) { /* possibly there follow 1,2,3 or 4 + sign bits after the codeword-body */ + /* PCW_Body and PCW_Sign */ + /*=======================*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + int err; + numDecodedBits = 0; + + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + err = DecodePCW_Sign( + bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal, + pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + if (err != 0) { + return; + } + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < (numDecodedBits + ERROR_PCW_BODY_SIGN_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN, pHcr, + PCW_BODY_SIGN, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - dimension, + dimension)) { + return; + } + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } else if ((pCbSign[codebook] == 1) && + (codebook >= 11)) { /* possibly there follow some sign bits and + maybe one or two escape sequences after + the cw-body */ + /* PCW_Body, PCW_Sign and maybe PCW_Escape */ + /*=========================================*/ + + for (curExtSortCwInSec = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + curExtSortCwInSec != 0; curExtSortCwInSec--) { + int err; + numDecodedBits = 0; + + /* decode PCW_BODY */ + pQuantVal = DecodePCW_Body( + bs, pHcr->decInOut.bitstreamAnchor, pCurrentTree, pQuantValBase, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + + err = DecodePCW_Sign( + bs, pHcr->decInOut.bitstreamAnchor, dimension, pQuantVal, + pQuantizedSpectralCoefficients, &quantizedSpectralCoefficientsIdx, + pLeftStartOfSegment, pRemainingBitsInSegment, &numDecodedBits); + if (err != 0) { + return; + } + + /* decode PCW_ESCAPE if present */ + quantizedSpectralCoefficientsIdx -= DIMENSION_OF_ESCAPE_CODEBOOK; + + if (fixp_abs(pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx]) == + (FIXP_DBL)ESCAPE_VALUE) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)DecodeEscapeSequence( + bs, pHcr->decInOut.bitstreamAnchor, + pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, pRemainingBitsInSegment, + &numDecodedBits); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + if (fixp_abs(pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx]) == + (FIXP_DBL)ESCAPE_VALUE) { + pQuantizedSpectralCoefficients[quantizedSpectralCoefficientsIdx] = + (FIXP_DBL)DecodeEscapeSequence( + bs, pHcr->decInOut.bitstreamAnchor, + pQuantizedSpectralCoefficients + [quantizedSpectralCoefficientsIdx], + pLeftStartOfSegment, pRemainingBitsInSegment, + &numDecodedBits); + } + quantizedSpectralCoefficientsIdx++; + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + + /* one more PCW should be decoded */ + + if (maxAllowedCwLen < + (numDecodedBits + ERROR_PCW_BODY_SIGN_ESC_TOO_LONG)) { + pHcr->decInOut.errorLog |= TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED; + } + + if (1 == errDetectPcwSegmentation( + *pRemainingBitsInSegment - ERROR_PCW_BODY_SIGN_ESC, pHcr, + PCW_BODY_SIGN_ESC, + pQuantizedSpectralCoefficients + + quantizedSpectralCoefficientsIdx - + DIMENSION_OF_ESCAPE_CODEBOOK, + DIMENSION_OF_ESCAPE_CODEBOOK)) { + return; + } + pLeftStartOfSegment++; + pRemainingBitsInSegment++; + } + } + + /* all PCWs belonging to this extended section should be decoded */ + numExtendedSortedCodewordInSectionIdx++; + if (numExtendedSortedCodewordInSectionIdx >= MAX_SFB_HCR + MAX_HCR_SETS) { + return; + } + } + /* all PCWs should be decoded */ + + numExtendedSortedSectionsInSetsIdx++; + if (numExtendedSortedSectionsInSetsIdx >= MAX_HCR_SETS) { + return; + } + + /* Write back indexes into structure */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = + numExtendedSortedSectionsInSetsIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = + quantizedSpectralCoefficientsIdx; + pHcr->sectionInfo.maxLenOfCbInExtSrtSecIdx = maxLenOfCbInExtSrtSecIdx; +} + +/*--------------------------------------------------------------------------------------------- + description: This function checks immediately after every decoded PCW, +whether out of the current segment too many bits have been read or not. If an +error occurrs, probably the sideinfo or the HCR-bitstream block holding the +huffman encoded quantized spectral coefficients is distorted. In this case the +two or four quantized spectral coefficients belonging to the current codeword + are marked (for being detected by concealment later). +-------------------------------------------------------------------------------------------- +*/ +static UCHAR errDetectPcwSegmentation(SCHAR remainingBitsInSegment, + H_HCR_INFO pHcr, PCW_TYPE kind, + FIXP_DBL *qsc_base_of_cw, + UCHAR dimension) { + SCHAR i; + if (remainingBitsInSegment < 0) { + /* log the error */ + switch (kind) { + case PCW_BODY: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY; + break; + case PCW_BODY_SIGN: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN; + break; + case PCW_BODY_SIGN_ESC: + pHcr->decInOut.errorLog |= SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC; + break; + } + /* mark the erred lines */ + for (i = dimension; i != 0; i--) { + *qsc_base_of_cw++ = (FIXP_DBL)Q_VALUE_INVALID; + } + return 1; + } + return 0; +} + +/*--------------------------------------------------------------------------------------------- + description: This function checks if all segments are empty after +decoding. There are _no lines markded_ as invalid because it could not be traced +back where from the remaining bits are. +-------------------------------------------------------------------------------------------- +*/ +static void errDetectWithinSegmentationFinal(H_HCR_INFO pHcr) { + UCHAR segmentationErrorFlag = 0; + USHORT i; + SCHAR *pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + UINT numSegment = pHcr->segmentInfo.numSegment; + + for (i = numSegment; i != 0; i--) { + if (*pRemainingBitsInSegment++ != 0) { + segmentationErrorFlag = 1; + } + } + if (segmentationErrorFlag == 1) { + pHcr->decInOut.errorLog |= BIT_IN_SEGMENTATION_ERROR; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function walks one step within the decoding tree. Which +branch is taken depends on the decoded carryBit input parameter. +-------------------------------------------------------------------------------------------- +*/ +void CarryBitToBranchValue(UCHAR carryBit, UINT treeNode, UINT *branchValue, + UINT *branchNode) { + if (carryBit == 0) { + *branchNode = + (treeNode & MASK_LEFT) >> LEFT_OFFSET; /* MASK_LEFT: 00FFF000 */ + } else { + *branchNode = treeNode & MASK_RIGHT; /* MASK_RIGHT: 00000FFF */ + } + + *branchValue = *branchNode & CLR_BIT_10; /* clear bit 10 (if set) */ +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a priority codeword (PCW) +----------------------------------------------------------------------------------------------- + return: - return value is pointer to first of two or four quantized +spectral coefficients +-------------------------------------------------------------------------------------------- +*/ +static const SCHAR *DecodePCW_Body(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + const UINT *pCurrentTree, + const SCHAR *pQuantValBase, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits) { + UCHAR carryBit; + UINT branchNode; + UINT treeNode; + UINT branchValue; + const SCHAR *pQuantVal; + + /* decode PCW_BODY */ + treeNode = *pCurrentTree; /* get first node of current tree belonging to + current codebook */ + + /* decode whole PCW-codeword-body */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> codeword-body is complete */ + break; /* end of branch in tree reached i.e. a whole PCW-Body is decoded + */ + } else { + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pQuantVal = + pQuantValBase + branchValue; /* update pointer to valid first of 2 or 4 + quantized values */ + + return pQuantVal; +} + +/*--------------------------------------------------------------------------------------------- + description: This function decodes one escape sequence. In case of a +escape codebook and in case of the absolute value of the quantized spectral +value == 16, a escapeSequence is decoded in two steps: + 1. escape prefix + 2. escape word +-------------------------------------------------------------------------------------------- +*/ + +static INT DecodeEscapeSequence(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT quantSpecCoef, INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits) { + UINT i; + INT sign; + UINT escapeOnesCounter = 0; + UINT carryBit; + INT escape_word = 0; + + /* decode escape prefix */ + while (1) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + if (carryBit != 0) { + escapeOnesCounter += 1; + } else { + escapeOnesCounter += 4; + break; + } + } + + /* decode escape word */ + for (i = escapeOnesCounter; i != 0; i--) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + + escape_word <<= 1; + escape_word = escape_word | carryBit; + } + + sign = (quantSpecCoef >= 0) ? 1 : -1; + + quantSpecCoef = sign * (((INT)1 << escapeOnesCounter) + escape_word); + + return quantSpecCoef; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the Signbits of a priority codeword (PCW) and writes +out the resulting quantized spectral values into unsorted sections +----------------------------------------------------------------------------------------------- + output: - two or four lines at position in corresponding section +(which are not located at the desired position, i.e. they must be reordered in +the last of eight function of HCR) +----------------------------------------------------------------------------------------------- + return: - updated pQuantSpecCoef pointer (to next empty storage for a +line) +-------------------------------------------------------------------------------------------- +*/ +static int DecodePCW_Sign(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + UINT codebookDim, const SCHAR *pQuantVal, + FIXP_DBL *pQuantSpecCoef, int *quantSpecCoefIdx, + INT *pLeftStartOfSegment, + SCHAR *pRemainingBitsInSegment, + int *pNumDecodedBits) { + UINT i; + UINT carryBit; + INT quantSpecCoef; + + for (i = codebookDim; i != 0; i--) { + quantSpecCoef = *pQuantVal++; + if (quantSpecCoef != 0) { + carryBit = HcrGetABitFromBitstream(bs, bsAnchor, pLeftStartOfSegment, + pLeftStartOfSegment, /* dummy */ + FROM_LEFT_TO_RIGHT); + *pRemainingBitsInSegment -= 1; + *pNumDecodedBits += 1; + if (*pRemainingBitsInSegment < 0 || *pNumDecodedBits >= (1024 >> 1)) { + return -1; + } + + /* adapt sign of values according to the decoded sign bit */ + if (carryBit != 0) { + pQuantSpecCoef[*quantSpecCoefIdx] = -(FIXP_DBL)quantSpecCoef; + } else { + pQuantSpecCoef[*quantSpecCoefIdx] = (FIXP_DBL)quantSpecCoef; + } + } else { + pQuantSpecCoef[*quantSpecCoefIdx] = FL2FXCONST_DBL(0.0f); + } + *quantSpecCoefIdx += 1; + if (*quantSpecCoefIdx >= 1024) { + return -1; + } + } + return 0; +} + +/*--------------------------------------------------------------------------------------------- + description: Mutes spectral lines which have been marked as erroneous +(Q_VALUE_INVALID) +-------------------------------------------------------------------------------------------- +*/ +void HcrMuteErroneousLines(H_HCR_INFO hHcr) { + int c; + FIXP_DBL *RESTRICT pLong = + SPEC_LONG(hHcr->decInOut.pQuantizedSpectralCoefficientsBase); + + /* if there is a line with value Q_VALUE_INVALID mute it */ + for (c = 0; c < 1024; c++) { + if (pLong[c] == (FIXP_DBL)Q_VALUE_INVALID) { + pLong[c] = FL2FXCONST_DBL(0.0f); /* muting */ + } + } +} diff --git a/fdk-aac/libAACdec/src/aacdec_hcr.h b/fdk-aac/libAACdec/src/aacdec_hcr.h new file mode 100644 index 0000000..be21144 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcr.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Interface function declaration; common defines + and structures; defines for switching error-generator, + -detector, and -concealment + +*******************************************************************************/ + +#ifndef AACDEC_HCR_H +#define AACDEC_HCR_H + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +UINT HcrInit(H_HCR_INFO pHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +UINT HcrDecoder(H_HCR_INFO hHcr, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, + HANDLE_FDK_BITSTREAM bs); +void CarryBitToBranchValue(UCHAR carryBit, UINT treeNode, UINT *branchValue, + UINT *branchNode); + +void CHcr_Read(HANDLE_FDK_BITSTREAM bs, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const MP4_ELEMENT_ID globalHcrType); +void HcrMuteErroneousLines(H_HCR_INFO hHcr); + +void setHcrType(H_HCR_INFO hHcr, MP4_ELEMENT_ID type); +INT getHcrType(H_HCR_INFO hHcr); + +#endif /* AACDEC_HCR_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp b/fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp new file mode 100644 index 0000000..0198659 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcr_bit.cpp @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Bitstream reading + +*******************************************************************************/ + +#include "aacdec_hcr_bit.h" + +/*--------------------------------------------------------------------------------------------- + description: This function toggles the read direction. +----------------------------------------------------------------------------------------------- + input: current read direction +----------------------------------------------------------------------------------------------- + return: new read direction +-------------------------------------------------------------------------------------------- +*/ +UCHAR ToggleReadDirection(UCHAR readDirection) { + if (readDirection == FROM_LEFT_TO_RIGHT) { + return FROM_RIGHT_TO_LEFT; + } else { + return FROM_LEFT_TO_RIGHT; + } +} + +/*--------------------------------------------------------------------------------------------- + description: This function returns a bit from the bitstream according to +read direction. It is called very often, therefore it makes sense to inline it +(runtime). +----------------------------------------------------------------------------------------------- + input: - handle to FDK bitstream + - reference value marking start of bitfield + - pLeftStartOfSegment + - pRightStartOfSegment + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- +*/ +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pLeftStartOfSegment, + INT *pRightStartOfSegment, UCHAR readDirection) { + UINT bit; + INT readBitOffset; + + if (readDirection == FROM_LEFT_TO_RIGHT) { + readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pLeftStartOfSegment; + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + bit = FDKreadBits(bs, 1); + + *pLeftStartOfSegment += 1; + } else { + readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pRightStartOfSegment; + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pRightStartOfSegment -= 1; + } + + return (bit); +} diff --git a/fdk-aac/libAACdec/src/aacdec_hcr_bit.h b/fdk-aac/libAACdec/src/aacdec_hcr_bit.h new file mode 100644 index 0000000..77242ac --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcr_bit.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Bitstream reading prototypes + +*******************************************************************************/ + +#ifndef AACDEC_HCR_BIT_H +#define AACDEC_HCR_BIT_H + +#include "aacdec_hcr.h" + +UCHAR ToggleReadDirection(UCHAR readDirection); + +UINT HcrGetABitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pLeftStartOfSegment, + INT *pRightStartOfSegment, UCHAR readDirection); + +#endif /* AACDEC_HCR_BIT_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_hcr_types.h b/fdk-aac/libAACdec/src/aacdec_hcr_types.h new file mode 100644 index 0000000..1cc3cb0 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcr_types.h @@ -0,0 +1,432 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Common defines and structures; defines for + switching error-generator, -detector, and -concealment; + +*******************************************************************************/ + +#ifndef AACDEC_HCR_TYPES_H +#define AACDEC_HCR_TYPES_H + +#include "FDK_bitstream.h" +#include "overlapadd.h" + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define LINES_PER_UNIT 4 + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ----------- basic HCR configuration ------------ */ + +#define MAX_SFB_HCR \ + (((1024 / 8) / LINES_PER_UNIT) * 8) /* (8 * 16) is not enough because sfbs \ + are split in units for blocktype \ + short */ +#define NUMBER_OF_UNIT_GROUPS (LINES_PER_UNIT * 8) +#define LINES_PER_UNIT_GROUP (1024 / NUMBER_OF_UNIT_GROUPS) /* 15 16 30 32 */ + +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ +/* ------------------------------------------------ */ + +#define FROM_LEFT_TO_RIGHT 0 +#define FROM_RIGHT_TO_LEFT 1 + +#define MAX_CB_PAIRS 23 +#define MAX_HCR_SETS 14 + +#define ESCAPE_VALUE 16 +#define POSITION_OF_FLAG_A 21 +#define POSITION_OF_FLAG_B 20 + +#define MAX_CB 32 /* last used CB is cb #31 when VCB11 is used */ + +#define MAX_CB_CHECK \ + 32 /* support for VCB11 available -- is more general, could therefore used \ + in both cases */ + +#define NUMBER_OF_BIT_IN_WORD 32 + +/* log */ +#define THIRTYTWO_LOG_DIV_TWO_LOG 5 +#define EIGHT_LOG_DIV_TWO_LOG 3 +#define FOUR_LOG_DIV_TWO_LOG 2 + +/* borders */ +#define CPE_TOP_LENGTH 12288 +#define SCE_TOP_LENGTH 6144 +#define LEN_OF_LONGEST_CW_TOP_LENGTH 49 + +/* qsc's of high level */ +#define Q_VALUE_INVALID \ + 8192 /* mark a invalid line with this value (to be concealed later on) */ +#define HCR_DIRAC 500 /* a line of high level */ + +/* masks */ +#define MASK_LEFT 0xFFF000 +#define MASK_RIGHT 0xFFF +#define CLR_BIT_10 0x3FF +#define TEST_BIT_10 0x400 + +#define LEFT_OFFSET 12 + +/* when set HCR is replaced by a dummy-module which just fills the outputbuffer + * with a dirac sequence */ +/* use this if HCR is suspected to write in other modules -- if error is stell + * there, HCR is innocent */ + +/* ------------------------------ */ +/* - insert HCR errors - */ +/* ------------------------------ */ + +/* modify input lengths -- high protected */ +#define ERROR_LORSD 0 /* offset: error if different from zero */ +#define ERROR_LOLC 0 /* offset: error if different from zero */ + +/* segments are earlier empty as expected when decoding PCWs */ +#define ERROR_PCW_BODY \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ +#define ERROR_PCW_BODY_SIGN \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ +#define ERROR_PCW_BODY_SIGN_ESC \ + 0 /* set a positive values to trigger the error (make segments earlyer \ + appear to be empty) */ + +/* pretend there are too many bits decoded (enlarge length of codeword) at PCWs + * -- use a positive value */ +#define ERROR_PCW_BODY_ONLY_TOO_LONG \ + 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_TOO_LONG \ + 0 /* set a positive values to trigger the error */ +#define ERROR_PCW_BODY_SIGN_ESC_TOO_LONG \ + 0 /* set a positive values to trigger the error */ + +/* modify HCR bitstream block */ + +#define MODULO_DIVISOR_HCR 30 + +/* ------------------------------ */ +/* - detect HCR errors - */ +/* ------------------------------ */ +/* check input data */ + +/* during decoding */ + +/* all the segments are checked -- therefore -- if this check passes, its a kind + of evidence that the decoded PCWs and non-PCWs are fine */ + +/* if a codeword is decoded there exists a border for the number of bits, which + are allowed to read for this codeword. This border is the minimum of the + length of the longest codeword (for the currently used codebook) and the + separately transmitted 'lengthOfLongestCodeword' in this frame and channel. + The number of decoded bits is counted (for PCWs only -- there it makes really + sense in my opinion). If this number exceeds the border (derived as minimum + -- see above), a error is detected. */ + +/* ----------------------------------------------------------------------------------------------------- + This error check could be set to zero because due to a test within + RVLC-Escape-huffman-Decoder a too long codeword could not be detected -- it + seems that for RVLC-Escape-Codeword the coderoom is used to 100%. Therefore I + assume that the coderoom is used to 100% also for the codebooks 1..11 used at + HCR Therefore this test is deactivated pending further notice + ----------------------------------------------------------------------------------------------------- + */ + +/* test if the number of remaining bits in a segment is _below_ zero. If there + are no errors the lowest allowed value for remainingBitsInSegment is zero. + This check also could be set to zero (save runtime) */ + +/* other */ +/* when set to '1', avoid setting the LAV-Flag in errorLog due to a + previous-line-marking (at PCW decoder). A little more runtime is needed then + when writing values out into output-buffer. */ + +/* ------------------------------ */ +/* - conceal HCR errors - */ +/* ------------------------------ */ + +#define HCR_ERROR_CONCEALMENT \ + 1 /* if set to '1', HCR _mutes_ the erred quantized spectral coefficients */ + +// ------------------------------------------------------------------------------------------------------------------ +// errorLog: A word of 32 bits used for +// logging possible errors within HCR +// in case of distorted +// bitstreams. Table of all +// known errors: +// ------------------------------------------------------------------------------------------------------------------------ +// bit fatal location meaning +// ----+-----+-----------+-------------------------------------- +#define SEGMENT_OVERRIDE_ERR_PCW_BODY \ + 0x80000000 // 31 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN \ + 0x40000000 // 30 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define SEGMENT_OVERRIDE_ERR_PCW_BODY_SIGN_ESC \ + 0x20000000 // 29 no PCW-Dec During PCW decoding it is checked after + // every PCW if there are too many bits decoded (immediate + // check). +#define EXTENDED_SORTED_COUNTER_OVERFLOW \ + 0x10000000 // 28 yes Init-Dec Error during extending sideinfo + // (neither a PCW nor a nonPCW was decoded so far) + // 0x08000000 // 27 reserved + // 0x04000000 // 26 reserved + // 0x02000000 // 25 reserved + // 0x01000000 // 24 reserved + // 0x00800000 // 23 reserved + // 0x00400000 // 22 reserved + // 0x00200000 // 21 reserved + // 0x00100000 // 20 reserved + +/* special errors */ +#define TOO_MANY_PCW_BODY_BITS_DECODED \ + 0x00080000 // 19 yes PCW-Dec During PCW-body-decoding too many bits + // have been read from bitstream -- advice: skip non-PCW decoding +#define TOO_MANY_PCW_BODY_SIGN_BITS_DECODED \ + 0x00040000 // 18 yes PCW-Dec During PCW-body-sign-decoding too many + // bits have been read from bitstream -- advice: skip non-PCW + // decoding +#define TOO_MANY_PCW_BODY_SIGN_ESC_BITS_DECODED \ + 0x00020000 // 17 yes PCW-Dec During PCW-body-sign-esc-decoding too + // many bits have been read from bitstream -- advice: skip + // non-PCW decoding + +// 0x00010000 // 16 reserved +#define STATE_ERROR_BODY_ONLY \ + 0x00008000 // 15 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__BODY \ + 0x00004000 // 14 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN__SIGN \ + 0x00002000 // 13 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__BODY \ + 0x00001000 // 12 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__SIGN \ + 0x00000800 // 11 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX \ + 0x00000400 // 10 no NonPCW-Dec State machine returned with error +#define STATE_ERROR_BODY_SIGN_ESC__ESC_WORD \ + 0x00000200 // 9 no NonPCW-Dec State machine returned with error +#define HCR_SI_LENGTHS_FAILURE \ + 0x00000100 // 8 yes Init-Dec LengthOfLongestCodeword must not be + // less than lenghtOfReorderedSpectralData +#define NUM_SECT_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000080 // 7 yes Init-Dec The number of sections is not within + // the allowed range (short block) +#define NUM_SECT_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000040 // 6 yes Init-Dec The number of sections is not within + // the allowed range (long block) +#define LINE_IN_SECT_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000020 // 5 yes Init-Dec The number of lines per section is not + // within the allowed range (short block) +#define CB_OUT_OF_RANGE_SHORT_BLOCK \ + 0x00000010 // 4 yes Init-Dec The codebook is not within the allowed + // range (short block) +#define LINE_IN_SECT_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000008 // 3 yes Init-Dec The number of lines per section is not + // within the allowed range (long block) +#define CB_OUT_OF_RANGE_LONG_BLOCK \ + 0x00000004 // 2 yes Init-Dec The codebook is not within the allowed + // range (long block) +#define LAV_VIOLATION \ + 0x00000002 // 1 no Final The absolute value of at least one + // decoded line was too high for the according codebook. +#define BIT_IN_SEGMENTATION_ERROR \ + 0x00000001 // 0 no Final After PCW and non-PWC-decoding at least + // one segment is not zero (global check). + +/*----------*/ +#define HCR_FATAL_PCW_ERROR_MASK 0x100E01FC + +typedef enum { PCW_BODY, PCW_BODY_SIGN, PCW_BODY_SIGN_ESC } PCW_TYPE; + +/* interface Decoder <---> HCR */ +typedef struct { + UINT errorLog; + SPECTRAL_PTR pQuantizedSpectralCoefficientsBase; + int quantizedSpectralCoefficientsIdx; + SHORT lengthOfReorderedSpectralData; + SHORT numSection; + SHORT *pNumLineInSect; + INT bitstreamAnchor; + SCHAR lengthOfLongestCodeword; + UCHAR *pCodebook; +} HCR_INPUT_OUTPUT; + +typedef struct { + const UCHAR *pMinOfCbPair; + const UCHAR *pMaxOfCbPair; +} HCR_CB_PAIRS; + +typedef struct { + const USHORT *pLargestAbsVal; + const UCHAR *pMaxCwLength; + const UCHAR *pCbDimension; + const UCHAR *pCbDimShift; + const UCHAR *pCbSign; + const UCHAR *pCbPriority; +} HCR_TABLE_INFO; + +typedef struct { + UINT numSegment; + UINT pSegmentBitfield[((1024 >> 1) / NUMBER_OF_BIT_IN_WORD + 1)]; + UINT pCodewordBitfield[((1024 >> 1) / NUMBER_OF_BIT_IN_WORD + 1)]; + UINT segmentOffset; + INT pLeftStartOfSegment[1024 >> 1]; + INT pRightStartOfSegment[1024 >> 1]; + SCHAR pRemainingBitsInSegment[1024 >> 1]; + UCHAR readDirection; + UCHAR numWordForBitfield; + USHORT pNumBitValidInLastWord; +} HCR_SEGMENT_INFO; + +typedef struct { + UINT numCodeword; + UINT numSortedSection; + USHORT pNumCodewordInSection[MAX_SFB_HCR]; + USHORT pNumSortedCodewordInSection[MAX_SFB_HCR]; + USHORT pNumExtendedSortedCodewordInSection[MAX_SFB_HCR + MAX_HCR_SETS]; + int numExtendedSortedCodewordInSectionIdx; + USHORT pNumExtendedSortedSectionsInSets[MAX_HCR_SETS]; + int numExtendedSortedSectionsInSetsIdx; + USHORT pReorderOffset[MAX_SFB_HCR]; + UCHAR pSortedCodebook[MAX_SFB_HCR]; + + UCHAR pExtendedSortedCodebook[MAX_SFB_HCR + MAX_HCR_SETS]; + int extendedSortedCodebookIdx; + UCHAR pMaxLenOfCbInExtSrtSec[MAX_SFB_HCR + MAX_HCR_SETS]; + int maxLenOfCbInExtSrtSecIdx; + UCHAR pCodebookSwitch[MAX_SFB_HCR]; +} HCR_SECTION_INFO; + +typedef UINT (*STATEFUNC)(HANDLE_FDK_BITSTREAM, void *); + +typedef struct { + /* worst-case and 1024/4 non-PCWs exist in worst-case */ + FIXP_DBL + *pResultBase; /* Base address for spectral data output target buffer */ + UINT iNode[1024 >> 2]; /* Helper indices for code books */ + USHORT + iResultPointer[1024 >> 2]; /* Helper indices for accessing pResultBase */ + UINT pEscapeSequenceInfo[1024 >> 2]; + UINT codewordOffset; + STATEFUNC pState; + UCHAR pCodebook[1024 >> 2]; + UCHAR pCntSign[1024 >> 2]; + /* this array holds the states coded as integer values within the range + * [0,1,..,7] */ + SCHAR pSta[1024 >> 2]; +} HCR_NON_PCW_SIDEINFO; + +typedef struct { + HCR_INPUT_OUTPUT decInOut; + HCR_SEGMENT_INFO segmentInfo; + HCR_SECTION_INFO sectionInfo; + HCR_NON_PCW_SIDEINFO nonPcwSideinfo; +} CErHcrInfo; + +typedef CErHcrInfo *H_HCR_INFO; + +#endif /* AACDEC_HCR_TYPES_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_hcrs.cpp b/fdk-aac/libAACdec/src/aacdec_hcrs.cpp new file mode 100644 index 0000000..d2bc867 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcrs.cpp @@ -0,0 +1,1551 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Prepare decoding of non-PCWs, segmentation- and + bitfield-handling, HCR-Statemachine + +*******************************************************************************/ + +#include "aacdec_hcrs.h" + +#include "aacdec_hcr.h" + +#include "aacdec_hcr_bit.h" +#include "aac_rom.h" +#include "aac_ram.h" + +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord); + +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr); + +static INT ModuloValue(INT input, INT bufferlength); + +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield); + +/*--------------------------------------------------------------------------------------------- + description: This function decodes all non-priority codewords (non-PCWs) by +using a state-machine. +-------------------------------------------------------------------------------------------- +*/ +void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO pHcr) { + UINT numValidSegment; + INT segmentOffset; + INT codewordOffsetBase; + INT codewordOffset; + UINT trial; + + UINT *pNumSegment; + SCHAR *pRemainingBitsInSegment; + UINT *pSegmentBitfield; + UCHAR *pNumWordForBitfield; + USHORT *pNumBitValidInLastWord; + UINT *pCodewordBitfield; + INT bitfieldWord; + INT bitInWord; + UINT tempWord; + UINT interMediateWord; + INT tempBit; + INT carry; + + UINT numCodeword; + UCHAR numSet; + UCHAR currentSet; + UINT codewordInSet; + UINT remainingCodewordsInSet; + SCHAR *pSta; + UINT ret; + + pNumSegment = &(pHcr->segmentInfo.numSegment); + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pNumWordForBitfield = &(pHcr->segmentInfo.numWordForBitfield); + pNumBitValidInLastWord = &(pHcr->segmentInfo.pNumBitValidInLastWord); + pSta = pHcr->nonPcwSideinfo.pSta; + + numValidSegment = InitSegmentBitfield(pNumSegment, pRemainingBitsInSegment, + pSegmentBitfield, pNumWordForBitfield, + pNumBitValidInLastWord); + + if (numValidSegment != 0) { + numCodeword = pHcr->sectionInfo.numCodeword; + numSet = ((numCodeword - 1) / *pNumSegment) + 1; + + pHcr->segmentInfo.readDirection = FROM_RIGHT_TO_LEFT; + + /* Process sets subsequently */ + for (currentSet = 1; currentSet < numSet; currentSet++) { + /* step 1 */ + numCodeword -= + *pNumSegment; /* number of remaining non PCWs [for all sets] */ + if (numCodeword < *pNumSegment) { + codewordInSet = numCodeword; /* for last set */ + } else { + codewordInSet = *pNumSegment; /* for all sets except last set */ + } + + /* step 2 */ + /* prepare array 'CodewordBitfield'; as much ones are written from left in + * all words, as much decodedCodewordInSetCounter nonPCWs exist in this + * set */ + tempWord = 0xFFFFFFFF; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + for (bitfieldWord = *pNumWordForBitfield; bitfieldWord != 0; + bitfieldWord--) { /* loop over all used words */ + if (codewordInSet > NUMBER_OF_BIT_IN_WORD) { /* more codewords than + number of bits => fill + ones */ + /* fill a whole word with ones */ + *pCodewordBitfield++ = tempWord; + codewordInSet -= NUMBER_OF_BIT_IN_WORD; /* subtract number of bits */ + } else { + /* prepare last tempWord */ + for (remainingCodewordsInSet = codewordInSet; + remainingCodewordsInSet < NUMBER_OF_BIT_IN_WORD; + remainingCodewordsInSet++) { + tempWord = + tempWord & + ~(1 + << (NUMBER_OF_BIT_IN_WORD - 1 - + remainingCodewordsInSet)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) + in tempWord */ + } + *pCodewordBitfield++ = tempWord; + tempWord = 0x00000000; + } + } + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + + /* step 3 */ + /* build non-PCW sideinfo for each non-PCW of the current set */ + InitNonPCWSideInformationForCurrentSet(pHcr); + + /* step 4 */ + /* decode all non-PCWs belonging to this set */ + + /* loop over trials */ + codewordOffsetBase = 0; + for (trial = *pNumSegment; trial > 0; trial--) { + /* loop over number of words in bitfields */ + segmentOffset = 0; /* start at zero in every segment */ + pHcr->segmentInfo.segmentOffset = + segmentOffset; /* store in structure for states */ + codewordOffset = codewordOffsetBase; + pHcr->nonPcwSideinfo.codewordOffset = + codewordOffset; /* store in structure for states */ + + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield; + bitfieldWord++) { + /* derive tempWord with bitwise and */ + tempWord = + pSegmentBitfield[bitfieldWord] & pCodewordBitfield[bitfieldWord]; + + /* if tempWord is not zero, decode something */ + if (tempWord != 0) { + /* loop over all bits in tempWord; start state machine if & is true + */ + for (bitInWord = NUMBER_OF_BIT_IN_WORD; bitInWord > 0; + bitInWord--) { + interMediateWord = ((UINT)1 << (bitInWord - 1)); + if ((tempWord & interMediateWord) == interMediateWord) { + /* get state and start state machine */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; + + while (pHcr->nonPcwSideinfo.pState) { + ret = ((STATEFUNC)pHcr->nonPcwSideinfo.pState)(bs, pHcr); + if (ret != 0) { + return; + } + } + } + + /* update both offsets */ + segmentOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += 1; /* add NUMBER_OF_BIT_IN_WORD times one */ + codewordOffset = + ModuloValue(codewordOffset, + *pNumSegment); /* index of the current codeword + lies within modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } else { + segmentOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + pHcr->segmentInfo.segmentOffset = segmentOffset; + codewordOffset += + NUMBER_OF_BIT_IN_WORD; /* add NUMBER_OF_BIT_IN_WORD at once */ + codewordOffset = ModuloValue( + codewordOffset, + *pNumSegment); /* index of the current codeword lies within + modulo range */ + pHcr->nonPcwSideinfo.codewordOffset = codewordOffset; + } + } /* end of bitfield word loop */ + + /* decrement codeword - pointer */ + codewordOffsetBase -= 1; + codewordOffsetBase = + ModuloValue(codewordOffsetBase, *pNumSegment); /* index of the + current codeword + base lies within + modulo range */ + + /* rotate numSegment bits in codewordBitfield */ + /* rotation of *numSegment bits in bitfield of codewords + * (circle-rotation) */ + /* get last valid bit */ + tempBit = pCodewordBitfield[*pNumWordForBitfield - 1] & + (1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + tempBit = tempBit >> (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); + + /* write zero into place where tempBit was fetched from */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord)); + + /* rotate last valid word */ + pCodewordBitfield[*pNumWordForBitfield - 1] = + pCodewordBitfield[*pNumWordForBitfield - 1] >> 1; + + /* transfare carry bit 0 from current word into bitposition 31 from next + * word and rotate current word */ + for (bitfieldWord = *pNumWordForBitfield - 2; bitfieldWord > -1; + bitfieldWord--) { + /* get carry (=bit at position 0) from current word */ + carry = pCodewordBitfield[bitfieldWord] & 1; + + /* put the carry bit at position 31 into word right from current word + */ + pCodewordBitfield[bitfieldWord + 1] = + pCodewordBitfield[bitfieldWord + 1] | + (carry << (NUMBER_OF_BIT_IN_WORD - 1)); + + /* shift current word */ + pCodewordBitfield[bitfieldWord] = + pCodewordBitfield[bitfieldWord] >> 1; + } + + /* put tempBit into free bit-position 31 from first word */ + pCodewordBitfield[0] = + pCodewordBitfield[0] | (tempBit << (NUMBER_OF_BIT_IN_WORD - 1)); + + } /* end of trial loop */ + + /* toggle read direction */ + pHcr->segmentInfo.readDirection = + ToggleReadDirection(pHcr->segmentInfo.readDirection); + } + /* end of set loop */ + + /* all non-PCWs of this spectrum are decoded */ + } + + /* all PCWs and all non PCWs are decoded. They are unbacksorted in output + * buffer. Here is the Interface with comparing QSCs to asm decoding */ +} + +/*--------------------------------------------------------------------------------------------- + description: This function prepares the bitfield used for the + segments. The list is set up once to be used in all +following sets. If a segment is decoded empty, the according bit from the +Bitfield is removed. +----------------------------------------------------------------------------------------------- + return: numValidSegment = the number of valid segments +-------------------------------------------------------------------------------------------- +*/ +static UINT InitSegmentBitfield(UINT *pNumSegment, + SCHAR *pRemainingBitsInSegment, + UINT *pSegmentBitfield, + UCHAR *pNumWordForBitfield, + USHORT *pNumBitValidInLastWord) { + SHORT i; + USHORT r; + UCHAR bitfieldWord; + UINT tempWord; + USHORT numValidSegment; + + *pNumWordForBitfield = + (*pNumSegment == 0) + ? 0 + : ((*pNumSegment - 1) >> THIRTYTWO_LOG_DIV_TWO_LOG) + 1; + + /* loop over all words, which are completely used or only partial */ + /* bit in pSegmentBitfield is zero if segment is empty; bit in + * pSegmentBitfield is one if segment is not empty */ + numValidSegment = 0; + *pNumBitValidInLastWord = *pNumSegment; + + /* loop over words */ + for (bitfieldWord = 0; bitfieldWord < *pNumWordForBitfield - 1; + bitfieldWord++) { + tempWord = 0xFFFFFFFF; /* set ones */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < NUMBER_OF_BIT_IN_WORD; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + *pNumBitValidInLastWord -= NUMBER_OF_BIT_IN_WORD; /* calculate number of + zeros on LSB side in + the last word */ + } + + /* calculate last word: prepare special tempWord */ + tempWord = 0xFFFFFFFF; + for (i = 0; i < (NUMBER_OF_BIT_IN_WORD - *pNumBitValidInLastWord); i++) { + tempWord = tempWord & ~(1 << i); /* clear bit i in tempWord */ + } + + /* calculate last word */ + r = bitfieldWord << THIRTYTWO_LOG_DIV_TWO_LOG; + for (i = 0; i < *pNumBitValidInLastWord; i++) { + if (pRemainingBitsInSegment[r + i] == 0) { + tempWord = tempWord & ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - + i)); /* set a zero at bit number + (NUMBER_OF_BIT_IN_WORD-1-i) in + tempWord */ + } else { + numValidSegment += 1; /* count segments which are not empty */ + } + } + pSegmentBitfield[bitfieldWord] = tempWord; /* store result */ + + return numValidSegment; +} + +/*--------------------------------------------------------------------------------------------- + description: This function sets up sideinfo for the non-PCW decoder (for the +current set). +---------------------------------------------------------------------------------------------*/ +static void InitNonPCWSideInformationForCurrentSet(H_HCR_INFO pHcr) { + USHORT i, k; + UCHAR codebookDim; + UINT startNode; + + UCHAR *pCodebook = pHcr->nonPcwSideinfo.pCodebook; + UINT *iNode = pHcr->nonPcwSideinfo.iNode; + UCHAR *pCntSign = pHcr->nonPcwSideinfo.pCntSign; + USHORT *iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + UINT *pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + SCHAR *pSta = pHcr->nonPcwSideinfo.pSta; + USHORT *pNumExtendedSortedCodewordInSection = + pHcr->sectionInfo.pNumExtendedSortedCodewordInSection; + int numExtendedSortedCodewordInSectionIdx = + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx; + UCHAR *pExtendedSortedCodebook = pHcr->sectionInfo.pExtendedSortedCodebook; + int extendedSortedCodebookIdx = pHcr->sectionInfo.extendedSortedCodebookIdx; + USHORT *pNumExtendedSortedSectionsInSets = + pHcr->sectionInfo.pNumExtendedSortedSectionsInSets; + int numExtendedSortedSectionsInSetsIdx = + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx; + int quantizedSpectralCoefficientsIdx = + pHcr->decInOut.quantizedSpectralCoefficientsIdx; + const UCHAR *pCbDimension = aDimCb; + int iterationCounter = 0; + + /* loop over number of extended sorted sections in the current set so all + * codewords sideinfo variables within this set can be prepared for decoding + */ + for (i = pNumExtendedSortedSectionsInSets[numExtendedSortedSectionsInSetsIdx]; + i != 0; i--) { + codebookDim = + pCbDimension[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + startNode = *aHuffTable[pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + + for (k = pNumExtendedSortedCodewordInSection + [numExtendedSortedCodewordInSectionIdx]; + k != 0; k--) { + iterationCounter++; + if (iterationCounter > (1024 >> 2)) { + return; + } + *pSta++ = aCodebook2StartInt + [pExtendedSortedCodebook[extendedSortedCodebookIdx]]; + *pCodebook++ = pExtendedSortedCodebook[extendedSortedCodebookIdx]; + *iNode++ = startNode; + *pCntSign++ = 0; + *iResultPointer++ = quantizedSpectralCoefficientsIdx; + *pEscapeSequenceInfo++ = 0; + quantizedSpectralCoefficientsIdx += + codebookDim; /* update pointer by codebookDim --> point to next + starting value for writing out */ + if (quantizedSpectralCoefficientsIdx >= 1024) { + return; + } + } + numExtendedSortedCodewordInSectionIdx++; /* inc ptr for next ext sort sec in + current set */ + extendedSortedCodebookIdx++; /* inc ptr for next ext sort sec in current set + */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS) || + extendedSortedCodebookIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + } + numExtendedSortedSectionsInSetsIdx++; /* inc ptr for next set of non-PCWs */ + if (numExtendedSortedCodewordInSectionIdx >= (MAX_SFB_HCR + MAX_HCR_SETS)) { + return; + } + + /* Write back indexes */ + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->sectionInfo.extendedSortedCodebookIdx = extendedSortedCodebookIdx; + pHcr->sectionInfo.numExtendedSortedSectionsInSetsIdx = + numExtendedSortedSectionsInSetsIdx; + pHcr->sectionInfo.numExtendedSortedCodewordInSectionIdx = + numExtendedSortedCodewordInSectionIdx; + pHcr->decInOut.quantizedSpectralCoefficientsIdx = + quantizedSpectralCoefficientsIdx; +} + +/*--------------------------------------------------------------------------------------------- + description: This function returns the input value if the value is in the + range of bufferlength. If is smaller, one bufferlength +is added, if is bigger one bufferlength is subtracted. +----------------------------------------------------------------------------------------------- + return: modulo result +-------------------------------------------------------------------------------------------- +*/ +static INT ModuloValue(INT input, INT bufferlength) { + if (input > (bufferlength - 1)) { + return (input - bufferlength); + } + if (input < 0) { + return (input + bufferlength); + } + return input; +} + +/*--------------------------------------------------------------------------------------------- + description: This function clears a bit from current bitfield and + switches off the statemachine. + + A bit is cleared in two cases: + a) a codeword is decoded, then a bit is cleared in codeword +bitfield b) a segment is decoded empty, then a bit is cleared in segment +bitfield +-------------------------------------------------------------------------------------------- +*/ +static void ClearBitFromBitfield(STATEFUNC *ptrState, UINT offset, + UINT *pBitfield) { + UINT numBitfieldWord; + UINT numBitfieldBit; + + /* get both values needed for clearing the bit */ + numBitfieldWord = offset >> THIRTYTWO_LOG_DIV_TWO_LOG; /* int = wordNr */ + numBitfieldBit = offset - (numBitfieldWord + << THIRTYTWO_LOG_DIV_TWO_LOG); /* fract = bitNr */ + + /* clear a bit in bitfield */ + pBitfield[numBitfieldWord] = + pBitfield[numBitfieldWord] & + ~(1 << (NUMBER_OF_BIT_IN_WORD - 1 - numBitfieldBit)); + + /* switch off state machine because codeword is decoded and/or because segment + * is empty */ + *ptrState = NULL; +} + +/* ========================================================================================= + the states of the statemachine + ========================================================================================= + */ + +/*--------------------------------------------------------------------------------------------- + description: Decodes the body of a codeword. This State is used for +codebooks 1,2,5 and 6. No sign bits are decoded, because the table of the +quantized spectral values has got a valid sign at the quantized spectral lines. +----------------------------------------------------------------------------------------------- + output: Two or four quantizes spectral values written at position +where pResultPointr points to +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + FIXP_DBL *pResultBase; + UINT *iNode; + USHORT *iResultPointer; + UINT codewordOffset; + UINT branchNode; + UINT branchValue; + UINT iQSC; + UINT treeNode; + UCHAR carryBit; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + SCHAR *pRemainingBitsInSegment; + UCHAR readDirection; + UCHAR *pCodebook; + UCHAR dimCntr; + const UINT *pCurrentTree; + const UCHAR *pCbDimension; + const SCHAR *pQuantVal; + const SCHAR *pQuantValBase; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; ==> body is complete */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing out result */ + + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal++; /* write out 2 or 4 lines into + spectrum; no Sign bits + available in this state */ + } + + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_ONLY; + return BODY_ONLY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body, writes out result and counts the +number of quantized spectral values, which are different form zero. For those +values sign bits are needed. + + If sign bit counter cntSign is different from zero, switch to +next state to decode sign Bits there. If sign bit counter cntSign is zero, no +sign bits are needed and codeword is decoded. +----------------------------------------------------------------------------------------------- + output: Two or four written quantizes spectral values written at +position where pResultPointr points to. The signs of those lines may be wrong. +If the signs [on just one signle sign] is wrong, the next state will correct it. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCodebook; + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UINT iQSC; + UINT cntSign; + UCHAR dimCntr; + UCHAR carryBit; + SCHAR *pSta; + UINT treeNode; + UINT branchValue; + UINT branchNode; + const UCHAR *pCbDimension; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pCodebook = pHcr->nonPcwSideinfo.pCodebook; + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + pCbDimension = aDimCb; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[pCodebook[codewordOffset]]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + CarryBitToBranchValue(carryBit, /* make a step in decoding tree */ + treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + /* body completely decoded; branchValue is valid, set pQuantVal to first + * (of two or four) quantized spectral coefficients */ + pQuantValBase = aQuantTable[pCodebook[codewordOffset]]; /* get base + address of + quantized + values + belonging to + current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + iQSC = iResultPointer[codewordOffset]; /* get position of first line for + writing result */ + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + for (dimCntr = pCbDimension[pCodebook[codewordOffset]]; dimCntr != 0; + dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + pCntSign[codewordOffset] = cntSign; /* write sign count result into + codewordsideinfo of current + codeword */ + pSta[codewordOffset] = BODY_SIGN__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + treeNode = *( + pCurrentTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + iNode[codewordOffset] = treeNode; /* store updated treeNode because maybe + decoding of codeword body not finished + yet */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__BODY; + return BODY_SIGN__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits belonging to a codeword. The +state is called as often in different "trials" until pCntSgn[codewordOffset] is +zero. +----------------------------------------------------------------------------------------------- + output: The two or four quantizes spectral values (written in previous +state) have now the correct sign. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UCHAR cntSign; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + /*pCodebook = */ + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + cntSign -= + 1; /* decrement sign counter because one sign bit has been read */ + + /* search for a line (which was decoded in previous state) which is not + * zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { /* points to current value different from zero */ + return BODY_SIGN__SIGN; + } + } + + /* put sign together with line; if carryBit is zero, the sign is ok already; + * no write operation necessary in this case */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + + iQSC++; /* update pointer to next (maybe valid) value */ + + if (cntSign == 0) { /* if (cntSign==0) ==> set state CODEWORD_DECODED */ + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and + switch off statemachine */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + break; /* whole nonPCW-Body and according sign bits are decoded */ + } + } + pCntSign[codewordOffset] = cntSign; + iResultPointer[codewordOffset] = iQSC; /* store updated pResultPointer */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN__SIGN; + return BODY_SIGN__SIGN; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decodes the codeword body in case of codebook is 11. Writes +out resulting two or four lines [with probably wrong sign] and counts the number +of lines, which are different form zero. This information is needed in next + state where sign bits will be decoded, if necessary. + If sign bit counter cntSign is zero, no sign bits are needed +and codeword is decoded completely. +----------------------------------------------------------------------------------------------- + output: Two lines (quantizes spectral coefficients) which are probably +wrong. The sign may be wrong and if one or two values is/are 16, the following +states will decode the escape sequence to correct the values which are wirtten +here. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT codewordOffset; + + UCHAR carryBit; + UINT iQSC; + UINT cntSign; + UINT dimCntr; + UINT treeNode; + SCHAR *pSta; + UINT branchNode; + UINT branchValue; + const UINT *pCurrentTree; + const SCHAR *pQuantValBase; + const SCHAR *pQuantVal; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + treeNode = iNode[codewordOffset]; + pCurrentTree = aHuffTable[ESCAPE_CODEBOOK]; + + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* make a step in tree */ + CarryBitToBranchValue(carryBit, treeNode, &branchValue, &branchNode); + + /* if end of branch reached write out lines and count bits needed for sign, + * otherwise store node in codeword sideinfo */ + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set body complete */ + + /* body completely decoded; branchValue is valid */ + /* set pQuantVol to first (of two or four) quantized spectral coefficients + */ + pQuantValBase = aQuantTable[ESCAPE_CODEBOOK]; /* get base address of + quantized values + belonging to current + codebook */ + pQuantVal = pQuantValBase + branchValue; /* set pointer to first valid + line [of 2 or 4 quantized + values] */ + + /* make backup from original resultPointer in node storage for state + * BODY_SIGN_ESC__SIGN */ + iNode[codewordOffset] = iResultPointer[codewordOffset]; + + /* get position of first line for writing result */ + iQSC = iResultPointer[codewordOffset]; + + /* codeword decoding result is written out here: Write out 2 or 4 + * quantized spectral values with probably */ + /* wrong sign and count number of values which are different from zero for + * sign bit decoding [which happens in next state] */ + cntSign = 0; + + for (dimCntr = DIMENSION_OF_ESCAPE_CODEBOOK; dimCntr != 0; dimCntr--) { + pResultBase[iQSC++] = + (FIXP_DBL)*pQuantVal; /* write quant. spec. coef. into spectrum */ + if (*pQuantVal++ != 0) { + cntSign += 1; + } + } + + if (cntSign == 0) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + /* codeword decoded */ + } else { + /* write sign count result into codewordsideinfo of current codeword */ + pCntSign[codewordOffset] = cntSign; + pSta[codewordOffset] = BODY_SIGN_ESC__SIGN; /* change state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + pRemainingBitsInSegment[segmentOffset] -= 1; /* the last reinitialzation + of for loop counter (see + above) is done here */ + break; /* end of branch in tree reached i.e. a whole nonPCW-Body is + decoded */ + } else { /* body is not decoded completely: */ + /* update treeNode for further step in decoding tree and store updated + * treeNode because maybe no more bits left in segment */ + treeNode = *(pCurrentTree + branchValue); + iNode[codewordOffset] = treeNode; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__BODY; + return BODY_SIGN_ESC__BODY; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: This state decodes the sign bits, if a codeword of codebook 11 +needs some. A flag named 'flagB' in codeword sideinfo is set, if the second line +of quantized spectral values is 16. The 'flagB' is used in case of decoding of a +escape sequence is necessary as far as the second line is concerned. + + If only the first line needs an escape sequence, the flagB is +cleared. If only the second line needs an escape sequence, the flagB is not +used. + + For storing sideinfo in case of escape sequence decoding one +single word can be used for both escape sequences because they are decoded not +at the same time: + + + bit 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 +4 3 2 1 0 + ===== == == =========== =========== +=================================== ^ ^ ^ ^ ^ +^ | | | | | | res. flagA flagB +escapePrefixUp escapePrefixDown escapeWord + +----------------------------------------------------------------------------------------------- + output: Two lines with correct sign. If one or two values is/are 16, +the lines are not valid, otherwise they are. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + UINT *iNode; + UCHAR *pCntSign; + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT iQSC; + UCHAR cntSign; + UINT flagA; + UINT flagB; + UINT flags; + UCHAR carryBit; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + iNode = pHcr->nonPcwSideinfo.iNode; + pCntSign = pHcr->nonPcwSideinfo.pCntSign; + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + iQSC = iResultPointer[codewordOffset]; + cntSign = pCntSign[codewordOffset]; + + /* loop for sign bit decoding */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* decrement sign counter because one sign bit has been read */ + cntSign -= 1; + pCntSign[codewordOffset] = cntSign; + + /* get a quantized spectral value (which was decoded in previous state) + * which is not zero. [This value will get a sign] */ + while (pResultBase[iQSC] == (FIXP_DBL)0) { + if (++iQSC >= 1024) { + return BODY_SIGN_ESC__SIGN; + } + } + iResultPointer[codewordOffset] = iQSC; + + /* put negative sign together with quantized spectral value; if carryBit is + * zero, the sign is ok already; no write operation necessary in this case + */ + if (carryBit != 0) { + pResultBase[iQSC] = -pResultBase[iQSC]; /* carryBit = 1 --> minus */ + } + iQSC++; /* update index to next (maybe valid) value */ + iResultPointer[codewordOffset] = iQSC; + + if (cntSign == 0) { + /* all sign bits are decoded now */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* check decoded values if codeword is decoded: Check if one or two escape + * sequences 16 follow */ + + /* step 0 */ + /* restore pointer to first decoded quantized value [ = original + * pResultPointr] from index iNode prepared in State_BODY_SIGN_ESC__BODY + */ + iQSC = iNode[codewordOffset]; + + /* step 1 */ + /* test first value if escape sequence follows */ + flagA = 0; /* for first possible escape sequence */ + if (fixp_abs(pResultBase[iQSC++]) == (FIXP_DBL)ESCAPE_VALUE) { + flagA = 1; + } + + /* step 2 */ + /* test second value if escape sequence follows */ + flagB = 0; /* for second possible escape sequence */ + if (fixp_abs(pResultBase[iQSC]) == (FIXP_DBL)ESCAPE_VALUE) { + flagB = 1; + } + + /* step 3 */ + /* evaluate flag result and go on if necessary */ + if (!flagA && !flagB) { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } else { + /* at least one of two lines is 16 */ + /* store both flags at correct positions in non PCW codeword sideinfo + * pEscapeSequenceInfo[codewordOffset] */ + flags = flagA << POSITION_OF_FLAG_A; + flags |= (flagB << POSITION_OF_FLAG_B); + pEscapeSequenceInfo[codewordOffset] = flags; + + /* set next state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + + /* set result pointer to the first line of the two decoded lines */ + iResultPointer[codewordOffset] = iNode[codewordOffset]; + + if (!flagA && flagB) { + /* update pResultPointr ==> state Stat_BODY_SIGN_ESC__ESC_WORD writes + * to correct position. Second value is the one and only escape value + */ + iQSC = iResultPointer[codewordOffset]; + iQSC++; + iResultPointer[codewordOffset] = iQSC; + } + + } /* at least one of two lines is 16 */ + break; /* nonPCW-Body at cb 11 and according sign bits are decoded */ + + } /* if ( cntSign == 0 ) */ + } /* loop over remaining Bits in segment */ + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__SIGN; + return BODY_SIGN_ESC__SIGN; + } + } + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escape prefix of first or second escape sequence. The +escape prefix consists of ones. The following zero is also decoded here. +----------------------------------------------------------------------------------------------- + output: If the single separator-zero which follows the +escape-prefix-ones is not yet decoded: The value 'escapePrefixUp' in word +pEscapeSequenceInfo[codewordOffset] is updated. + + If the single separator-zero which follows the +escape-prefix-ones is decoded: Two updated values 'escapePrefixUp' and +'escapePrefixDown' in word pEscapeSequenceInfo[codewordOffset]. This State is +finished. Switch to next state. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT segmentOffset; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + UCHAR carryBit; + UINT escapePrefixUp; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* decode escape prefix */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* count ones and store sum in escapePrefixUp */ + if (carryBit == 1) { + escapePrefixUp += 1; /* update conter for ones */ + + /* store updated counter in sideinfo of current codeword */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + } else { /* separator [zero] reached */ + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + escapePrefixUp += + 4; /* if escape_separator '0' appears, add 4 and ==> break */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixUp */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_UP; /* delete old escapePrefixUp */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_UP; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixUp */ + escapePrefixUp >>= LSB_ESCAPE_PREFIX_UP; /* shift back down */ + + /* store escapePrefixUp in pEscapeSequenceInfo[codewordOffset] at bit + * position escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixUp <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixUp; /* insert new escapePrefixDown */ + + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_WORD; /* set next state */ + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from separate + array of cw-sideinfo */ + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_PREFIX; + return BODY_SIGN_ESC__ESC_PREFIX; + } + } + + return STOP_THIS_STATE; +} + +/*--------------------------------------------------------------------------------------------- + description: Decode escapeWord of escape sequence. If the escape sequence +is decoded completely, assemble quantized-spectral-escape-coefficient and +replace the previous decoded 16 by the new value. Test flagB. If flagB is set, +the second escape sequence must be decoded. If flagB is not set, the codeword is +decoded and the state machine is switched off. +----------------------------------------------------------------------------------------------- + output: Two lines with valid sign. At least one of both lines has got +the correct value. +----------------------------------------------------------------------------------------------- + return: 0 +-------------------------------------------------------------------------------------------- +*/ +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM bs, void *ptr) { + H_HCR_INFO pHcr = (H_HCR_INFO)ptr; + SCHAR *pRemainingBitsInSegment; + INT *pLeftStartOfSegment; + INT *pRightStartOfSegment; + UCHAR readDirection; + UINT *pSegmentBitfield; + UINT *pCodewordBitfield; + UINT segmentOffset; + + FIXP_DBL *pResultBase; + USHORT *iResultPointer; + UINT *pEscapeSequenceInfo; + UINT codewordOffset; + + UINT escapeWord; + UINT escapePrefixDown; + UINT escapePrefixUp; + UCHAR carryBit; + UINT iQSC; + INT sign; + UINT flagA; + UINT flagB; + SCHAR *pSta; + + pRemainingBitsInSegment = pHcr->segmentInfo.pRemainingBitsInSegment; + pLeftStartOfSegment = pHcr->segmentInfo.pLeftStartOfSegment; + pRightStartOfSegment = pHcr->segmentInfo.pRightStartOfSegment; + readDirection = pHcr->segmentInfo.readDirection; + pSegmentBitfield = pHcr->segmentInfo.pSegmentBitfield; + pCodewordBitfield = pHcr->segmentInfo.pCodewordBitfield; + segmentOffset = pHcr->segmentInfo.segmentOffset; + + pResultBase = pHcr->nonPcwSideinfo.pResultBase; + iResultPointer = pHcr->nonPcwSideinfo.iResultPointer; + pEscapeSequenceInfo = pHcr->nonPcwSideinfo.pEscapeSequenceInfo; + codewordOffset = pHcr->nonPcwSideinfo.codewordOffset; + pSta = pHcr->nonPcwSideinfo.pSta; + + escapeWord = pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_WORD; + escapePrefixDown = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_DOWN) >> + LSB_ESCAPE_PREFIX_DOWN; + + /* decode escape word */ + for (; pRemainingBitsInSegment[segmentOffset] > 0; + pRemainingBitsInSegment[segmentOffset] -= 1) { + carryBit = HcrGetABitFromBitstream( + bs, pHcr->decInOut.bitstreamAnchor, &pLeftStartOfSegment[segmentOffset], + &pRightStartOfSegment[segmentOffset], readDirection); + + /* build escape word */ + escapeWord <<= + 1; /* left shift previous decoded part of escapeWord by on bit */ + escapeWord = escapeWord | carryBit; /* assemble escape word by bitwise or */ + + /* decrement counter for length of escape word because one more bit was + * decoded */ + escapePrefixDown -= 1; + + /* store updated escapePrefixDown */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_PREFIX_DOWN; /* delete old escapePrefixDown */ + escapePrefixDown <<= LSB_ESCAPE_PREFIX_DOWN; /* shift to correct position */ + pEscapeSequenceInfo[codewordOffset] |= + escapePrefixDown; /* insert new escapePrefixDown */ + escapePrefixDown >>= LSB_ESCAPE_PREFIX_DOWN; /* shift back */ + + /* store updated escapeWord */ + pEscapeSequenceInfo[codewordOffset] &= + ~MASK_ESCAPE_WORD; /* delete old escapeWord */ + pEscapeSequenceInfo[codewordOffset] |= + escapeWord; /* insert new escapeWord */ + + if (escapePrefixDown == 0) { + pRemainingBitsInSegment[segmentOffset] -= 1; /* last reinitialzation of + for loop counter (see + above) is done here */ + + /* escape sequence decoded. Assemble escape-line and replace original line + */ + + /* step 0 */ + /* derive sign */ + iQSC = iResultPointer[codewordOffset]; + sign = (pResultBase[iQSC] >= (FIXP_DBL)0) + ? 1 + : -1; /* get sign of escape value 16 */ + + /* step 1 */ + /* get escapePrefixUp */ + escapePrefixUp = + (pEscapeSequenceInfo[codewordOffset] & MASK_ESCAPE_PREFIX_UP) >> + LSB_ESCAPE_PREFIX_UP; + + /* step 2 */ + /* calculate escape value */ + pResultBase[iQSC] = + (FIXP_DBL)(sign * (((INT)1 << escapePrefixUp) + (INT)escapeWord)); + + /* get both flags from sideinfo (flags are not shifted to the + * lsb-position) */ + flagA = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_A; + flagB = pEscapeSequenceInfo[codewordOffset] & MASK_FLAG_B; + + /* step 3 */ + /* clear the whole escape sideinfo word */ + pEscapeSequenceInfo[codewordOffset] = 0; + + /* change state in dependence of flag flagB */ + if (flagA != 0) { + /* first escape sequence decoded; previous decoded 16 has been replaced + * by valid line */ + + /* clear flagA in sideinfo word because this escape sequence has already + * beed decoded */ + pEscapeSequenceInfo[codewordOffset] &= ~MASK_FLAG_A; + + if (flagB == 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield + and switch off + statemachine */ + } else { + /* updated pointer to next and last 16 */ + iQSC++; + iResultPointer[codewordOffset] = iQSC; + + /* change state */ + pSta[codewordOffset] = BODY_SIGN_ESC__ESC_PREFIX; + pHcr->nonPcwSideinfo.pState = + aStateConstant2State[pSta[codewordOffset]]; /* get state from + separate array of + cw-sideinfo */ + } + } else { + ClearBitFromBitfield( + &(pHcr->nonPcwSideinfo.pState), segmentOffset, + pCodewordBitfield); /* clear a bit in bitfield and switch off + statemachine */ + } + break; + } + } + + if (pRemainingBitsInSegment[segmentOffset] <= 0) { + ClearBitFromBitfield(&(pHcr->nonPcwSideinfo.pState), segmentOffset, + pSegmentBitfield); /* clear a bit in bitfield and + switch off statemachine */ + + if (pRemainingBitsInSegment[segmentOffset] < 0) { + pHcr->decInOut.errorLog |= STATE_ERROR_BODY_SIGN_ESC__ESC_WORD; + return BODY_SIGN_ESC__ESC_WORD; + } + } + + return STOP_THIS_STATE; +} diff --git a/fdk-aac/libAACdec/src/aacdec_hcrs.h b/fdk-aac/libAACdec/src/aacdec_hcrs.h new file mode 100644 index 0000000..acb2f40 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_hcrs.h @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: HCR Decoder: Defines of state-constants, masks and + state-prototypes + +*******************************************************************************/ + +#ifndef AACDEC_HCRS_H +#define AACDEC_HCRS_H + +#include "FDK_bitstream.h" +#include "aacdec_hcr_types.h" +/* The four different kinds of types of states are: */ +/* different states are defined as constants */ /* start middle=self next + stop */ +#define STOP_THIS_STATE \ + 0 /* */ +#define BODY_ONLY \ + 1 /* X X X */ +#define BODY_SIGN__BODY \ + 2 /* X X X X [stop if no sign] */ +#define BODY_SIGN__SIGN \ + 3 /* X X [stop if sign bits decoded] */ +#define BODY_SIGN_ESC__BODY \ + 4 /* X X X X [stop if no sign] */ +#define BODY_SIGN_ESC__SIGN \ + 5 /* X X X [stop if no escape sequence] */ +#define BODY_SIGN_ESC__ESC_PREFIX \ + 6 /* X X */ +#define BODY_SIGN_ESC__ESC_WORD \ + 7 /* X X X [stop if abs(second qsc) != 16] */ + +/* examples: */ + +/* BODY_ONLY means only the codeword body will be decoded; no + * sign bits will follow and no escapesequence will follow */ + +/* BODY_SIGN__BODY means that the codeword consists of two parts; + * body and sign part. The part '__BODY' after the two underscores shows */ +/* that the bits which are currently decoded belong + * to the '__BODY' of the codeword and not to the sign part. */ + +/* BODY_SIGN_ESC__ESC_PB means that the codeword consists of three parts; + * body, sign and (here: two) escape sequences; */ +/* P = Prefix = ones */ +/* W = Escape Word */ +/* A = first possible (of two) Escape sequeces */ +/* B = second possible (of two) Escape sequeces */ +/* The part after the two underscores shows that + * the current bits which are decoded belong to the '__ESC_PB' - part of the */ +/* codeword. That means the body and the sign bits + * are decoded completely and the bits which are decoded now belong to */ +/* the escape sequence [P = prefix; B=second + * possible escape sequence] */ + +#define MSB_31_MASK 0x80000000 /* masks MSB (= Bit 31) in a 32 bit word */ +#define DIMENSION_OF_ESCAPE_CODEBOOK 2 /* for cb >= 11 is dimension 2 */ +#define ESCAPE_CODEBOOK 11 + +#define MASK_ESCAPE_PREFIX_UP 0x000F0000 +#define LSB_ESCAPE_PREFIX_UP 16 + +#define MASK_ESCAPE_PREFIX_DOWN 0x0000F000 +#define LSB_ESCAPE_PREFIX_DOWN 12 + +#define MASK_ESCAPE_WORD 0x00000FFF +#define MASK_FLAG_A 0x00200000 +#define MASK_FLAG_B 0x00100000 + +extern void DecodeNonPCWs(HANDLE_FDK_BITSTREAM bs, H_HCR_INFO hHcr); + +UINT Hcr_State_BODY_ONLY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__BODY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN__SIGN(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__BODY(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__SIGN(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_PREFIX(HANDLE_FDK_BITSTREAM, void*); +UINT Hcr_State_BODY_SIGN_ESC__ESC_WORD(HANDLE_FDK_BITSTREAM, void*); + +#endif /* AACDEC_HCRS_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_pns.cpp b/fdk-aac/libAACdec/src/aacdec_pns.cpp new file mode 100644 index 0000000..432cd4e --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_pns.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: perceptual noise substitution tool + +*******************************************************************************/ + +#include "aacdec_pns.h" + +#include "aac_ram.h" +#include "aac_rom.h" +#include "channelinfo.h" +#include "block.h" +#include "FDK_bitstream.h" + +#include "genericStds.h" + +#define NOISE_OFFSET 90 /* cf. ISO 14496-3 p. 175 */ + +/*! + \brief Reset InterChannel and PNS data + + The function resets the InterChannel and PNS data +*/ +void CPns_ResetData(CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData) { + FDK_ASSERT(pPnsData != NULL); + FDK_ASSERT(pPnsInterChannelData != NULL); + /* Assign pointer always, since pPnsData is not persistent data */ + pPnsData->pPnsInterChannelData = pPnsInterChannelData; + pPnsData->PnsActive = 0; + pPnsData->CurrentEnergy = 0; + + FDKmemclear(pPnsData->pnsUsed, (8 * 16) * sizeof(UCHAR)); + FDKmemclear(pPnsInterChannelData->correlated, (8 * 16) * sizeof(UCHAR)); +} + +/*! + \brief Update PNS noise generator state. + + The function sets the seed for PNS noise generation. + It can be used to link two or more channels in terms of PNS. +*/ +void CPns_UpdateNoiseState(CPnsData *pPnsData, INT *currentSeed, + INT *randomSeed) { + /* use pointer because seed has to be + same, left and right channel ! */ + pPnsData->currentSeed = currentSeed; + pPnsData->randomSeed = randomSeed; +} + +/*! + \brief Indicates if PNS is used + + The function returns a value indicating whether PNS is used or not + acordding to the noise energy + + \return PNS used +*/ +int CPns_IsPnsUsed(const CPnsData *pPnsData, const int group, const int band) { + unsigned pns_band = group * 16 + band; + + return pPnsData->pnsUsed[pns_band] & (UCHAR)1; +} + +/*! + \brief Set correlation + + The function activates the noise correlation between the channel pair +*/ +void CPns_SetCorrelation(CPnsData *pPnsData, const int group, const int band, + const int outofphase) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + pInterChannelData->correlated[pns_band] = (outofphase) ? 3 : 1; +} + +/*! + \brief Indicates if correlation is used + + The function indicates if the noise correlation between the channel pair + is activated + + \return PNS is correlated +*/ +static int CPns_IsCorrelated(const CPnsData *pPnsData, const int group, + const int band) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + return (pInterChannelData->correlated[pns_band] & 0x01) ? 1 : 0; +} + +/*! + \brief Indicates if correlated out of phase mode is used. + + The function indicates if the noise correlation between the channel pair + is activated in out-of-phase mode. + + \return PNS is out-of-phase +*/ +static int CPns_IsOutOfPhase(const CPnsData *pPnsData, const int group, + const int band) { + CPnsInterChannelData *pInterChannelData = pPnsData->pPnsInterChannelData; + unsigned pns_band = group * 16 + band; + + return (pInterChannelData->correlated[pns_band] & 0x02) ? 1 : 0; +} + +/*! + \brief Read PNS information + + The function reads the PNS information from the bitstream +*/ +void CPns_Read(CPnsData *pPnsData, HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, SHORT *pScaleFactor, + UCHAR global_gain, int band, int group /* = 0 */) { + int delta; + UINT pns_band = group * 16 + band; + + if (pPnsData->PnsActive) { + /* Next PNS band case */ + delta = CBlock_DecodeHuffmanWord(bs, hcb) - 60; + } else { + /* First PNS band case */ + int noiseStartValue = FDKreadBits(bs, 9); + + delta = noiseStartValue - 256; + pPnsData->PnsActive = 1; + pPnsData->CurrentEnergy = global_gain - NOISE_OFFSET; + } + + pPnsData->CurrentEnergy += delta; + pScaleFactor[pns_band] = pPnsData->CurrentEnergy; + + pPnsData->pnsUsed[pns_band] = 1; +} + +/** + * \brief Generate a vector of noise of given length. The noise values are + * scaled in order to yield a noise energy of 1.0 + * \param spec pointer to were the noise values will be written to. + * \param size amount of noise values to be generated. + * \param pRandomState pointer to the state of the random generator being used. + * \return exponent of generated noise vector. + */ +static int GenerateRandomVector(FIXP_DBL *RESTRICT spec, int size, + int *pRandomState) { + int i, invNrg_e = 0, nrg_e = 0; + FIXP_DBL invNrg_m, nrg_m = FL2FXCONST_DBL(0.0f); + FIXP_DBL *RESTRICT ptr = spec; + int randomState = *pRandomState; + +#define GEN_NOISE_NRG_SCALE 7 + + /* Generate noise and calculate energy. */ + for (i = 0; i < size; i++) { + randomState = + (((INT64)1664525 * randomState) + (INT64)1013904223) & 0xFFFFFFFF; + nrg_m = fPow2AddDiv2(nrg_m, (FIXP_DBL)randomState >> GEN_NOISE_NRG_SCALE); + *ptr++ = (FIXP_DBL)randomState; + } + nrg_e = GEN_NOISE_NRG_SCALE * 2 + 1; + + /* weight noise with = 1 / sqrt_nrg; */ + invNrg_m = invSqrtNorm2(nrg_m << 1, &invNrg_e); + invNrg_e += -((nrg_e - 1) >> 1); + + for (i = size; i--;) { + spec[i] = fMult(spec[i], invNrg_m); + } + + /* Store random state */ + *pRandomState = randomState; + + return invNrg_e; +} + +static void ScaleBand(FIXP_DBL *RESTRICT spec, int size, int scaleFactor, + int specScale, int noise_e, int out_of_phase) { + int i, shift, sfExponent; + FIXP_DBL sfMatissa; + + /* Get gain from scale factor value = 2^(scaleFactor * 0.25) */ + sfMatissa = MantissaTable[scaleFactor & 0x03][0]; + /* sfExponent = (scaleFactor >> 2) + ExponentTable[scaleFactor & 0x03][0]; */ + /* Note: ExponentTable[scaleFactor & 0x03][0] is always 1. */ + sfExponent = (scaleFactor >> 2) + 1; + + if (out_of_phase != 0) { + sfMatissa = -sfMatissa; + } + + /* +1 because of fMultDiv2 below. */ + shift = sfExponent - specScale + 1 + noise_e; + + /* Apply gain to noise values */ + if (shift >= 0) { + shift = fixMin(shift, DFRACT_BITS - 1); + for (i = size; i-- != 0;) { + spec[i] = fMultDiv2(spec[i], sfMatissa) << shift; + } + } else { + shift = fixMin(-shift, DFRACT_BITS - 1); + for (i = size; i-- != 0;) { + spec[i] = fMultDiv2(spec[i], sfMatissa) >> shift; + } + } +} + +/*! + \brief Apply PNS + + The function applies PNS (i.e. it generates noise) on the bands + flagged as noisy bands + +*/ +void CPns_Apply(const CPnsData *pPnsData, const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const int channel) { + if (pPnsData->PnsActive) { + const short *BandOffsets = + GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo); + + int ScaleFactorBandsTransmitted = GetScaleFactorBandsTransmitted(pIcsInfo); + + for (int window = 0, group = 0; group < GetWindowGroups(pIcsInfo); + group++) { + for (int groupwin = 0; groupwin < GetWindowGroupLength(pIcsInfo, group); + groupwin++, window++) { + FIXP_DBL *spectrum = SPEC(pSpectrum, window, granuleLength); + + for (int band = 0; band < ScaleFactorBandsTransmitted; band++) { + if (CPns_IsPnsUsed(pPnsData, group, band)) { + UINT pns_band = window * 16 + band; + + int bandWidth = BandOffsets[band + 1] - BandOffsets[band]; + int noise_e; + + FDK_ASSERT(bandWidth >= 0); + + if (channel > 0 && CPns_IsCorrelated(pPnsData, group, band)) { + noise_e = + GenerateRandomVector(spectrum + BandOffsets[band], bandWidth, + &pPnsData->randomSeed[pns_band]); + } else { + pPnsData->randomSeed[pns_band] = *pPnsData->currentSeed; + + noise_e = GenerateRandomVector(spectrum + BandOffsets[band], + bandWidth, pPnsData->currentSeed); + } + + int outOfPhase = CPns_IsOutOfPhase(pPnsData, group, band); + + ScaleBand(spectrum + BandOffsets[band], bandWidth, + pScaleFactor[group * 16 + band], pSpecScale[window], + noise_e, outOfPhase); + } + } + } + } + } +} diff --git a/fdk-aac/libAACdec/src/aacdec_pns.h b/fdk-aac/libAACdec/src/aacdec_pns.h new file mode 100644 index 0000000..45cd989 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_pns.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: perceptual noise substitution tool + +*******************************************************************************/ + +#ifndef AACDEC_PNS_H +#define AACDEC_PNS_H + +#include "common_fix.h" + +#define NO_OFBANDS ((8 * 16)) + +typedef struct { + UCHAR correlated[NO_OFBANDS]; +} CPnsInterChannelData; + +typedef struct { + CPnsInterChannelData *pPnsInterChannelData; + UCHAR pnsUsed[NO_OFBANDS]; + int CurrentEnergy; + UCHAR PnsActive; + INT *currentSeed; + INT *randomSeed; +} CPnsData; + +void CPns_UpdateNoiseState(CPnsData *pPnsData, INT *currentSeed, + INT *randomSeed); + +void CPns_ResetData(CPnsData *pPnsData, + CPnsInterChannelData *pPnsInterChannelData); + +#endif /* #ifndef AACDEC_PNS_H */ diff --git a/fdk-aac/libAACdec/src/aacdec_tns.cpp b/fdk-aac/libAACdec/src/aacdec_tns.cpp new file mode 100644 index 0000000..fb3fe33 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_tns.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: temporal noise shaping tool + +*******************************************************************************/ + +#include "aacdec_tns.h" +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" + +#include "FDK_lpc.h" + +#define TNS_MAXIMUM_ORDER_AAC 12 + +/*! + \brief Reset tns data + + The function resets the tns data + + \return none +*/ +void CTns_Reset(CTnsData *pTnsData) { + /* Note: the following FDKmemclear should not be required. */ + FDKmemclear(pTnsData->Filter, + TNS_MAX_WINDOWS * TNS_MAXIMUM_FILTERS * sizeof(CFilter)); + FDKmemclear(pTnsData->NumberOfFilters, TNS_MAX_WINDOWS * sizeof(UCHAR)); + pTnsData->DataPresent = 0; + pTnsData->Active = 0; +} + +void CTns_ReadDataPresentFlag( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + CTnsData *pTnsData) /*!< pointer to aac decoder channel info */ +{ + pTnsData->DataPresent = (UCHAR)FDKreadBits(bs, 1); +} + +/*! + \brief Read tns data from bitstream + + The function reads the elements for tns from + the bitstream. + + \return none +*/ +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, const UINT flags) { + UCHAR n_filt, order; + UCHAR length, coef_res, coef_compress; + UCHAR window; + UCHAR wins_per_frame; + UCHAR isLongFlag; + UCHAR start_window; + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + if (!pTnsData->DataPresent) { + return ErrorStatus; + } + + { + start_window = 0; + wins_per_frame = GetWindowsPerFrame(pIcsInfo); + isLongFlag = IsLongBlock(pIcsInfo); + } + + pTnsData->GainLd = 0; + + for (window = start_window; window < wins_per_frame; window++) { + pTnsData->NumberOfFilters[window] = n_filt = + (UCHAR)FDKreadBits(bs, isLongFlag ? 2 : 1); + + if (n_filt) { + int index; + UCHAR nextstopband; + + coef_res = (UCHAR)FDKreadBits(bs, 1); + + nextstopband = GetScaleFactorBandsTotal(pIcsInfo); + + for (index = 0; index < n_filt; index++) { + CFilter *filter = &pTnsData->Filter[window][index]; + + length = (UCHAR)FDKreadBits(bs, isLongFlag ? 6 : 4); + + if (length > nextstopband) { + length = nextstopband; + } + + filter->StartBand = nextstopband - length; + filter->StopBand = nextstopband; + nextstopband = filter->StartBand; + + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + /* max(Order) = 15 (long), 7 (short) */ + filter->Order = order = (UCHAR)FDKreadBits(bs, isLongFlag ? 4 : 3); + } else { + filter->Order = order = (UCHAR)FDKreadBits(bs, isLongFlag ? 5 : 3); + + if (filter->Order > TNS_MAXIMUM_ORDER) { + ErrorStatus = AAC_DEC_TNS_READ_ERROR; + return ErrorStatus; + } + } + + FDK_ASSERT(order <= + TNS_MAXIMUM_ORDER); /* avoid illegal memory access */ + if (order) { + UCHAR coef, s_mask; + UCHAR i; + SCHAR n_mask; + + static const UCHAR sgn_mask[] = {0x2, 0x4, 0x8}; + static const SCHAR neg_mask[] = {~0x3, ~0x7, ~0xF}; + + filter->Direction = FDKreadBits(bs, 1) ? -1 : 1; + + coef_compress = (UCHAR)FDKreadBits(bs, 1); + + filter->Resolution = coef_res + 3; + + s_mask = sgn_mask[coef_res + 1 - coef_compress]; + n_mask = neg_mask[coef_res + 1 - coef_compress]; + + for (i = 0; i < order; i++) { + coef = (UCHAR)FDKreadBits(bs, filter->Resolution - coef_compress); + filter->Coeff[i] = (coef & s_mask) ? (coef | n_mask) : coef; + } + pTnsData->GainLd = 4; + } + } + } + } + + pTnsData->Active = 1; + + return ErrorStatus; +} + +void CTns_ReadDataPresentUsac(HANDLE_FDK_BITSTREAM hBs, CTnsData *pTnsData0, + CTnsData *pTnsData1, UCHAR *ptns_on_lr, + const CIcsInfo *pIcsInfo, const UINT flags, + const UINT elFlags, const int fCommonWindow) { + int common_tns = 0; + + if (fCommonWindow) { + common_tns = FDKreadBit(hBs); + } + { *ptns_on_lr = FDKreadBit(hBs); } + if (common_tns) { + pTnsData0->DataPresent = 1; + CTns_Read(hBs, pTnsData0, pIcsInfo, flags); + + pTnsData0->DataPresent = 0; + pTnsData0->Active = 1; + *pTnsData1 = *pTnsData0; + } else { + int tns_present_both; + + tns_present_both = FDKreadBit(hBs); + if (tns_present_both) { + pTnsData0->DataPresent = 1; + pTnsData1->DataPresent = 1; + } else { + pTnsData1->DataPresent = FDKreadBit(hBs); + pTnsData0->DataPresent = !pTnsData1->DataPresent; + } + } +} + +/*! + \brief Apply tns to spectral lines + + The function applies the tns to the spectrum, + + \return none +*/ +void CTns_Apply(CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const UCHAR nbands, + const UCHAR igf_active, const UINT flags) { + int window, index, start, stop, size, start_window, wins_per_frame; + + if (pTnsData->Active) { + C_AALLOC_SCRATCH_START(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER) + + { + start_window = 0; + wins_per_frame = GetWindowsPerFrame(pIcsInfo); + } + + for (window = start_window; window < wins_per_frame; window++) { + FIXP_DBL *pSpectrum; + + { pSpectrum = SPEC(pSpectralCoefficient, window, granuleLength); } + + for (index = 0; index < pTnsData->NumberOfFilters[window]; index++) { + CFilter *filter = &pTnsData->Filter[window][index]; + + if (filter->Order > 0) { + FIXP_TCC *pCoeff; + UCHAR tns_max_bands; + + pCoeff = coeff; + if (filter->Resolution == 3) { + int i; + for (i = 0; i < filter->Order; i++) + *pCoeff++ = FDKaacDec_tnsCoeff3[filter->Coeff[i] + 4]; + } else { + int i; + for (i = 0; i < filter->Order; i++) + *pCoeff++ = FDKaacDec_tnsCoeff4[filter->Coeff[i] + 8]; + } + + switch (granuleLength) { + case 480: + tns_max_bands = + tns_max_bands_tbl_480[pSamplingRateInfo->samplingRateIndex]; + break; + case 512: + tns_max_bands = + tns_max_bands_tbl_512[pSamplingRateInfo->samplingRateIndex]; + break; + default: + tns_max_bands = GetMaximumTnsBands( + pIcsInfo, pSamplingRateInfo->samplingRateIndex); + /* See redefinition of TNS_MAX_BANDS table */ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pSamplingRateInfo->samplingRateIndex > 5)) { + tns_max_bands += 1; + } + break; + } + + start = fixMin(fixMin(filter->StartBand, tns_max_bands), nbands); + + start = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[start]; + + if (igf_active) { + stop = fixMin(filter->StopBand, nbands); + } else { + stop = fixMin(fixMin(filter->StopBand, tns_max_bands), nbands); + } + + stop = GetScaleFactorBandOffsets(pIcsInfo, pSamplingRateInfo)[stop]; + + size = stop - start; + + if (size) { + C_ALLOC_SCRATCH_START(state, FIXP_DBL, TNS_MAXIMUM_ORDER) + + FDKmemclear(state, TNS_MAXIMUM_ORDER * sizeof(FIXP_DBL)); + CLpc_SynthesisLattice(pSpectrum + start, size, 0, 0, + filter->Direction, coeff, filter->Order, + state); + + C_ALLOC_SCRATCH_END(state, FIXP_DBL, TNS_MAXIMUM_ORDER) + } + } + } + } + C_AALLOC_SCRATCH_END(coeff, FIXP_TCC, TNS_MAXIMUM_ORDER) + } +} diff --git a/fdk-aac/libAACdec/src/aacdec_tns.h b/fdk-aac/libAACdec/src/aacdec_tns.h new file mode 100644 index 0000000..1a63bed --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdec_tns.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: temporal noise shaping tool + +*******************************************************************************/ + +#ifndef AACDEC_TNS_H +#define AACDEC_TNS_H + +#include "common_fix.h" + +enum { + TNS_MAX_WINDOWS = 8, /* 8 */ + TNS_MAXIMUM_FILTERS = 3 +}; + +/* TNS_MAXIMUM_ORDER (for memory allocation) + 12 for AAC-LC and AAC-SSR. Set to 20 for AAC-Main (AOT 1). Some broken + encoders also do order 20 for AAC-LC :( 15 for USAC (AOT 42) +*/ +#define TNS_MAXIMUM_ORDER (20) + +#if (TNS_MAXIMUM_ORDER < 15) +#error USAC: TNS filter order up 15 can be signaled! +#endif + +typedef struct { + SCHAR Coeff[TNS_MAXIMUM_ORDER]; + + UCHAR StartBand; + UCHAR StopBand; + + SCHAR Direction; + SCHAR Resolution; + + UCHAR Order; +} CFilter; + +typedef struct { + CFilter Filter[TNS_MAX_WINDOWS][TNS_MAXIMUM_FILTERS]; + UCHAR NumberOfFilters[TNS_MAX_WINDOWS]; + UCHAR DataPresent; + UCHAR Active; + + /* log2 of the maximum total filter gains. The value is required to + keep necessary mantissa headroom so that while applying the TNS predictor + the mantissas do not overflow. */ + UCHAR GainLd; +} CTnsData; + +void CTns_Reset(CTnsData *pTnsData); + +#endif /* #ifndef AACDEC_TNS_H */ diff --git a/fdk-aac/libAACdec/src/aacdecoder.cpp b/fdk-aac/libAACdec/src/aacdecoder.cpp new file mode 100644 index 0000000..8f03328 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdecoder.cpp @@ -0,0 +1,3464 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +/*! + \page default General Overview of the AAC Decoder Implementation + + The main entry point to decode a AAC frame is CAacDecoder_DecodeFrame(). It + handles the different transport multiplexes and bitstream formats supported by + this implementation. It extracts the AAC_raw_data_blocks from these bitstreams + to further process then in the actual decoding stages. + + Note: Click on a function of file in the above image to see details about the + function. Also note, that this is just an overview of the most important + functions and not a complete call graph. + +

1 Bitstream deformatter

+ The basic bit stream parser function CChannelElement_Read() is called. It uses + other subcalls in order to parse and unpack the bitstreams. Note, that this + includes huffmann decoding of the coded spectral data. This operation can be + computational significant specifically at higher bitrates. Optimization is + likely in CBlock_ReadSpectralData(). + + The bitstream deformatter also includes many bitfield operations. Profiling on + the target will determine required optimizations. + +

2 Actual decoding to retain the time domain output

+ The basic bitstream deformatter function CChannelElement_Decode() for CPE + elements and SCE elements are called. Except for the stereo processing (2.1) + which is only used for CPE elements, the function calls for CPE or SCE are + similar, except that CPE always processes to independent channels while SCE + only processes one channel. + + Often there is the distinction between long blocks and short blocks. However, + computational expensive functions that ususally require optimization are being + shared by these two groups, + +

2.1 Stereo processing for CPE elements

+ CChannelPairElement_Decode() first calles the joint stereo tools in + stereo.cpp when required. + +

2.2 Scaling of spectral data

+ CBlock_ScaleSpectralData(). + +

2.3 Apply additional coding tools

+ ApplyTools() calles the PNS tools in case of MPEG-4 bitstreams, and TNS + filtering CTns_Apply() for MPEG-2 and MPEG-4 bitstreams. The function + TnsFilterIIR() which is called by CTns_Apply() (2.3.1) might require some + optimization. + +

3 Frequency-To-Time conversion

+ The filterbank is called using CBlock_FrequencyToTime() using the MDCT module + from the FDK Tools + +*/ + +#include "aacdecoder.h" + +#include "aac_rom.h" +#include "aac_ram.h" +#include "channel.h" +#include "FDK_audio.h" + +#include "aacdec_pns.h" + +#include "sbrdecoder.h" + +#include "sac_dec_lib.h" + +#include "aacdec_hcr.h" +#include "rvlc.h" + +#include "usacdec_lpd.h" + +#include "ac_arith_coder.h" + +#include "tpdec_lib.h" + +#include "conceal.h" + +#include "FDK_crc.h" +#define PS_IS_EXPLICITLY_DISABLED(aot, flags) \ + (((aot) == AOT_DRM_AAC) && !(flags & AC_PS_PRESENT)) + +#define IS_STEREO_SBR(el_id, stereoConfigIndex) \ + (((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 0) || \ + ((el_id) == ID_USAC_CPE && (stereoConfigIndex) == 3)) + +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self) { + FDK_ASSERT( + !((self->flags[0] & AC_MPS_PRESENT) && (self->flags[0] & AC_PS_PRESENT))); + + /* Assign user requested mode */ + self->qmfModeCurr = self->qmfModeUser; + + if (IS_USAC(self->streamInfo.aot)) { + self->qmfModeCurr = MODE_HQ; + } + + if (self->qmfModeCurr == NOT_DEFINED) { + if ((IS_LOWDELAY(self->streamInfo.aot) && + (self->flags[0] & AC_MPS_PRESENT)) || + ((self->streamInfo.aacNumChannels == 1) && + ((CAN_DO_PS(self->streamInfo.aot) && + !(self->flags[0] & AC_MPS_PRESENT)) || + (IS_USAC(self->streamInfo.aot))))) { + self->qmfModeCurr = MODE_HQ; + } else { + self->qmfModeCurr = MODE_LP; + } + } + + if (self->mpsEnableCurr) { + if (IS_LOWDELAY(self->streamInfo.aot) && + (self->qmfModeCurr == MODE_LP)) { /* Overrule user requested QMF mode */ + self->qmfModeCurr = MODE_HQ; + } + /* Set and check if MPS decoder allows the current mode */ + switch (mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_PARTIALLY_COMPLEX, self->qmfModeCurr == MODE_LP)) { + case MPS_OK: + break; + case MPS_INVALID_PARAMETER: { /* Only one mode supported. Find out which + one: */ + LIB_INFO libInfo[FDK_MODULE_LAST]; + UINT mpsCaps; + + FDKinitLibInfo(libInfo); + mpegSurroundDecoder_GetLibInfo(libInfo); + mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC); + + if (((mpsCaps & CAPF_MPS_LP) && (self->qmfModeCurr == MODE_LP)) || + ((mpsCaps & CAPF_MPS_HQ) && + (self->qmfModeCurr == + MODE_HQ))) { /* MPS decoder does support the requested mode. */ + break; + } + } + FDK_FALLTHROUGH; + default: + if (self->qmfModeUser == NOT_DEFINED) { + /* Revert in case mpegSurroundDecoder_SetParam() fails. */ + self->qmfModeCurr = + (self->qmfModeCurr == MODE_LP) ? MODE_HQ : MODE_LP; + } else { + /* in case specific mode was requested we disable MPS and playout the + * downmix */ + self->mpsEnableCurr = 0; + } + } + } + + /* Set SBR to current QMF mode. Error does not matter. */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_QMF_MODE, + (self->qmfModeCurr == MODE_LP)); + self->psPossible = + ((CAN_DO_PS(self->streamInfo.aot) && + !PS_IS_EXPLICITLY_DISABLED(self->streamInfo.aot, self->flags[0]) && + self->streamInfo.aacNumChannels == 1 && + !(self->flags[0] & AC_MPS_PRESENT))) && + self->qmfModeCurr == MODE_HQ; + FDK_ASSERT(!((self->flags[0] & AC_MPS_PRESENT) && self->psPossible)); +} + +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self) { + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + int i; + + for (i = 0; i < fMin(self->aacChannels, (8)); i++) { + if (self->pAacDecoderStaticChannelInfo + [i]) { /* number of active channels can be smaller */ + self->pAacDecoderStaticChannelInfo[i]->hArCo->m_numberLinesPrev = 0; + } + } + } +} + +/*! + \brief Calculates the number of element channels + + \type channel type + \usacStereoConfigIndex usac stereo config index + + \return element channels +*/ +static int CAacDecoder_GetELChannels(MP4_ELEMENT_ID type, + UCHAR usacStereoConfigIndex) { + int el_channels = 0; + + switch (type) { + case ID_USAC_CPE: + if (usacStereoConfigIndex == 1) { + el_channels = 1; + } else { + el_channels = 2; + } + break; + case ID_CPE: + el_channels = 2; + break; + case ID_USAC_SCE: + case ID_USAC_LFE: + case ID_SCE: + case ID_LFE: + el_channels = 1; + break; + default: + el_channels = 0; + break; + } + + return el_channels; +} + +/*! + \brief Reset ancillary data struct. Call before parsing a new frame. + + \ancData Pointer to ancillary data structure + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataReset(CAncData *ancData) { + int i; + for (i = 0; i < 8; i++) { + ancData->offset[i] = 0; + } + ancData->nrElements = 0; + + return AAC_DEC_OK; +} + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, + unsigned char *buffer, int size) { + if (size >= 0) { + ancData->buffer = buffer; + ancData->bufferSize = size; + + CAacDecoder_AncDataReset(ancData); + + return AAC_DEC_OK; + } + + return AAC_DEC_ANC_DATA_ERROR; +} + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data + element in bytes + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, + unsigned char **ptr, int *size) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + + *ptr = NULL; + *size = 0; + + if (index >= 0 && index < 8 - 1 && index < ancData->nrElements) { + *ptr = &ancData->buffer[ancData->offset[index]]; + *size = ancData->offset[index + 1] - ancData->offset[index]; + } + + return error; +} + +/*! + \brief Parse ancillary data + + \ancData Pointer to ancillary data structure + \hBs Handle to FDK bitstream + \ancBytes Length of ancillary data to read from the bitstream + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_AncDataParse(CAncData *ancData, + HANDLE_FDK_BITSTREAM hBs, + const int ancBytes) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + int readBytes = 0; + + if (ancData->buffer != NULL) { + if (ancBytes > 0) { + /* write ancillary data to external buffer */ + int offset = ancData->offset[ancData->nrElements]; + + if ((offset + ancBytes) > ancData->bufferSize) { + error = AAC_DEC_TOO_SMALL_ANC_BUFFER; + } else if (ancData->nrElements >= 8 - 1) { + error = AAC_DEC_TOO_MANY_ANC_ELEMENTS; + } else { + int i; + + for (i = 0; i < ancBytes; i++) { + ancData->buffer[i + offset] = FDKreadBits(hBs, 8); + readBytes++; + } + + ancData->nrElements++; + ancData->offset[ancData->nrElements] = + ancBytes + ancData->offset[ancData->nrElements - 1]; + } + } + } + + readBytes = ancBytes - readBytes; + + if (readBytes > 0) { + /* skip data */ + FDKpushFor(hBs, readBytes << 3); + } + + return error; +} + +/*! + \brief Read Stream Data Element + + \bs Bitstream Handle + + \return Error code +*/ +static AAC_DECODER_ERROR CDataStreamElement_Read(HANDLE_AACDECODER self, + HANDLE_FDK_BITSTREAM bs, + UCHAR *elementInstanceTag, + UINT alignmentAnchor) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + UINT dseBits; + INT dataStart; + int dataByteAlignFlag, count; + + FDK_ASSERT(self != NULL); + + int crcReg = transportDec_CrcStartReg(self->hInput, 0); + + /* Element Instance Tag */ + *elementInstanceTag = FDKreadBits(bs, 4); + /* Data Byte Align Flag */ + dataByteAlignFlag = FDKreadBits(bs, 1); + + count = FDKreadBits(bs, 8); + + if (count == 255) { + count += FDKreadBits(bs, 8); /* EscCount */ + } + dseBits = count * 8; + + if (dataByteAlignFlag) { + FDKbyteAlign(bs, alignmentAnchor); + } + + dataStart = (INT)FDKgetValidBits(bs); + + error = CAacDecoder_AncDataParse(&self->ancData, bs, count); + transportDec_CrcEndReg(self->hInput, crcReg); + + { + /* Move to the beginning of the data chunk */ + FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs)); + + /* Read Anc data if available */ + aacDecoder_drcMarkPayload(self->hDrcInfo, bs, DVB_DRC_ANC_DATA); + } + + { + PCMDMX_ERROR dmxErr = PCMDMX_OK; + + /* Move to the beginning of the data chunk */ + FDKpushBack(bs, dataStart - (INT)FDKgetValidBits(bs)); + + /* Read DMX meta-data */ + dmxErr = pcmDmx_Parse(self->hPcmUtils, bs, dseBits, 0 /* not mpeg2 */); + if (error == AAC_DEC_OK && dmxErr != PCMDMX_OK) { + error = AAC_DEC_UNKNOWN; + } + } + + /* Move to the very end of the element. */ + FDKpushBiDirectional(bs, (INT)FDKgetValidBits(bs) - dataStart + (INT)dseBits); + + return error; +} + +/*! + \brief Read Program Config Element + + \bs Bitstream Handle + \pTp Transport decoder handle for CRC handling + \pce Pointer to PCE buffer + \channelConfig Current channel configuration + \alignAnchor Anchor for byte alignment + + \return PCE status (-1: fail, 0: no new PCE, 1: PCE updated, 2: PCE updated + need re-config). +*/ +static int CProgramConfigElement_Read(HANDLE_FDK_BITSTREAM bs, + HANDLE_TRANSPORTDEC pTp, + CProgramConfig *pce, + const UINT channelConfig, + const UINT alignAnchor) { + int pceStatus = 0; + int crcReg; + + /* read PCE to temporal buffer first */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_Init(tmpPce); + + crcReg = transportDec_CrcStartReg(pTp, 0); + + CProgramConfig_Read(tmpPce, bs, alignAnchor); + + transportDec_CrcEndReg(pTp, crcReg); + + if (CProgramConfig_IsValid(tmpPce) && (tmpPce->Profile == 1)) { + if (!CProgramConfig_IsValid(pce) && (channelConfig > 0)) { + /* Create a standard channel config PCE to compare with */ + CProgramConfig_GetDefault(pce, channelConfig); + } + + if (CProgramConfig_IsValid(pce)) { + /* Compare the new and the old PCE (tags ignored) */ + switch (CProgramConfig_Compare(pce, tmpPce)) { + case 1: /* Channel configuration not changed. Just new metadata. */ + FDKmemcpy(pce, tmpPce, + sizeof(CProgramConfig)); /* Store the complete PCE */ + pceStatus = 1; /* New PCE but no change of config */ + break; + case 2: /* The number of channels are identical but not the config */ + case -1: /* The channel configuration is completely different */ + pceStatus = -1; /* Not supported! */ + break; + case 0: /* Nothing to do because PCE matches the old one exactly. */ + default: + /* pceStatus = 0; */ + break; + } + } + } + + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + + return pceStatus; +} + +/*! + \brief Prepares crossfade for USAC DASH IPF config change + + \pTimeData Pointer to time data + \pTimeDataFlush Pointer to flushed time data + \numChannels Number of channels + \frameSize Size of frame + \interleaved Indicates if time data is interleaved + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade( + const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved) { + int i, ch, s1, s2; + AAC_DECODER_ERROR ErrorStatus; + + ErrorStatus = AAC_DEC_OK; + + if (interleaved) { + s1 = 1; + s2 = numChannels; + } else { + s1 = frameSize; + s2 = 1; + } + + for (ch = 0; ch < numChannels; ch++) { + const INT_PCM *pIn = &pTimeData[ch * s1]; + for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + pTimeDataFlush[ch][i] = *pIn; + pIn += s2; + } + } + + return ErrorStatus; +} + +/*! + \brief Applies crossfade for USAC DASH IPF config change + + \pTimeData Pointer to time data + \pTimeDataFlush Pointer to flushed time data + \numChannels Number of channels + \frameSize Size of frame + \interleaved Indicates if time data is interleaved + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade( + INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved) { + int i, ch, s1, s2; + AAC_DECODER_ERROR ErrorStatus; + + ErrorStatus = AAC_DEC_OK; + + if (interleaved) { + s1 = 1; + s2 = numChannels; + } else { + s1 = frameSize; + s2 = 1; + } + + for (ch = 0; ch < numChannels; ch++) { + INT_PCM *pIn = &pTimeData[ch * s1]; + for (i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + FIXP_SGL alpha = (FIXP_SGL)i + << (FRACT_BITS - 1 - TIME_DATA_FLUSH_SIZE_SF); + FIXP_DBL time = FX_PCM2FX_DBL(*pIn); + FIXP_DBL timeFlush = FX_PCM2FX_DBL(pTimeDataFlush[ch][i]); + + *pIn = (INT_PCM)(FIXP_PCM)FX_DBL2FX_PCM( + timeFlush - fMult(timeFlush, alpha) + fMult(time, alpha)); + pIn += s2; + } + } + + return ErrorStatus; +} + +/*! + \brief Parse PreRoll Extension Payload + + \self Handle of AAC decoder + \numPrerollAU Number of preRoll AUs + \prerollAUOffset Offset to each preRoll AU + \prerollAULength Length of each preRoll AU + + \return Error code +*/ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse( + HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset, + UINT *prerollAULength) { + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs; + AAC_DECODER_ERROR ErrorStatus; + + INT auStartAnchor; + UINT independencyFlag; + UINT extPayloadPresentFlag; + UINT useDefaultLengthFlag; + UINT configLength = 0; + UINT preRollPossible = 1; + UINT i; + UCHAR configChanged = 0; + UCHAR config[TP_USAC_MAX_CONFIG_LEN] = {0}; + UCHAR + implicitExplicitCfgDiff = 0; /* in case implicit and explicit config is + equal preroll AU's should be processed + after decoder reset */ + + ErrorStatus = AAC_DEC_OK; + + hBs = transportDec_GetBitstream(self->hInput, 0); + bs = *hBs; + + auStartAnchor = (INT)FDKgetValidBits(hBs); + if (auStartAnchor <= 0) { + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + } + + /* Independency flag */ + FDKreadBit(hBs); + + /* Payload present flag of extension ID_EXT_ELE_AUDIOPREROLL must be one */ + extPayloadPresentFlag = FDKreadBits(hBs, 1); + if (!extPayloadPresentFlag) { + preRollPossible = 0; + } + + /* Default length flag of extension ID_EXT_ELE_AUDIOPREROLL must be zero */ + useDefaultLengthFlag = FDKreadBits(hBs, 1); + if (useDefaultLengthFlag) { + preRollPossible = 0; + } + + if (preRollPossible) { /* extPayloadPresentFlag && !useDefaultLengthFlag */ + /* Read overall ext payload length, useDefaultLengthFlag must be zero. */ + escapedValue(hBs, 8, 16, 0); + + /* Read RSVD60 Config size */ + configLength = escapedValue(hBs, 4, 4, 8); + + /* Avoid decoding pre roll frames if there was no config change and no + * config is included in the pre roll ext payload. */ + } + + /* If pre roll not possible then exit. */ + if (preRollPossible == 0) { + /* Sanity check: if flushing is switched on, preRollPossible must be 1 */ + if (self->flushStatus != AACDEC_FLUSH_OFF) { + /* Mismatch of current payload and flushing status */ + self->flushStatus = AACDEC_FLUSH_OFF; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + goto bail; + } + + if (self->flags[0] & AC_USAC) { + if (configLength > 0) { + /* DASH IPF USAC Config Change: Read new config and compare with current + * config. Apply reconfiguration if config's are different. */ + for (i = 0; i < configLength; i++) { + config[i] = FDKreadBits(hBs, 8); + } + TRANSPORTDEC_ERROR terr; + terr = transportDec_InBandConfig(self->hInput, config, configLength, + self->buildUpStatus, &configChanged, 0, + &implicitExplicitCfgDiff); + if (terr != TRANSPORTDEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + + /* For the first frame buildUpStatus is not set and no flushing is performed + * but preroll AU's should processed. */ + /* For USAC there is no idle state. */ + if ((self->streamInfo.numChannels == 0) && !implicitExplicitCfgDiff && + (self->flags[0] & AC_USAC)) { + self->buildUpStatus = AACDEC_USAC_BUILD_UP_ON; + /* sanity check: if buildUp status on -> flushing must be off */ + if (self->flushStatus != AACDEC_FLUSH_OFF) { + self->flushStatus = AACDEC_FLUSH_OFF; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + if (self->flags[0] & AC_USAC) { + /* We are interested in preroll AUs if an explicit or an implicit config + * change is signalized in other words if the build up status is set. */ + if (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON) { + self->applyCrossfade |= FDKreadBit(hBs); + FDKreadBit(hBs); /* reserved */ + /* Read num preroll AU's */ + *numPrerollAU = escapedValue(hBs, 2, 4, 0); + /* check limits for USAC */ + if (*numPrerollAU > AACDEC_MAX_NUM_PREROLL_AU_USAC) { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + + for (i = 0; i < *numPrerollAU; i++) { + /* For every AU get length and offset in the bitstream */ + prerollAULength[i] = escapedValue(hBs, 16, 16, 0); + if (prerollAULength[i] > 0) { + prerollAUOffset[i] = auStartAnchor - (INT)FDKgetValidBits(hBs); + independencyFlag = FDKreadBit(hBs); + if (i == 0 && !independencyFlag) { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + FDKpushFor(hBs, prerollAULength[i] * 8 - 1); + self->prerollAULength[i] = (prerollAULength[i] * 8) + prerollAUOffset[i]; + } else { + *numPrerollAU = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; /* Something is wrong */ + goto bail; + } + } + +bail: + + *hBs = bs; + + return ErrorStatus; +} + +/*! + \brief Parse Extension Payload + + \self Handle of AAC decoder + \count Pointer to bit counter. + \previous_element ID of previous element (required by some extension payloads) + + \return Error code +*/ +static AAC_DECODER_ERROR CAacDecoder_ExtPayloadParse( + HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM hBs, int *count, + MP4_ELEMENT_ID previous_element, int elIndex, int fIsFillElement) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + EXT_PAYLOAD_TYPE extension_type; + int bytes = (*count) >> 3; + int crcFlag = 0; + + if (*count < 4) { + return AAC_DEC_PARSE_ERROR; + } else if ((INT)FDKgetValidBits(hBs) < *count) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + extension_type = + (EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4); /* bs_extension_type */ + *count -= 4; + + /* For ELD, the SBR signaling is explicit and parsed in + aacDecoder_ParseExplicitMpsAndSbr(), therefore skip SBR if implicit + present. */ + if ((self->flags[0] & AC_ELD) && ((extension_type == EXT_SBR_DATA_CRC) || + (extension_type == EXT_SBR_DATA))) { + extension_type = EXT_FIL; /* skip sbr data */ + } + + switch (extension_type) { + case EXT_DYNAMIC_RANGE: { + INT readBits = + aacDecoder_drcMarkPayload(self->hDrcInfo, hBs, MPEG_DRC_EXT_DATA); + + if (readBits > *count) { /* Read too much. Something went wrong! */ + error = AAC_DEC_PARSE_ERROR; + } + *count -= readBits; + } break; + case EXT_UNI_DRC: { + DRC_DEC_ERROR drcErr = DRC_DEC_OK; + DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + INT nBitsRemaining = FDKgetValidBits(hBs); + INT readBits; + + switch (self->streamInfo.aot) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + drcDecCodecMode = DRC_DEC_MPEG_4_AAC; + break; + default: + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + drcErr = FDK_drcDec_SetCodecMode(self->hUniDrcDecoder, drcDecCodecMode); + if (drcErr) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + drcErr = FDK_drcDec_ReadUniDrc(self->hUniDrcDecoder, hBs); + if (drcErr) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + readBits = (INT)nBitsRemaining - (INT)FDKgetValidBits(hBs); + if (readBits > *count) { /* Read too much. Something went wrong! */ + error = AAC_DEC_PARSE_ERROR; + } + *count -= readBits; + /* Skip any trailing bits */ + FDKpushFor(hBs, *count); + *count = 0; + } break; + case EXT_LDSAC_DATA: + case EXT_SAC_DATA: + /* Read MPEG Surround Extension payload */ + { + int err, mpsSampleRate, mpsFrameSize; + + if (self->flags[0] & AC_PS_PRESENT) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + /* Handle SBR dual rate case */ + if (self->streamInfo.extSamplingRate != 0) { + mpsSampleRate = self->streamInfo.extSamplingRate; + mpsFrameSize = self->streamInfo.aacSamplesPerFrame * + (self->streamInfo.extSamplingRate / + self->streamInfo.aacSampleRate); + } else { + mpsSampleRate = self->streamInfo.aacSampleRate; + mpsFrameSize = self->streamInfo.aacSamplesPerFrame; + } + /* Setting of internal MPS state; may be reset in + CAacDecoder_SyncQmfMode if decoder is unable to decode with user + defined qmfMode */ + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD))) { + self->mpsEnableCurr = self->mpsEnableUser; + } + if (self->mpsEnableCurr) { + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig) { + /* if not done yet, allocate full MPEG Surround decoder instance */ + if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) == + SAC_INSTANCE_NOT_FULL_AVAILABLE) { + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1, + &self->qmfDomain)) { + return AAC_DEC_OUT_OF_MEMORY; + } + } + } + err = mpegSurroundDecoder_Parse( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, hBs, count, + self->streamInfo.aot, mpsSampleRate, mpsFrameSize, + self->flags[0] & AC_INDEP); + if (err == MPS_OK) { + self->flags[0] |= AC_MPS_PRESENT; + } else { + error = AAC_DEC_PARSE_ERROR; + } + } + /* Skip any trailing bytes */ + FDKpushFor(hBs, *count); + *count = 0; + } + break; + + case EXT_SBR_DATA_CRC: + crcFlag = 1; + FDK_FALLTHROUGH; + case EXT_SBR_DATA: + if (IS_CHANNEL_ELEMENT(previous_element)) { + SBR_ERROR sbrError; + UCHAR configMode = 0; + UCHAR configChanged = 0; + + CAacDecoder_SyncQmfMode(self); + + configMode |= AC_CM_ALLOC_MEM; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, + previous_element, elIndex, + 2, /* Signalize that harmonicSBR shall be ignored in the config + change detection */ + 0, configMode, &configChanged, self->downscaleFactor); + + if (sbrError == SBRDEC_OK) { + sbrError = sbrDecoder_Parse(self->hSbrDecoder, hBs, + self->pDrmBsBuffer, self->drmBsBufferSize, + count, *count, crcFlag, previous_element, + elIndex, self->flags[0], self->elFlags); + /* Enable SBR for implicit SBR signalling but only if no severe error + * happend. */ + if ((sbrError == SBRDEC_OK) || (sbrError == SBRDEC_PARSE_ERROR)) { + self->sbrEnabled = 1; + } + } else { + /* Do not try to apply SBR because initializing the element failed. */ + self->sbrEnabled = 0; + } + /* Citation from ISO/IEC 14496-3 chapter 4.5.2.1.5.2 + Fill elements containing an extension_payload() with an extension_type + of EXT_SBR_DATA or EXT_SBR_DATA_CRC shall not contain any other + extension_payload of any other extension_type. + */ + if (fIsFillElement) { + FDKpushBiDirectional(hBs, *count); + *count = 0; + } else { + /* If this is not a fill element with a known length, we are screwed + * and further parsing makes no sense. */ + if (sbrError != SBRDEC_OK) { + self->frameOK = 0; + } + } + } else { + error = AAC_DEC_PARSE_ERROR; + } + break; + + case EXT_FILL_DATA: { + int temp; + + temp = FDKreadBits(hBs, 4); + bytes--; + if (temp != 0) { + error = AAC_DEC_PARSE_ERROR; + break; + } + while (bytes > 0) { + temp = FDKreadBits(hBs, 8); + bytes--; + if (temp != 0xa5) { + error = AAC_DEC_PARSE_ERROR; + break; + } + } + *count = bytes << 3; + } break; + + case EXT_DATA_ELEMENT: { + int dataElementVersion; + + dataElementVersion = FDKreadBits(hBs, 4); + *count -= 4; + if (dataElementVersion == 0) /* ANC_DATA */ + { + int temp, dataElementLength = 0; + do { + temp = FDKreadBits(hBs, 8); + *count -= 8; + dataElementLength += temp; + } while (temp == 255); + + CAacDecoder_AncDataParse(&self->ancData, hBs, dataElementLength); + *count -= (dataElementLength << 3); + } else { + /* align = 0 */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } break; + + case EXT_DATA_LENGTH: + if (!fIsFillElement /* Makes no sens to have an additional length in a + fill ... */ + && + (self->flags[0] & + AC_ER)) /* ... element because this extension payload type was ... */ + { /* ... created to circumvent the missing length in ER-Syntax. */ + int bitCnt, len = FDKreadBits(hBs, 4); + *count -= 4; + + if (len == 15) { + int add_len = FDKreadBits(hBs, 8); + *count -= 8; + len += add_len; + + if (add_len == 255) { + len += FDKreadBits(hBs, 16); + *count -= 16; + } + } + len <<= 3; + bitCnt = len; + + if ((EXT_PAYLOAD_TYPE)FDKreadBits(hBs, 4) == EXT_DATA_LENGTH) { + /* Check NOTE 2: The extension_payload() included here must + not have extension_type == EXT_DATA_LENGTH. */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } else { + /* rewind and call myself again. */ + FDKpushBack(hBs, 4); + + error = CAacDecoder_ExtPayloadParse( + self, hBs, &bitCnt, previous_element, elIndex, + 1); /* Treat same as fill element */ + + *count -= len - bitCnt; + } + /* Note: the fall through in case the if statement above is not taken is + * intentional. */ + break; + } + FDK_FALLTHROUGH; + + case EXT_FIL: + + default: + /* align = 4 */ + FDKpushFor(hBs, *count); + *count = 0; + break; + } + +bail: + if ((error != AAC_DEC_OK) && + fIsFillElement) { /* Skip the remaining extension bytes */ + FDKpushBiDirectional(hBs, *count); + *count = 0; + /* Patch error code because decoding can go on. */ + error = AAC_DEC_OK; + /* Be sure that parsing errors have been stored. */ + } + return error; +} + +static AAC_DECODER_ERROR aacDecoder_ParseExplicitMpsAndSbr( + HANDLE_AACDECODER self, HANDLE_FDK_BITSTREAM bs, + const MP4_ELEMENT_ID previous_element, const int previous_element_index, + const int element_index, const int el_cnt[]) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + INT bitCnt = 0; + + /* get the remaining bits of this frame */ + bitCnt = transportDec_GetAuBitsRemaining(self->hInput, 0); + + if ((self->flags[0] & AC_SBR_PRESENT) && + (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_ELD | AC_DRM))) { + SBR_ERROR err = SBRDEC_OK; + int chElIdx, numChElements = el_cnt[ID_SCE] + el_cnt[ID_CPE] + + el_cnt[ID_LFE] + el_cnt[ID_USAC_SCE] + + el_cnt[ID_USAC_CPE] + el_cnt[ID_USAC_LFE]; + INT bitCntTmp = bitCnt; + + if (self->flags[0] & AC_USAC) { + chElIdx = numChElements - 1; + } else { + chElIdx = 0; /* ELD case */ + } + + for (; chElIdx < numChElements; chElIdx += 1) { + MP4_ELEMENT_ID sbrType; + SBR_ERROR errTmp; + if (self->flags[0] & (AC_USAC)) { + FDK_ASSERT((self->elements[element_index] == ID_USAC_SCE) || + (self->elements[element_index] == ID_USAC_CPE)); + sbrType = IS_STEREO_SBR(self->elements[element_index], + self->usacStereoConfigIndex[element_index]) + ? ID_CPE + : ID_SCE; + } else + sbrType = self->elements[chElIdx]; + errTmp = sbrDecoder_Parse(self->hSbrDecoder, bs, self->pDrmBsBuffer, + self->drmBsBufferSize, &bitCnt, -1, + self->flags[0] & AC_SBRCRC, sbrType, chElIdx, + self->flags[0], self->elFlags); + if (errTmp != SBRDEC_OK) { + err = errTmp; + bitCntTmp = bitCnt; + bitCnt = 0; + } + } + switch (err) { + case SBRDEC_PARSE_ERROR: + /* Can not go on parsing because we do not + know the length of the SBR extension data. */ + FDKpushFor(bs, bitCntTmp); + bitCnt = 0; + break; + case SBRDEC_OK: + self->sbrEnabled = 1; + break; + default: + self->frameOK = 0; + break; + } + } + + if ((bitCnt > 0) && (self->flags[0] & (AC_USAC | AC_RSVD50))) { + if ((self->flags[0] & AC_MPS_PRESENT) || + (self->elFlags[element_index] & AC_EL_USAC_MPS212)) { + int err; + + err = mpegSurroundDecoder_ParseNoHeader( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, bs, &bitCnt, + self->flags[0] & AC_INDEP); + if (err != MPS_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + } + } + + if (self->flags[0] & AC_DRM) { + if ((bitCnt = (INT)FDKgetValidBits(bs)) != 0) { + FDKpushBiDirectional(bs, bitCnt); + } + } + + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_DRM))) { + while (bitCnt > 7) { + ErrorStatus = CAacDecoder_ExtPayloadParse( + self, bs, &bitCnt, previous_element, previous_element_index, 0); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + } + } + return ErrorStatus; +} + +/* Stream Configuration and Information. + + This class holds configuration and information data for a stream to be + decoded. It provides the calling application as well as the decoder with + substantial information, e.g. profile, sampling rate, number of channels + found in the bitstream etc. +*/ +static void CStreamInfoInit(CStreamInfo *pStreamInfo) { + pStreamInfo->aacSampleRate = 0; + pStreamInfo->profile = -1; + pStreamInfo->aot = AOT_NONE; + + pStreamInfo->channelConfig = -1; + pStreamInfo->bitRate = 0; + pStreamInfo->aacSamplesPerFrame = 0; + + pStreamInfo->extAot = AOT_NONE; + pStreamInfo->extSamplingRate = 0; + + pStreamInfo->flags = 0; + + pStreamInfo->epConfig = -1; /* default: no ER */ + + pStreamInfo->numChannels = 0; + pStreamInfo->sampleRate = 0; + pStreamInfo->frameSize = 0; + + pStreamInfo->outputDelay = 0; + + /* DRC */ + pStreamInfo->drcProgRefLev = + -1; /* set program reference level to not indicated */ + pStreamInfo->drcPresMode = -1; /* default: presentation mode not indicated */ +} + +/*! + \brief Initialization of AacDecoderChannelInfo + + The function initializes the pointers to AacDecoderChannelInfo for each + channel, set the start values for window shape and window sequence of + overlap&add to zero, set the overlap buffer to zero and initializes the + pointers to the window coefficients. \param bsFormat is the format of the AAC + bitstream + + \return AACDECODER instance +*/ +LINKSPEC_CPP HANDLE_AACDECODER CAacDecoder_Open( + TRANSPORT_TYPE bsFormat) /*!< bitstream format (adif,adts,loas,...). */ +{ + HANDLE_AACDECODER self; + + self = GetAacDecoder(); + if (self == NULL) { + goto bail; + } + + FDK_QmfDomain_ClearRequested(&self->qmfDomain.globalConf); + + /* Assign channel mapping info arrays (doing so removes dependency of settings + * header in API header). */ + self->streamInfo.pChannelIndices = self->channelIndices; + self->streamInfo.pChannelType = self->channelType; + self->downscaleFactor = 1; + self->downscaleFactorInBS = 1; + + /* initialize anc data */ + CAacDecoder_AncDataInit(&self->ancData, NULL, 0); + + /* initialize stream info */ + CStreamInfoInit(&self->streamInfo); + + /* initialize progam config */ + CProgramConfig_Init(&self->pce); + + /* initialize error concealment common data */ + CConcealment_InitCommonData(&self->concealCommonData); + self->concealMethodUser = ConcealMethodNone; /* undefined -> auto mode */ + + self->hDrcInfo = GetDrcInfo(); + if (self->hDrcInfo == NULL) { + goto bail; + } + /* Init common DRC structure */ + aacDecoder_drcInit(self->hDrcInfo); + /* Set default frame delay */ + aacDecoder_drcSetParam(self->hDrcInfo, DRC_BS_DELAY, + CConcealment_GetDelay(&self->concealCommonData)); + + self->workBufferCore2 = GetWorkBufferCore2(); + if (self->workBufferCore2 == NULL) goto bail; + + /* When RSVD60 is active use dedicated memory for core decoding */ + self->pTimeData2 = GetWorkBufferCore5(); + self->timeData2Size = GetRequiredMemWorkBufferCore5(); + if (self->pTimeData2 == NULL) { + goto bail; + } + + return self; + +bail: + CAacDecoder_Close(self); + + return NULL; +} + +/* Revert CAacDecoder_Init() */ +static void CAacDecoder_DeInit(HANDLE_AACDECODER self, + const int subStreamIndex) { + int ch; + int aacChannelOffset = 0, aacChannels = (8); + int numElements = (((8)) + (8)), elementOffset = 0; + + if (self == NULL) return; + + { + self->ascChannels[0] = 0; + self->elements[0] = ID_END; + } + + for (ch = aacChannelOffset; ch < aacChannelOffset + aacChannels; ch++) { + if (self->pAacDecoderChannelInfo[ch] != NULL) { + if (self->pAacDecoderChannelInfo[ch]->pComStaticData != NULL) { + if (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 != NULL) { + if (ch == aacChannelOffset) { + FreeWorkBufferCore1(&self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1); + } + } + if (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->cplxPredictionData != NULL) { + FreeCplxPredictionData(&self->pAacDecoderChannelInfo[ch] + ->pComStaticData->cplxPredictionData); + } + /* Avoid double free of linked pComStaticData in case of CPE by settings + * pointer to NULL. */ + if (ch < (8) - 1) { + if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) && + (self->pAacDecoderChannelInfo[ch + 1]->pComStaticData == + self->pAacDecoderChannelInfo[ch]->pComStaticData)) { + self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = NULL; + } + } + FDKfree(self->pAacDecoderChannelInfo[ch]->pComStaticData); + self->pAacDecoderChannelInfo[ch]->pComStaticData = NULL; + } + if (self->pAacDecoderChannelInfo[ch]->pComData != NULL) { + /* Avoid double free of linked pComData in case of CPE by settings + * pointer to NULL. */ + if (ch < (8) - 1) { + if ((self->pAacDecoderChannelInfo[ch + 1] != NULL) && + (self->pAacDecoderChannelInfo[ch + 1]->pComData == + self->pAacDecoderChannelInfo[ch]->pComData)) { + self->pAacDecoderChannelInfo[ch + 1]->pComData = NULL; + } + } + if (ch == aacChannelOffset) { + FreeWorkBufferCore6( + (SCHAR **)&self->pAacDecoderChannelInfo[ch]->pComData); + } else { + FDKafree(self->pAacDecoderChannelInfo[ch]->pComData); + } + self->pAacDecoderChannelInfo[ch]->pComData = NULL; + } + } + if (self->pAacDecoderStaticChannelInfo[ch] != NULL) { + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer != NULL) { + FreeOverlapBuffer( + &self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer); + } + if (self->pAacDecoderStaticChannelInfo[ch]->hArCo != NULL) { + CArco_Destroy(self->pAacDecoderStaticChannelInfo[ch]->hArCo); + } + FreeAacDecoderStaticChannelInfo(&self->pAacDecoderStaticChannelInfo[ch]); + } + if (self->pAacDecoderChannelInfo[ch] != NULL) { + FreeAacDecoderChannelInfo(&self->pAacDecoderChannelInfo[ch]); + } + } + + { + int el; + for (el = elementOffset; el < elementOffset + numElements; el++) { + if (self->cpeStaticData[el] != NULL) { + FreeCpePersistentData(&self->cpeStaticData[el]); + } + } + } + + FDK_Delay_Destroy(&self->usacResidualDelay); + + self->aacChannels = 0; + self->streamInfo.aacSampleRate = 0; + self->streamInfo.sampleRate = 0; + /* This samplerate value is checked for configuration change, not the others + * above. */ + self->samplingRateInfo[subStreamIndex].samplingRate = 0; +} + +/*! + * \brief CAacDecoder_CtrlCFGChange Set config change parameters. + * + * \param self [i] handle to AACDECODER structure + * \param flushStatus [i] flush status: on|off + * \param flushCnt [i] flush frame counter + * \param buildUpStatus [i] build up status: on|off + * \param buildUpCnt [i] build up frame counter + * + * \return error + */ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self, + UCHAR flushStatus, + SCHAR flushCnt, + UCHAR buildUpStatus, + SCHAR buildUpCnt) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + + self->flushStatus = flushStatus; + self->flushCnt = flushCnt; + self->buildUpStatus = buildUpStatus; + self->buildUpCnt = buildUpCnt; + + return (err); +} + +/*! + * \brief CAacDecoder_FreeMem Free config dependent AAC memory. + * + * \param self [i] handle to AACDECODER structure + * + * \return error + */ +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self, + const int subStreamIndex) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + + CAacDecoder_DeInit(self, subStreamIndex); + + return (err); +} + +/* Destroy aac decoder */ +LINKSPEC_CPP void CAacDecoder_Close(HANDLE_AACDECODER self) { + if (self == NULL) return; + + CAacDecoder_DeInit(self, 0); + + { + int ch; + for (ch = 0; ch < (8); ch++) { + if (self->pTimeDataFlush[ch] != NULL) { + FreeTimeDataFlush(&self->pTimeDataFlush[ch]); + } + } + } + + if (self->hDrcInfo) { + FreeDrcInfo(&self->hDrcInfo); + } + + /* Free WorkBufferCore2 */ + if (self->workBufferCore2 != NULL) { + FreeWorkBufferCore2(&self->workBufferCore2); + } + if (self->pTimeData2 != NULL) { + FreeWorkBufferCore5(&self->pTimeData2); + } + + FDK_QmfDomain_Close(&self->qmfDomain); + + FreeAacDecoder(&self); +} + +/*! + \brief Initialization of decoder instance + + The function initializes the decoder. + + \return error status: 0 for success, <>0 for unsupported configurations +*/ +LINKSPEC_CPP AAC_DECODER_ERROR +CAacDecoder_Init(HANDLE_AACDECODER self, const CSAudioSpecificConfig *asc, + UCHAR configMode, UCHAR *configChanged) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + INT ascChannels, ascChanged = 0; + AACDEC_RENDER_MODE initRenderMode = AACDEC_RENDER_INVALID; + SCHAR usacStereoConfigIndex = -1; + int usacResidualDelayCompSamples = 0; + int elementOffset, aacChannelsOffset, aacChannelsOffsetIdx; + const int streamIndex = 0; + INT flushChannels = 0; + + if (!self) return AAC_DEC_INVALID_HANDLE; + + UCHAR downscaleFactor = self->downscaleFactor; + UCHAR downscaleFactorInBS = self->downscaleFactorInBS; + + // set profile and check for supported aot + // leave profile on default (=-1) for all other supported MPEG-4 aot's except + // aot=2 (=AAC-LC) + switch (asc->m_aot) { + case AOT_AAC_LC: + self->streamInfo.profile = 1; + FDK_FALLTHROUGH; + case AOT_ER_AAC_SCAL: + if (asc->m_sc.m_gaSpecificConfig.m_layer > 0) { + /* aac_scalable_extension_element() currently not supported. */ + return AAC_DEC_UNSUPPORTED_FORMAT; + } + FDK_FALLTHROUGH; + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + initRenderMode = AACDEC_RENDER_IMDCT; + break; + case AOT_ER_AAC_ELD: + initRenderMode = AACDEC_RENDER_ELDFB; + break; + case AOT_USAC: + initRenderMode = AACDEC_RENDER_IMDCT; + break; + default: + return AAC_DEC_UNSUPPORTED_AOT; + } + + if (CProgramConfig_IsValid(&self->pce) && (asc->m_channelConfiguration > 0)) { + /* Compare the stored (old) PCE with a default PCE created from the (new) + channel_config (on a temporal buffer) to find out wheter we can keep it + (and its metadata) or not. */ + int pceCmpResult; + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + + CProgramConfig_GetDefault(tmpPce, asc->m_channelConfiguration); + pceCmpResult = CProgramConfig_Compare(&self->pce, tmpPce); + if ((pceCmpResult < 0) /* Reset if PCEs are completely different ... */ + || + (pceCmpResult > 1)) { /* ... or have a different layout. */ + CProgramConfig_Init(&self->pce); + } /* Otherwise keep the PCE (and its metadata). */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } else { + CProgramConfig_Init(&self->pce); + } + + /* set channels */ + switch (asc->m_channelConfiguration) { + case 0: + switch (asc->m_aot) { + case AOT_USAC: + self->chMapIndex = 0; + ascChannels = asc->m_sc.m_usacConfig.m_nUsacChannels; + break; + default: + /* get channels from program config (ASC) */ + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + ascChannels = asc->m_progrConfigElement.NumChannels; + if (ascChannels > 0) { + int el_tmp; + /* valid number of channels -> copy program config element (PCE) + * from ASC */ + FDKmemcpy(&self->pce, &asc->m_progrConfigElement, + sizeof(CProgramConfig)); + /* Built element table */ + el_tmp = CProgramConfig_GetElementTable( + &asc->m_progrConfigElement, self->elements, (((8)) + (8)), + &self->chMapIndex); + for (; el_tmp < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + el_tmp++) { + self->elements[el_tmp] = ID_NONE; + } + } else { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + } else { + self->chMapIndex = 0; + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + break; + } + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + ascChannels = asc->m_channelConfiguration; + break; + case 11: + ascChannels = 7; + break; + case 7: + case 12: + case 14: + ascChannels = 8; + break; + default: + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + if (asc->m_aot == AOT_USAC) { + flushChannels = fMin(ascChannels, (8)); + INT numChannel; + pcmDmx_GetParam(self->hPcmUtils, MIN_NUMBER_OF_OUTPUT_CHANNELS, + &numChannel); + flushChannels = fMin(fMax(numChannel, flushChannels), (8)); + } + + if (IS_USAC(asc->m_aot)) { + for (int el = 0; el < (INT)asc->m_sc.m_usacConfig.m_usacNumElements; el++) { + /* fix number of core channels aka ascChannels for stereoConfigIndex = 1 + * cases */ + if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 1) { + ascChannels--; /* stereoConfigIndex == 1 stereo cases do actually + contain only a mono core channel. */ + } else if (asc->m_sc.m_usacConfig.element[el].m_stereoConfigIndex == 2) { + /* In this case it is necessary to follow up the DMX signal delay caused + by HBE also with the residual signal (2nd core channel). The SBR + overlap delay is not regarded here, this is handled by the MPS212 + implementation. + */ + if (asc->m_sc.m_usacConfig.element[el].m_harmonicSBR) { + usacResidualDelayCompSamples += asc->m_samplesPerFrame; + } + if (asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex == 4) { + usacResidualDelayCompSamples += + 6 * 16; /* difference between 12 SBR + overlap slots from SBR and 6 + slots delayed in MPS212 */ + } + } + } + } + + aacChannelsOffset = 0; + aacChannelsOffsetIdx = 0; + elementOffset = 0; + if ((ascChannels <= 0) || (ascChannels > (8)) || + (asc->m_channelConfiguration > AACDEC_MAX_CH_CONF)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Set syntax flags */ + self->flags[streamIndex] = 0; + { FDKmemclear(self->elFlags, sizeof(self->elFlags)); } + + if ((asc->m_channelConfiguration > 0) || IS_USAC(asc->m_aot)) { + if (IS_USAC(asc->m_aot)) { + /* copy pointer to usac config + (this is preliminary since there's an ongoing discussion about storing + the config-part of the bitstream rather than the complete decoded + configuration) */ + self->pUsacConfig[streamIndex] = &asc->m_sc.m_usacConfig; + + /* copy list of elements */ + if (self->pUsacConfig[streamIndex]->m_usacNumElements > + (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + goto bail; + } + + if (self->numUsacElements[streamIndex] != + asc->m_sc.m_usacConfig.m_usacNumElements) { + ascChanged = 1; + } + + if (configMode & AC_CM_ALLOC_MEM) { + self->numUsacElements[streamIndex] = + asc->m_sc.m_usacConfig.m_usacNumElements; + } + + self->mpsEnableCurr = 0; + for (int _el = 0; + _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements; + _el++) { + int el = _el + elementOffset; + if (self->elements[el] != + self->pUsacConfig[streamIndex]->element[_el].usacElementType) { + ascChanged = 1; + } + if (self->usacStereoConfigIndex[el] != + asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->elements[el] = + self->pUsacConfig[streamIndex]->element[_el].usacElementType; + /* for Unified Stereo Coding */ + self->usacStereoConfigIndex[el] = + asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex; + if (self->elements[el] == ID_USAC_CPE) { + self->mpsEnableCurr |= self->usacStereoConfigIndex[el] ? 1 : 0; + } + } + + self->elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].m_noiseFilling) + ? AC_EL_USAC_NOISE + : 0; + self->elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].m_stereoConfigIndex > 0) + ? AC_EL_USAC_MPS212 + : 0; + self->elFlags[el] |= (asc->m_sc.m_usacConfig.element[_el].m_interTes) + ? AC_EL_USAC_ITES + : 0; + self->elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].m_pvc) ? AC_EL_USAC_PVC : 0; + self->elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE) + ? AC_EL_USAC_LFE + : 0; + self->elFlags[el] |= + (asc->m_sc.m_usacConfig.element[_el].usacElementType == ID_USAC_LFE) + ? AC_EL_LFE + : 0; + if ((asc->m_sc.m_usacConfig.element[_el].usacElementType == + ID_USAC_CPE) && + ((self->usacStereoConfigIndex[el] == 0))) { + self->elFlags[el] |= AC_EL_USAC_CP_POSSIBLE; + } + } + + self->hasAudioPreRoll = 0; + if (self->pUsacConfig[streamIndex]->m_usacNumElements) { + self->hasAudioPreRoll = asc->m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->elements[elementOffset + + self->pUsacConfig[streamIndex]->m_usacNumElements] = + ID_END; + } + } else { + /* Initialize constant mappings for channel config 1-7 */ + int i; + for (i = 0; i < AACDEC_CH_ELEMENTS_TAB_SIZE; i++) { + self->elements[i] = elementsTab[asc->m_channelConfiguration - 1][i]; + } + for (; i < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); i++) { + self->elements[i] = ID_NONE; + } + } + + { + int ch; + + for (ch = 0; ch < ascChannels; ch++) { + self->chMapping[ch] = ch; + } + for (; ch < (8); ch++) { + self->chMapping[ch] = 255; + } + } + + self->chMapIndex = asc->m_channelConfiguration; + } else { + if (CProgramConfig_IsValid(&asc->m_progrConfigElement)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce( + self->hPcmUtils, asc->m_progrConfigElement.MatrixMixdownIndexPresent, + asc->m_progrConfigElement.MatrixMixdownIndex, + asc->m_progrConfigElement.PseudoSurroundEnable); + } + } + + self->streamInfo.channelConfig = asc->m_channelConfiguration; + + if (self->streamInfo.aot != asc->m_aot) { + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.aot = asc->m_aot; + } + ascChanged = 1; + } + + if (asc->m_aot == AOT_ER_AAC_ELD && + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency != 0) { + if (self->samplingRateInfo[0].samplingRate != + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency || + self->samplingRateInfo[0].samplingRate * self->downscaleFactor != + asc->m_samplingFrequency) { + /* get downscaledSamplingFrequency from ESC and compute the downscale + * factor */ + downscaleFactorInBS = + asc->m_samplingFrequency / + asc->m_sc.m_eldSpecificConfig.m_downscaledSamplingFrequency; + if (downscaleFactorInBS == 1 || downscaleFactorInBS == 2 || + downscaleFactorInBS == 3 || downscaleFactorInBS == 4) { + downscaleFactor = downscaleFactorInBS; + } + } + } else { + downscaleFactorInBS = 1; + downscaleFactor = 1; + } + + if (self->downscaleFactorInBS != downscaleFactorInBS) { + if (configMode & AC_CM_ALLOC_MEM) { + self->downscaleFactorInBS = downscaleFactorInBS; + self->downscaleFactor = downscaleFactor; + } + ascChanged = 1; + } + + if ((INT)asc->m_samplesPerFrame % downscaleFactor != 0) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* frameSize/dsf must be an integer + number */ + } + + self->streamInfo.bitRate = 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + if (self->useLdQmfTimeAlign != + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->useLdQmfTimeAlign = + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign; + } + } + + self->streamInfo.extAot = asc->m_extensionAudioObjectType; + if (self->streamInfo.extSamplingRate != + (INT)asc->m_extensionSamplingFrequency) { + ascChanged = 1; + } + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.extSamplingRate = asc->m_extensionSamplingFrequency; + } + self->flags[streamIndex] |= (asc->m_sbrPresentFlag) ? AC_SBR_PRESENT : 0; + self->flags[streamIndex] |= (asc->m_psPresentFlag) ? AC_PS_PRESENT : 0; + if (asc->m_sbrPresentFlag) { + self->sbrEnabled = 1; + self->sbrEnabledPrev = 1; + } else { + self->sbrEnabled = 0; + self->sbrEnabledPrev = 0; + } + if (self->sbrEnabled && asc->m_extensionSamplingFrequency) { + if (downscaleFactor != 1 && (downscaleFactor)&1) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; /* SBR needs an even downscale + factor */ + } + if (configMode & AC_CM_ALLOC_MEM) { + self->streamInfo.extSamplingRate = + self->streamInfo.extSamplingRate / self->downscaleFactor; + } + } + + /* --------- vcb11 ------------ */ + self->flags[streamIndex] |= (asc->m_vcb11Flag) ? AC_ER_VCB11 : 0; + + /* ---------- rvlc ------------ */ + self->flags[streamIndex] |= (asc->m_rvlcFlag) ? AC_ER_RVLC : 0; + + /* ----------- hcr ------------ */ + self->flags[streamIndex] |= (asc->m_hcrFlag) ? AC_ER_HCR : 0; + + if (asc->m_aot == AOT_ER_AAC_ELD) { + self->mpsEnableCurr = 0; + self->flags[streamIndex] |= AC_ELD; + self->flags[streamIndex] |= + (asc->m_sbrPresentFlag) + ? AC_SBR_PRESENT + : 0; /* Need to set the SBR flag for backward-compatibility + reasons. Even if SBR is not supported. */ + self->flags[streamIndex] |= + (asc->m_sc.m_eldSpecificConfig.m_sbrCrcFlag) ? AC_SBRCRC : 0; + self->flags[streamIndex] |= + (asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) ? AC_MPS_PRESENT + : 0; + if (self->mpsApplicable) { + self->mpsEnableCurr = asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign; + } + } + self->flags[streamIndex] |= (asc->m_aot == AOT_ER_AAC_LD) ? AC_LD : 0; + self->flags[streamIndex] |= (asc->m_epConfig >= 0) ? AC_ER : 0; + + if (asc->m_aot == AOT_USAC) { + self->flags[streamIndex] |= AC_USAC; + self->flags[streamIndex] |= + (asc->m_sc.m_usacConfig.element[0].m_stereoConfigIndex > 0) + ? AC_MPS_PRESENT + : 0; + } + if (asc->m_aot == AOT_DRM_AAC) { + self->flags[streamIndex] |= AC_DRM | AC_SBRCRC | AC_SCALABLE; + } + if (asc->m_aot == AOT_DRM_SURROUND) { + self->flags[streamIndex] |= + AC_DRM | AC_SBRCRC | AC_SCALABLE | AC_MPS_PRESENT; + FDK_ASSERT(!asc->m_psPresentFlag); + } + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + self->flags[streamIndex] |= AC_SCALABLE; + } + + if ((asc->m_epConfig >= 0) && (asc->m_channelConfiguration <= 0)) { + /* we have to know the number of channels otherwise no decoding is possible + */ + return AAC_DEC_UNSUPPORTED_ER_FORMAT; + } + + self->streamInfo.epConfig = asc->m_epConfig; + /* self->hInput->asc.m_epConfig = asc->m_epConfig; */ + + if (asc->m_epConfig > 1) return AAC_DEC_UNSUPPORTED_ER_FORMAT; + + /* Check if samplerate changed. */ + if ((self->samplingRateInfo[streamIndex].samplingRate != + asc->m_samplingFrequency) || + (self->streamInfo.aacSamplesPerFrame != + (INT)asc->m_samplesPerFrame / downscaleFactor)) { + AAC_DECODER_ERROR error; + + ascChanged = 1; + + if (configMode & AC_CM_ALLOC_MEM) { + /* Update samplerate info. */ + error = getSamplingRateInfo( + &self->samplingRateInfo[streamIndex], asc->m_samplesPerFrame, + asc->m_samplingFrequencyIndex, asc->m_samplingFrequency); + if (error != AAC_DEC_OK) { + return error; + } + self->streamInfo.aacSampleRate = + self->samplingRateInfo[0].samplingRate / self->downscaleFactor; + self->streamInfo.aacSamplesPerFrame = + asc->m_samplesPerFrame / self->downscaleFactor; + } + } + + /* Check if amount of channels has changed. */ + if (self->ascChannels[streamIndex] != ascChannels) { + ascChanged = 1; + } + + /* detect config change */ + if (configMode & AC_CM_DET_CFG_CHANGE) { + if (ascChanged != 0) { + *configChanged = 1; + } + return err; + } + + /* set AC_USAC_SCFGI3 globally if any usac element uses */ + switch (asc->m_aot) { + case AOT_USAC: + if (self->sbrEnabled) { + for (int _el = 0; + _el < (int)self->pUsacConfig[streamIndex]->m_usacNumElements; + _el++) { + int el = elementOffset + _el; + if (IS_USAC_CHANNEL_ELEMENT(self->elements[el])) { + if (usacStereoConfigIndex < 0) { + usacStereoConfigIndex = self->usacStereoConfigIndex[el]; + } else { + if ((usacStereoConfigIndex != self->usacStereoConfigIndex[el]) || + (self->usacStereoConfigIndex[el] > 0)) { + goto bail; + } + } + } + } + + if (usacStereoConfigIndex < 0) { + goto bail; + } + + if (usacStereoConfigIndex == 3) { + self->flags[streamIndex] |= AC_USAC_SCFGI3; + } + } + break; + default: + break; + } + + if (*configChanged) { + /* Set up QMF domain for AOTs with explicit signalling of SBR and or MPS. + This is to be able to play out the first frame alway with the correct + frame size and sampling rate even in case of concealment. + */ + switch (asc->m_aot) { + case AOT_USAC: + if (self->sbrEnabled) { + const UCHAR map_sbrRatio_2_nAnaBands[] = {16, 24, 32}; + + FDK_ASSERT(asc->m_sc.m_usacConfig.m_sbrRatioIndex > 0); + FDK_ASSERT(streamIndex == 0); + + self->qmfDomain.globalConf.nInputChannels_requested = ascChannels; + self->qmfDomain.globalConf.nOutputChannels_requested = + (usacStereoConfigIndex == 1) ? 2 : ascChannels; + self->qmfDomain.globalConf.flags_requested = 0; + self->qmfDomain.globalConf.nBandsAnalysis_requested = + map_sbrRatio_2_nAnaBands[asc->m_sc.m_usacConfig.m_sbrRatioIndex - + 1]; + self->qmfDomain.globalConf.nBandsSynthesis_requested = 64; + self->qmfDomain.globalConf.nQmfTimeSlots_requested = + (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 64 : 32; + self->qmfDomain.globalConf.nQmfOvTimeSlots_requested = + (asc->m_sc.m_usacConfig.m_sbrRatioIndex == 1) ? 12 : 6; + self->qmfDomain.globalConf.nQmfProcBands_requested = 64; + self->qmfDomain.globalConf.nQmfProcChannels_requested = 1; + self->qmfDomain.globalConf.parkChannel = + (usacStereoConfigIndex == 3) ? 1 : 0; + self->qmfDomain.globalConf.parkChannel_requested = + (usacStereoConfigIndex == 3) ? 1 : 0; + self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1; + } + break; + case AOT_ER_AAC_ELD: + if (self->mpsEnableCurr && + asc->m_sc.m_eldSpecificConfig.m_useLdQmfTimeAlign) { + SAC_INPUT_CONFIG sac_interface = + (self->sbrEnabled && self->hSbrDecoder) ? SAC_INTERFACE_QMF + : SAC_INTERFACE_TIME; + mpegSurroundDecoder_ConfigureQmfDomain( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface, + (UINT)self->streamInfo.aacSampleRate, asc->m_aot); + self->qmfDomain.globalConf.qmfDomainExplicitConfig = 1; + } + break; + default: + self->qmfDomain.globalConf.qmfDomainExplicitConfig = + 0; /* qmfDomain is initialized by SBR and MPS init functions if + required */ + break; + } + + /* Allocate all memory structures for each channel */ + { + int ch = aacChannelsOffset; + for (int _ch = 0; _ch < ascChannels; _ch++) { + if (ch >= (8)) { + goto bail; + } + self->pAacDecoderChannelInfo[ch] = GetAacDecoderChannelInfo(ch); + /* This is temporary until the DynamicData is split into two or more + regions! The memory could be reused after completed core decoding. */ + if (self->pAacDecoderChannelInfo[ch] == NULL) { + goto bail; + } + ch++; + } + + int chIdx = aacChannelsOffsetIdx; + ch = aacChannelsOffset; + int _numElements; + _numElements = (((8)) + (8)); + if (self->flags[streamIndex] & (AC_RSV603DA | AC_USAC)) { + _numElements = (int)asc->m_sc.m_usacConfig.m_usacNumElements; + } + for (int _el = 0; _el < _numElements; _el++) { + int el_channels = 0; + int el = elementOffset + _el; + + if (self->flags[streamIndex] & + (AC_ER | AC_LD | AC_ELD | AC_RSV603DA | AC_USAC | AC_RSVD50)) { + if (ch >= ascChannels) { + break; + } + } + + switch (self->elements[el]) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + + el_channels = CAacDecoder_GetELChannels( + self->elements[el], self->usacStereoConfigIndex[el]); + + { + self->pAacDecoderChannelInfo[ch]->pComStaticData = + (CAacDecoderCommonStaticData *)FDKcalloc( + 1, sizeof(CAacDecoderCommonStaticData)); + if (self->pAacDecoderChannelInfo[ch]->pComStaticData == NULL) { + goto bail; + } + if (ch == aacChannelsOffset) { + self->pAacDecoderChannelInfo[ch]->pComData = + (CAacDecoderCommonData *)GetWorkBufferCore6(); + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 = GetWorkBufferCore1(); + } else { + self->pAacDecoderChannelInfo[ch]->pComData = + (CAacDecoderCommonData *)FDKaalloc( + sizeof(CAacDecoderCommonData), ALIGNMENT_DEFAULT); + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 = + self->pAacDecoderChannelInfo[aacChannelsOffset] + ->pComStaticData->pWorkBufferCore1; + } + if ((self->pAacDecoderChannelInfo[ch]->pComData == NULL) || + (self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1 == NULL)) { + goto bail; + } + self->pAacDecoderChannelInfo[ch]->pDynData = + &(self->pAacDecoderChannelInfo[ch] + ->pComData->pAacDecoderDynamicData[0]); + self->pAacDecoderChannelInfo[ch]->pSpectralCoefficient = + (SPECTRAL_PTR)&self->workBufferCore2[ch * 1024]; + + if (el_channels == 2) { + if (ch >= (8) - 1) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + self->pAacDecoderChannelInfo[ch + 1]->pComData = + self->pAacDecoderChannelInfo[ch]->pComData; + self->pAacDecoderChannelInfo[ch + 1]->pComStaticData = + self->pAacDecoderChannelInfo[ch]->pComStaticData; + self->pAacDecoderChannelInfo[ch + 1] + ->pComStaticData->pWorkBufferCore1 = + self->pAacDecoderChannelInfo[ch] + ->pComStaticData->pWorkBufferCore1; + self->pAacDecoderChannelInfo[ch + 1]->pDynData = + &(self->pAacDecoderChannelInfo[ch] + ->pComData->pAacDecoderDynamicData[1]); + self->pAacDecoderChannelInfo[ch + 1]->pSpectralCoefficient = + (SPECTRAL_PTR)&self->workBufferCore2[(ch + 1) * 1024]; + } + + ch += el_channels; + } + chIdx += el_channels; + break; + + default: + break; + } + + if (self->elements[el] == ID_END) { + break; + } + + el++; + } + + chIdx = aacChannelsOffsetIdx; + ch = aacChannelsOffset; + for (int _ch = 0; _ch < ascChannels; _ch++) { + /* Allocate persistent channel memory */ + { + self->pAacDecoderStaticChannelInfo[ch] = + GetAacDecoderStaticChannelInfo(ch); + if (self->pAacDecoderStaticChannelInfo[ch] == NULL) { + goto bail; + } + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer = + GetOverlapBuffer(ch); /* This area size depends on the AOT */ + if (self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer == NULL) { + goto bail; + } + if (self->flags[streamIndex] & + (AC_USAC | AC_RSVD50 | AC_RSV603DA /*|AC_BSAC*/)) { + self->pAacDecoderStaticChannelInfo[ch]->hArCo = CArco_Create(); + if (self->pAacDecoderStaticChannelInfo[ch]->hArCo == NULL) { + goto bail; + } + } + + if (!(self->flags[streamIndex] & (AC_USAC | AC_RSV603DA))) { + CPns_UpdateNoiseState( + &self->pAacDecoderChannelInfo[ch]->data.aac.PnsData, + &self->pAacDecoderStaticChannelInfo[ch]->pnsCurrentSeed, + self->pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed); + } + ch++; + } + chIdx++; + } + + if (self->flags[streamIndex] & AC_USAC) { + for (int _ch = 0; _ch < flushChannels; _ch++) { + ch = aacChannelsOffset + _ch; + if (self->pTimeDataFlush[ch] == NULL) { + self->pTimeDataFlush[ch] = GetTimeDataFlush(ch); + if (self->pTimeDataFlush[ch] == NULL) { + goto bail; + } + } + } + } + + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA)) { + int complexStereoPredPossible = 0; + ch = aacChannelsOffset; + chIdx = aacChannelsOffsetIdx; + for (int _el2 = 0; _el2 < (int)asc->m_sc.m_usacConfig.m_usacNumElements; + _el2++) { + int el2 = elementOffset + _el2; + int elCh = 0, ch2; + + if ((self->elements[el2] == ID_USAC_CPE) && + !(self->usacStereoConfigIndex[el2] == 1)) { + elCh = 2; + } else if (IS_CHANNEL_ELEMENT(self->elements[el2])) { + elCh = 1; + } + + if (self->elFlags[el2] & AC_EL_USAC_CP_POSSIBLE) { + complexStereoPredPossible = 1; + if (self->cpeStaticData[el2] == NULL) { + self->cpeStaticData[el2] = GetCpePersistentData(); + if (self->cpeStaticData[el2] == NULL) { + goto bail; + } + } + } + + for (ch2 = 0; ch2 < elCh; ch2++) { + /* Hook element specific cpeStaticData into channel specific + * aacDecoderStaticChannelInfo */ + self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData = + self->cpeStaticData[el2]; + if (self->pAacDecoderStaticChannelInfo[ch]->pCpeStaticData != + NULL) { + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData + .spectralCoeffs[ch2] = + self->pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.spectralCoefficient; + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData.specScale[ch2] = + self->pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.specScale; + self->pAacDecoderStaticChannelInfo[ch] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer = + (FIXP_DBL *)self->pTimeData2; + } + chIdx++; + ch++; + } /* for each channel in current element */ + if (complexStereoPredPossible && (elCh == 2)) { + /* needed once for all channels */ + if (self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData == NULL) { + self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData = + GetCplxPredictionData(); + } + if (self->pAacDecoderChannelInfo[ch - 1] + ->pComStaticData->cplxPredictionData == NULL) { + goto bail; + } + } + if (elCh > 0) { + self->pAacDecoderStaticChannelInfo[ch - elCh]->nfRandomSeed = + (ULONG)0x3039; + if (self->elements[el2] == ID_USAC_CPE) { + if (asc->m_sc.m_usacConfig.element[el2].m_stereoConfigIndex != + 1) { + self->pAacDecoderStaticChannelInfo[ch - elCh + 1] + ->nfRandomSeed = (ULONG)0x10932; + } + } + } + } /* for each element */ + } + + if (ascChannels != self->aacChannels) { + /* Make allocated channel count persistent in decoder context. */ + self->aacChannels = aacChannelsOffset + ch; + } + } + + if (usacResidualDelayCompSamples) { + INT delayErr = FDK_Delay_Create(&self->usacResidualDelay, + (USHORT)usacResidualDelayCompSamples, 1); + if (delayErr) { + goto bail; + } + } + + /* Make amount of signalled channels persistent in decoder context. */ + self->ascChannels[streamIndex] = ascChannels; + /* Init the previous channel count values. This is required to avoid a + mismatch of memory accesses in the error concealment module and the + allocated channel structures in this function. */ + self->aacChannelsPrev = 0; + } + + if (self->pAacDecoderChannelInfo[0] != NULL) { + self->pDrmBsBuffer = self->pAacDecoderChannelInfo[0] + ->pComStaticData->pWorkBufferCore1->DrmBsBuffer; + self->drmBsBufferSize = DRM_BS_BUFFER_SIZE; + } + + /* Update structures */ + if (*configChanged) { + /* Things to be done for each channel, which do not involve allocating + memory. Doing these things only on the channels needed for the current + configuration (ascChannels) could lead to memory access violation later + (error concealment). */ + int ch = 0; + int chIdx = 0; + for (int _ch = 0; _ch < self->ascChannels[streamIndex]; _ch++) { + switch (self->streamInfo.aot) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + self->pAacDecoderChannelInfo[ch]->granuleLength = + self->streamInfo.aacSamplesPerFrame; + break; + default: + self->pAacDecoderChannelInfo[ch]->granuleLength = + self->streamInfo.aacSamplesPerFrame / 8; + break; + } + self->pAacDecoderChannelInfo[ch]->renderMode = initRenderMode; + + mdct_init(&self->pAacDecoderStaticChannelInfo[ch]->IMdct, + self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize); + + self->pAacDecoderStaticChannelInfo[ch]->last_core_mode = FD_LONG; + self->pAacDecoderStaticChannelInfo[ch]->last_lpd_mode = 255; + + self->pAacDecoderStaticChannelInfo[ch]->last_tcx_pitch = L_DIV; + + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->drcData); + + /* Delete mixdown metadata from the past */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + + /* Reset concealment only if ASC changed. Otherwise it will be done with + any config callback. E.g. every time the LATM SMC is present. */ + CConcealment_InitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, initRenderMode, + self->streamInfo.aacSamplesPerFrame); + ch++; + chIdx++; + } + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags[0]; + + if (*configChanged) { + int drcDecSampleRate, drcDecFrameSize; + + if (self->streamInfo.extSamplingRate != 0) { + drcDecSampleRate = self->streamInfo.extSamplingRate; + drcDecFrameSize = (self->streamInfo.aacSamplesPerFrame * + self->streamInfo.extSamplingRate) / + self->streamInfo.aacSampleRate; + } else { + drcDecSampleRate = self->streamInfo.aacSampleRate; + drcDecFrameSize = self->streamInfo.aacSamplesPerFrame; + } + + if (FDK_drcDec_Init(self->hUniDrcDecoder, drcDecFrameSize, drcDecSampleRate, + self->aacChannels) != 0) + goto bail; + } + + if (asc->m_aot == AOT_USAC) { + pcmLimiter_SetAttack(self->hLimiter, (5)); + pcmLimiter_SetThreshold(self->hLimiter, FL2FXCONST_DBL(0.89125094f)); + } + + return err; + +bail: + CAacDecoder_DeInit(self, 0); + return AAC_DEC_OUT_OF_MEMORY; +} + +LINKSPEC_CPP AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData, + const INT timeDataSize, const int timeDataChannelOffset) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + CProgramConfig *pce; + HANDLE_FDK_BITSTREAM bs = transportDec_GetBitstream(self->hInput, 0); + + MP4_ELEMENT_ID type = ID_NONE; /* Current element type */ + INT aacChannels = 0; /* Channel counter for channels found in the bitstream */ + const int streamIndex = 0; /* index of the current substream */ + + INT auStartAnchor = (INT)FDKgetValidBits( + bs); /* AU start bit buffer position for AU byte alignment */ + + INT checkSampleRate = self->streamInfo.aacSampleRate; + + INT CConceal_TDFading_Applied[(8)] = { + 0}; /* Initialize status of Time Domain fading */ + + if (self->aacChannels <= 0) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + /* Any supported base layer valid AU will require more than 16 bits. */ + if ((transportDec_GetAuBitsRemaining(self->hInput, 0) < 15) && + (flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) == 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + /* Reset Program Config structure */ + pce = &self->pce; + CProgramConfig_Reset(pce); + + CAacDecoder_AncDataReset(&self->ancData); + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && + !(self->flags[0] & (AC_USAC | AC_RSV603DA))) { + int ch; + if (self->streamInfo.channelConfig == 0) { + /* Init Channel/Element mapping table */ + for (ch = 0; ch < (8); ch++) { + self->chMapping[ch] = 255; + } + if (!CProgramConfig_IsValid(pce)) { + int el; + for (el = 0; el < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + el++) { + self->elements[el] = ID_NONE; + } + } + } + } + + if (self->downscaleFactor > 1 && (self->flags[0] & AC_ELD)) { + self->flags[0] |= AC_ELD_DOWNSCALE; + } else { + self->flags[0] &= ~AC_ELD_DOWNSCALE; + } + /* unsupported dsf (aacSampleRate has not yet been divided by dsf) -> divide + */ + if (self->downscaleFactorInBS > 1 && + (self->flags[0] & AC_ELD_DOWNSCALE) == 0) { + checkSampleRate = + self->streamInfo.aacSampleRate / self->downscaleFactorInBS; + } + + /* Check sampling frequency */ + if (self->streamInfo.aacSampleRate <= 0) { + /* Instance maybe uninitialized! */ + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + switch (checkSampleRate) { + case 96000: + case 88200: + case 64000: + case 16000: + case 12000: + case 11025: + case 8000: + case 7350: + case 48000: + case 44100: + case 32000: + case 24000: + case 22050: + break; + default: + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + return AAC_DEC_UNSUPPORTED_SAMPLINGRATE; + } + break; + } + + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + int ch; + /* Clear history */ + for (ch = 0; ch < self->aacChannels; ch++) { + /* Reset concealment */ + CConcealment_InitChannelData( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + &self->concealCommonData, + self->pAacDecoderChannelInfo[0]->renderMode, + self->streamInfo.aacSamplesPerFrame); + /* Clear overlap-add buffers to avoid clicks. */ + FDKmemclear(self->pAacDecoderStaticChannelInfo[ch]->pOverlapBuffer, + OverlapBufferSize * sizeof(FIXP_DBL)); + } + if (self->streamInfo.channelConfig > 0) { + /* Declare the possibly adopted old PCE (with outdated metadata) + * invalid. */ + CProgramConfig_Init(pce); + } + } + } + + int pceRead = 0; /* Flag indicating a PCE in the current raw_data_block() */ + + INT hdaacDecoded = 0; + MP4_ELEMENT_ID previous_element = + ID_END; /* Last element ID (required for extension payload mapping */ + UCHAR previous_element_index = 0; /* Canonical index of last element */ + int element_count = + 0; /* Element counter for elements found in the bitstream */ + int channel_element_count = 0; /* Channel element counter */ + MP4_ELEMENT_ID + channel_elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /* Channel elements in bit stream order. */ + int el_cnt[ID_LAST] = {0}; /* element counter ( robustness ) */ + int element_count_prev_streams = + 0; /* Element count of all previous sub streams. */ + + while ((type != ID_END) && (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) && + self->frameOK) { + int el_channels; + + if (!(self->flags[0] & + (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD | AC_SCALABLE | AC_ER))) + type = (MP4_ELEMENT_ID)FDKreadBits(bs, 3); + else { + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + type = self->elements[element_count]; + } + + if ((self->flags[streamIndex] & (AC_USAC | AC_RSVD50) && + element_count == 0) || + (self->flags[streamIndex] & AC_RSV603DA)) { + self->flags[streamIndex] &= ~AC_INDEP; + + if (FDKreadBit(bs)) { + self->flags[streamIndex] |= AC_INDEP; + } + + int ch = aacChannels; + for (int chIdx = aacChannels; chIdx < self->ascChannels[streamIndex]; + chIdx++) { + { + /* Robustness check */ + if (ch >= self->aacChannels) { + return AAC_DEC_UNKNOWN; + } + + /* if last frame was broken and this frame is no independent frame, + * correct decoding is impossible we need to trigger concealment */ + if ((CConcealment_GetLastFrameOk( + &self->pAacDecoderStaticChannelInfo[ch]->concealmentInfo, + 1) == 0) && + !(self->flags[streamIndex] & AC_INDEP)) { + self->frameOK = 0; + } + ch++; + } + } + } + + if ((INT)FDKgetValidBits(bs) < 0) { + self->frameOK = 0; + } + + switch (type) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + + el_channels = CAacDecoder_GetELChannels( + type, self->usacStereoConfigIndex[element_count]); + + /* + Consistency check + */ + { + int totalAscChannels = 0; + + for (int i = 0; i < (1 * 1); i++) { + totalAscChannels += self->ascChannels[i]; + } + if ((el_cnt[type] >= (totalAscChannels >> (el_channels - 1))) || + (aacChannels > (totalAscChannels - el_channels))) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + } + + if (!(self->flags[streamIndex] & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + int ch; + for (ch = 0; ch < el_channels; ch += 1) { + CPns_ResetData(&self->pAacDecoderChannelInfo[aacChannels + ch] + ->data.aac.PnsData, + &self->pAacDecoderChannelInfo[aacChannels + ch] + ->pComData->pnsInterChannelData); + } + } + + if (self->frameOK) { + ErrorStatus = CChannelElement_Read( + bs, &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + self->streamInfo.aot, &self->samplingRateInfo[streamIndex], + self->flags[streamIndex], self->elFlags[element_count], + self->streamInfo.aacSamplesPerFrame, el_channels, + self->streamInfo.epConfig, self->hInput); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + } + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the current + * program */ + if (CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, + self->pAacDecoderChannelInfo[aacChannels]->ElementInstanceTag, + aacChannels, self->chMapping, self->channelType, + self->channelIndices, (8), &previous_element_index, + self->elements, type)) { + channel_elements[channel_element_count++] = type; + aacChannels += el_channels; + } else { + self->frameOK = 0; + } + /* Create SBR element for SBR for upsampling for LFE elements, + and if SBR was implicitly signaled, because the first frame(s) + may not contain SBR payload (broken encoder, bit errors). */ + if (self->frameOK && + ((self->flags[streamIndex] & AC_SBR_PRESENT) || + (self->sbrEnabled == 1)) && + !(self->flags[streamIndex] & + AC_USAC) /* Is done during explicit config set up */ + ) { + SBR_ERROR sbrError; + UCHAR configMode = 0; + UCHAR configChanged = 0; + configMode |= AC_CM_ALLOC_MEM; + + sbrError = sbrDecoder_InitElement( + self->hSbrDecoder, self->streamInfo.aacSampleRate, + self->streamInfo.extSamplingRate, + self->streamInfo.aacSamplesPerFrame, self->streamInfo.aot, type, + previous_element_index, 2, /* Signalize that harmonicSBR shall + be ignored in the config change + detection */ + 0, configMode, &configChanged, self->downscaleFactor); + if (sbrError != SBRDEC_OK) { + /* Do not try to apply SBR because initializing the element + * failed. */ + self->sbrEnabled = 0; + } + } + } + + el_cnt[type]++; + if (self->frameOK && (self->flags[streamIndex] & AC_USAC) && + (type == ID_USAC_CPE || type == ID_USAC_SCE)) { + ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr( + self, bs, previous_element, previous_element_index, element_count, + el_cnt); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + } + } + break; + + case ID_CCE: + /* + Consistency check + */ + if (el_cnt[type] > self->ascChannels[streamIndex]) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + if (self->frameOK) { + CAacDecoderCommonData commonData; + CAacDecoderCommonStaticData commonStaticData; + CWorkBufferCore1 workBufferCore1; + commonStaticData.pWorkBufferCore1 = &workBufferCore1; + /* memory for spectral lines temporal on scratch */ + C_AALLOC_SCRATCH_START(mdctSpec, FIXP_DBL, 1024); + + /* create dummy channel for CCE parsing on stack */ + CAacDecoderChannelInfo tmpAacDecoderChannelInfo, + *pTmpAacDecoderChannelInfo; + + FDKmemclear(mdctSpec, 1024 * sizeof(FIXP_DBL)); + + tmpAacDecoderChannelInfo.pDynData = commonData.pAacDecoderDynamicData; + tmpAacDecoderChannelInfo.pComData = &commonData; + tmpAacDecoderChannelInfo.pComStaticData = &commonStaticData; + tmpAacDecoderChannelInfo.pSpectralCoefficient = + (SPECTRAL_PTR)mdctSpec; + /* Assume AAC-LC */ + tmpAacDecoderChannelInfo.granuleLength = + self->streamInfo.aacSamplesPerFrame / 8; + /* Reset PNS data. */ + CPns_ResetData( + &tmpAacDecoderChannelInfo.data.aac.PnsData, + &tmpAacDecoderChannelInfo.pComData->pnsInterChannelData); + pTmpAacDecoderChannelInfo = &tmpAacDecoderChannelInfo; + /* do CCE parsing */ + ErrorStatus = CChannelElement_Read( + bs, &pTmpAacDecoderChannelInfo, NULL, self->streamInfo.aot, + &self->samplingRateInfo[streamIndex], self->flags[streamIndex], + AC_EL_GA_CCE, self->streamInfo.aacSamplesPerFrame, 1, + self->streamInfo.epConfig, self->hInput); + + C_AALLOC_SCRATCH_END(mdctSpec, FIXP_DBL, 1024); + + if (ErrorStatus) { + self->frameOK = 0; + } + + if (self->frameOK) { + /* Lookup the element and decode it only if it belongs to the + * current program */ + if (CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, + pTmpAacDecoderChannelInfo->ElementInstanceTag, 0, + self->chMapping, self->channelType, self->channelIndices, + (8), &previous_element_index, self->elements, type)) { + /* decoding of CCE not supported */ + } else { + self->frameOK = 0; + } + } + } + el_cnt[type]++; + break; + + case ID_DSE: { + UCHAR element_instance_tag; + + CDataStreamElement_Read(self, bs, &element_instance_tag, auStartAnchor); + + if (!CProgramConfig_LookupElement( + pce, self->streamInfo.channelConfig, element_instance_tag, 0, + self->chMapping, self->channelType, self->channelIndices, (8), + &previous_element_index, self->elements, type)) { + /* most likely an error in bitstream occured */ + // self->frameOK = 0; + } + } break; + + case ID_PCE: { + int result = CProgramConfigElement_Read(bs, self->hInput, pce, + self->streamInfo.channelConfig, + auStartAnchor); + if (result < 0) { + /* Something went wrong */ + ErrorStatus = AAC_DEC_PARSE_ERROR; + self->frameOK = 0; + } else if (result > 1) { + /* Built element table */ + int elIdx = CProgramConfig_GetElementTable( + pce, self->elements, (((8)) + (8)), &self->chMapIndex); + /* Reset the remaining tabs */ + for (; elIdx < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1); + elIdx++) { + self->elements[elIdx] = ID_NONE; + } + /* Make new number of channel persistent */ + self->ascChannels[streamIndex] = pce->NumChannels; + /* If PCE is not first element conceal this frame to avoid + * inconsistencies */ + if (element_count != 0) { + self->frameOK = 0; + } + } + pceRead = (result >= 0) ? 1 : 0; + } break; + + case ID_FIL: { + int bitCnt = FDKreadBits(bs, 4); /* bs_count */ + + if (bitCnt == 15) { + int esc_count = FDKreadBits(bs, 8); /* bs_esc_count */ + bitCnt = esc_count + 14; + } + + /* Convert to bits */ + bitCnt <<= 3; + + while (bitCnt > 0) { + ErrorStatus = CAacDecoder_ExtPayloadParse( + self, bs, &bitCnt, previous_element, previous_element_index, 1); + if (ErrorStatus != AAC_DEC_OK) { + self->frameOK = 0; + break; + } + } + } break; + + case ID_EXT: + if (element_count >= (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + + ErrorStatus = aacDecoder_ParseExplicitMpsAndSbr( + self, bs, previous_element, previous_element_index, element_count, + el_cnt); + break; + + case ID_USAC_EXT: { + if ((element_count - element_count_prev_streams) >= + TP_USAC_MAX_ELEMENTS) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + break; + } + /* parse extension element payload + q.v. rsv603daExtElement() ISO/IEC DIS 23008-3 Table 30 + or UsacExElement() ISO/IEC FDIS 23003-3:2011(E) Table 21 + */ + int usacExtElementPayloadLength; + /* int usacExtElementStart, usacExtElementStop; */ + + if (FDKreadBit(bs)) { /* usacExtElementPresent */ + if (FDKreadBit(bs)) { /* usacExtElementUseDefaultLength */ + usacExtElementPayloadLength = + self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementDefaultLength; + } else { + usacExtElementPayloadLength = FDKreadBits(bs, 8); + if (usacExtElementPayloadLength == (UINT)(1 << 8) - 1) { + UINT valueAdd = FDKreadBits(bs, 16); + usacExtElementPayloadLength += (INT)valueAdd - 2; + } + } + if (usacExtElementPayloadLength > 0) { + int usacExtBitPos; + + if (self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementPayloadFrag) { + /* usacExtElementStart = */ FDKreadBit(bs); + /* usacExtElementStop = */ FDKreadBit(bs); + } else { + /* usacExtElementStart = 1; */ + /* usacExtElementStop = 1; */ + } + + usacExtBitPos = (INT)FDKgetValidBits(bs); + + USAC_EXT_ELEMENT_TYPE usacExtElementType = + self->pUsacConfig[streamIndex] + ->element[element_count - element_count_prev_streams] + .extElement.usacExtElementType; + + switch (usacExtElementType) { + case ID_EXT_ELE_UNI_DRC: /* uniDrcGain() */ + if (streamIndex == 0) { + int drcErr; + + drcErr = FDK_drcDec_ReadUniDrcGain(self->hUniDrcDecoder, bs); + if (drcErr != 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + } + break; + + default: + break; + } + + /* Skip any remaining bits of extension payload */ + usacExtBitPos = (usacExtElementPayloadLength * 8) - + (usacExtBitPos - (INT)FDKgetValidBits(bs)); + if (usacExtBitPos < 0) { + self->frameOK = 0; + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + FDKpushBiDirectional(bs, usacExtBitPos); + } + } + } break; + case ID_END: + case ID_USAC_END: + break; + + default: + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + self->frameOK = 0; + break; + } + + previous_element = type; + element_count++; + + } /* while ( (type != ID_END) ... ) */ + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + /* float decoder checks if bitsLeft is in range 0-7; only prerollAUs are + * byteAligned with respect to the first bit */ + /* Byte alignment with respect to the first bit of the raw_data_block(). */ + if (!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) || + (self->prerollAULength[self->accessUnit]) /* indicates preroll */ + ) { + FDKbyteAlign(bs, auStartAnchor); + } + + /* Check if all bits of the raw_data_block() have been read. */ + if (transportDec_GetAuBitsTotal(self->hInput, 0) > 0) { + INT unreadBits = transportDec_GetAuBitsRemaining(self->hInput, 0); + /* for pre-roll frames pre-roll length has to be used instead of total AU + * lenght */ + /* unreadBits regarding preroll bounds */ + if (self->prerollAULength[self->accessUnit]) { + unreadBits = unreadBits - transportDec_GetAuBitsTotal(self->hInput, 0) + + (INT)self->prerollAULength[self->accessUnit]; + } + if (((self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) && + ((unreadBits < 0) || (unreadBits > 7)) && + !(self->prerollAULength[self->accessUnit])) || + ((!(self->flags[streamIndex] & (AC_RSVD50 | AC_USAC)) || + (self->prerollAULength[self->accessUnit])) && + (unreadBits != 0))) { + if ((((unreadBits < 0) || (unreadBits > 7)) && self->frameOK) && + ((transportDec_GetFormat(self->hInput) == TT_DRM) && + (self->flags[streamIndex] & AC_USAC))) { + /* Set frame OK because of fill bits. */ + self->frameOK = 1; + } else { + self->frameOK = 0; + } + + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK && self->frameOK == 0) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + /* Always put the bitbuffer at the right position after the current + * Access Unit. */ + FDKpushBiDirectional(bs, unreadBits); + } + } + + /* Check the last element. The terminator (ID_END) has to be the last one + * (even if ER syntax is used). */ + if (self->frameOK && type != ID_END) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + self->frameOK = 0; + } + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) { + channel_elements[channel_element_count++] = ID_END; + } + element_count = 0; + aacChannels = 0; + type = ID_NONE; + previous_element_index = 0; + + while (type != ID_END && + element_count < (3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)) { + int el_channels; + + if ((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || !self->frameOK) { + channel_elements[element_count] = self->elements[element_count]; + if (channel_elements[element_count] == ID_NONE) { + channel_elements[element_count] = ID_END; + } + } + + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) { + type = self->elements[element_count]; + } else { + type = channel_elements[element_count]; + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && self->frameOK) { + switch (type) { + case ID_SCE: + case ID_CPE: + case ID_LFE: + case ID_USAC_SCE: + case ID_USAC_CPE: + case ID_USAC_LFE: + + el_channels = CAacDecoder_GetELChannels( + type, self->usacStereoConfigIndex[element_count]); + + if (!hdaacDecoded) { + if (self->pAacDecoderStaticChannelInfo[aacChannels] + ->pCpeStaticData != NULL) { + self->pAacDecoderStaticChannelInfo[aacChannels] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer = + (FIXP_DBL *)pTimeData; + } + CChannelElement_Decode( + &self->pAacDecoderChannelInfo[aacChannels], + &self->pAacDecoderStaticChannelInfo[aacChannels], + &self->samplingRateInfo[streamIndex], self->flags[streamIndex], + self->elFlags[element_count], el_channels); + } + aacChannels += el_channels; + break; + case ID_NONE: + type = ID_END; + break; + default: + break; + } + } + element_count++; + } + + /* More AAC channels than specified by the ASC not allowed. */ + if ((aacChannels == 0 || aacChannels > self->aacChannels) && + !(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + /* Do not overwrite current error */ + if (ErrorStatus == AAC_DEC_OK) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + self->frameOK = 0; + aacChannels = 0; + } + + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH))) { + if (TRANSPORTDEC_OK != transportDec_CrcCheck(self->hInput)) { + ErrorStatus = AAC_DEC_CRC_ERROR; + self->frameOK = 0; + } + } + + /* Ensure that in case of concealment a proper error status is set. */ + if ((self->frameOK == 0) && (ErrorStatus == AAC_DEC_OK)) { + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + if (self->frameOK && (flags & AACDEC_FLUSH)) { + aacChannels = self->aacChannelsPrev; + /* Because the downmix could be active, its necessary to restore the channel + * type and indices. */ + FDKmemcpy(self->channelType, self->channelTypePrev, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */ + FDKmemcpy(self->channelIndices, self->channelIndicesPrev, + (8) * sizeof(UCHAR)); /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } else { + /* store or restore the number of channels and the corresponding info */ + if (self->frameOK && !(flags & AACDEC_CONCEAL)) { + self->aacChannelsPrev = aacChannels; /* store */ + FDKmemcpy(self->channelTypePrev, self->channelType, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* store */ + FDKmemcpy(self->channelIndicesPrev, self->channelIndices, + (8) * sizeof(UCHAR)); /* store */ + self->sbrEnabledPrev = self->sbrEnabled; + } else { + if (self->aacChannels > 0) { + if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) || + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + aacChannels = self->aacChannels; + self->aacChannelsPrev = aacChannels; /* store */ + } else { + aacChannels = self->aacChannelsPrev; /* restore */ + } + FDKmemcpy(self->channelType, self->channelTypePrev, + (8) * sizeof(AUDIO_CHANNEL_TYPE)); /* restore */ + FDKmemcpy(self->channelIndices, self->channelIndicesPrev, + (8) * sizeof(UCHAR)); /* restore */ + self->sbrEnabled = self->sbrEnabledPrev; + } + } + } + + /* Update number of output channels */ + self->streamInfo.aacNumChannels = aacChannels; + + /* Ensure consistency of IS_OUTPUT_VALID() macro. */ + if (aacChannels == 0) { + ErrorStatus = AAC_DEC_UNKNOWN; + } + + if (pceRead == 1 && CProgramConfig_IsValid(pce)) { + /* Set matrix mixdown infos if available from PCE. */ + pcmDmx_SetMatrixMixdownFromPce( + self->hPcmUtils, pce->MatrixMixdownIndexPresent, + pce->MatrixMixdownIndex, pce->PseudoSurroundEnable); + ; + } + + /* If there is no valid data to transfrom into time domain, return. */ + if (!IS_OUTPUT_VALID(ErrorStatus)) { + return ErrorStatus; + } + + /* Setup the output channel mapping. The table below shows the three + * possibilities: # | chCfg | PCE | chMapIndex + * ---+-------+-----+------------------ + * 1 | > 0 | no | chCfg + * 2 | 0 | yes | cChCfg + * 3 | 0 | no | aacChannels || 0 + * ---+-------+-----+--------+------------------ + * Where chCfg is the channel configuration index from ASC and cChCfg is a + * corresponding chCfg derived from a given PCE. The variable aacChannels + * represents the number of channel found during bitstream decoding. Due to + * the structure of the mapping table it can only be used for mapping if its + * value is smaller than 7. Otherwise we use the fallback (0) which is a + * simple pass-through. The possibility #3 should appear only with MPEG-2 + * (ADTS) streams. This is mode is called "implicit channel mapping". + */ + if ((self->streamInfo.channelConfig == 0) && !pce->isValid) { + self->chMapIndex = (aacChannels < 7) ? aacChannels : 0; + } + + /* + Inverse transform + */ + { + int c, cIdx; + int mapped, fCopyChMap = 1; + UCHAR drcChMap[(8)]; + + if ((self->streamInfo.channelConfig == 0) && CProgramConfig_IsValid(pce)) { + /* ISO/IEC 14496-3 says: + If a PCE is present, the exclude_mask bits correspond to the audio + channels in the SCE, CPE, CCE and LFE syntax elements in the order of + their appearance in the PCE. In the case of a CPE, the first + transmitted mask bit corresponds to the first channel in the CPE, the + second transmitted mask bit to the second channel. In the case of a + CCE, a mask bit is transmitted only if the coupling channel is + specified to be an independently switched coupling channel. Thus we + have to convert the internal channel mapping from "canonical" MPEG to + PCE order: */ + UCHAR tmpChMap[(8)]; + if (CProgramConfig_GetPceChMap(pce, tmpChMap, (8)) == 0) { + for (c = 0; c < aacChannels; c += 1) { + drcChMap[c] = + (self->chMapping[c] == 255) ? 255 : tmpChMap[self->chMapping[c]]; + } + fCopyChMap = 0; + } + } + if (fCopyChMap != 0) { + FDKmemcpy(drcChMap, self->chMapping, (8) * sizeof(UCHAR)); + } + + /* Turn on/off DRC modules level normalization in digital domain depending + * on the limiter status. */ + aacDecoder_drcSetParam(self->hDrcInfo, APPLY_NORMALIZATION, + (self->limiterEnableCurr) ? 0 : 1); + + /* deactivate legacy DRC in case uniDrc is active, i.e. uniDrc payload is + * present and one of DRC or Loudness Normalization is switched on */ + aacDecoder_drcSetParam( + self->hDrcInfo, UNIDRC_PRECEDENCE, + FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)); + + /* Extract DRC control data and map it to channels (without bitstream delay) + */ + mapped = aacDecoder_drcProlog( + self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo, + pce->ElementInstanceTag, drcChMap, aacChannels); + if (mapped > 0) { + /* If at least one DRC thread has been mapped to a channel threre was DRC + * data in the bitstream. */ + self->flags[streamIndex] |= AC_DRC_PRESENT; + } + + /* Create a reverse mapping table */ + UCHAR Reverse_chMapping[((8) * 2)]; + for (c = 0; c < aacChannels; c++) { + int d; + for (d = 0; d < aacChannels - 1; d++) { + if (self->chMapping[d] == c) { + break; + } + } + Reverse_chMapping[c] = d; + } + + int el; + int el_channels; + c = 0; + cIdx = 0; + el_channels = 0; + for (el = 0; el < element_count; el++) { + int frameOk_butConceal = + 0; /* Force frame concealment during mute release active state. */ + int concealApplyReturnCode; + + if (self->flags[streamIndex] & (AC_USAC | AC_RSV603DA | AC_BSAC)) { + type = self->elements[el]; + } else { + type = channel_elements[el]; + } + + { + int nElementChannels; + + nElementChannels = + CAacDecoder_GetELChannels(type, self->usacStereoConfigIndex[el]); + + el_channels += nElementChannels; + + if (nElementChannels == 0) { + continue; + } + } + + int offset; + int elCh = 0; + /* "c" iterates in canonical MPEG channel order */ + for (; cIdx < el_channels; c++, cIdx++, elCh++) { + /* Robustness check */ + if (c >= aacChannels) { + return AAC_DEC_UNKNOWN; + } + + CAacDecoderChannelInfo *pAacDecoderChannelInfo = + self->pAacDecoderChannelInfo[c]; + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo = + self->pAacDecoderStaticChannelInfo[c]; + + /* Setup offset for time buffer traversal. */ + { + pAacDecoderStaticChannelInfo = + self->pAacDecoderStaticChannelInfo[Reverse_chMapping[c]]; + offset = + FDK_chMapDescr_getMapValue( + &self->mapDescr, Reverse_chMapping[cIdx], self->chMapIndex) * + timeDataChannelOffset; + } + + if (flags & AACDEC_FLUSH) { + /* Clear pAacDecoderChannelInfo->pSpectralCoefficient because with + * AACDEC_FLUSH set it contains undefined data. */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, + sizeof(FIXP_DBL) * self->streamInfo.aacSamplesPerFrame); + } + + /* if The ics info is not valid and it will be stored and used in the + * following concealment method, mark the frame as erroneous */ + { + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + CConcealmentInfo *hConcealmentInfo = + &pAacDecoderStaticChannelInfo->concealmentInfo; + const int mute_release_active = + (self->frameOK && !(flags & AACDEC_CONCEAL)) && + ((hConcealmentInfo->concealState >= ConcealState_Mute) && + (hConcealmentInfo->cntValidFrames + 1 <= + hConcealmentInfo->pConcealParams->numMuteReleaseFrames)); + const int icsIsInvalid = (GetScaleFactorBandsTransmitted(pIcsInfo) > + GetScaleFactorBandsTotal(pIcsInfo)); + const int icsInfoUsedinFadeOut = + !(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderStaticChannelInfo->last_lpd_mode == 0); + if (icsInfoUsedinFadeOut && icsIsInvalid && !mute_release_active) { + self->frameOK = 0; + } + } + + /* + Conceal defective spectral data + */ + { + CAacDecoderChannelInfo **ppAacDecoderChannelInfo = + &pAacDecoderChannelInfo; + CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo = + &pAacDecoderStaticChannelInfo; + { + concealApplyReturnCode = CConcealment_Apply( + &(*ppAacDecoderStaticChannelInfo)->concealmentInfo, + *ppAacDecoderChannelInfo, *ppAacDecoderStaticChannelInfo, + &self->samplingRateInfo[streamIndex], + self->streamInfo.aacSamplesPerFrame, + pAacDecoderStaticChannelInfo->last_lpd_mode, + (self->frameOK && !(flags & AACDEC_CONCEAL)), + self->flags[streamIndex]); + } + } + if (concealApplyReturnCode == -1) { + frameOk_butConceal = 1; + } + + if (flags & (AACDEC_INTR)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData(&pAacDecoderStaticChannelInfo->drcData); + } + if (flags & (AACDEC_CLRHIST)) { + if (!(self->flags[0] & AC_USAC)) { + /* Reset DRC control data for this channel */ + aacDecoder_drcInitChannelData( + &pAacDecoderStaticChannelInfo->drcData); + } + } + /* The DRC module demands to be called with the gain field holding the + * gain scale. */ + self->extGain[0] = (FIXP_DBL)TDL_GAIN_SCALING; + /* DRC processing */ + aacDecoder_drcApply( + self->hDrcInfo, self->hSbrDecoder, pAacDecoderChannelInfo, + &pAacDecoderStaticChannelInfo->drcData, self->extGain, c, + self->streamInfo.aacSamplesPerFrame, self->sbrEnabled + + ); + + if (timeDataSize < timeDataChannelOffset * self->aacChannels) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + break; + } + if (self->flushStatus && (self->flushCnt > 0) && + !(flags & AACDEC_CONCEAL)) { + FDKmemclear(pTimeData + offset, + sizeof(FIXP_PCM) * self->streamInfo.aacSamplesPerFrame); + } else + switch (pAacDecoderChannelInfo->renderMode) { + case AACDEC_RENDER_IMDCT: + + CBlock_FrequencyToTime( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame, + (self->frameOK && !(flags & AACDEC_CONCEAL) && + !frameOk_butConceal), + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1 + ->mdctOutTemp, + self->elFlags[el], elCh); + + self->extGainDelay = self->streamInfo.aacSamplesPerFrame; + break; + case AACDEC_RENDER_ELDFB: { + CBlock_FrequencyToTimeLowDelay( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame); + self->extGainDelay = + (self->streamInfo.aacSamplesPerFrame * 2 - + self->streamInfo.aacSamplesPerFrame / 2 - 1) / + 2; + } break; + case AACDEC_RENDER_LPD: + + CLpd_RenderTimeSignal( + pAacDecoderStaticChannelInfo, pAacDecoderChannelInfo, + pTimeData + offset, self->streamInfo.aacSamplesPerFrame, + &self->samplingRateInfo[streamIndex], + (self->frameOK && !(flags & AACDEC_CONCEAL) && + !frameOk_butConceal), + flags, self->flags[streamIndex]); + + self->extGainDelay = self->streamInfo.aacSamplesPerFrame; + break; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + break; + } + /* TimeDomainFading */ + if (!CConceal_TDFading_Applied[c]) { + CConceal_TDFading_Applied[c] = CConcealment_TDFading( + self->streamInfo.aacSamplesPerFrame, + &self->pAacDecoderStaticChannelInfo[c], pTimeData + offset, 0); + if (c + 1 < (8) && c < aacChannels - 1) { + /* update next TDNoise Seed to avoid muting in case of Parametric + * Stereo */ + self->pAacDecoderStaticChannelInfo[c + 1] + ->concealmentInfo.TDNoiseSeed = + self->pAacDecoderStaticChannelInfo[c] + ->concealmentInfo.TDNoiseSeed; + } + } + } + } + + if (self->flags[streamIndex] & AC_USAC) { + int bsPseudoLr = 0; + mpegSurroundDecoder_IsPseudoLR( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, &bsPseudoLr); + /* ISO/IEC 23003-3, 7.11.2.6 Modification of core decoder output (pseudo + * LR) */ + if ((aacChannels == 2) && bsPseudoLr) { + int i, offset2; + const FIXP_SGL invSqrt2 = FL2FXCONST_SGL(0.707106781186547f); + FIXP_PCM *pTD = pTimeData; + + offset2 = timeDataChannelOffset; + + for (i = 0; i < self->streamInfo.aacSamplesPerFrame; i++) { + FIXP_DBL L = FX_PCM2FX_DBL(pTD[0]); + FIXP_DBL R = FX_PCM2FX_DBL(pTD[offset2]); + L = fMult(L, invSqrt2); + R = fMult(R, invSqrt2); +#if (SAMPLE_BITS == 16) + pTD[0] = FX_DBL2FX_PCM(fAddSaturate(L + R, (FIXP_DBL)0x8000)); + pTD[offset2] = FX_DBL2FX_PCM(fAddSaturate(L - R, (FIXP_DBL)0x8000)); +#else + pTD[0] = FX_DBL2FX_PCM(L + R); + pTD[offset2] = FX_DBL2FX_PCM(L - R); +#endif + pTD++; + } + } + } + + /* Extract DRC control data and map it to channels (with bitstream delay) */ + mapped = aacDecoder_drcEpilog( + self->hDrcInfo, bs, self->pAacDecoderStaticChannelInfo, + pce->ElementInstanceTag, drcChMap, aacChannels); + if (mapped > 0) { + /* If at least one DRC thread has been mapped to a channel threre was DRC + * data in the bitstream. */ + self->flags[streamIndex] |= AC_DRC_PRESENT; + } + } + + /* Add additional concealment delay */ + self->streamInfo.outputDelay += + CConcealment_GetDelay(&self->concealCommonData) * + self->streamInfo.aacSamplesPerFrame; + + /* Map DRC data to StreamInfo structure */ + aacDecoder_drcGetInfo(self->hDrcInfo, &self->streamInfo.drcPresMode, + &self->streamInfo.drcProgRefLev); + + /* Reorder channel type information tables. */ + if (!(self->flags[0] & AC_RSV603DA)) { + AUDIO_CHANNEL_TYPE types[(8)]; + UCHAR idx[(8)]; + int c; + int mapValue; + + FDK_ASSERT(sizeof(self->channelType) == sizeof(types)); + FDK_ASSERT(sizeof(self->channelIndices) == sizeof(idx)); + + FDKmemcpy(types, self->channelType, sizeof(types)); + FDKmemcpy(idx, self->channelIndices, sizeof(idx)); + + for (c = 0; c < aacChannels; c++) { + mapValue = + FDK_chMapDescr_getMapValue(&self->mapDescr, c, self->chMapIndex); + self->channelType[mapValue] = types[c]; + self->channelIndices[mapValue] = idx[c]; + } + } + + self->blockNumber++; + + return ErrorStatus; +} + +/*! + \brief returns the streaminfo pointer + + The function hands back a pointer to the streaminfo structure + + \return pointer to the struct +*/ +LINKSPEC_CPP CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self) { + if (!self) { + return NULL; + } + return &self->streamInfo; +} diff --git a/fdk-aac/libAACdec/src/aacdecoder.h b/fdk-aac/libAACdec/src/aacdecoder.h new file mode 100644 index 0000000..20f4c45 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdecoder.h @@ -0,0 +1,465 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef AACDECODER_H +#define AACDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" + +#include "channel.h" + +#include "tpdec_lib.h" +#include "FDK_audio.h" + +#include "block.h" + +#include "genericStds.h" + +#include "FDK_qmf_domain.h" + +#include "sbrdecoder.h" + +#include "aacdec_drc.h" + +#include "pcmdmx_lib.h" + +#include "FDK_drcDecLib.h" + +#include "limiter.h" + +#include "FDK_delay.h" + +#define TIME_DATA_FLUSH_SIZE (128) +#define TIME_DATA_FLUSH_SIZE_SF (7) + +#define AACDEC_MAX_NUM_PREROLL_AU_USAC (3) +#if (AACDEC_MAX_NUM_PREROLL_AU < 3) +#undef AACDEC_MAX_NUM_PREROLL_AU +#define AACDEC_MAX_NUM_PREROLL_AU AACDEC_MAX_NUM_PREROLL_AU_USAC +#endif + +typedef struct AAC_DECODER_INSTANCE *HANDLE_AACDECODER; + +enum { L = 0, R = 1 }; + +typedef struct { + unsigned char *buffer; + int bufferSize; + int offset[8]; + int nrElements; +} CAncData; + +typedef enum { NOT_DEFINED = -1, MODE_HQ = 0, MODE_LP = 1 } QMF_MODE; + +typedef struct { + int bsDelay; +} SBR_PARAMS; + +enum { + AACDEC_FLUSH_OFF = 0, + AACDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + AACDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + AACDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + AACDEC_BUILD_UP_OFF = 0, + AACDEC_RSV60_BUILD_UP_ON = 1, + AACDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + AACDEC_USAC_BUILD_UP_ON = 3, + AACDEC_RSV60_BUILD_UP_IDLE = 4, + AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +typedef struct { + /* Usac Extension Elements */ + USAC_EXT_ELEMENT_TYPE usacExtElementType[(3)]; + UINT usacExtElementDefaultLength[(3)]; + UCHAR usacExtElementPayloadFrag[(3)]; +} CUsacCoreExtensions; + +/* AAC decoder (opaque toward userland) struct declaration */ +struct AAC_DECODER_INSTANCE { + INT aacChannels; /*!< Amount of AAC decoder channels allocated. */ + INT ascChannels[(1 * + 1)]; /*!< Amount of AAC decoder channels signalled in ASC. */ + INT blockNumber; /*!< frame counter */ + + INT nrOfLayers; + + INT outputInterleaved; /*!< PCM output format (interleaved/none interleaved). + */ + + HANDLE_TRANSPORTDEC hInput; /*!< Transport layer handle. */ + + SamplingRateInfo + samplingRateInfo[(1 * 1)]; /*!< Sampling Rate information table */ + + UCHAR + frameOK; /*!< Will be unset if a consistency check, e.g. CRC etc. fails */ + + UINT flags[(1 * 1)]; /*!< Flags for internal decoder use. DO NOT USE + self::streaminfo::flags ! */ + UINT elFlags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Flags for internal decoder use (element specific). DO + NOT USE self::streaminfo::flags ! */ + + MP4_ELEMENT_ID elements[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Table where the element Id's are listed */ + UCHAR elTags[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Table where the elements id Tags are listed */ + UCHAR chMapping[((8) * 2)]; /*!< Table of MPEG canonical order to bitstream + channel order mapping. */ + + AUDIO_CHANNEL_TYPE channelType[(8)]; /*!< Audio channel type of each output + audio channel (from 0 upto + numChannels). */ + UCHAR channelIndices[(8)]; /*!< Audio channel index for each output audio + channel (from 0 upto numChannels). */ + /* See ISO/IEC 13818-7:2005(E), 8.5.3.2 Explicit channel mapping using a + * program_config_element() */ + + FDK_channelMapDescr mapDescr; /*!< Describes the output channel mapping. */ + UCHAR chMapIndex; /*!< Index to access one line of the channelOutputMapping + table. This is required because not all 8 channel + configurations have the same output mapping. */ + INT sbrDataLen; /*!< Expected length of the SBR remaining in bitbuffer after + the AAC payload has been pared. */ + + CProgramConfig pce; + CStreamInfo + streamInfo; /*!< Pointer to StreamInfo data (read from the bitstream) */ + CAacDecoderChannelInfo + *pAacDecoderChannelInfo[(8)]; /*!< Temporal channel memory */ + CAacDecoderStaticChannelInfo + *pAacDecoderStaticChannelInfo[(8)]; /*!< Persistent channel memory */ + + FIXP_DBL *workBufferCore2; + PCM_DEC *pTimeData2; + INT timeData2Size; + + CpePersistentData *cpeStaticData[( + 3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + + 1)]; /*!< Pointer to persistent data shared by both channels of a CPE. +This structure is allocated once for each CPE. */ + + CConcealParams concealCommonData; + CConcealmentMethod concealMethodUser; + + CUsacCoreExtensions usacCoreExt; /*!< Data and handles to extend USAC FD/LPD + core decoder (SBR, MPS, ...) */ + UINT numUsacElements[(1 * 1)]; + UCHAR usacStereoConfigIndex[(3 * ((8) * 2) + (((8) * 2)) / 2 + 4 * (1) + 1)]; + const CSUsacConfig *pUsacConfig[(1 * 1)]; + INT nbDiv; /*!< number of frame divisions in LPD-domain */ + + UCHAR useLdQmfTimeAlign; + + INT aacChannelsPrev; /*!< The amount of AAC core channels of the last + successful decode call. */ + AUDIO_CHANNEL_TYPE channelTypePrev[(8)]; /*!< Array holding the channelType + values of the last successful + decode call. */ + UCHAR + channelIndicesPrev[(8)]; /*!< Array holding the channelIndices values of + the last successful decode call. */ + + UCHAR + downscaleFactor; /*!< Variable to store a supported ELD downscale factor + of 1, 2, 3 or 4 */ + UCHAR downscaleFactorInBS; /*!< Variable to store the (not necessarily + supported) ELD downscale factor discovered in + the bitstream */ + + HANDLE_SBRDECODER hSbrDecoder; /*!< SBR decoder handle. */ + UCHAR sbrEnabled; /*!< flag to store if SBR has been detected */ + UCHAR sbrEnabledPrev; /*!< flag to store if SBR has been detected from + previous frame */ + UCHAR psPossible; /*!< flag to store if PS is possible */ + SBR_PARAMS sbrParams; /*!< struct to store all sbr parameters */ + + UCHAR *pDrmBsBuffer; /*!< Pointer to dynamic buffer which is used to reverse + the bits of the DRM SBR payload */ + USHORT drmBsBufferSize; /*!< Size of the dynamic buffer which is used to + reverse the bits of the DRM SBR payload */ + FDK_QMF_DOMAIN + qmfDomain; /*!< Instance of module for QMF domain data handling */ + + QMF_MODE qmfModeCurr; /*!< The current QMF mode */ + QMF_MODE qmfModeUser; /*!< The QMF mode requested by the library user */ + + HANDLE_AAC_DRC hDrcInfo; /*!< handle to DRC data structure */ + INT metadataExpiry; /*!< Metadata expiry time in milli-seconds. */ + + void *pMpegSurroundDecoder; /*!< pointer to mpeg surround decoder structure */ + UCHAR mpsEnableUser; /*!< MPS enable user flag */ + UCHAR mpsEnableCurr; /*!< MPS enable decoder state */ + UCHAR mpsApplicable; /*!< MPS applicable */ + SCHAR mpsOutputMode; /*!< setting: normal = 0, binaural = 1, stereo = 2, 5.1ch + = 3 */ + INT mpsOutChannelsLast; /*!< The amount of channels returned by the last + successful MPS decoder call. */ + INT mpsFrameSizeLast; /*!< The frame length returned by the last successful + MPS decoder call. */ + + CAncData ancData; /*!< structure to handle ancillary data */ + + HANDLE_PCM_DOWNMIX hPcmUtils; /*!< privat data for the PCM utils. */ + + TDLimiterPtr hLimiter; /*!< Handle of time domain limiter. */ + UCHAR limiterEnableUser; /*!< The limiter configuration requested by the + library user */ + UCHAR limiterEnableCurr; /*!< The current limiter configuration. */ + FIXP_DBL extGain[1]; /*!< Gain that must be applied to the output signal. */ + UINT extGainDelay; /*!< Delay that must be accounted for extGain. */ + + INT_PCM pcmOutputBuffer[(8) * (1024 * 2)]; + + HANDLE_DRC_DECODER hUniDrcDecoder; + UCHAR multibandDrcPresent; + UCHAR numTimeSlots; + UINT loudnessInfoSetPosition[3]; + SCHAR defaultTargetLoudness; + + INT_PCM + *pTimeDataFlush[((8) * 2)]; /*!< Pointer to the flushed time data which + will be used for the crossfade in case of + an USAC DASH IPF config change */ + + UCHAR flushStatus; /*!< Indicates flush status: on|off */ + SCHAR flushCnt; /*!< Flush frame counter */ + UCHAR buildUpStatus; /*!< Indicates build up status: on|off */ + SCHAR buildUpCnt; /*!< Build up frame counter */ + UCHAR hasAudioPreRoll; /*!< Indicates preRoll status: on|off */ + UINT prerollAULength[AACDEC_MAX_NUM_PREROLL_AU + 1]; /*!< Relative offset of + the prerollAU end + position to the AU + start position in the + bitstream */ + INT accessUnit; /*!< Number of the actual processed preroll accessUnit */ + UCHAR applyCrossfade; /*!< if set crossfade for seamless stream switching is + applied */ + + FDK_SignalDelay usacResidualDelay; /*!< Delay residual signal to compensate + for eSBR delay of DMX signal in case of + stereoConfigIndex==2. */ +}; + +#define AAC_DEBUG_EXTHLP \ + "\ +--- AAC-Core ---\n\ + 0x00010000 Header data\n\ + 0x00020000 CRC data\n\ + 0x00040000 Channel info\n\ + 0x00080000 Section data\n\ + 0x00100000 Scalefactor data\n\ + 0x00200000 Pulse data\n\ + 0x00400000 Tns data\n\ + 0x00800000 Quantized spectrum\n\ + 0x01000000 Requantized spectrum\n\ + 0x02000000 Time output\n\ + 0x04000000 Fatal errors\n\ + 0x08000000 Buffer fullness\n\ + 0x10000000 Average bitrate\n\ + 0x20000000 Synchronization\n\ + 0x40000000 Concealment\n\ + 0x7FFF0000 all AAC-Core-Info\n\ +" + +/** + * \brief Synchronise QMF mode for all modules using QMF data. + * \param self decoder handle + */ +void CAacDecoder_SyncQmfMode(HANDLE_AACDECODER self); + +/** + * \brief Signal a bit stream interruption to the decoder + * \param self decoder handle + */ +void CAacDecoder_SignalInterruption(HANDLE_AACDECODER self); + +/*! + \brief Initialize ancillary buffer + + \ancData Pointer to ancillary data structure + \buffer Pointer to (external) anc data buffer + \size Size of the buffer pointed on by buffer + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataInit(CAncData *ancData, + unsigned char *buffer, int size); + +/*! + \brief Get one ancillary data element + + \ancData Pointer to ancillary data structure + \index Index of the anc data element to get + \ptr Pointer to a buffer receiving a pointer to the requested anc data element + \size Pointer to a buffer receiving the length of the requested anc data + element + + \return Error code +*/ +AAC_DECODER_ERROR CAacDecoder_AncDataGet(CAncData *ancData, int index, + unsigned char **ptr, int *size); + +/* initialization of aac decoder */ +LINKSPEC_H HANDLE_AACDECODER CAacDecoder_Open(TRANSPORT_TYPE bsFormat); + +/* Initialization of channel elements */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_Init(HANDLE_AACDECODER self, + const CSAudioSpecificConfig *asc, + UCHAR configMode, + UCHAR *configChanged); +/*! + \brief Decodes one aac frame + + The function decodes one aac frame. The decoding of coupling channel + elements are not supported. The transport layer might signal, that the + data of the current frame is invalid, e.g. as a result of a packet + loss in streaming mode. + The bitstream position of transportDec_GetBitstream(self->hInput) must + be exactly the end of the access unit, including all byte alignment bits. + For this purpose, the variable auStartAnchor is used. + + \return error status +*/ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_DecodeFrame( + HANDLE_AACDECODER self, const UINT flags, FIXP_PCM *pTimeData, + const INT timeDataSize, const int timeDataChannelOffset); + +/* Free config dependent AAC memory */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_FreeMem(HANDLE_AACDECODER self, + const int subStreamIndex); + +/* Prepare crossfade for USAC DASH IPF config change */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PrepareCrossFade( + const INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved); + +/* Apply crossfade for USAC DASH IPF config change */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_ApplyCrossFade( + INT_PCM *pTimeData, INT_PCM **pTimeDataFlush, const INT numChannels, + const INT frameSize, const INT interleaved); + +/* Set flush and build up mode */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_CtrlCFGChange(HANDLE_AACDECODER self, + UCHAR flushStatus, + SCHAR flushCnt, + UCHAR buildUpStatus, + SCHAR buildUpCnt); + +/* Parse preRoll Extension Payload */ +LINKSPEC_H AAC_DECODER_ERROR CAacDecoder_PreRollExtensionPayloadParse( + HANDLE_AACDECODER self, UINT *numPrerollAU, UINT *prerollAUOffset, + UINT *prerollAULength); + +/* Destroy aac decoder */ +LINKSPEC_H void CAacDecoder_Close(HANDLE_AACDECODER self); + +/* get streaminfo handle from decoder */ +LINKSPEC_H CStreamInfo *CAacDecoder_GetStreamInfo(HANDLE_AACDECODER self); + +#endif /* #ifndef AACDECODER_H */ diff --git a/fdk-aac/libAACdec/src/aacdecoder_lib.cpp b/fdk-aac/libAACdec/src/aacdecoder_lib.cpp new file mode 100644 index 0000000..7df17b9 --- /dev/null +++ b/fdk-aac/libAACdec/src/aacdecoder_lib.cpp @@ -0,0 +1,2035 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +#include "aacdecoder_lib.h" + +#include "aac_ram.h" +#include "aacdecoder.h" +#include "tpdec_lib.h" +#include "FDK_core.h" /* FDK_tools version info */ + +#include "sbrdecoder.h" + +#include "conceal.h" + +#include "aacdec_drc.h" + +#include "sac_dec_lib.h" + +#include "pcm_utils.h" + +/* Decoder library info */ +#define AACDECODER_LIB_VL0 3 +#define AACDECODER_LIB_VL1 0 +#define AACDECODER_LIB_VL2 0 +#define AACDECODER_LIB_TITLE "AAC Decoder Lib" +#ifdef __ANDROID__ +#define AACDECODER_LIB_BUILD_DATE "" +#define AACDECODER_LIB_BUILD_TIME "" +#else +#define AACDECODER_LIB_BUILD_DATE __DATE__ +#define AACDECODER_LIB_BUILD_TIME __TIME__ +#endif + +static AAC_DECODER_ERROR setConcealMethod(const HANDLE_AACDECODER self, + const INT method); + +static void aacDecoder_setMetadataExpiry(const HANDLE_AACDECODER self, + const INT value) { + /* check decoder handle */ + if (self != NULL) { + INT mdExpFrame = 0; /* default: disable */ + + if ((value > 0) && + (self->streamInfo.aacSamplesPerFrame > + 0)) { /* Determine the corresponding number of frames: */ + FIXP_DBL frameTime = fDivNorm(self->streamInfo.aacSampleRate, + self->streamInfo.aacSamplesPerFrame * 1000); + mdExpFrame = fMultIceil(frameTime, value); + } + + /* Configure DRC module */ + aacDecoder_drcSetParam(self->hDrcInfo, DRC_DATA_EXPIRY_FRAME, mdExpFrame); + + /* Configure PCM downmix module */ + pcmDmx_SetParam(self->hPcmUtils, DMX_BS_DATA_EXPIRY_FRAME, mdExpFrame); + } +} + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_GetFreeBytes(const HANDLE_AACDECODER self, UINT *pFreeBytes) { + /* reset free bytes */ + *pFreeBytes = 0; + + /* check handle */ + if (!self) return AAC_DEC_INVALID_HANDLE; + + /* return nr of free bytes */ + HANDLE_FDK_BITSTREAM hBs = transportDec_GetBitstream(self->hInput, 0); + *pFreeBytes = FDKgetFreeBits(hBs) >> 3; + + /* success */ + return AAC_DEC_OK; +} + +/** + * Config Decoder using a CSAudioSpecificConfig struct. + */ +static LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Config( + HANDLE_AACDECODER self, const CSAudioSpecificConfig *pAscStruct, + UCHAR configMode, UCHAR *configChanged) { + AAC_DECODER_ERROR err; + + /* Initialize AAC core decoder, and update self->streaminfo */ + err = CAacDecoder_Init(self, pAscStruct, configMode, configChanged); + + if (!FDK_chMapDescr_isValid(&self->mapDescr)) { + return AAC_DEC_UNSUPPORTED_CHANNELCONFIG; + } + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_ConfigRaw(HANDLE_AACDECODER self, + UCHAR *conf[], + const UINT length[]) { + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + UINT layer, nrOfLayers = self->nrOfLayers; + + for (layer = 0; layer < nrOfLayers; layer++) { + if (length[layer] > 0) { + errTp = transportDec_OutOfBandConfig(self->hInput, conf[layer], + length[layer], layer); + if (errTp != TRANSPORTDEC_OK) { + switch (errTp) { + case TRANSPORTDEC_NEED_TO_RESTART: + err = AAC_DEC_NEED_TO_RESTART; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + err = AAC_DEC_UNSUPPORTED_FORMAT; + break; + default: + err = AAC_DEC_UNKNOWN; + break; + } + /* if baselayer is OK we continue decoding */ + if (layer >= 1) { + self->nrOfLayers = layer; + err = AAC_DEC_OK; + } + break; + } + } + } + + return err; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_RawISOBMFFData(HANDLE_AACDECODER self, + UCHAR *buffer, + UINT length) { + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + AAC_DECODER_ERROR err = AAC_DEC_OK; + + if (length < 8) return AAC_DEC_UNKNOWN; + + while (length >= 8) { + UINT size = + (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; + DRC_DEC_ERROR uniDrcErr = DRC_DEC_OK; + + if (length < size) return AAC_DEC_UNKNOWN; + if (size <= 8) return AAC_DEC_UNKNOWN; + + FDKinitBitStream(hBs, buffer + 8, 0x10000000, (size - 8) * 8); + + if ((buffer[4] == 'l') && (buffer[5] == 'u') && (buffer[6] == 'd') && + (buffer[7] == 't')) { + uniDrcErr = FDK_drcDec_ReadLoudnessBox(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'd') && (buffer[5] == 'm') && (buffer[6] == 'i') && + (buffer[7] == 'x')) { + uniDrcErr = + FDK_drcDec_ReadDownmixInstructions_Box(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'u') && (buffer[5] == 'd') && (buffer[6] == 'i') && + (buffer[7] == '2')) { + uniDrcErr = + FDK_drcDec_ReadUniDrcInstructions_Box(self->hUniDrcDecoder, hBs); + } else if ((buffer[4] == 'u') && (buffer[5] == 'd') && (buffer[6] == 'c') && + (buffer[7] == '2')) { + uniDrcErr = + FDK_drcDec_ReadUniDrcCoefficients_Box(self->hUniDrcDecoder, hBs); + } + + if (uniDrcErr != DRC_DEC_OK) err = AAC_DEC_UNKNOWN; + + buffer += size; + length -= size; + } + + return err; +} + +static INT aacDecoder_ConfigCallback(void *handle, + const CSAudioSpecificConfig *pAscStruct, + UCHAR configMode, UCHAR *configChanged) { + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + AAC_DECODER_ERROR err = AAC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + + FDK_ASSERT(self != NULL); + { + { err = aacDecoder_Config(self, pAscStruct, configMode, configChanged); } + } + if (err == AAC_DEC_OK) { + /* + revert concealment method if either + - Interpolation concealment might not be meaningful + - Interpolation concealment is not implemented + */ + if ((self->flags[0] & (AC_LD | AC_ELD) && + (self->concealMethodUser == ConcealMethodNone) && + CConcealment_GetDelay(&self->concealCommonData) > + 0) /* might not be meaningful but allow if user has set it + expicitly */ + || (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && + CConcealment_GetDelay(&self->concealCommonData) > + 0) /* not implemented */ + ) { + /* Revert to error concealment method Noise Substitution. + Because interpolation is not implemented for USAC or + the additional delay is unwanted for low delay codecs. */ + setConcealMethod(self, 1); + } + aacDecoder_setMetadataExpiry(self, self->metadataExpiry); + errTp = TRANSPORTDEC_OK; + } else { + if (err == AAC_DEC_NEED_TO_RESTART) { + errTp = TRANSPORTDEC_NEED_TO_RESTART; + } else if (IS_INIT_ERROR(err)) { + errTp = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } /* Fatal errors */ + else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + return errTp; +} + +static INT aacDecoder_FreeMemCallback(void *handle, + const CSAudioSpecificConfig *pAscStruct) { + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + + const int subStreamIndex = 0; + + FDK_ASSERT(self != NULL); + + if (CAacDecoder_FreeMem(self, subStreamIndex) != AAC_DEC_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + /* free Ram_SbrDecoder and Ram_SbrDecChannel */ + if (self->hSbrDecoder != NULL) { + if (sbrDecoder_FreeMem(&self->hSbrDecoder) != SBRDEC_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + /* free pSpatialDec and mpsData */ + if (self->pMpegSurroundDecoder != NULL) { + if (mpegSurroundDecoder_FreeMem( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) != MPS_OK) { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + } + + /* free persistent qmf domain buffer, QmfWorkBufferCore3, QmfWorkBufferCore4, + * QmfWorkBufferCore5 and configuration variables */ + FDK_QmfDomain_FreeMem(&self->qmfDomain); + + return errTp; +} + +static INT aacDecoder_CtrlCFGChangeCallback( + void *handle, const CCtrlCFGChange *pCtrlCFGChangeStruct) { + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AACDECODER self = (HANDLE_AACDECODER)handle; + + if (self != NULL) { + CAacDecoder_CtrlCFGChange( + self, pCtrlCFGChangeStruct->flushStatus, pCtrlCFGChangeStruct->flushCnt, + pCtrlCFGChangeStruct->buildUpStatus, pCtrlCFGChangeStruct->buildUpCnt); + } else { + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + return errTp; +} + +static INT aacDecoder_SbrCallback( + void *handle, HANDLE_FDK_BITSTREAM hBs, const INT sampleRateIn, + const INT sampleRateOut, const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, const MP4_ELEMENT_ID elementID, + const INT elementIndex, const UCHAR harmonicSBR, + const UCHAR stereoConfigIndex, const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + HANDLE_SBRDECODER self = (HANDLE_SBRDECODER)handle; + + INT errTp = sbrDecoder_Header(self, hBs, sampleRateIn, sampleRateOut, + samplesPerFrame, coreCodec, elementID, + elementIndex, harmonicSBR, stereoConfigIndex, + configMode, configChanged, downscaleFactor); + + return errTp; +} + +static INT aacDecoder_SscCallback(void *handle, HANDLE_FDK_BITSTREAM hBs, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, + const INT configBytes, const UCHAR configMode, + UCHAR *configChanged) { + SACDEC_ERROR err; + TRANSPORTDEC_ERROR errTp; + HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle; + + err = mpegSurroundDecoder_Config( + (CMpegSurroundDecoder *)hAacDecoder->pMpegSurroundDecoder, hBs, coreCodec, + samplingRate, frameSize, stereoConfigIndex, coreSbrFrameLengthIndex, + configBytes, configMode, configChanged); + + switch (err) { + case MPS_UNSUPPORTED_CONFIG: + /* MPS found but invalid or not decodable by this instance */ + /* We switch off MPS and keep going */ + hAacDecoder->mpsEnableCurr = 0; + hAacDecoder->mpsApplicable = 0; + errTp = TRANSPORTDEC_OK; + break; + case MPS_PARSE_ERROR: + /* MPS found but invalid or not decodable by this instance */ + hAacDecoder->mpsEnableCurr = 0; + hAacDecoder->mpsApplicable = 0; + if ((coreCodec == AOT_USAC) || (coreCodec == AOT_DRM_USAC) || + IS_LOWDELAY(coreCodec)) { + errTp = TRANSPORTDEC_PARSE_ERROR; + } else { + errTp = TRANSPORTDEC_OK; + } + break; + case MPS_OK: + hAacDecoder->mpsApplicable = 1; + errTp = TRANSPORTDEC_OK; + break; + default: + /* especially Parsing error is critical for transport layer */ + hAacDecoder->mpsApplicable = 0; + errTp = TRANSPORTDEC_UNKOWN_ERROR; + } + + return (INT)errTp; +} + +static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, + const INT payloadType, + const INT subStreamIndex, + const INT payloadStart, + const AUDIO_OBJECT_TYPE aot) { + DRC_DEC_ERROR err = DRC_DEC_OK; + TRANSPORTDEC_ERROR errTp; + HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle; + DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + + if (subStreamIndex != 0) { + return TRANSPORTDEC_OK; + } + + else if (aot == AOT_USAC) { + drcDecCodecMode = DRC_DEC_MPEG_D_USAC; + } + + err = FDK_drcDec_SetCodecMode(hAacDecoder->hUniDrcDecoder, drcDecCodecMode); + if (err) return (INT)TRANSPORTDEC_UNKOWN_ERROR; + + if (payloadType == 0) /* uniDrcConfig */ + { + err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hBs); + } else /* loudnessInfoSet */ + { + err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hBs); + hAacDecoder->loudnessInfoSetPosition[1] = payloadStart; + hAacDecoder->loudnessInfoSetPosition[2] = fullPayloadLength; + } + + if (err == DRC_DEC_OK) + errTp = TRANSPORTDEC_OK; + else + errTp = TRANSPORTDEC_UNKOWN_ERROR; + + return (INT)errTp; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_AncDataInit(HANDLE_AACDECODER self, + UCHAR *buffer, int size) { + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataInit(ancData, buffer, size); +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_AncDataGet(HANDLE_AACDECODER self, + int index, UCHAR **ptr, + int *size) { + CAncData *ancData = &self->ancData; + + return CAacDecoder_AncDataGet(ancData, index, ptr, size); +} + +/* If MPS is present in stream, but not supported by this instance, we'll + have to switch off MPS and use QMF synthesis in the SBR module if required */ +static int isSupportedMpsConfig(AUDIO_OBJECT_TYPE aot, + unsigned int numInChannels, + unsigned int fMpsPresent) { + LIB_INFO libInfo[FDK_MODULE_LAST]; + UINT mpsCaps; + int isSupportedCfg = 1; + + FDKinitLibInfo(libInfo); + + mpegSurroundDecoder_GetLibInfo(libInfo); + + mpsCaps = FDKlibInfo_getCapabilities(libInfo, FDK_MPSDEC); + + if (!(mpsCaps & CAPF_MPS_LD) && IS_LOWDELAY(aot)) { + /* We got an LD AOT but MPS decoder does not support LD. */ + isSupportedCfg = 0; + } + if ((mpsCaps & CAPF_MPS_LD) && IS_LOWDELAY(aot) && !fMpsPresent) { + /* We got an LD AOT and the MPS decoder supports it. + * But LD-MPS is not explicitly signaled. */ + isSupportedCfg = 0; + } + if (!(mpsCaps & CAPF_MPS_USAC) && IS_USAC(aot)) { + /* We got an USAC AOT but MPS decoder does not support USAC. */ + isSupportedCfg = 0; + } + if (!(mpsCaps & CAPF_MPS_STD) && !IS_LOWDELAY(aot) && !IS_USAC(aot)) { + /* We got an GA AOT but MPS decoder does not support it. */ + isSupportedCfg = 0; + } + /* Check whether the MPS modul supports the given number of input channels: */ + switch (numInChannels) { + case 1: + if (!(mpsCaps & CAPF_MPS_1CH_IN)) { + /* We got a one channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + case 2: + if (!(mpsCaps & CAPF_MPS_2CH_IN)) { + /* We got a two channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + case 5: + case 6: + if (!(mpsCaps & CAPF_MPS_6CH_IN)) { + /* We got a six channel input to MPS decoder but it does not support it. + */ + isSupportedCfg = 0; + } + break; + default: + isSupportedCfg = 0; + } + + return (isSupportedCfg); +} + +static AAC_DECODER_ERROR setConcealMethod( + const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const INT method) { + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + CConcealParams *pConcealData = NULL; + int method_revert = 0; + HANDLE_SBRDECODER hSbrDec = NULL; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + CConcealmentMethod backupMethod = ConcealMethodNone; + int backupDelay = 0; + int bsDelay = 0; + + /* check decoder handle */ + if (self != NULL) { + pConcealData = &self->concealCommonData; + hSbrDec = self->hSbrDecoder; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && method >= 2) { + /* Interpolation concealment is not implemented for USAC/RSVD50 */ + /* errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; */ + method_revert = 1; + } + if (self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && method >= 2) { + /* Interpolation concealment is not implemented for USAC/RSVD50 */ + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + /* Get current method/delay */ + backupMethod = CConcealment_GetMethod(pConcealData); + backupDelay = CConcealment_GetDelay(pConcealData); + + /* Be sure to set AAC and SBR concealment method simultaneously! */ + errorStatus = CConcealment_SetParams( + pConcealData, + (method_revert == 0) ? (int)method : (int)1, // concealMethod + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeOutSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealFadeInSlope + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, // concealMuteRelease + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED // concealComfNoiseLevel + ); + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + goto bail; + } + + /* Get new delay */ + bsDelay = CConcealment_GetDelay(pConcealData); + + { + SBR_ERROR sbrErr = SBRDEC_OK; + + /* set SBR bitstream delay */ + sbrErr = sbrDecoder_SetParam(hSbrDec, SBR_SYSTEM_BITSTREAM_DELAY, bsDelay); + + switch (sbrErr) { + case SBRDEC_OK: + case SBRDEC_NOT_INITIALIZED: + if (self != NULL) { + /* save the param value and set later + (when SBR has been initialized) */ + self->sbrParams.bsDelay = bsDelay; + } + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BS_DELAY, bsDelay); + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + goto bail; + } + + if (errorStatus == AAC_DEC_OK) { + PCMDMX_ERROR err = pcmDmx_SetParam(hPcmDmx, DMX_BS_DATA_DELAY, bsDelay); + switch (err) { + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + case PCMDMX_OK: + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } + +bail: + if ((errorStatus != AAC_DEC_OK) && (errorStatus != AAC_DEC_INVALID_HANDLE)) { + /* Revert to the initial state */ + CConcealment_SetParams( + pConcealData, (int)backupMethod, AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, AACDEC_CONCEAL_PARAM_NOT_SPECIFIED, + AACDEC_CONCEAL_PARAM_NOT_SPECIFIED); + /* Revert SBR bitstream delay */ + sbrDecoder_SetParam(hSbrDec, SBR_SYSTEM_BITSTREAM_DELAY, backupDelay); + /* Revert DRC bitstream delay */ + aacDecoder_drcSetParam(hDrcInfo, DRC_BS_DELAY, backupDelay); + /* Revert PCM mixdown bitstream delay */ + pcmDmx_SetParam(hPcmDmx, DMX_BS_DATA_DELAY, backupDelay); + } + + return errorStatus; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_SetParam( + const HANDLE_AACDECODER self, /*!< Handle of the decoder instance */ + const AACDEC_PARAM param, /*!< Parameter to set */ + const INT value) /*!< Parameter valued */ +{ + AAC_DECODER_ERROR errorStatus = AAC_DEC_OK; + HANDLE_TRANSPORTDEC hTpDec = NULL; + TRANSPORTDEC_ERROR errTp = TRANSPORTDEC_OK; + HANDLE_AAC_DRC hDrcInfo = NULL; + HANDLE_PCM_DOWNMIX hPcmDmx = NULL; + PCMDMX_ERROR dmxErr = PCMDMX_OK; + TDLimiterPtr hPcmTdl = NULL; + DRC_DEC_ERROR uniDrcErr = DRC_DEC_OK; + + /* check decoder handle */ + if (self != NULL) { + hTpDec = self->hInput; + hDrcInfo = self->hDrcInfo; + hPcmDmx = self->hPcmUtils; + hPcmTdl = self->hLimiter; + } else { + errorStatus = AAC_DEC_INVALID_HANDLE; + goto bail; + } + + /* configure the subsystems */ + switch (param) { + case AAC_PCM_MIN_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, MIN_NUMBER_OF_OUTPUT_CHANNELS, value); + break; + + case AAC_PCM_MAX_OUTPUT_CHANNELS: + if (value < -1 || value > (8)) { + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, MAX_NUMBER_OF_OUTPUT_CHANNELS, value); + + if (dmxErr != PCMDMX_OK) { + goto bail; + } + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, MAX_OUTPUT_CHANNELS, value); + if (value > 0) { + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, + DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED, + (FIXP_DBL)value); + } + break; + + case AAC_PCM_DUAL_CHANNEL_OUTPUT_MODE: + dmxErr = pcmDmx_SetParam(hPcmDmx, DMX_DUAL_CHANNEL_MODE, value); + break; + + case AAC_PCM_LIMITER_ENABLE: + if (value < -2 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + self->limiterEnableUser = value; + break; + + case AAC_PCM_LIMITER_ATTACK_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (pcmLimiter_SetAttack(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_PCM_LIMITER_RELEAS_TIME: + if (value <= 0) { /* module function converts value to unsigned */ + return AAC_DEC_SET_PARAM_FAIL; + } + switch (pcmLimiter_SetRelease(hPcmTdl, value)) { + case TDLIMIT_OK: + break; + case TDLIMIT_INVALID_HANDLE: + return AAC_DEC_INVALID_HANDLE; + case TDLIMIT_INVALID_PARAMETER: + default: + return AAC_DEC_SET_PARAM_FAIL; + } + break; + + case AAC_METADATA_PROFILE: { + DMX_PROFILE_TYPE dmxProfile; + INT mdExpiry = -1; /* in ms (-1: don't change) */ + + switch ((AAC_MD_PROFILE)value) { + case AAC_MD_PROFILE_MPEG_STANDARD: + dmxProfile = DMX_PRFL_STANDARD; + break; + case AAC_MD_PROFILE_MPEG_LEGACY: + dmxProfile = DMX_PRFL_MATRIX_MIX; + break; + case AAC_MD_PROFILE_MPEG_LEGACY_PRIO: + dmxProfile = DMX_PRFL_FORCE_MATRIX_MIX; + break; + case AAC_MD_PROFILE_ARIB_JAPAN: + dmxProfile = DMX_PRFL_ARIB_JAPAN; + mdExpiry = 550; /* ms */ + break; + default: + return AAC_DEC_SET_PARAM_FAIL; + } + dmxErr = pcmDmx_SetParam(hPcmDmx, DMX_PROFILE_SETTING, (INT)dmxProfile); + if (dmxErr != PCMDMX_OK) { + goto bail; + } + if ((self != NULL) && (mdExpiry >= 0)) { + self->metadataExpiry = mdExpiry; + /* Determine the corresponding number of frames and configure all + * related modules. */ + aacDecoder_setMetadataExpiry(self, mdExpiry); + } + } break; + + case AAC_METADATA_EXPIRY_TIME: + if (value < 0) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (self != NULL) { + self->metadataExpiry = value; + /* Determine the corresponding number of frames and configure all + * related modules. */ + aacDecoder_setMetadataExpiry(self, value); + } + break; + + case AAC_PCM_OUTPUT_CHANNEL_MAPPING: + if (value < 0 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + /* CAUTION: The given value must be inverted to match the logic! */ + FDK_chMapDescr_setPassThrough(&self->mapDescr, !value); + break; + + case AAC_QMF_LOWPOWER: + if (value < -1 || value > 1) { + return AAC_DEC_SET_PARAM_FAIL; + } + + /** + * Set QMF mode (might be overriden) + * 0:HQ (complex) + * 1:LP (partially complex) + */ + self->qmfModeUser = (QMF_MODE)value; + break; + + case AAC_DRC_ATTENUATION_FACTOR: + /* DRC compression factor (where 0 is no and 127 is max compression) */ + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_CUT_SCALE, value); + break; + + case AAC_DRC_BOOST_FACTOR: + /* DRC boost factor (where 0 is no and 127 is max boost) */ + errorStatus = aacDecoder_drcSetParam(hDrcInfo, DRC_BOOST_SCALE, value); + break; + + case AAC_DRC_REFERENCE_LEVEL: + if ((value >= 0) && + ((value < 40) || (value > 127))) /* allowed range: -10 to -31.75 dB */ + return AAC_DEC_SET_PARAM_FAIL; + /* DRC target reference level quantized in 0.25dB steps using values + [40..127]. Negative values switch off loudness normalisation. Negative + values also switch off MPEG-4 DRC, while MPEG-D DRC can be separately + switched on/off with AAC_UNIDRC_SET_EFFECT */ + errorStatus = aacDecoder_drcSetParam(hDrcInfo, TARGET_REF_LEVEL, value); + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, + DRC_DEC_LOUDNESS_NORMALIZATION_ON, + (FIXP_DBL)(value >= 0)); + /* set target loudness also for MPEG-D DRC */ + self->defaultTargetLoudness = (SCHAR)value; + break; + + case AAC_DRC_HEAVY_COMPRESSION: + /* Don't need to overwrite cut/boost values */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, APPLY_HEAVY_COMPRESSION, value); + break; + + case AAC_DRC_DEFAULT_PRESENTATION_MODE: + /* DRC default presentation mode */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, DEFAULT_PRESENTATION_MODE, value); + break; + + case AAC_DRC_ENC_TARGET_LEVEL: + /* Encoder target level for light (i.e. not heavy) compression: + Target reference level assumed at encoder for deriving limiting gains + */ + errorStatus = + aacDecoder_drcSetParam(hDrcInfo, ENCODER_TARGET_LEVEL, value); + break; + + case AAC_UNIDRC_SET_EFFECT: + if ((value < -1) || (value > 6)) return AAC_DEC_SET_PARAM_FAIL; + uniDrcErr = FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_EFFECT_TYPE, + (FIXP_DBL)value); + break; + case AAC_TPDEC_CLEAR_BUFFER: + errTp = transportDec_SetParam(hTpDec, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + /* aacDecoder_SignalInterruption(self); */ + break; + case AAC_CONCEAL_METHOD: + /* Changing the concealment method can introduce additional bitstream + delay. And that in turn affects sub libraries and modules which makes + the whole thing quite complex. So the complete changing routine is + packed into a helper function which keeps all modules and libs in a + consistent state even in the case an error occures. */ + errorStatus = setConcealMethod(self, value); + if (errorStatus == AAC_DEC_OK) { + self->concealMethodUser = (CConcealmentMethod)value; + } + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } /* switch(param) */ + +bail: + + if (errorStatus == AAC_DEC_OK) { + /* Check error code returned by DMX module library: */ + switch (dmxErr) { + case PCMDMX_OK: + break; + case PCMDMX_INVALID_HANDLE: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + } + } + + if (errTp != TRANSPORTDEC_OK && errorStatus == AAC_DEC_OK) { + errorStatus = AAC_DEC_SET_PARAM_FAIL; + } + + if (errorStatus == AAC_DEC_OK) { + /* Check error code returned by MPEG-D DRC decoder library: */ + switch (uniDrcErr) { + case 0: + break; + case -9998: + errorStatus = AAC_DEC_INVALID_HANDLE; + break; + default: + errorStatus = AAC_DEC_SET_PARAM_FAIL; + break; + } + } + + return (errorStatus); +} +LINKSPEC_CPP HANDLE_AACDECODER aacDecoder_Open(TRANSPORT_TYPE transportFmt, + UINT nrOfLayers) { + AAC_DECODER_INSTANCE *aacDec = NULL; + HANDLE_TRANSPORTDEC pIn; + int err = 0; + int stereoConfigIndex = -1; + + UINT nrOfLayers_min = fMin(nrOfLayers, (UINT)1); + + /* Allocate transport layer struct. */ + pIn = transportDec_Open(transportFmt, TP_FLAG_MPEG4, nrOfLayers_min); + if (pIn == NULL) { + return NULL; + } + + transportDec_SetParam(pIn, TPDEC_PARAM_IGNORE_BUFFERFULLNESS, 1); + + /* Allocate AAC decoder core struct. */ + aacDec = CAacDecoder_Open(transportFmt); + + if (aacDec == NULL) { + transportDec_Close(&pIn); + goto bail; + } + aacDec->hInput = pIn; + + aacDec->nrOfLayers = nrOfLayers_min; + + /* Setup channel mapping descriptor. */ + FDK_chMapDescr_init(&aacDec->mapDescr, NULL, 0, 0); + + /* Register Config Update callback. */ + transportDec_RegisterAscCallback(pIn, aacDecoder_ConfigCallback, + (void *)aacDec); + + /* Register Free Memory callback. */ + transportDec_RegisterFreeMemCallback(pIn, aacDecoder_FreeMemCallback, + (void *)aacDec); + + /* Register config switch control callback. */ + transportDec_RegisterCtrlCFGChangeCallback( + pIn, aacDecoder_CtrlCFGChangeCallback, (void *)aacDec); + + FDKmemclear(&aacDec->qmfDomain, sizeof(FDK_QMF_DOMAIN)); + /* open SBR decoder */ + if (SBRDEC_OK != sbrDecoder_Open(&aacDec->hSbrDecoder, &aacDec->qmfDomain)) { + err = -1; + goto bail; + } + aacDec->qmfModeUser = NOT_DEFINED; + transportDec_RegisterSbrCallback(aacDec->hInput, aacDecoder_SbrCallback, + (void *)aacDec->hSbrDecoder); + + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&aacDec->pMpegSurroundDecoder, + stereoConfigIndex, &aacDec->qmfDomain)) { + err = -1; + goto bail; + } + /* Set MPEG Surround defaults */ + aacDec->mpsEnableUser = 0; + aacDec->mpsEnableCurr = 0; + aacDec->mpsApplicable = 0; + aacDec->mpsOutputMode = (SCHAR)SACDEC_OUT_MODE_NORMAL; + transportDec_RegisterSscCallback(pIn, aacDecoder_SscCallback, (void *)aacDec); + + { + if (FDK_drcDec_Open(&(aacDec->hUniDrcDecoder), DRC_DEC_ALL) != 0) { + err = -1; + goto bail; + } + } + + transportDec_RegisterUniDrcConfigCallback(pIn, aacDecoder_UniDrcCallback, + (void *)aacDec, + aacDec->loudnessInfoSetPosition); + aacDec->defaultTargetLoudness = (SCHAR)96; + + pcmDmx_Open(&aacDec->hPcmUtils); + if (aacDec->hPcmUtils == NULL) { + err = -1; + goto bail; + } + + aacDec->hLimiter = + pcmLimiter_Create(TDL_ATTACK_DEFAULT_MS, TDL_RELEASE_DEFAULT_MS, + (FIXP_DBL)MAXVAL_DBL, (8), 96000); + if (NULL == aacDec->hLimiter) { + err = -1; + goto bail; + } + aacDec->limiterEnableUser = (UCHAR)-1; + aacDec->limiterEnableCurr = 0; + + /* Assure that all modules have same delay */ + if (setConcealMethod(aacDec, + CConcealment_GetMethod(&aacDec->concealCommonData))) { + err = -1; + goto bail; + } + +bail: + if (err == -1) { + aacDecoder_Close(aacDec); + aacDec = NULL; + } + return aacDec; +} + +LINKSPEC_CPP AAC_DECODER_ERROR aacDecoder_Fill(HANDLE_AACDECODER self, + UCHAR *pBuffer[], + const UINT bufferSize[], + UINT *pBytesValid) { + TRANSPORTDEC_ERROR tpErr; + /* loop counter for layers; if not TT_MP4_RAWPACKETS used as index for only + available layer */ + INT layer = 0; + INT nrOfLayers = self->nrOfLayers; + + { + for (layer = 0; layer < nrOfLayers; layer++) { + { + tpErr = transportDec_FillData(self->hInput, pBuffer[layer], + bufferSize[layer], &pBytesValid[layer], + layer); + if (tpErr != TRANSPORTDEC_OK) { + return AAC_DEC_UNKNOWN; /* Must be an internal error */ + } + } + } + } + + return AAC_DEC_OK; +} + +static void aacDecoder_SignalInterruption(HANDLE_AACDECODER self) { + CAacDecoder_SignalInterruption(self); + + if (self->hSbrDecoder != NULL) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_BS_INTERRUPTION, 1); + } + if (self->mpsEnableUser) { + mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_BS_INTERRUPTION, 1); + } +} + +static void aacDecoder_UpdateBitStreamCounters(CStreamInfo *pSi, + HANDLE_FDK_BITSTREAM hBs, + INT nBits, + AAC_DECODER_ERROR ErrorStatus) { + /* calculate bit difference (amount of bits moved forward) */ + nBits = nBits - (INT)FDKgetValidBits(hBs); + + /* Note: The amount of bits consumed might become negative when parsing a + bit stream with several sub frames, and we find out at the last sub frame + that the total frame length does not match the sum of sub frame length. + If this happens, the transport decoder might want to rewind to the supposed + ending of the transport frame, and this position might be before the last + access unit beginning. */ + + /* Calc bitrate. */ + if (pSi->frameSize > 0) { + /* bitRate = nBits * sampleRate / frameSize */ + int ratio_e = 0; + FIXP_DBL ratio_m = fDivNorm(pSi->sampleRate, pSi->frameSize, &ratio_e); + pSi->bitRate = (INT)fMultNorm(nBits, DFRACT_BITS - 1, ratio_m, ratio_e, + DFRACT_BITS - 1); + } + + /* bit/byte counters */ + { + INT nBytes; + + nBytes = nBits >> 3; + pSi->numTotalBytes += nBytes; + if (IS_OUTPUT_VALID(ErrorStatus)) { + pSi->numTotalAccessUnits++; + } + if (IS_DECODE_ERROR(ErrorStatus)) { + pSi->numBadBytes += nBytes; + pSi->numBadAccessUnits++; + } + } +} + +static INT aacDecoder_EstimateNumberOfLostFrames(HANDLE_AACDECODER self) { + INT n; + + transportDec_GetMissingAccessUnitCount(&n, self->hInput); + + return n; +} + +LINKSPEC_CPP AAC_DECODER_ERROR +aacDecoder_DecodeFrame(HANDLE_AACDECODER self, INT_PCM *pTimeData_extern, + const INT timeDataSize_extern, const UINT flags) { + AAC_DECODER_ERROR ErrorStatus; + INT layer; + INT nBits; + HANDLE_FDK_BITSTREAM hBs; + int fTpInterruption = 0; /* Transport originated interruption detection. */ + int fTpConceal = 0; /* Transport originated concealment. */ + INT_PCM *pTimeData = NULL; + INT timeDataSize = 0; + UINT accessUnit = 0; + UINT numAccessUnits = 1; + UINT numPrerollAU = 0; + int fEndAuNotAdjusted = 0; /* The end of the access unit was not adjusted */ + int applyCrossfade = 1; /* flag indicates if flushing was possible */ + FIXP_PCM *pTimeDataFixpPcm; /* Signal buffer for decoding process before PCM + processing */ + INT timeDataFixpPcmSize; + PCM_DEC *pTimeDataPcmPost; /* Signal buffer for PCM post-processing */ + INT timeDataPcmPostSize; + + if (self == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + pTimeData = self->pcmOutputBuffer; + timeDataSize = sizeof(self->pcmOutputBuffer) / sizeof(*self->pcmOutputBuffer); + + if (flags & AACDEC_INTR) { + self->streamInfo.numLostAccessUnits = 0; + } + hBs = transportDec_GetBitstream(self->hInput, 0); + + /* Get current bits position for bitrate calculation. */ + nBits = FDKgetValidBits(hBs); + + if (flags & AACDEC_CLRHIST) { + if (self->flags[0] & AC_USAC) { + /* 1) store AudioSpecificConfig always in AudioSpecificConfig_Parse() */ + /* 2) free memory of dynamic allocated data */ + CSAudioSpecificConfig asc; + transportDec_GetAsc(self->hInput, 0, &asc); + aacDecoder_FreeMemCallback(self, &asc); + self->streamInfo.numChannels = 0; + /* 3) restore AudioSpecificConfig */ + transportDec_OutOfBandConfig(self->hInput, asc.config, + (asc.configBits + 7) >> 3, 0); + } + } + + if (!((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || + (self->flushStatus == AACDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND))) { + TRANSPORTDEC_ERROR err; + + for (layer = 0; layer < self->nrOfLayers; layer++) { + err = transportDec_ReadAccessUnit(self->hInput, layer); + if (err != TRANSPORTDEC_OK) { + switch (err) { + case TRANSPORTDEC_NOT_ENOUGH_BITS: + ErrorStatus = AAC_DEC_NOT_ENOUGH_BITS; + goto bail; + case TRANSPORTDEC_SYNC_ERROR: + self->streamInfo.numLostAccessUnits = + aacDecoder_EstimateNumberOfLostFrames(self); + fTpInterruption = 1; + break; + case TRANSPORTDEC_NEED_TO_RESTART: + ErrorStatus = AAC_DEC_NEED_TO_RESTART; + goto bail; + case TRANSPORTDEC_CRC_ERROR: + fTpConceal = 1; + break; + case TRANSPORTDEC_UNSUPPORTED_FORMAT: + ErrorStatus = AAC_DEC_UNSUPPORTED_FORMAT; + goto bail; + default: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + } else { + if (self->streamInfo.numLostAccessUnits > 0) { + self->streamInfo.numLostAccessUnits--; + } + } + + self->frameOK = 1; + + UINT prerollAUOffset[AACDEC_MAX_NUM_PREROLL_AU]; + UINT prerollAULength[AACDEC_MAX_NUM_PREROLL_AU]; + for (int i = 0; i < AACDEC_MAX_NUM_PREROLL_AU + 1; i++) + self->prerollAULength[i] = 0; + + INT auStartAnchor; + HANDLE_FDK_BITSTREAM hBsAu; + + /* Process preroll frames and current frame */ + do { + if (!(flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) && + (self->flushStatus != AACDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON) && + (accessUnit == 0) && + (self->hasAudioPreRoll || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) && + !fTpInterruption && + !fTpConceal /* Bit stream pointer needs to be at the beginning of a + (valid) AU. */ + ) { + ErrorStatus = CAacDecoder_PreRollExtensionPayloadParse( + self, &numPrerollAU, prerollAUOffset, prerollAULength); + + if (ErrorStatus != AAC_DEC_OK) { + switch (ErrorStatus) { + case AAC_DEC_NOT_ENOUGH_BITS: + goto bail; + case AAC_DEC_PARSE_ERROR: + self->frameOK = 0; + break; + default: + break; + } + } + + numAccessUnits += numPrerollAU; + } + + hBsAu = transportDec_GetBitstream(self->hInput, 0); + auStartAnchor = (INT)FDKgetValidBits(hBsAu); + + self->accessUnit = accessUnit; + if (accessUnit < numPrerollAU) { + FDKpushFor(hBsAu, prerollAUOffset[accessUnit]); + } + + /* Signal bit stream interruption to other modules if required. */ + if (fTpInterruption || (flags & AACDEC_INTR)) { + aacDecoder_SignalInterruption(self); + if (!(flags & AACDEC_INTR)) { + ErrorStatus = AAC_DEC_TRANSPORT_SYNC_ERROR; + goto bail; + } + } + + /* Clearing core data will be done in CAacDecoder_DecodeFrame() below. + Tell other modules to clear states if required. */ + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + sbrDecoder_SetParam(self->hSbrDecoder, SBR_CLEAR_HISTORY, 1); + mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_CLEAR_HISTORY, 1); + if (FDK_QmfDomain_ClearPersistentMemory(&self->qmfDomain) != 0) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + } + } + + /* Empty bit buffer in case of flush request. */ + if (flags & AACDEC_FLUSH && !(flags & AACDEC_CONCEAL)) { + if (!self->flushStatus) { + transportDec_SetParam(self->hInput, TPDEC_PARAM_RESET, 1); + self->streamInfo.numLostAccessUnits = 0; + self->streamInfo.numBadBytes = 0; + self->streamInfo.numTotalBytes = 0; + } + } + /* Reset the output delay field. The modules will add their figures one + * after another. */ + self->streamInfo.outputDelay = 0; + + if (self->limiterEnableUser == (UCHAR)-2) { + /* Enable limiter only for RSVD60. */ + self->limiterEnableCurr = (self->flags[0] & AC_RSV603DA) ? 1 : 0; + } else if (self->limiterEnableUser == (UCHAR)-1) { + /* Enable limiter for all non-lowdelay AOT's. */ + self->limiterEnableCurr = (self->flags[0] & (AC_LD | AC_ELD)) ? 0 : 1; + } else { + /* Use limiter configuration as requested. */ + self->limiterEnableCurr = self->limiterEnableUser; + } + /* reset limiter gain on a per frame basis */ + self->extGain[0] = FL2FXCONST_DBL(1.0f / (float)(1 << TDL_GAIN_SCALING)); + + pTimeDataFixpPcm = pTimeData; + timeDataFixpPcmSize = timeDataSize; + + ErrorStatus = CAacDecoder_DecodeFrame( + self, + flags | (fTpConceal ? AACDEC_CONCEAL : 0) | + ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH + : 0), + pTimeDataFixpPcm + 0, timeDataFixpPcmSize, + self->streamInfo.aacSamplesPerFrame + 0); + + /* if flushing for USAC DASH IPF was not possible go on with decoding + * preroll */ + if ((self->flags[0] & AC_USAC) && + (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) && + !(flags & AACDEC_CONCEAL) && (ErrorStatus != AAC_DEC_OK)) { + applyCrossfade = 0; + } else /* USAC DASH IPF flushing possible begin */ + { + if (!((flags & (AACDEC_CONCEAL | AACDEC_FLUSH)) || fTpConceal || + self->flushStatus) && + (!(IS_OUTPUT_VALID(ErrorStatus)) || !(accessUnit < numPrerollAU))) { + TRANSPORTDEC_ERROR tpErr; + tpErr = transportDec_EndAccessUnit(self->hInput); + if (tpErr != TRANSPORTDEC_OK) { + self->frameOK = 0; + } + } else { /* while preroll processing later possibly an error in the + renderer part occurrs */ + if (IS_OUTPUT_VALID(ErrorStatus)) { + fEndAuNotAdjusted = 1; + } + } + + /* If the current pTimeDataFixpPcm does not contain a valid signal, there + * nothing else we can do, so bail. */ + if (!IS_OUTPUT_VALID(ErrorStatus)) { + goto bail; + } + + { + self->streamInfo.sampleRate = self->streamInfo.aacSampleRate; + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + } + + self->streamInfo.numChannels = self->streamInfo.aacNumChannels; + + { + FDK_Delay_Apply(&self->usacResidualDelay, + pTimeDataFixpPcm + + 1 * (self->streamInfo.aacSamplesPerFrame + 0) + 0, + self->streamInfo.frameSize, 0); + } + + /* Setting of internal MPS state; may be reset in CAacDecoder_SyncQmfMode + if decoder is unable to decode with user defined qmfMode */ + if (!(self->flags[0] & (AC_USAC | AC_RSVD50 | AC_RSV603DA | AC_ELD))) { + self->mpsEnableCurr = + (self->mpsEnableUser && + isSupportedMpsConfig(self->streamInfo.aot, + self->streamInfo.numChannels, + (self->flags[0] & AC_MPS_PRESENT) ? 1 : 0)); + } + + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig && + self->mpsEnableCurr) { + /* if not done yet, allocate full MPEG Surround decoder instance */ + if (mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder) == + SAC_INSTANCE_NOT_FULL_AVAILABLE) { + if (mpegSurroundDecoder_Open( + (CMpegSurroundDecoder **)&self->pMpegSurroundDecoder, -1, + &self->qmfDomain)) { + return AAC_DEC_OUT_OF_MEMORY; + } + } + } + + CAacDecoder_SyncQmfMode(self); + + if (!self->qmfDomain.globalConf.qmfDomainExplicitConfig && + self->mpsEnableCurr) { + SAC_INPUT_CONFIG sac_interface = (self->sbrEnabled && self->hSbrDecoder) + ? SAC_INTERFACE_QMF + : SAC_INTERFACE_TIME; + /* needs to be done before first SBR apply. */ + mpegSurroundDecoder_ConfigureQmfDomain( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, sac_interface, + (UINT)self->streamInfo.aacSampleRate, self->streamInfo.aot); + if (self->qmfDomain.globalConf.nBandsAnalysis_requested > 0) { + self->qmfDomain.globalConf.nQmfTimeSlots_requested = + self->streamInfo.aacSamplesPerFrame / + self->qmfDomain.globalConf.nBandsAnalysis_requested; + } else { + self->qmfDomain.globalConf.nQmfTimeSlots_requested = 0; + } + } + + self->qmfDomain.globalConf.TDinput = pTimeData; + + switch (FDK_QmfDomain_Configure(&self->qmfDomain)) { + default: + case QMF_DOMAIN_INIT_ERROR: + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + case QMF_DOMAIN_OUT_OF_MEMORY: + ErrorStatus = AAC_DEC_OUT_OF_MEMORY; + goto bail; + case QMF_DOMAIN_OK: + break; + } + + /* sbr decoder */ + + if ((ErrorStatus != AAC_DEC_OK) || (flags & AACDEC_CONCEAL) || + self->pAacDecoderStaticChannelInfo[0]->concealmentInfo.concealState > + ConcealState_FadeIn) { + self->frameOK = 0; /* if an error has occured do concealment in the SBR + decoder too */ + } + + if (self->sbrEnabled && (!(self->flags[0] & AC_USAC_SCFGI3))) { + SBR_ERROR sbrError = SBRDEC_OK; + int chIdx, numCoreChannel = self->streamInfo.numChannels; + + /* set params */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + sbrDecoder_SetParam( + self->hSbrDecoder, SBR_FLUSH_DATA, + (flags & AACDEC_FLUSH) | + ((self->flushStatus && !(flags & AACDEC_CONCEAL)) ? AACDEC_FLUSH + : 0)); + + if (self->streamInfo.aot == AOT_ER_AAC_ELD) { + /* Configure QMF */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_LD_QMF_TIME_ALIGN, + (self->flags[0] & AC_MPS_PRESENT) ? 1 : 0); + } + + { + PCMDMX_ERROR dmxErr; + INT maxOutCh = 0; + + dmxErr = pcmDmx_GetParam(self->hPcmUtils, + MAX_NUMBER_OF_OUTPUT_CHANNELS, &maxOutCh); + if ((dmxErr == PCMDMX_OK) && (maxOutCh == 1)) { + /* Disable PS processing if we have to create a mono output signal. + */ + self->psPossible = 0; + } + } + + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, + (self->mpsEnableCurr) ? 2 : 0); + + INT_PCM *input; + input = (INT_PCM *)self->workBufferCore2; + FDKmemcpy(input, pTimeData, + sizeof(INT_PCM) * (self->streamInfo.numChannels) * + (self->streamInfo.frameSize)); + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply(self->hSbrDecoder, input, pTimeData, + timeDataSize, &self->streamInfo.numChannels, + &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, + self->frameOK, &self->psPossible); + + if (sbrError == SBRDEC_OK) { + /* Update data in streaminfo structure. Assume that the SBR upsampling + factor is either 1, 2, 8/3 or 4. Maximum upsampling factor is 4 + (CELP+SBR or USAC 4:1 SBR) */ + self->flags[0] |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.aacSampleRate >> 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = + self->streamInfo.aacSamplesPerFrame >> 2; + self->streamInfo.outputDelay = self->streamInfo.outputDelay >> 2; + } else if (self->streamInfo.aacSampleRate >> 1 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = + self->streamInfo.aacSamplesPerFrame >> 1; + self->streamInfo.outputDelay = self->streamInfo.outputDelay >> 1; + } else if (self->streamInfo.aacSampleRate << 1 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 1; + self->streamInfo.outputDelay = self->streamInfo.outputDelay << 1; + } else if (self->streamInfo.aacSampleRate << 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 2; + self->streamInfo.outputDelay = self->streamInfo.outputDelay << 2; + } else if (self->streamInfo.frameSize == 768) { + self->streamInfo.frameSize = + (self->streamInfo.aacSamplesPerFrame << 3) / 3; + self->streamInfo.outputDelay = + (self->streamInfo.outputDelay << 3) / 3; + } else { + ErrorStatus = AAC_DEC_SET_PARAM_FAIL; + goto bail; + } + } else { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame; + } + self->streamInfo.outputDelay += + sbrDecoder_GetDelay(self->hSbrDecoder); + + if (self->psPossible) { + self->flags[0] |= AC_PS_PRESENT; + } + for (chIdx = numCoreChannel; chIdx < self->streamInfo.numChannels; + chIdx += 1) { + self->channelType[chIdx] = ACT_FRONT; + self->channelIndices[chIdx] = chIdx; + } + } + if (sbrError == SBRDEC_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + } + + if (self->mpsEnableCurr) { + int err, sac_interface, nChannels, frameSize; + + nChannels = self->streamInfo.numChannels; + frameSize = self->streamInfo.frameSize; + sac_interface = SAC_INTERFACE_TIME; + + if (self->sbrEnabled && self->hSbrDecoder) + sac_interface = SAC_INTERFACE_QMF; + if (self->streamInfo.aot == AOT_USAC) { + if (self->flags[0] & AC_USAC_SCFGI3) { + sac_interface = SAC_INTERFACE_TIME; + } + } + err = mpegSurroundDecoder_SetParam( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + SACDEC_INTERFACE, sac_interface); + + if (err == 0) { + err = mpegSurroundDecoder_Apply( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder, + (INT_PCM *)self->workBufferCore2, pTimeData, timeDataSize, + self->streamInfo.aacSamplesPerFrame, &nChannels, &frameSize, + self->streamInfo.sampleRate, self->streamInfo.aot, + self->channelType, self->channelIndices, &self->mapDescr); + } + + if (err == MPS_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + if (err == 0) { + /* Update output parameter */ + self->streamInfo.numChannels = nChannels; + self->streamInfo.frameSize = frameSize; + self->streamInfo.outputDelay += mpegSurroundDecoder_GetDelay( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder); + /* Save current parameter for possible concealment of next frame */ + self->mpsOutChannelsLast = nChannels; + self->mpsFrameSizeLast = frameSize; + } else if ((self->mpsOutChannelsLast > 0) && + (self->mpsFrameSizeLast > 0)) { + /* Restore parameters of last frame ... */ + self->streamInfo.numChannels = self->mpsOutChannelsLast; + self->streamInfo.frameSize = self->mpsFrameSizeLast; + /* ... and clear output buffer so that potentially corrupted data does + * not reach the framework. */ + FDKmemclear(pTimeData, self->mpsOutChannelsLast * + self->mpsFrameSizeLast * sizeof(INT_PCM)); + /* Additionally proclaim that this frame had errors during decoding. + */ + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } else { + ErrorStatus = AAC_DEC_UNKNOWN; /* no output */ + } + } + + /* SBR decoder for Unified Stereo Config (stereoConfigIndex == 3) */ + + if (self->sbrEnabled && (self->flags[0] & AC_USAC_SCFGI3)) { + SBR_ERROR sbrError = SBRDEC_OK; + + /* set params */ + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SYSTEM_BITSTREAM_DELAY, + self->sbrParams.bsDelay); + + sbrDecoder_SetParam(self->hSbrDecoder, SBR_SKIP_QMF, 1); + + /* apply SBR processing */ + sbrError = sbrDecoder_Apply(self->hSbrDecoder, pTimeData, pTimeData, + timeDataSize, &self->streamInfo.numChannels, + &self->streamInfo.sampleRate, + &self->mapDescr, self->chMapIndex, + self->frameOK, &self->psPossible); + + if (sbrError == SBRDEC_OK) { + /* Update data in streaminfo structure. Assume that the SBR upsampling + * factor is either 1,2 or 4 */ + self->flags[0] |= AC_SBR_PRESENT; + if (self->streamInfo.aacSampleRate != self->streamInfo.sampleRate) { + if (self->streamInfo.frameSize == 768) { + self->streamInfo.frameSize = + (self->streamInfo.aacSamplesPerFrame * 8) / 3; + } else if (self->streamInfo.aacSampleRate << 2 == + self->streamInfo.sampleRate) { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 2; + } else { + self->streamInfo.frameSize = self->streamInfo.aacSamplesPerFrame + << 1; + } + } + + self->flags[0] &= ~AC_PS_PRESENT; + } + if (sbrError == SBRDEC_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + } + + /* Use dedicated memory for PCM postprocessing */ + pTimeDataPcmPost = self->pTimeData2; + timeDataPcmPostSize = self->timeData2Size; + + { + const int size = + self->streamInfo.frameSize * self->streamInfo.numChannels; + FDK_ASSERT(timeDataPcmPostSize >= size); + for (int i = 0; i < size; i++) { + pTimeDataPcmPost[i] = + (PCM_DEC)FX_PCM2PCM_DEC(pTimeData[i]) >> PCM_OUT_HEADROOM; + } + } + + { + if ((FDK_drcDec_GetParam(self->hUniDrcDecoder, DRC_DEC_IS_ACTIVE)) && + !(self->flags[0] & AC_RSV603DA)) { + /* Apply DRC gains*/ + int ch, drcDelay = 0; + int needsDeinterleaving = 0; + FIXP_DBL *drcWorkBuffer = NULL; + FIXP_DBL channelGain[(8)]; + int reverseInChannelMap[(8)]; + int reverseOutChannelMap[(8)]; + int numDrcOutChannels = FDK_drcDec_GetParam( + self->hUniDrcDecoder, DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED); + FDKmemclear(channelGain, sizeof(channelGain)); + for (ch = 0; ch < (8); ch++) { + reverseInChannelMap[ch] = ch; + reverseOutChannelMap[ch] = ch; + } + + /* If SBR and/or MPS is active, the DRC gains are aligned to the QMF + domain signal before the QMF synthesis. Therefore the DRC gains + need to be delayed by the QMF synthesis delay. */ + if (self->sbrEnabled) drcDelay = 257; + if (self->mpsEnableCurr) drcDelay = 257; + /* Take into account concealment delay */ + drcDelay += CConcealment_GetDelay(&self->concealCommonData) * + self->streamInfo.frameSize; + + for (ch = 0; ch < self->streamInfo.numChannels; ch++) { + UCHAR mapValue = FDK_chMapDescr_getMapValue( + &self->mapDescr, (UCHAR)ch, self->chMapIndex); + if (mapValue < (8)) reverseInChannelMap[mapValue] = ch; + } + for (ch = 0; ch < (int)numDrcOutChannels; ch++) { + UCHAR mapValue = FDK_chMapDescr_getMapValue( + &self->mapDescr, (UCHAR)ch, numDrcOutChannels); + if (mapValue < (8)) reverseOutChannelMap[mapValue] = ch; + } + + /* The output of SBR and MPS is interleaved. Deinterleaving may be + * necessary for FDK_drcDec_ProcessTime, which accepts deinterleaved + * audio only. */ + if ((self->streamInfo.numChannels > 1) && + (0 || (self->sbrEnabled) || (self->mpsEnableCurr))) { + /* interleaving/deinterleaving is performed on upper part of + * pTimeDataPcmPost. Check if this buffer is large enough. */ + if (timeDataPcmPostSize < + (INT)(2 * self->streamInfo.numChannels * + self->streamInfo.frameSize * sizeof(PCM_DEC))) { + ErrorStatus = AAC_DEC_UNKNOWN; + goto bail; + } + needsDeinterleaving = 1; + drcWorkBuffer = + (FIXP_DBL *)pTimeDataPcmPost + + self->streamInfo.numChannels * self->streamInfo.frameSize; + FDK_deinterleave( + pTimeDataPcmPost, drcWorkBuffer, self->streamInfo.numChannels, + self->streamInfo.frameSize, self->streamInfo.frameSize); + } else { + drcWorkBuffer = (FIXP_DBL *)pTimeDataPcmPost; + } + + /* prepare Loudness Normalisation gain */ + FDK_drcDec_SetParam(self->hUniDrcDecoder, DRC_DEC_TARGET_LOUDNESS, + (INT)-self->defaultTargetLoudness * + FL2FXCONST_DBL(1.0f / (float)(1 << 9))); + FDK_drcDec_SetChannelGains(self->hUniDrcDecoder, + self->streamInfo.numChannels, + self->streamInfo.frameSize, channelGain, + drcWorkBuffer, self->streamInfo.frameSize); + FDK_drcDec_Preprocess(self->hUniDrcDecoder); + + /* apply DRC1 gain sequence */ + for (ch = 0; ch < self->streamInfo.numChannels; ch++) { + FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, DRC_DEC_DRC1, + ch, reverseInChannelMap[ch] - ch, 1, + drcWorkBuffer, self->streamInfo.frameSize); + } + /* apply downmix */ + FDK_drcDec_ApplyDownmix( + self->hUniDrcDecoder, reverseInChannelMap, reverseOutChannelMap, + drcWorkBuffer, + &self->streamInfo.numChannels); /* self->streamInfo.numChannels + may change here */ + /* apply DRC2/3 gain sequence */ + for (ch = 0; ch < self->streamInfo.numChannels; ch++) { + FDK_drcDec_ProcessTime(self->hUniDrcDecoder, drcDelay, + DRC_DEC_DRC2_DRC3, ch, + reverseOutChannelMap[ch] - ch, 1, + drcWorkBuffer, self->streamInfo.frameSize); + } + + if (needsDeinterleaving) { + FDK_interleave( + drcWorkBuffer, pTimeDataPcmPost, self->streamInfo.numChannels, + self->streamInfo.frameSize, self->streamInfo.frameSize); + } + } + } + + if (self->streamInfo.extAot != AOT_AAC_SLS) { + INT pcmLimiterScale = 0; + PCMDMX_ERROR dmxErr = PCMDMX_OK; + if (flags & (AACDEC_INTR)) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + } + if (flags & (AACDEC_CLRHIST)) { + if (!(self->flags[0] & AC_USAC)) { + /* delete data from the past (e.g. mixdown coeficients) */ + pcmDmx_Reset(self->hPcmUtils, PCMDMX_RESET_BS_DATA); + } + } + + INT interleaved = 0; + interleaved |= (self->sbrEnabled) ? 1 : 0; + interleaved |= (self->mpsEnableCurr) ? 1 : 0; + + /* do PCM post processing */ + dmxErr = pcmDmx_ApplyFrame( + self->hPcmUtils, pTimeDataPcmPost, timeDataFixpPcmSize, + self->streamInfo.frameSize, &self->streamInfo.numChannels, + interleaved, self->channelType, self->channelIndices, + &self->mapDescr, + (self->limiterEnableCurr) ? &pcmLimiterScale : NULL); + if (dmxErr == PCMDMX_OUTPUT_BUFFER_TOO_SMALL) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + if ((ErrorStatus == AAC_DEC_OK) && (dmxErr == PCMDMX_INVALID_MODE)) { + /* Announce the framework that the current combination of channel + * configuration and downmix settings are not know to produce a + * predictable behavior and thus maybe produce strange output. */ + ErrorStatus = AAC_DEC_DECODE_FRAME_ERROR; + } + + if (flags & AACDEC_CLRHIST) { + if (!(self->flags[0] & AC_USAC)) { + /* Delete the delayed signal. */ + pcmLimiter_Reset(self->hLimiter); + } + } + + if (self->limiterEnableCurr) { + /* use workBufferCore2 buffer for interleaving */ + PCM_LIM *pInterleaveBuffer; + int blockLength = self->streamInfo.frameSize; + + /* Set actual signal parameters */ + pcmLimiter_SetNChannels(self->hLimiter, self->streamInfo.numChannels); + pcmLimiter_SetSampleRate(self->hLimiter, self->streamInfo.sampleRate); + pcmLimiterScale += PCM_OUT_HEADROOM; + + if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || + (self->mpsEnableCurr)) { + pInterleaveBuffer = (PCM_LIM *)pTimeDataPcmPost; + } else { + pInterleaveBuffer = (PCM_LIM *)pTimeData; + /* applyLimiter requests for interleaved data */ + /* Interleave ouput buffer */ + FDK_interleave(pTimeDataPcmPost, pInterleaveBuffer, + self->streamInfo.numChannels, blockLength, + self->streamInfo.frameSize); + } + + pcmLimiter_Apply(self->hLimiter, pInterleaveBuffer, pTimeData, + self->extGain, &pcmLimiterScale, 1, + self->extGainDelay, self->streamInfo.frameSize); + + { + /* Announce the additional limiter output delay */ + self->streamInfo.outputDelay += pcmLimiter_GetDelay(self->hLimiter); + } + } else { + /* If numChannels = 1 we do not need interleaving. The same applies if + SBR or MPS are used, since their output is interleaved already + (resampled or not) */ + if ((self->streamInfo.numChannels == 1) || (self->sbrEnabled) || + (self->mpsEnableCurr)) { + scaleValuesSaturate( + pTimeData, pTimeDataPcmPost, + self->streamInfo.frameSize * self->streamInfo.numChannels, + PCM_OUT_HEADROOM); + + } else { + scaleValuesSaturate( + (INT_PCM *)self->workBufferCore2, pTimeDataPcmPost, + self->streamInfo.frameSize * self->streamInfo.numChannels, + PCM_OUT_HEADROOM); + /* Interleave ouput buffer */ + FDK_interleave((INT_PCM *)self->workBufferCore2, pTimeData, + self->streamInfo.numChannels, + self->streamInfo.frameSize, + self->streamInfo.frameSize); + } + } + } /* if (self->streamInfo.extAot != AOT_AAC_SLS)*/ + + if (self->flags[0] & AC_USAC) { + if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON && + !(flags & AACDEC_CONCEAL)) { + CAacDecoder_PrepareCrossFade(pTimeData, self->pTimeDataFlush, + self->streamInfo.numChannels, + self->streamInfo.frameSize, 1); + } + + /* prepare crossfade buffer for fade in */ + if (!applyCrossfade && self->applyCrossfade && + !(flags & AACDEC_CONCEAL)) { + for (int ch = 0; ch < self->streamInfo.numChannels; ch++) { + for (int i = 0; i < TIME_DATA_FLUSH_SIZE; i++) { + self->pTimeDataFlush[ch][i] = 0; + } + } + applyCrossfade = 1; + } + + if (applyCrossfade && self->applyCrossfade && + !(accessUnit < numPrerollAU) && + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + CAacDecoder_ApplyCrossFade(pTimeData, self->pTimeDataFlush, + self->streamInfo.numChannels, + self->streamInfo.frameSize, 1); + self->applyCrossfade = 0; + } + } + + /* Signal interruption to take effect in next frame. */ + if ((flags & AACDEC_FLUSH || self->flushStatus) && + !(flags & AACDEC_CONCEAL)) { + aacDecoder_SignalInterruption(self); + } + + /* Update externally visible copy of flags */ + self->streamInfo.flags = self->flags[0]; + + } /* USAC DASH IPF flushing possible end */ + if (accessUnit < numPrerollAU) { + FDKpushBack(hBsAu, auStartAnchor - (INT)FDKgetValidBits(hBsAu)); + } else { + if ((self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON) || + (self->buildUpStatus == AACDEC_RSV60_BUILD_UP_ON_IN_BAND) || + (self->buildUpStatus == AACDEC_USAC_BUILD_UP_ON)) { + self->buildUpCnt--; + + if (self->buildUpCnt < 0) { + self->buildUpStatus = 0; + } + } + + if (self->flags[0] & AC_USAC) { + if (self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON && + !(flags & AACDEC_CONCEAL)) { + self->streamInfo.frameSize = 0; + } + } + } + + if (self->flushStatus != AACDEC_USAC_DASH_IPF_FLUSH_ON) { + accessUnit++; + } + } while ((accessUnit < numAccessUnits) || + ((self->flushStatus == AACDEC_USAC_DASH_IPF_FLUSH_ON) && + !(flags & AACDEC_CONCEAL))); + +bail: + + /* error in renderer part occurred, ErrorStatus was set to invalid output */ + if (fEndAuNotAdjusted && !IS_OUTPUT_VALID(ErrorStatus) && + (accessUnit < numPrerollAU)) { + transportDec_EndAccessUnit(self->hInput); + } + + /* Update Statistics */ + aacDecoder_UpdateBitStreamCounters(&self->streamInfo, hBs, nBits, + ErrorStatus); + if (((self->streamInfo.numChannels <= 0) || + (self->streamInfo.frameSize <= 0) || + (self->streamInfo.sampleRate <= 0)) && + IS_OUTPUT_VALID(ErrorStatus)) { + /* Ensure consistency of IS_OUTPUT_VALID() macro. */ + ErrorStatus = AAC_DEC_UNKNOWN; + } + + /* Check whether external output buffer is large enough. */ + if (timeDataSize_extern < + self->streamInfo.numChannels * self->streamInfo.frameSize) { + ErrorStatus = AAC_DEC_OUTPUT_BUFFER_TOO_SMALL; + } + + /* Update external output buffer. */ + if (IS_OUTPUT_VALID(ErrorStatus)) { + FDKmemcpy(pTimeData_extern, pTimeData, + self->streamInfo.numChannels * self->streamInfo.frameSize * + sizeof(*pTimeData)); + } else { + FDKmemclear(pTimeData_extern, + timeDataSize_extern * sizeof(*pTimeData_extern)); + } + + return ErrorStatus; +} + +LINKSPEC_CPP void aacDecoder_Close(HANDLE_AACDECODER self) { + if (self == NULL) return; + + if (self->hLimiter != NULL) { + pcmLimiter_Destroy(self->hLimiter); + } + + if (self->hPcmUtils != NULL) { + pcmDmx_Close(&self->hPcmUtils); + } + + FDK_drcDec_Close(&self->hUniDrcDecoder); + + if (self->pMpegSurroundDecoder != NULL) { + mpegSurroundDecoder_Close( + (CMpegSurroundDecoder *)self->pMpegSurroundDecoder); + } + + if (self->hSbrDecoder != NULL) { + sbrDecoder_Close(&self->hSbrDecoder); + } + + if (self->hInput != NULL) { + transportDec_Close(&self->hInput); + } + + CAacDecoder_Close(self); +} + +LINKSPEC_CPP CStreamInfo *aacDecoder_GetStreamInfo(HANDLE_AACDECODER self) { + return CAacDecoder_GetStreamInfo(self); +} + +LINKSPEC_CPP INT aacDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + sbrDecoder_GetLibInfo(info); + mpegSurroundDecoder_GetLibInfo(info); + transportDec_GetLibInfo(info); + FDK_toolsGetLibInfo(info); + pcmDmx_GetLibInfo(info); + pcmLimiter_GetLibInfo(info); + FDK_drcDec_GetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_AACDEC; + /* build own library info */ + info->version = + LIB_VERSION(AACDECODER_LIB_VL0, AACDECODER_LIB_VL1, AACDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = AACDECODER_LIB_BUILD_DATE; + info->build_time = AACDECODER_LIB_BUILD_TIME; + info->title = AACDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 | CAPF_AAC_LC | CAPF_ER_AAC_LC | CAPF_ER_AAC_SCAL | + CAPF_AAC_VCB11 | CAPF_AAC_HCR | CAPF_AAC_RVLC | CAPF_ER_AAC_LD | + CAPF_ER_AAC_ELD | CAPF_AAC_CONCEALMENT | CAPF_AAC_DRC | + CAPF_AAC_MPEG4 | CAPF_AAC_DRM_BSFORMAT | CAPF_AAC_1024 | + CAPF_AAC_960 | CAPF_AAC_512 | CAPF_AAC_480 | + CAPF_AAC_ELD_DOWNSCALE + + | CAPF_AAC_USAC | CAPF_ER_AAC_ELDV2 | CAPF_AAC_UNIDRC; + /* End of flags */ + + return 0; +} diff --git a/fdk-aac/libAACdec/src/arm/block_arm.cpp b/fdk-aac/libAACdec/src/arm/block_arm.cpp new file mode 100644 index 0000000..3c1b4ba --- /dev/null +++ b/fdk-aac/libAACdec/src/arm/block_arm.cpp @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Arthur Tritthart + + Description: (ARM optimised) Scaling of spectral data + +*******************************************************************************/ + +#define FUNCTION_CBlock_ScaleSpectralData_func1 + +/* Note: This loop is only separated for ARM in order to save cycles + by loop unrolling. The ARM core provides by default a 5-cycle + loop overhead per sample, that goes down to 1-cycle per sample + with an optimal 4x-loop construct (do - 4x - while). +*/ +static inline void CBlock_ScaleSpectralData_func1( + FIXP_DBL *pSpectrum, int maxSfbs, const SHORT *RESTRICT BandOffsets, + int SpecScale_window, const SHORT *RESTRICT pSfbScale, int window) { + int band_offset = 0; + for (int band = 0; band < maxSfbs; band++) { + int runs = band_offset; + band_offset = BandOffsets[band + 1]; + runs = band_offset - runs; /* is always a multiple of 4 */ + FDK_ASSERT((runs & 3) == 0); + int scale = + fMin(DFRACT_BITS - 1, SpecScale_window - pSfbScale[window * 16 + band]); + + if (scale) { + do { + FIXP_DBL tmp0, tmp1, tmp2, tmp3; + tmp0 = pSpectrum[0]; + tmp1 = pSpectrum[1]; + tmp2 = pSpectrum[2]; + tmp3 = pSpectrum[3]; + tmp0 >>= scale; + tmp1 >>= scale; + tmp2 >>= scale; + tmp3 >>= scale; + *pSpectrum++ = tmp0; + *pSpectrum++ = tmp1; + *pSpectrum++ = tmp2; + *pSpectrum++ = tmp3; + } while ((runs = runs - 4) != 0); + } else { + pSpectrum += runs; + } + } +} diff --git a/fdk-aac/libAACdec/src/block.cpp b/fdk-aac/libAACdec/src/block.cpp new file mode 100644 index 0000000..b3d09a6 --- /dev/null +++ b/fdk-aac/libAACdec/src/block.cpp @@ -0,0 +1,1260 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: long/short-block decoding + +*******************************************************************************/ + +#include "block.h" + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "scale.h" +#include "FDK_tools_rom.h" + +#include "usacdec_fac.h" +#include "usacdec_lpd.h" +#include "usacdec_lpc.h" +#include "FDK_trigFcts.h" + +#include "ac_arith_coder.h" + +#include "aacdec_hcr.h" +#include "rvlc.h" + +#if defined(__arm__) +#include "arm/block_arm.cpp" +#endif + +/*! + \brief Read escape sequence of codeword + + The function reads the escape sequence from the bitstream, + if the absolute value of the quantized coefficient has the + value 16. + A limitation is implemented to maximal 21 bits according to + ISO/IEC 14496-3:2009(E) 4.6.3.3. + This limits the escape prefix to a maximum of eight 1's. + If more than eight 1's are read, MAX_QUANTIZED_VALUE + 1 is + returned, independent of the sign of parameter q. + + \return quantized coefficient +*/ +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const LONG q) /*!< quantized coefficient */ +{ + if (fAbs(q) != 16) return (q); + + LONG i, off; + for (i = 4; i < 13; i++) { + if (FDKreadBit(bs) == 0) break; + } + + if (i == 13) return (MAX_QUANTIZED_VALUE + 1); + + off = FDKreadBits(bs, i); + i = off + (1 << i); + + if (q < 0) i = -i; + + return i; +} + +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, HANDLE_FDK_BITSTREAM bs, + UINT flags) { + int temp; + int band; + int group; + int position = 0; /* accu for intensity delta coding */ + int factor = pAacDecoderChannelInfo->pDynData->RawDataInfo + .GlobalGain; /* accu for scale factor delta coding */ + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + group++) { + for (band = 0; band < ScaleFactorBandsTransmitted; band++) { + switch (pCodeBook[band]) { + case ZERO_HCB: /* zero book */ + pScaleFactor[band] = 0; + break; + + default: /* decode scale factor */ + if (!((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && band == 0 && + group == 0)) { + temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + factor += temp - 60; /* MIDFAC 1.5 dB */ + } + pScaleFactor[band] = factor - 100; + break; + + case INTENSITY_HCB: /* intensity steering */ + case INTENSITY_HCB2: + temp = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + position += temp - 60; + pScaleFactor[band] = position - 100; + break; + + case NOISE_HCB: /* PNS */ + if (flags & (AC_MPEGD_RES | AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + return AAC_DEC_PARSE_ERROR; + } + CPns_Read(&pAacDecoderChannelInfo->data.aac.PnsData, bs, hcb, + pAacDecoderChannelInfo->pDynData->aScaleFactor, + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain, + band, group); + break; + } + } + pCodeBook += 16; + pScaleFactor += 16; + } + + return AAC_DEC_OK; +} + +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR maxSfbs, + SamplingRateInfo *pSamplingRateInfo) { + int band; + int window; + const SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT *RESTRICT pSpecScale = pAacDecoderChannelInfo->specScale; + int groupwin, group; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + SPECTRAL_PTR RESTRICT pSpectralCoefficient = + pAacDecoderChannelInfo->pSpectralCoefficient; + + FDKmemclear(pSpecScale, 8 * sizeof(SHORT)); + + for (window = 0, group = 0; + group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) { + for (groupwin = 0; groupwin < GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + groupwin++, window++) { + int SpecScale_window = pSpecScale[window]; + FIXP_DBL *pSpectrum = SPEC(pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength); + + /* find scaling for current window */ + for (band = 0; band < maxSfbs; band++) { + SpecScale_window = + fMax(SpecScale_window, (int)pSfbScale[window * 16 + band]); + } + + if (pAacDecoderChannelInfo->pDynData->TnsData.Active && + pAacDecoderChannelInfo->pDynData->TnsData.NumberOfFilters[window] > + 0) { + int filter_index, SpecScale_window_tns; + int tns_start, tns_stop; + + /* Find max scale of TNS bands */ + SpecScale_window_tns = 0; + tns_start = GetMaximumTnsBands(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo->samplingRateIndex); + tns_stop = 0; + for (filter_index = 0; + filter_index < (int)pAacDecoderChannelInfo->pDynData->TnsData + .NumberOfFilters[window]; + filter_index++) { + for (band = pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StartBand; + band < pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StopBand; + band++) { + SpecScale_window_tns = + fMax(SpecScale_window_tns, (int)pSfbScale[window * 16 + band]); + } + /* Find TNS line boundaries for all TNS filters */ + tns_start = + fMin(tns_start, (int)pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StartBand); + tns_stop = + fMax(tns_stop, (int)pAacDecoderChannelInfo->pDynData->TnsData + .Filter[window][filter_index] + .StopBand); + } + SpecScale_window_tns = SpecScale_window_tns + + pAacDecoderChannelInfo->pDynData->TnsData.GainLd; + FDK_ASSERT(tns_stop >= tns_start); + /* Consider existing headroom of all MDCT lines inside the TNS bands. */ + SpecScale_window_tns -= + getScalefactor(pSpectrum + BandOffsets[tns_start], + BandOffsets[tns_stop] - BandOffsets[tns_start]); + if (SpecScale_window <= 17) { + SpecScale_window_tns++; + } + /* Add enough mantissa head room such that the spectrum is still + representable after applying TNS. */ + SpecScale_window = fMax(SpecScale_window, SpecScale_window_tns); + } + + /* store scaling of current window */ + pSpecScale[window] = SpecScale_window; + +#ifdef FUNCTION_CBlock_ScaleSpectralData_func1 + + CBlock_ScaleSpectralData_func1(pSpectrum, maxSfbs, BandOffsets, + SpecScale_window, pSfbScale, window); + +#else /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + for (band = 0; band < maxSfbs; band++) { + int scale = fMin(DFRACT_BITS - 1, + SpecScale_window - pSfbScale[window * 16 + band]); + if (scale) { + FDK_ASSERT(scale > 0); + + /* following relation can be used for optimizations: + * (BandOffsets[i]%4) == 0 for all i */ + int max_index = BandOffsets[band + 1]; + DWORD_ALIGNED(pSpectrum); + for (int index = BandOffsets[band]; index < max_index; index++) { + pSpectrum[index] >>= scale; + } + } + } +#endif /* FUNCTION_CBlock_ScaleSpectralData_func1 */ + } + } +} + +AAC_DECODER_ERROR CBlock_ReadSectionData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags) { + int top, band; + int sect_len, sect_len_incr; + int group; + UCHAR sect_cb; + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + /* HCR input (long) */ + SHORT *pNumLinesInSec = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aNumLineInSec4Hcr; + int numLinesInSecIdx = 0; + UCHAR *pHcrCodeBook = + pAacDecoderChannelInfo->pDynData->specificTo.aac.aCodeBooks4Hcr; + const SHORT *BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection = 0; + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + FDKmemclear(pCodeBook, sizeof(UCHAR) * (8 * 16)); + + const int nbits = + (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) == 1) ? 5 : 3; + + int sect_esc_val = (1 << nbits) - 1; + + UCHAR ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + for (group = 0; group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + group++) { + for (band = 0; band < ScaleFactorBandsTransmitted;) { + sect_len = 0; + if (flags & AC_ER_VCB11) { + sect_cb = (UCHAR)FDKreadBits(bs, 5); + } else + sect_cb = (UCHAR)FDKreadBits(bs, 4); + + if (((flags & AC_ER_VCB11) == 0) || (sect_cb < 11) || + ((sect_cb > 11) && (sect_cb < 16))) { + sect_len_incr = FDKreadBits(bs, nbits); + while (sect_len_incr == sect_esc_val) { + sect_len += sect_esc_val; + sect_len_incr = FDKreadBits(bs, nbits); + } + } else { + sect_len_incr = 1; + } + + sect_len += sect_len_incr; + + top = band + sect_len; + + if (flags & AC_ER_HCR) { + /* HCR input (long) -- collecting sideinfo (for HCR-_long_ only) */ + if (numLinesInSecIdx >= MAX_SFB_HCR) { + return AAC_DEC_PARSE_ERROR; + } + if (top > (int)GetNumberOfScaleFactorBands( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo)) { + return AAC_DEC_PARSE_ERROR; + } + pNumLinesInSec[numLinesInSecIdx] = BandOffsets[top] - BandOffsets[band]; + numLinesInSecIdx++; + if (sect_cb == BOOKSCL) { + return AAC_DEC_INVALID_CODE_BOOK; + } else { + *pHcrCodeBook++ = sect_cb; + } + pAacDecoderChannelInfo->pDynData->specificTo.aac.numberSection++; + } + + /* Check spectral line limits */ + if (IsLongBlock(&(pAacDecoderChannelInfo->icsInfo))) { + if (top > 64) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } else { /* short block */ + if (top + group * 16 > (8 * 16)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + /* Check if decoded codebook index is feasible */ + if ((sect_cb == BOOKSCL) || + ((sect_cb == INTENSITY_HCB || sect_cb == INTENSITY_HCB2) && + pAacDecoderChannelInfo->pDynData->RawDataInfo.CommonWindow == 0)) { + return AAC_DEC_INVALID_CODE_BOOK; + } + + /* Store codebook index */ + for (; band < top; band++) { + pCodeBook[group * 16 + band] = sect_cb; + } + } + } + + return ErrorStatus; +} + +/* mso: provides a faster way to i-quantize a whole band in one go */ + +/** + * \brief inverse quantize one sfb. Each value of the sfb is processed according + * to the formula: spectrum[i] = Sign(spectrum[i]) * Matissa(spectrum[i])^(4/3) + * * 2^(lsb/4). + * \param spectrum pointer to first line of the sfb to be inverse quantized. + * \param noLines number of lines belonging to the sfb. + * \param lsb last 2 bits of the scale factor of the sfb. + * \param scale max allowed shift scale for the sfb. + */ +static inline void InverseQuantizeBand( + FIXP_DBL *RESTRICT spectrum, const FIXP_DBL *RESTRICT InverseQuantTabler, + const FIXP_DBL *RESTRICT MantissaTabler, + const SCHAR *RESTRICT ExponentTabler, INT noLines, INT scale) { + scale = scale + 1; /* +1 to compensate fMultDiv2 shift-right in loop */ + + FIXP_DBL *RESTRICT ptr = spectrum; + FIXP_DBL signedValue; + + for (INT i = noLines; i--;) { + if ((signedValue = *ptr++) != FL2FXCONST_DBL(0)) { + FIXP_DBL value = fAbs(signedValue); + UINT freeBits = CntLeadingZeros(value); + UINT exponent = 32 - freeBits; + + UINT x = (UINT)(LONG)value << (INT)freeBits; + x <<= 1; /* shift out sign bit to avoid masking later on */ + UINT tableIndex = x >> 24; + x = (x >> 20) & 0x0F; + + UINT r0 = (UINT)(LONG)InverseQuantTabler[tableIndex + 0]; + UINT r1 = (UINT)(LONG)InverseQuantTabler[tableIndex + 1]; + UINT temp = (r1 - r0) * x + (r0 << 4); + + value = fMultDiv2((FIXP_DBL)temp, MantissaTabler[exponent]); + + /* + 1 compensates fMultDiv2() */ + scaleValueInPlace(&value, scale + ExponentTabler[exponent]); + + signedValue = (signedValue < (FIXP_DBL)0) ? -value : value; + ptr[-1] = signedValue; + } + } +} + +static inline FIXP_DBL maxabs_D(const FIXP_DBL *pSpectralCoefficient, + const int noLines) { + /* Find max spectral line value of the current sfb */ + FIXP_DBL locMax = (FIXP_DBL)0; + int i; + + DWORD_ALIGNED(pSpectralCoefficient); + + for (i = noLines; i-- > 0;) { + /* Expensive memory access */ + locMax = fMax(fixp_abs(pSpectralCoefficient[i]), locMax); + } + + return locMax; +} + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, UCHAR *band_is_noise, + UCHAR active_band_search) { + int window, group, groupwin, band; + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *RESTRICT pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + SHORT *RESTRICT pSfbScale = pAacDecoderChannelInfo->pDynData->aSfbScale; + SHORT *RESTRICT pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + const SHORT total_bands = + GetScaleFactorBandsTotal(&pAacDecoderChannelInfo->icsInfo); + + FDKmemclear(pAacDecoderChannelInfo->pDynData->aSfbScale, + (8 * 16) * sizeof(SHORT)); + + for (window = 0, group = 0; + group < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++) { + for (groupwin = 0; groupwin < GetWindowGroupLength( + &pAacDecoderChannelInfo->icsInfo, group); + groupwin++, window++) { + /* inverse quantization */ + for (band = 0; band < ScaleFactorBandsTransmitted; band++) { + FIXP_DBL *pSpectralCoefficient = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength) + + BandOffsets[band]; + FIXP_DBL locMax; + + const int noLines = BandOffsets[band + 1] - BandOffsets[band]; + const int bnds = group * 16 + band; + + if ((pCodeBook[bnds] == ZERO_HCB) || + (pCodeBook[bnds] == INTENSITY_HCB) || + (pCodeBook[bnds] == INTENSITY_HCB2)) + continue; + + if (pCodeBook[bnds] == NOISE_HCB) { + /* Leave headroom for PNS values. + 1 because ceil(log2(2^(0.25*3))) = + 1, worst case of additional headroom required because of the + scalefactor. */ + pSfbScale[window * 16 + band] = (pScaleFactor[bnds] >> 2) + 1; + continue; + } + + locMax = maxabs_D(pSpectralCoefficient, noLines); + + if (active_band_search) { + if (locMax != FIXP_DBL(0)) { + band_is_noise[group * 16 + band] = 0; + } + } + + /* Cheap robustness improvement - Do not remove!!! */ + if (fixp_abs(locMax) > (FIXP_DBL)MAX_QUANTIZED_VALUE) { + return AAC_DEC_PARSE_ERROR; + } + + /* Added by Youliy Ninov: + The inverse quantization operation is given by (ISO/IEC 14496-3:2009(E)) + by: + + x_invquant=Sign(x_quant). abs(x_quant)^(4/3) + + We apply a gain, derived from the scale factor for the particular sfb, + according to the following function: + + gain=2^(0.25*ScaleFactor) + + So, after scaling we have: + + x_rescale=gain*x_invquant=Sign(x_quant)*2^(0.25*ScaleFactor)*abs(s_quant)^(4/3) + + We could represent the ScaleFactor as: + + ScaleFactor= (ScaleFactor >> 2)*4 + ScaleFactor %4 + + When we substitute it we get: + + x_rescale=Sign(x_quant)*2^(ScaleFactor>>2)* ( + 2^(0.25*(ScaleFactor%4))*abs(s_quant)^(4/3)) + + When we set: msb=(ScaleFactor>>2) and lsb=(ScaleFactor%4), we obtain: + + x_rescale=Sign(x_quant)*(2^msb)* ( 2^(lsb/4)*abs(s_quant)^(4/3)) + + The rescaled output can be represented by: + mantissa : Sign(x_quant)*( 2^(lsb/4)*abs(s_quant)^(4/3)) + exponent :(2^msb) + + */ + + int msb = pScaleFactor[bnds] >> 2; + + /* Inverse quantize band only if it is not empty */ + if (locMax != FIXP_DBL(0)) { + int lsb = pScaleFactor[bnds] & 0x03; + + int scale = EvaluatePower43(&locMax, lsb); + + scale = CntLeadingZeros(locMax) - scale - 2; + + pSfbScale[window * 16 + band] = msb - scale; + InverseQuantizeBand(pSpectralCoefficient, InverseQuantTable, + MantissaTable[lsb], ExponentTable[lsb], noLines, + scale); + } else { + pSfbScale[window * 16 + band] = msb; + } + + } /* for (band=0; band < ScaleFactorBandsTransmitted; band++) */ + + /* Make sure the array is cleared to the end */ + SHORT start_clear = BandOffsets[ScaleFactorBandsTransmitted]; + SHORT end_clear = BandOffsets[total_bands]; + int diff_clear = (int)(end_clear - start_clear); + FIXP_DBL *pSpectralCoefficient = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, window, + pAacDecoderChannelInfo->granuleLength) + + start_clear; + FDKmemclear(pSpectralCoefficient, diff_clear * sizeof(FIXP_DBL)); + + } /* for (groupwin=0; groupwin < + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo,group); + groupwin++, window++) */ + } /* for (window=0, group=0; group < + GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); group++)*/ + + return AAC_DEC_OK; +} + +AAC_DECODER_ERROR CBlock_ReadSpectralData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags) { + int index, i; + const SHORT *RESTRICT BandOffsets = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + + SPECTRAL_PTR pSpectralCoefficient = + pAacDecoderChannelInfo->pSpectralCoefficient; + + FDK_ASSERT(BandOffsets != NULL); + + FDKmemclear(pSpectralCoefficient, sizeof(SPECTRUM)); + + if ((flags & AC_ER_HCR) == 0) { + int group; + int groupoffset; + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + int ScaleFactorBandsTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + int granuleLength = pAacDecoderChannelInfo->granuleLength; + + groupoffset = 0; + + /* plain huffman decoder short */ + int max_group = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + + for (group = 0; group < max_group; group++) { + int max_groupwin = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, group); + int band; + + int bnds = group * 16; + + int bandOffset1 = BandOffsets[0]; + for (band = 0; band < ScaleFactorBandsTransmitted; band++, bnds++) { + UCHAR currentCB = pCodeBook[bnds]; + int bandOffset0 = bandOffset1; + bandOffset1 = BandOffsets[band + 1]; + + /* patch to run plain-huffman-decoder with vcb11 input codebooks + * (LAV-checking might be possible below using the virtual cb and a + * LAV-table) */ + if ((currentCB >= 16) && (currentCB <= 31)) { + pCodeBook[bnds] = currentCB = 11; + } + if (((currentCB != ZERO_HCB) && (currentCB != NOISE_HCB) && + (currentCB != INTENSITY_HCB) && (currentCB != INTENSITY_HCB2))) { + const CodeBookDescription *hcb = + &AACcodeBookDescriptionTable[currentCB]; + int step = hcb->Dimension; + int offset = hcb->Offset; + int bits = hcb->numBits; + int mask = (1 << bits) - 1; + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + int groupwin; + + FIXP_DBL *mdctSpectrum = + &pSpectralCoefficient[groupoffset * granuleLength]; + + if (offset == 0) { + for (groupwin = 0; groupwin < max_groupwin; groupwin++) { + for (index = bandOffset0; index < bandOffset1; index += step) { + int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + for (i = 0; i < step; i++, idx >>= bits) { + FIXP_DBL tmp = (FIXP_DBL)((idx & mask) - offset); + if (tmp != FIXP_DBL(0)) tmp = (FDKreadBit(bs)) ? -tmp : tmp; + mdctSpectrum[index + i] = tmp; + } + + if (currentCB == ESCBOOK) { + for (int j = 0; j < 2; j++) + mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape( + bs, (LONG)mdctSpectrum[index + j]); + } + } + mdctSpectrum += granuleLength; + } + } else { + for (groupwin = 0; groupwin < max_groupwin; groupwin++) { + for (index = bandOffset0; index < bandOffset1; index += step) { + int idx = CBlock_DecodeHuffmanWordCB(bs, CodeBook); + for (i = 0; i < step; i++, idx >>= bits) { + mdctSpectrum[index + i] = (FIXP_DBL)((idx & mask) - offset); + } + if (currentCB == ESCBOOK) { + for (int j = 0; j < 2; j++) + mdctSpectrum[index + j] = (FIXP_DBL)CBlock_GetEscape( + bs, (LONG)mdctSpectrum[index + j]); + } + } + mdctSpectrum += granuleLength; + } + } + } + } + groupoffset += max_groupwin; + } + /* plain huffman decoding (short) finished */ + } + + /* HCR - Huffman Codeword Reordering short */ + else /* if ( flags & AC_ER_HCR ) */ + + { + H_HCR_INFO hHcr = &pAacDecoderChannelInfo->pComData->overlay.aac.erHcrInfo; + + int hcrStatus = 0; + + /* advanced Huffman decoding starts here (HCR decoding :) */ + if (pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData != 0) { + /* HCR initialization short */ + hcrStatus = HcrInit(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + /* HCR decoding short */ + hcrStatus = + HcrDecoder(hHcr, pAacDecoderChannelInfo, pSamplingRateInfo, bs); + + if (hcrStatus != 0) { +#if HCR_ERROR_CONCEALMENT + HcrMuteErroneousLines(hHcr); +#else + return AAC_DEC_DECODE_FRAME_ERROR; +#endif /* HCR_ERROR_CONCEALMENT */ + } + + FDKpushFor(bs, pAacDecoderChannelInfo->pDynData->specificTo.aac + .lenOfReorderedSpectralData); + } + } + /* HCR - Huffman Codeword Reordering short finished */ + + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo) && + !(flags & (AC_ELD | AC_SCALABLE))) { + /* apply pulse data */ + CPulseData_Apply( + &pAacDecoderChannelInfo->pDynData->specificTo.aac.PulseData, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo), + SPEC_LONG(pSpectralCoefficient)); + } + + return AAC_DEC_OK; +} + +static const FIXP_SGL noise_level_tab[8] = { + /* FDKpow(2, (float)(noise_level-14)/3.0f) * 2; (*2 to compensate for + fMultDiv2) noise_level_tab(noise_level==0) == 0 by definition + */ + FX_DBL2FXCONST_SGL(0x00000000 /*0x0a145173*/), + FX_DBL2FXCONST_SGL(0x0cb2ff5e), + FX_DBL2FXCONST_SGL(0x10000000), + FX_DBL2FXCONST_SGL(0x1428a2e7), + FX_DBL2FXCONST_SGL(0x1965febd), + FX_DBL2FXCONST_SGL(0x20000000), + FX_DBL2FXCONST_SGL(0x28514606), + FX_DBL2FXCONST_SGL(0x32cbfd33)}; + +void CBlock_ApplyNoise(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, ULONG *nfRandomSeed, + UCHAR *band_is_noise) { + const SHORT *swb_offset = GetScaleFactorBandOffsets( + &pAacDecoderChannelInfo->icsInfo, pSamplingRateInfo); + int g, win, gwin, sfb, noiseFillingStartOffset, nfStartOffset_sfb; + + /* Obtain noise level and scale factor offset. */ + int noise_level = pAacDecoderChannelInfo->pDynData->specificTo.usac + .fd_noise_level_and_offset >> + 5; + const FIXP_SGL noiseVal_pos = noise_level_tab[noise_level]; + + /* noise_offset can change even when noise_level=0. Neccesary for IGF stereo + * filling */ + const int noise_offset = (pAacDecoderChannelInfo->pDynData->specificTo.usac + .fd_noise_level_and_offset & + 0x1f) - + 16; + + int max_sfb = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + + noiseFillingStartOffset = + (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + ? 20 + : 160; + if (pAacDecoderChannelInfo->granuleLength == 96) { + noiseFillingStartOffset = + (3 * noiseFillingStartOffset) / + 4; /* scale offset with 3/4 for coreCoderFrameLength == 768 */ + } + + /* determine sfb from where on noise filling is applied */ + for (sfb = 0; swb_offset[sfb] < noiseFillingStartOffset; sfb++) + ; + nfStartOffset_sfb = sfb; + + /* if (noise_level!=0) */ + { + for (g = 0, win = 0; g < GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + g++) { + int windowGroupLength = + GetWindowGroupLength(&pAacDecoderChannelInfo->icsInfo, g); + for (sfb = nfStartOffset_sfb; sfb < max_sfb; sfb++) { + int bin_start = swb_offset[sfb]; + int bin_stop = swb_offset[sfb + 1]; + + int flagN = band_is_noise[g * 16 + sfb]; + + /* if all bins of one sfb in one window group are zero modify the scale + * factor by noise_offset */ + if (flagN) { + /* Change scaling factors for empty signal bands */ + pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] += + noise_offset; + /* scale factor "sf" implied gain "g" is g = 2^(sf/4) */ + for (gwin = 0; gwin < windowGroupLength; gwin++) { + pAacDecoderChannelInfo->pDynData + ->aSfbScale[(win + gwin) * 16 + sfb] += (noise_offset >> 2); + } + } + + ULONG seed = *nfRandomSeed; + /* + 1 because exponent of MantissaTable[lsb][0] is always 1. */ + int scale = + (pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] >> + 2) + + 1; + int lsb = + pAacDecoderChannelInfo->pDynData->aScaleFactor[g * 16 + sfb] & 3; + FIXP_DBL mantissa = MantissaTable[lsb][0]; + + for (gwin = 0; gwin < windowGroupLength; gwin++) { + FIXP_DBL *pSpec = + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, win + gwin, + pAacDecoderChannelInfo->granuleLength); + + int scale1 = scale - pAacDecoderChannelInfo->pDynData + ->aSfbScale[(win + gwin) * 16 + sfb]; + FIXP_DBL scaled_noiseVal_pos = + scaleValue(fMultDiv2(noiseVal_pos, mantissa), scale1); + FIXP_DBL scaled_noiseVal_neg = -scaled_noiseVal_pos; + + /* If the whole band is zero, just fill without checking */ + if (flagN) { + for (int bin = bin_start; bin < bin_stop; bin++) { + seed = (ULONG)( + (UINT64)seed * 69069 + + 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */ + pSpec[bin] = + (seed & 0x10000) ? scaled_noiseVal_neg : scaled_noiseVal_pos; + } /* for (bin...) */ + } + /*If band is sparsely filled, check for 0 and fill */ + else { + for (int bin = bin_start; bin < bin_stop; bin++) { + if (pSpec[bin] == (FIXP_DBL)0) { + seed = (ULONG)( + (UINT64)seed * 69069 + + 5); /* Inlined: UsacRandomSign - origin in usacdec_lpd.h */ + pSpec[bin] = (seed & 0x10000) ? scaled_noiseVal_neg + : scaled_noiseVal_pos; + } + } /* for (bin...) */ + } + + } /* for (gwin...) */ + *nfRandomSeed = seed; + } /* for (sfb...) */ + win += windowGroupLength; + } /* for (g...) */ + + } /* ... */ +} + +AAC_DECODER_ERROR CBlock_ReadAcSpectralData( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT frame_length, + const UINT flags) { + AAC_DECODER_ERROR errorAAC = AAC_DEC_OK; + ARITH_CODING_ERROR error = ARITH_CODER_OK; + int arith_reset_flag, lg, numWin, win, winLen; + const SHORT *RESTRICT BandOffsets; + + /* number of transmitted spectral coefficients */ + BandOffsets = GetScaleFactorBandOffsets(&pAacDecoderChannelInfo->icsInfo, + pSamplingRateInfo); + lg = BandOffsets[GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo->icsInfo)]; + + numWin = GetWindowsPerFrame(&pAacDecoderChannelInfo->icsInfo); + winLen = (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) + ? (int)frame_length + : (int)frame_length / numWin; + + if (flags & AC_INDEP) { + arith_reset_flag = 1; + } else { + arith_reset_flag = (USHORT)FDKreadBits(hBs, 1); + } + + for (win = 0; win < numWin; win++) { + error = + CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs, + SPEC(pAacDecoderChannelInfo->pSpectralCoefficient, + win, pAacDecoderChannelInfo->granuleLength), + lg, winLen, arith_reset_flag && (win == 0)); + if (error != ARITH_CODER_OK) { + goto bail; + } + } + +bail: + if (error == ARITH_CODER_ERROR) { + errorAAC = AAC_DEC_PARSE_ERROR; + } + + return errorAAC; +} + +void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, const UINT flags, + const UINT elFlags, const int channel, + const int common_window) { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_MPEGD_RES | AC_RSV603DA))) { + CPns_Apply(&pAacDecoderChannelInfo[channel]->data.aac.PnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pAacDecoderChannelInfo[channel]->specScale, + pAacDecoderChannelInfo[channel]->pDynData->aScaleFactor, + pSamplingRateInfo, + pAacDecoderChannelInfo[channel]->granuleLength, channel); + } + + UCHAR nbands = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[channel]->icsInfo); + + CTns_Apply(&pAacDecoderChannelInfo[channel]->pDynData->TnsData, + &pAacDecoderChannelInfo[channel]->icsInfo, + pAacDecoderChannelInfo[channel]->pSpectralCoefficient, + pSamplingRateInfo, pAacDecoderChannelInfo[channel]->granuleLength, + nbands, (elFlags & AC_EL_ENHANCED_NOISE) ? 1 : 0, flags); +} + +static int getWindow2Nr(int length, int shape) { + int nr = 0; + + if (shape == 2) { + /* Low Overlap, 3/4 zeroed */ + nr = (length * 3) >> 2; + } + + return nr; +} + +FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n) { + FIXP_DBL corr = (FIXP_DBL)0; + FIXP_DBL ener = (FIXP_DBL)1; + + int headroom_x = getScalefactor(x, n); + int headroom_y = getScalefactor(y, n); + + /*Calculate the normalization necessary due to addition*/ + /* Check for power of two /special case */ + INT width_shift = (INT)(fNormz((FIXP_DBL)n)); + /* Get the number of bits necessary minus one, because we need one sign bit + * only */ + width_shift = 31 - width_shift; + + for (int i = 0; i < n; i++) { + corr += + fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >> width_shift; + ener += fPow2Div2((y[i] << headroom_y)) >> width_shift; + } + + int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1; + int exp_ener = ((17 - headroom_y) << 1) + width_shift + 1; + + int temp_exp = 0; + FIXP_DBL output = fDivNormSigned(corr, ener, &temp_exp); + + int output_exp = (exp_corr - exp_ener) + temp_exp; + + INT output_shift = 17 - output_exp; + output_shift = fMin(output_shift, 31); + + output = scaleValue(output, -output_shift); + + return output; +} + +void CBlock_FrequencyToTime( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, + UINT elFlags, INT elCh) { + int fr, fl, tl, nSpec; + +#if defined(FDK_ASSERT_ENABLE) + LONG nSamples; +#endif + + /* Determine left slope length (fl), right slope length (fr) and transform + length (tl). USAC: The slope length may mismatch with the previous frame in + case of LPD / FD transitions. The adjustment is handled by the imdct + implementation. + */ + tl = frameLen; + nSpec = 1; + + switch (pAacDecoderChannelInfo->icsInfo.WindowSequence) { + default: + case BLOCK_LONG: + fl = frameLen; + fr = frameLen - + getWindow2Nr(frameLen, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)); + /* New startup needs differentiation between sine shape and low overlap + shape. This is a special case for the LD-AAC transformation windows, + because the slope length can be different while using the same window + sequence. */ + if (pAacDecoderStaticChannelInfo->IMdct.prev_tl == 0) { + fl = fr; + } + break; + case BLOCK_STOP: + fl = frameLen >> 3; + fr = frameLen; + break; + case BLOCK_START: /* or StopStartSequence */ + fl = frameLen; + fr = frameLen >> 3; + break; + case BLOCK_SHORT: + fl = fr = frameLen >> 3; + tl >>= 3; + nSpec = 8; + break; + } + + { + int last_frame_lost = pAacDecoderStaticChannelInfo->last_lpc_lost; + + if (pAacDecoderStaticChannelInfo->last_core_mode == LPD) { + INT fac_FB = 1; + if (elFlags & AC_EL_FULLBANDLPD) { + fac_FB = 2; + } + + FIXP_DBL *synth; + + /* Keep some free space at the beginning of the buffer. To be used for + * past data */ + if (!(elFlags & AC_EL_LPDSTEREOIDX)) { + synth = pWorkBuffer1 + ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB); + } else { + synth = pWorkBuffer1 + PIT_MAX_MAX * fac_FB; + } + + int fac_length = + (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT) + ? (frameLen >> 4) + : (frameLen >> 3); + + INT pitch[NB_SUBFR_SUPERFR + SYN_SFD]; + FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD]; + + int nbDiv = (elFlags & AC_EL_FULLBANDLPD) ? 2 : 4; + int lFrame = (elFlags & AC_EL_FULLBANDLPD) ? frameLen / 2 : frameLen; + int nbSubfr = + lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */ + int LpdSfd = (nbDiv * nbSubfr) >> 1; + int SynSfd = LpdSfd - BPF_SFD; + + FDKmemclear( + pitch, + sizeof( + pitch)); // added to prevent ferret errors in bass_pf_1sf_delay + FDKmemclear(pit_gain, sizeof(pit_gain)); + + /* FAC case */ + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0 || + pAacDecoderStaticChannelInfo->last_lpd_mode == 4) { + FIXP_DBL fac_buf[LFAC]; + FIXP_LPC *A = pAacDecoderChannelInfo->data.usac.lp_coeff[0]; + + if (!frameOk || last_frame_lost || + (pAacDecoderChannelInfo->data.usac.fac_data[0] == NULL)) { + FDKmemclear(fac_buf, + pAacDecoderChannelInfo->granuleLength * sizeof(FIXP_DBL)); + pAacDecoderChannelInfo->data.usac.fac_data[0] = fac_buf; + pAacDecoderChannelInfo->data.usac.fac_data_e[0] = 0; + } + + INT A_exp; /* linear prediction coefficients exponent */ + { + for (int i = 0; i < M_LP_FILTER_ORDER; i++) { + A[i] = FX_DBL2FX_LPC(fixp_cos( + fMult(pAacDecoderStaticChannelInfo->lpc4_lsf[i], + FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + + E_LPC_f_lsp_a_conversion(A, A, &A_exp); + } + +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + CLpd_FAC_Acelp2Mdct( + &pAacDecoderStaticChannelInfo->IMdct, synth, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, + pAacDecoderChannelInfo->data.usac.fac_data[0], + pAacDecoderChannelInfo->data.usac.fac_data_e[0], fac_length, + frameLen, tl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, A, A_exp, &pAacDecoderStaticChannelInfo->acelp, + (FIXP_DBL)0, /* FAC gain has already been applied. */ + (last_frame_lost || !frameOk), 1, + pAacDecoderStaticChannelInfo->last_lpd_mode, 0, + pAacDecoderChannelInfo->currAliasingSymmetry); + + } else { +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + imlt_block( + &pAacDecoderStaticChannelInfo->IMdct, synth, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl, + FDKgetWindowSlope( + fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, (FIXP_DBL)0, + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + } + FDK_ASSERT(nSamples == frameLen); + + /* The "if" clause is entered both for fullbandLpd mono and + * non-fullbandLpd*. The "else"-> just for fullbandLpd stereo*/ + if (!(elFlags & AC_EL_LPDSTEREOIDX)) { + FDKmemcpy(pitch, pAacDecoderStaticChannelInfo->old_T_pf, + SynSfd * sizeof(INT)); + FDKmemcpy(pit_gain, pAacDecoderStaticChannelInfo->old_gain_pf, + SynSfd * sizeof(FIXP_DBL)); + + for (int i = SynSfd; i < LpdSfd + 3; i++) { + pitch[i] = L_SUBFR; + pit_gain[i] = (FIXP_DBL)0; + } + + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 0) { + pitch[SynSfd] = pitch[SynSfd - 1]; + pit_gain[SynSfd] = pit_gain[SynSfd - 1]; + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + pitch[SynSfd + 1] = pitch[SynSfd]; + pit_gain[SynSfd + 1] = pit_gain[SynSfd]; + } + } + + /* Copy old data to the beginning of the buffer */ + { + FDKmemcpy( + pWorkBuffer1, pAacDecoderStaticChannelInfo->old_synth, + ((PIT_MAX_MAX - (1 * L_SUBFR)) * fac_FB) * sizeof(FIXP_DBL)); + } + + FIXP_DBL *p2_synth = pWorkBuffer1 + (PIT_MAX_MAX * fac_FB); + + /* recalculate pitch gain to allow postfilering on FAC area */ + for (int i = 0; i < SynSfd + 2; i++) { + int T = pitch[i]; + FIXP_DBL gain = pit_gain[i]; + + if (gain > (FIXP_DBL)0) { + gain = get_gain(&p2_synth[i * L_SUBFR * fac_FB], + &p2_synth[(i * L_SUBFR * fac_FB) - fac_FB * T], + L_SUBFR * fac_FB); + pit_gain[i] = gain; + } + } + + bass_pf_1sf_delay(p2_synth, pitch, pit_gain, frameLen, + (LpdSfd + 2) * L_SUBFR + BPF_SFD * L_SUBFR, + frameLen - (LpdSfd + 4) * L_SUBFR, outSamples, + pAacDecoderStaticChannelInfo->mem_bpf); + } + + } else /* last_core_mode was not LPD */ + { + FIXP_DBL *tmp = + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->mdctOutTemp; +#if defined(FDK_ASSERT_ENABLE) + nSamples = +#endif + imlt_block(&pAacDecoderStaticChannelInfo->IMdct, tmp, + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale, nSpec, frameLen, tl, + FDKgetWindowSlope( + fl, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope( + fr, GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, (FIXP_DBL)0, + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + + scaleValuesSaturate(outSamples, tmp, frameLen, MDCT_OUT_HEADROOM); + } + } + + FDK_ASSERT(nSamples == frameLen); + + pAacDecoderStaticChannelInfo->last_core_mode = + (pAacDecoderChannelInfo->icsInfo.WindowSequence == BLOCK_SHORT) ? FD_SHORT + : FD_LONG; + pAacDecoderStaticChannelInfo->last_lpd_mode = 255; +} + +#include "ldfiltbank.h" +void CBlock_FrequencyToTimeLowDelay( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + const short frameLen) { + InvMdctTransformLowDelay_fdk( + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient), + pAacDecoderChannelInfo->specScale[0], outSamples, + pAacDecoderStaticChannelInfo->pOverlapBuffer, frameLen); +} diff --git a/fdk-aac/libAACdec/src/block.h b/fdk-aac/libAACdec/src/block.h new file mode 100644 index 0000000..f0f56cd --- /dev/null +++ b/fdk-aac/libAACdec/src/block.h @@ -0,0 +1,345 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: long/short-block decoding + +*******************************************************************************/ + +#ifndef BLOCK_H +#define BLOCK_H + +#include "common_fix.h" + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +/* PNS (of block) */ +void CPns_Read(CPnsData *pPnsData, HANDLE_FDK_BITSTREAM bs, + const CodeBookDescription *hcb, SHORT *pScaleFactor, + UCHAR global_gain, int band, int group); + +void CPns_Apply(const CPnsData *pPnsData, const CIcsInfo *pIcsInfo, + SPECTRAL_PTR pSpectrum, const SHORT *pSpecScale, + const SHORT *pScaleFactor, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const int channel); + +void CBlock_ApplyNoise(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, ULONG *nfRandomSeed, + UCHAR *band_is_noise); + +/* TNS (of block) */ +/*! + \brief Read tns data-present flag from bitstream + + The function reads the data-present flag for tns from + the bitstream. + + \return none +*/ +void CTns_ReadDataPresentFlag(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData); + +void CTns_ReadDataPresentUsac(HANDLE_FDK_BITSTREAM hBs, CTnsData *pTnsData0, + CTnsData *pTnsData1, UCHAR *ptns_on_lr, + const CIcsInfo *pIcsInfo, const UINT flags, + const UINT elFlags, const int fCommonWindow); + +AAC_DECODER_ERROR CTns_Read(HANDLE_FDK_BITSTREAM bs, CTnsData *pTnsData, + const CIcsInfo *pIcsInfo, const UINT flags); + +void CTns_Apply(CTnsData *RESTRICT pTnsData, /*!< pointer to aac decoder info */ + const CIcsInfo *pIcsInfo, SPECTRAL_PTR pSpectralCoefficient, + const SamplingRateInfo *pSamplingRateInfo, + const INT granuleLength, const UCHAR nbands, + const UCHAR igf_active, const UINT flags); + +/* Block */ + +LONG CBlock_GetEscape(HANDLE_FDK_BITSTREAM bs, const LONG q); + +/** + * \brief Read scale factor data. See chapter 4.6.2.3.2 of ISO/IEC 14496-3. + * The SF_OFFSET = 100 value referenced in chapter 4.6.2.3.3 is already + * substracted from the scale factor values. Also includes PNS data reading. + * \param bs bit stream handle data source + * \param pAacDecoderChannelInfo channel context info were decoded data is + * stored into. + * \param flags the decoder flags. + */ +AAC_DECODER_ERROR CBlock_ReadScaleFactorData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, HANDLE_FDK_BITSTREAM bs, + const UINT flags); + +/** + * \brief Read Huffman encoded spectral data. + * \param pAacDecoderChannelInfo channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + * \param flags syntax flags. + */ +AAC_DECODER_ERROR CBlock_ReadSpectralData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags); + +/** + * \brief Read Arithmetic encoded spectral data. + * \param pAacDecoderChannelInfo channel context info. + * \param pAacDecoderStaticChannelInfo static channel context info. + * \param pSamplingRateInfo sampling rate info (sfb offsets). + * \param frame_length spectral window length. + * \param flags syntax flags. + * \return error code. + */ +AAC_DECODER_ERROR CBlock_ReadAcSpectralData( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT frame_length, + const UINT flags); + +AAC_DECODER_ERROR CBlock_ReadSectionData( + HANDLE_FDK_BITSTREAM bs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const UINT flags); + +/** + * \brief find a common exponent (shift factor) for all sfb in each Spectral + * window, and store them into CAacDecoderChannelInfo::specScale. + * \param pAacDecoderChannelInfo channel context info. + * \param UCHAR maxSfbs maximum number of SFBs to be processed (might differ + * from pAacDecoderChannelInfo->icsInfo.MaxSfBands) + * \param pSamplingRateInfo sampling rate info (sfb offsets). + */ +void CBlock_ScaleSpectralData(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR maxSfbs, + SamplingRateInfo *pSamplingRateInfo); + +/** + * \brief Apply TNS and PNS tools. + */ +void ApplyTools(CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + const SamplingRateInfo *pSamplingRateInfo, const UINT flags, + const UINT elFlags, const int channel, const int maybe_jstereo); + +/** + * \brief Transform MDCT spectral data into time domain + */ +void CBlock_FrequencyToTime( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + const SHORT frameLen, const int frameOk, FIXP_DBL *pWorkBuffer1, + UINT elFlags, INT elCh); + +/** + * \brief Transform double lapped MDCT (AAC-ELD) spectral data into time domain. + */ +void CBlock_FrequencyToTimeLowDelay( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM outSamples[], + const short frameLen); + +AAC_DECODER_ERROR CBlock_InverseQuantizeSpectralData( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + SamplingRateInfo *pSamplingRateInfo, UCHAR *band_is_noise, + UCHAR active_band_search); + +/** + * \brief Calculate 2^(lsb/4) * value^(4/3) + * \param pValue pointer to quantized value. The inverse quantized result is + * stored back here. + * \param lsb 2 LSBs of the scale factor (scaleFactor % 4) applied as power 2 + * factor to the resulting inverse quantized value. + * \return the exponent of the result (mantissa) stored into *pValue. + */ +FDK_INLINE +int EvaluatePower43(FIXP_DBL *pValue, UINT lsb) { + FIXP_DBL value; + UINT freeBits; + UINT exponent; + + value = *pValue; + freeBits = fNormz(value); + exponent = DFRACT_BITS - freeBits; + FDK_ASSERT(exponent < 14); + + UINT x = (((int)value << freeBits) >> 19); + UINT tableIndex = (x & 0x0FFF) >> 4; + FIXP_DBL invQVal; + + x = x & 0x0F; + + UINT r0 = (LONG)InverseQuantTable[tableIndex + 0]; + UINT r1 = (LONG)InverseQuantTable[tableIndex + 1]; + USHORT nx = 16 - x; + UINT temp = (r0)*nx + (r1)*x; + invQVal = (FIXP_DBL)temp; + + FDK_ASSERT(lsb < 4); + *pValue = fMultDiv2(invQVal, MantissaTable[lsb][exponent]); + + /* + 1 compensates fMultDiv2(). */ + return ExponentTable[lsb][exponent] + 1; +} + +/* Recalculate gain */ +FIXP_DBL get_gain(const FIXP_DBL *x, const FIXP_DBL *y, int n); + +/** + * \brief determine the required shift scale for the given quantized value and + * scale (factor % 4) value. + */ +FDK_INLINE int GetScaleFromValue(FIXP_DBL value, unsigned int lsb) { + if (value != (FIXP_DBL)0) { + int scale = EvaluatePower43(&value, lsb); + return CntLeadingZeros(value) - scale - 2; + } else + return 0; /* Return zero, because its useless to scale a zero value, saves + workload and avoids scaling overshifts. */ +} + +/*! + \brief Read huffman codeword + + The function reads the huffman codeword from the bitstream and + returns the index value. + + \return index value +*/ +inline int CBlock_DecodeHuffmanWord( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const CodeBookDescription *hcb) /*!< pointer to codebook description */ +{ + UINT val; + UINT index = 0; + const USHORT(*CodeBook)[HuffmanEntries] = hcb->CodeBook; + + while (1) { + val = CodeBook[index] + [FDKreadBits(bs, HuffmanBits)]; /* Expensive memory access */ + + if ((val & 1) == 0) { + index = val >> 2; + continue; + } else { + if (val & 2) { + FDKpushBackCache(bs, 1); + } + + val >>= 2; + break; + } + } + + return val; +} +inline int CBlock_DecodeHuffmanWordCB( + HANDLE_FDK_BITSTREAM bs, /*!< pointer to bitstream */ + const USHORT ( + *CodeBook)[HuffmanEntries]) /*!< pointer to codebook description */ +{ + UINT index = 0; + + while (1) { + index = CodeBook[index][FDKread2Bits(bs)]; /* Expensive memory access */ + if (index & 1) break; + index >>= 2; + } + if (index & 2) { + FDKpushBackCache(bs, 1); + } + return index >> 2; +} + +#endif /* #ifndef BLOCK_H */ diff --git a/fdk-aac/libAACdec/src/channel.cpp b/fdk-aac/libAACdec/src/channel.cpp new file mode 100644 index 0000000..a020034 --- /dev/null +++ b/fdk-aac/libAACdec/src/channel.cpp @@ -0,0 +1,924 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#include "channel.h" +#include "aacdecoder.h" +#include "block.h" +#include "aacdec_tns.h" +#include "FDK_bitstream.h" + +#include "conceal.h" + +#include "rvlc.h" + +#include "aacdec_hcr.h" + +#include "usacdec_lpd.h" +#include "usacdec_fac.h" + +static void MapMidSideMaskToPnsCorrelation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2]) { + int group; + + for (group = 0; group < pAacDecoderChannelInfo[L]->icsInfo.WindowGroups; + group++) { + UCHAR groupMask = 1 << group; + + for (UCHAR band = 0; band < pAacDecoderChannelInfo[L]->icsInfo.MaxSfBands; + band++) { + if (pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] & + groupMask) { /* channels are correlated */ + CPns_SetCorrelation(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, + band, 0); + + if (CPns_IsPnsUsed(&pAacDecoderChannelInfo[L]->data.aac.PnsData, group, + band) && + CPns_IsPnsUsed(&pAacDecoderChannelInfo[R]->data.aac.PnsData, group, + band)) + pAacDecoderChannelInfo[L]->pComData->jointStereoData.MsUsed[band] ^= + groupMask; /* clear the groupMask-bit */ + } + } + } +} + +static void Clean_Complex_Prediction_coefficients( + CJointStereoPersistentData *pJointStereoPersistentData, int windowGroups, + const int low_limit, const int high_limit) { + for (int group = 0; group < windowGroups; group++) { + for (int sfb = low_limit; sfb < high_limit; sfb++) { + pJointStereoPersistentData->alpha_q_re_prev[group][sfb] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][sfb] = 0; + } + } +} + +/*! + \brief Decode channel pair element + + The function decodes a channel pair element. + + \return none +*/ +void CChannelElement_Decode( + CAacDecoderChannelInfo + *pAacDecoderChannelInfo[2], /*!< pointer to aac decoder channel info */ + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, UINT flags, UINT elFlags, + int el_channels) { + int ch = 0; + + int maxSfBandsL = 0, maxSfBandsR = 0; + int maybe_jstereo = (el_channels > 1); + + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA) && el_channels == 2) { + if (pAacDecoderChannelInfo[L]->data.usac.core_mode || + pAacDecoderChannelInfo[R]->data.usac.core_mode) { + maybe_jstereo = 0; + } + } + + if (maybe_jstereo) { + maxSfBandsL = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[L]->icsInfo); + maxSfBandsR = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[R]->icsInfo); + + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + if (pAacDecoderChannelInfo[L]->data.aac.PnsData.PnsActive || + pAacDecoderChannelInfo[R]->data.aac.PnsData.PnsActive) { + MapMidSideMaskToPnsCorrelation(pAacDecoderChannelInfo); + } + } + /* if tns_on_lr == 1 run MS */ /* && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_active + == 1) */ + if (((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 1)) || + ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) == 0)) { + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + CJointStereo_ApplyMS( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + pAacDecoderChannelInfo[L]->pSpectralCoefficient, + pAacDecoderChannelInfo[R]->pSpectralCoefficient, + pAacDecoderChannelInfo[L]->pDynData->aSfbScale, + pAacDecoderChannelInfo[R]->pDynData->aSfbScale, + pAacDecoderChannelInfo[L]->specScale, + pAacDecoderChannelInfo[R]->specScale, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), max_sfb_ste, + maxSfBandsL, maxSfBandsR, + pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev, + &(pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev_e), + 1); + + } /* if ( ((elFlags & AC_EL_USAC_CP_POSSIBLE).... */ + } /* if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow)*/ + + /* apply intensity stereo */ /* modifies pAacDecoderChannelInfo[]->aSpecSfb + */ + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + if ((pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow == + 1) && + (el_channels == 2)) { + CJointStereo_ApplyIS( + pAacDecoderChannelInfo, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), + GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo[L]->icsInfo)); + } + } + } /* maybe_stereo */ + + for (ch = 0; ch < el_channels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_LPD) { + /* Decode LPD data */ + CLpdChannelStream_Decode(pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], flags); + } else { + UCHAR noSfbs = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo[ch]->icsInfo); + /* For USAC common window: max_sfb of both channels may differ + * (common_max_sfb == 0). */ + if ((maybe_jstereo == 1) && + (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow == + 1)) { + noSfbs = fMax(maxSfBandsL, maxSfBandsR); + } + int CP_active = 0; + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + CP_active = pAacDecoderChannelInfo[ch] + ->pComData->jointStereoData.cplx_pred_flag; + } + + /* Omit writing of pAacDecoderChannelInfo[ch]->specScale for complex + stereo prediction since scaling has already been carried out. */ + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + if ((!CP_active) || (CP_active && (max_sfb_ste < noSfbs)) || + ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0))) { + CBlock_ScaleSpectralData(pAacDecoderChannelInfo[ch], noSfbs, + pSamplingRateInfo); + + /*Active for the case of TNS applied before MS/CP*/ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0)) { + if (IsLongBlock(&pAacDecoderChannelInfo[ch]->icsInfo)) { + for (int i = 0; i < noSfbs; i++) { + pAacDecoderChannelInfo[ch]->pDynData->aSfbScale[i] = + pAacDecoderChannelInfo[ch]->specScale[0]; + } + } else { + for (int i = 0; i < 8; i++) { + for (int j = 0; j < noSfbs; j++) { + pAacDecoderChannelInfo[ch]->pDynData->aSfbScale[i * 16 + j] = + pAacDecoderChannelInfo[ch]->specScale[i]; + } + } + } + } + } + } + } /* End "for (ch = 0; ch < el_channels; ch++)" */ + + if (maybe_jstereo) { + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + } /* CommonWindow */ + else { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + FDKmemclear( + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.alpha_q_re_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * sizeof(SHORT)); + FDKmemclear( + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.alpha_q_im_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * sizeof(SHORT)); + } + } + + } /* if (maybe_jstereo) */ + + for (ch = 0; ch < el_channels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_LPD) { + } else { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + /* Use same seed for coupled channels (CPE) */ + int pnsCh = (ch > 0) ? L : ch; + CPns_UpdateNoiseState( + &pAacDecoderChannelInfo[ch]->data.aac.PnsData, + pAacDecoderChannelInfo[pnsCh]->data.aac.PnsData.currentSeed, + pAacDecoderChannelInfo[ch]->pComData->pnsRandomSeed); + } + + if ((!(flags & (AC_USAC))) || + ((flags & (AC_USAC)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_active == + 1)) || + (maybe_jstereo == 0)) { + ApplyTools( + pAacDecoderChannelInfo, pSamplingRateInfo, flags, elFlags, ch, + pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow); + } + } /* End "} else" */ + } /* End "for (ch = 0; ch < el_channels; ch++)" */ + + if (maybe_jstereo) { + /* apply ms */ + if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) { + /* if tns_on_lr == 0 run MS */ + if ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && + (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == + 0)) { + int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); + + CJointStereo_ApplyMS( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + pAacDecoderChannelInfo[L]->pSpectralCoefficient, + pAacDecoderChannelInfo[R]->pSpectralCoefficient, + pAacDecoderChannelInfo[L]->pDynData->aSfbScale, + pAacDecoderChannelInfo[R]->pDynData->aSfbScale, + pAacDecoderChannelInfo[L]->specScale, + pAacDecoderChannelInfo[R]->specScale, + GetScaleFactorBandOffsets(&pAacDecoderChannelInfo[L]->icsInfo, + pSamplingRateInfo), + GetWindowGroupLengthTable(&pAacDecoderChannelInfo[L]->icsInfo), + GetWindowGroups(&pAacDecoderChannelInfo[L]->icsInfo), max_sfb_ste, + maxSfBandsL, maxSfBandsR, + pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev, + &(pAacDecoderChannelInfo[L] + ->pComData->jointStereoData.store_dmx_re_prev_e), + 1); + } + + } /* if (pAacDecoderChannelInfo[L]->pDynData->RawDataInfo.CommonWindow) */ + + } /* if (maybe_jstereo) */ + + for (ch = 0; ch < el_channels; ch++) { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.clearSpectralCoeffs = 0; + } + } + + CRvlc_ElementCheck(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags, el_channels); +} + +void CChannel_CodebookTableInit( + CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + int b, w, maxBands, maxWindows; + int maxSfb = GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + UCHAR *pCodeBook = pAacDecoderChannelInfo->pDynData->aCodeBook; + + if (IsLongBlock(&pAacDecoderChannelInfo->icsInfo)) { + maxBands = 64; + maxWindows = 1; + } else { + maxBands = 16; + maxWindows = 8; + } + + for (w = 0; w < maxWindows; w++) { + for (b = 0; b < maxSfb; b++) { + pCodeBook[b] = ESCBOOK; + } + for (; b < maxBands; b++) { + pCodeBook[b] = ZERO_HCB; + } + pCodeBook += maxBands; + } +} + +/* + * Arbitrary order bitstream parser + */ +AAC_DECODER_ERROR CChannelElement_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const AUDIO_OBJECT_TYPE aot, SamplingRateInfo *pSamplingRateInfo, + const UINT flags, const UINT elFlags, const UINT frame_length, + const UCHAR numberOfChannels, const SCHAR epConfig, + HANDLE_TRANSPORTDEC pTpDec) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + const element_list_t *list; + int i, ch, decision_bit; + int crcReg1 = -1, crcReg2 = -1; + int cplxPred; + int ind_sw_cce_flag = 0, num_gain_element_lists = 0; + + FDK_ASSERT((numberOfChannels == 1) || (numberOfChannels == 2)); + + /* Get channel element sequence table */ + list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, elFlags); + if (list == NULL) { + error = AAC_DEC_UNSUPPORTED_FORMAT; + goto bail; + } + + CTns_Reset(&pAacDecoderChannelInfo[0]->pDynData->TnsData); + /* Set common window to 0 by default. If signalized in the bit stream it will + * be overwritten later explicitely */ + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 0; + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active = 0; + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr = 0; + } + if (numberOfChannels == 2) { + CTns_Reset(&pAacDecoderChannelInfo[1]->pDynData->TnsData); + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = 0; + } + + cplxPred = 0; + if (pAacDecoderStaticChannelInfo != NULL) { + if (elFlags & AC_EL_USAC_CP_POSSIBLE) { + pAacDecoderChannelInfo[0]->pComData->jointStereoData.cplx_pred_flag = 0; + cplxPred = 1; + } + } + + if (0 || (flags & (AC_ELD | AC_SCALABLE))) { + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 1; + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + switch (list->id[i]) { + case element_instance_tag: + pAacDecoderChannelInfo[0]->ElementInstanceTag = FDKreadBits(hBs, 4); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->ElementInstanceTag = + pAacDecoderChannelInfo[0]->ElementInstanceTag; + } + break; + case common_window: + decision_bit = + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow = + FDKreadBits(hBs, 1); + if (numberOfChannels == 2) { + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow; + } + break; + case ics_info: + /* store last window sequence (utilized in complex stereo prediction) + * before reading new channel-info */ + if (cplxPred) { + if (pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) { + pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData.winSeqPrev = + pAacDecoderChannelInfo[0]->icsInfo.WindowSequence; + pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData.winShapePrev = + pAacDecoderChannelInfo[0]->icsInfo.WindowShape; + } + } + /* Read individual channel info */ + error = IcsRead(hBs, &pAacDecoderChannelInfo[ch]->icsInfo, + pSamplingRateInfo, flags); + + if (elFlags & AC_EL_LFE && + GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) != + BLOCK_LONG) { + error = AAC_DEC_PARSE_ERROR; + break; + } + + if (numberOfChannels == 2 && + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow) { + pAacDecoderChannelInfo[1]->icsInfo = + pAacDecoderChannelInfo[0]->icsInfo; + } + break; + + case common_max_sfb: + if (FDKreadBit(hBs) == 0) { + error = IcsReadMaxSfb(hBs, &pAacDecoderChannelInfo[1]->icsInfo, + pSamplingRateInfo); + } + break; + + case ltp_data_present: + if (FDKreadBits(hBs, 1) != 0) { + error = AAC_DEC_UNSUPPORTED_PREDICTION; + } + break; + + case ms: + + INT max_sfb_ste; + INT max_sfb_ste_clear; + + max_sfb_ste = GetScaleMaxFactorBandsTransmitted( + &pAacDecoderChannelInfo[0]->icsInfo, + &pAacDecoderChannelInfo[1]->icsInfo); + + max_sfb_ste_clear = 64; + + pAacDecoderChannelInfo[0]->icsInfo.max_sfb_ste = (UCHAR)max_sfb_ste; + pAacDecoderChannelInfo[1]->icsInfo.max_sfb_ste = (UCHAR)max_sfb_ste; + + if (flags & (AC_USAC | AC_RSV603DA) && + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.CommonWindow == + 0) { + Clean_Complex_Prediction_coefficients( + &pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData, + GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo), 0, 64); + } + + if (CJointStereo_Read( + hBs, &pAacDecoderChannelInfo[0]->pComData->jointStereoData, + GetWindowGroups(&pAacDecoderChannelInfo[0]->icsInfo), + max_sfb_ste, max_sfb_ste_clear, + /* jointStereoPersistentData and cplxPredictionData are only + available/allocated if cplxPred is active. */ + ((cplxPred == 0) || (pAacDecoderStaticChannelInfo == NULL)) + ? NULL + : &pAacDecoderStaticChannelInfo[0] + ->pCpeStaticData->jointStereoPersistentData, + ((cplxPred == 0) || (pAacDecoderChannelInfo[0] == NULL)) + ? NULL + : pAacDecoderChannelInfo[0] + ->pComStaticData->cplxPredictionData, + cplxPred, + GetScaleFactorBandsTotal(&pAacDecoderChannelInfo[0]->icsInfo), + GetWindowSequence(&pAacDecoderChannelInfo[0]->icsInfo), + flags)) { + error = AAC_DEC_PARSE_ERROR; + } + + break; + + case global_gain: + pAacDecoderChannelInfo[ch]->pDynData->RawDataInfo.GlobalGain = + (UCHAR)FDKreadBits(hBs, 8); + break; + + case section_data: + error = CBlock_ReadSectionData(hBs, pAacDecoderChannelInfo[ch], + pSamplingRateInfo, flags); + break; + + case scale_factor_data_usac: + pAacDecoderChannelInfo[ch]->currAliasingSymmetry = 0; + /* Set active sfb codebook indexes to HCB_ESC to make them "active" */ + CChannel_CodebookTableInit( + pAacDecoderChannelInfo[ch]); /* equals ReadSectionData(self, + bs) in float soft. block.c + line: ~599 */ + /* Note: The missing "break" is intentional here, since we need to call + * CBlock_ReadScaleFactorData(). */ + FDK_FALLTHROUGH; + + case scale_factor_data: + if (flags & AC_ER_RVLC) { + /* read RVLC data from bitstream (error sens. cat. 1) */ + CRvlc_Read(pAacDecoderChannelInfo[ch], hBs); + } else { + error = CBlock_ReadScaleFactorData(pAacDecoderChannelInfo[ch], hBs, + flags); + } + break; + + case pulse: + if (CPulseData_Read( + hBs, + &pAacDecoderChannelInfo[ch]->pDynData->specificTo.aac.PulseData, + pSamplingRateInfo->ScaleFactorBands_Long, /* pulse data is only + allowed to be + present in long + blocks! */ + (void *)&pAacDecoderChannelInfo[ch]->icsInfo, + frame_length) != 0) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + break; + case tns_data_present: + CTns_ReadDataPresentFlag( + hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData); + if (elFlags & AC_EL_LFE && + pAacDecoderChannelInfo[ch]->pDynData->TnsData.DataPresent) { + error = AAC_DEC_PARSE_ERROR; + } + break; + case tns_data: + /* tns_data_present is checked inside CTns_Read(). */ + error = CTns_Read(hBs, &pAacDecoderChannelInfo[ch]->pDynData->TnsData, + &pAacDecoderChannelInfo[ch]->icsInfo, flags); + + break; + + case gain_control_data: + break; + + case gain_control_data_present: + if (FDKreadBits(hBs, 1)) { + error = AAC_DEC_UNSUPPORTED_GAIN_CONTROL_DATA; + } + break; + + case tw_data: + break; + case common_tw: + break; + case tns_data_present_usac: + if (pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active) { + CTns_ReadDataPresentUsac( + hBs, &pAacDecoderChannelInfo[0]->pDynData->TnsData, + &pAacDecoderChannelInfo[1]->pDynData->TnsData, + &pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr, + &pAacDecoderChannelInfo[0]->icsInfo, flags, elFlags, + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow); + } else { + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_on_lr = + (UCHAR)1; + } + break; + case core_mode: + decision_bit = FDKreadBits(hBs, 1); + pAacDecoderChannelInfo[ch]->data.usac.core_mode = decision_bit; + if ((ch == 1) && (pAacDecoderChannelInfo[0]->data.usac.core_mode != + pAacDecoderChannelInfo[1]->data.usac.core_mode)) { + /* StereoCoreToolInfo(core_mode[ch] ) */ + pAacDecoderChannelInfo[0]->pDynData->RawDataInfo.CommonWindow = 0; + pAacDecoderChannelInfo[1]->pDynData->RawDataInfo.CommonWindow = 0; + } + break; + case tns_active: + pAacDecoderChannelInfo[0]->pDynData->specificTo.usac.tns_active = + FDKreadBit(hBs); + break; + case noise: + if (elFlags & AC_EL_USAC_NOISE) { + pAacDecoderChannelInfo[ch] + ->pDynData->specificTo.usac.fd_noise_level_and_offset = + FDKreadBits(hBs, 3 + 5); /* Noise level */ + } + break; + case lpd_channel_stream: + + { + error = CLpdChannelStream_Read(/* = lpd_channel_stream() */ + hBs, pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], + pSamplingRateInfo, flags); + } + + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_LPD; + break; + case fac_data: { + int fFacDatPresent = FDKreadBit(hBs); + + /* Wee need a valid fac_data[0] even if no FAC data is present (as + * temporal buffer) */ + pAacDecoderChannelInfo[ch]->data.usac.fac_data[0] = + pAacDecoderChannelInfo[ch]->data.usac.fac_data0; + + if (fFacDatPresent) { + if (elFlags & AC_EL_LFE) { + error = AAC_DEC_PARSE_ERROR; + break; + } + /* FAC data present, this frame is FD, so the last mode had to be + * ACELP. */ + if (pAacDecoderStaticChannelInfo[ch]->last_core_mode != LPD || + pAacDecoderStaticChannelInfo[ch]->last_lpd_mode != 0) { + pAacDecoderChannelInfo[ch]->data.usac.core_mode_last = LPD; + pAacDecoderChannelInfo[ch]->data.usac.lpd_mode_last = 0; + /* We can't change the past! So look to the future and go ahead! */ + } + CLpd_FAC_Read(hBs, pAacDecoderChannelInfo[ch]->data.usac.fac_data[0], + pAacDecoderChannelInfo[ch]->data.usac.fac_data_e, + CLpd_FAC_getLength( + IsLongBlock(&pAacDecoderChannelInfo[ch]->icsInfo), + pAacDecoderChannelInfo[ch]->granuleLength), + 1, 0); + } else { + if (pAacDecoderStaticChannelInfo[ch]->last_core_mode == LPD && + pAacDecoderStaticChannelInfo[ch]->last_lpd_mode == 0) { + /* ACELP to FD transitons without FAC are possible. That is why we + zero it out (i.e FAC will not be considered in the subsequent + calculations */ + FDKmemclear(pAacDecoderChannelInfo[ch]->data.usac.fac_data0, + LFAC * sizeof(FIXP_DBL)); + } + } + } break; + case esc2_rvlc: + if (flags & AC_ER_RVLC) { + CRvlc_Decode(pAacDecoderChannelInfo[ch], + pAacDecoderStaticChannelInfo[ch], hBs); + } + break; + + case esc1_hcr: + if (flags & AC_ER_HCR) { + CHcr_Read(hBs, pAacDecoderChannelInfo[ch], + numberOfChannels == 2 ? ID_CPE : ID_SCE); + } + break; + + case spectral_data: + error = CBlock_ReadSpectralData(hBs, pAacDecoderChannelInfo[ch], + pSamplingRateInfo, flags); + if (flags & AC_ELD) { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_ELDFB; + } else { + if (flags & AC_HDAAC) { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_INTIMDCT; + } else { + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT; + } + } + break; + + case ac_spectral_data: + error = CBlock_ReadAcSpectralData( + hBs, pAacDecoderChannelInfo[ch], pAacDecoderStaticChannelInfo[ch], + pSamplingRateInfo, frame_length, flags); + pAacDecoderChannelInfo[ch]->renderMode = AACDEC_RENDER_IMDCT; + break; + + case coupled_elements: { + int num_coupled_elements, c; + + ind_sw_cce_flag = FDKreadBit(hBs); + num_coupled_elements = FDKreadBits(hBs, 3); + + for (c = 0; c < (num_coupled_elements + 1); c++) { + int cc_target_is_cpe; + + num_gain_element_lists++; + cc_target_is_cpe = FDKreadBit(hBs); /* cc_target_is_cpe[c] */ + FDKreadBits(hBs, 4); /* cc_target_tag_select[c] */ + + if (cc_target_is_cpe) { + int cc_l, cc_r; + + cc_l = FDKreadBit(hBs); /* cc_l[c] */ + cc_r = FDKreadBit(hBs); /* cc_r[c] */ + + if (cc_l && cc_r) { + num_gain_element_lists++; + } + } + } + FDKreadBit(hBs); /* cc_domain */ + FDKreadBit(hBs); /* gain_element_sign */ + FDKreadBits(hBs, 2); /* gain_element_scale */ + } break; + + case gain_element_lists: { + const CodeBookDescription *hcb; + UCHAR *pCodeBook; + int c; + + hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + pCodeBook = pAacDecoderChannelInfo[ch]->pDynData->aCodeBook; + + for (c = 1; c < num_gain_element_lists; c++) { + int cge; + if (ind_sw_cce_flag) { + cge = 1; + } else { + cge = FDKreadBits(hBs, 1); /* common_gain_element_present[c] */ + } + if (cge) { + /* Huffman */ + CBlock_DecodeHuffmanWord( + hBs, hcb); /* hcod_sf[common_gain_element[c]] 1..19 */ + } else { + int g, sfb; + for (g = 0; + g < GetWindowGroups(&pAacDecoderChannelInfo[ch]->icsInfo); + g++) { + for (sfb = 0; sfb < GetScaleFactorBandsTransmitted( + &pAacDecoderChannelInfo[ch]->icsInfo); + sfb++) { + if (pCodeBook[sfb] != ZERO_HCB) { + /* Huffman */ + CBlock_DecodeHuffmanWord( + hBs, + hcb); /* hcod_sf[dpcm_gain_element[c][g][sfb]] 1..19 */ + } + } + } + } + } + } break; + + /* CRC handling */ + case adtscrc_start_reg1: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 192); + } + break; + case adtscrc_start_reg2: + if (pTpDec != NULL) { + crcReg2 = transportDec_CrcStartReg(pTpDec, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg1); + crcReg1 = -1; + } + break; + case adtscrc_end_reg2: + if (crcReg1 != -1) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } else if (pTpDec != NULL) { + transportDec_CrcEndReg(pTpDec, crcReg2); + crcReg2 = -1; + } + break; + case drmcrc_start_reg: + if (pTpDec != NULL) { + crcReg1 = transportDec_CrcStartReg(pTpDec, 0); + } + break; + + /* Non data cases */ + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i = -1; + break; + + default: + error = AAC_DEC_UNSUPPORTED_FORMAT; + break; + } + + if (error != AAC_DEC_OK) { + goto bail; + } + + i++; + + } while (list->id[i] != end_of_sequence); + + for (ch = 0; ch < numberOfChannels; ch++) { + if (pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_IMDCT || + pAacDecoderChannelInfo[ch]->renderMode == AACDEC_RENDER_ELDFB) { + /* Shows which bands are empty. */ + UCHAR *band_is_noise = + pAacDecoderChannelInfo[ch]->pDynData->band_is_noise; + FDKmemset(band_is_noise, (UCHAR)1, sizeof(UCHAR) * (8 * 16)); + + error = CBlock_InverseQuantizeSpectralData( + pAacDecoderChannelInfo[ch], pSamplingRateInfo, band_is_noise, 1); + if (error != AAC_DEC_OK) { + return error; + } + + if (elFlags & AC_EL_USAC_NOISE) { + CBlock_ApplyNoise(pAacDecoderChannelInfo[ch], pSamplingRateInfo, + &pAacDecoderStaticChannelInfo[ch]->nfRandomSeed, + band_is_noise); + + } /* if (elFlags & AC_EL_USAC_NOISE) */ + } + } + +bail: + if (crcReg1 != -1 || crcReg2 != -1) { + if (error == AAC_DEC_OK) { + error = AAC_DEC_DECODE_FRAME_ERROR; + } + if (crcReg1 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg1); + } + if (crcReg2 != -1) { + transportDec_CrcEndReg(pTpDec, crcReg2); + } + } + return error; +} diff --git a/fdk-aac/libAACdec/src/channel.h b/fdk-aac/libAACdec/src/channel.h new file mode 100644 index 0000000..ed46666 --- /dev/null +++ b/fdk-aac/libAACdec/src/channel.h @@ -0,0 +1,160 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef CHANNEL_H +#define CHANNEL_H + +#include "common_fix.h" + +#include "FDK_tools_rom.h" +#include "channelinfo.h" +#include "tpdec_lib.h" + +/** + * \brief Init codeBook SFB indices (section data) with HCB_ESC. Useful for + * bitstreams which do not have any section data, but still SFB's (scale factor + * bands). This has the effect that upto the amount of transmitted SFB are + * treated as non-zero. + * \param pAacDecoderChannelInfo channel info structure containing a valid + * icsInfo struct. + */ +void CChannel_CodebookTableInit(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +/** + * \brief decode a channel element. To be called after CChannelElement_Read() + * \param pAacDecoderChannelInfo pointer to channel data struct. Depending on + * el_channels either one or two. + * \param pSamplingRateInfo pointer to sample rate information structure + * \param el_channels amount of channels of the element to be decoded. + * \param output pointer to time domain output buffer (ACELP) + */ +void CChannelElement_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + SamplingRateInfo *pSamplingRateInfo, UINT flags, UINT elFlags, + int el_channels); + +/** + * \brief Read channel element of given type from bitstream. + * \param hBs bitstream handle to access bitstream data. + * \param pAacDecoderChannelInfo pointer array to store channel information. + * \param aot Audio Object Type + * \param pSamplingRateInfo sampling rate info table. + * \param flags common parser guidance flags + * \param elFlags element specific parser guidance flags + * \param numberOfChannels amoun of channels contained in the object to be + * parsed. + * \param epConfig the current epConfig value obtained from the Audio Specific + * Config. + * \param pTp transport decoder handle required for ADTS CRC checking. + * ... + * \return an AAC_DECODER_ERROR error code. + */ +AAC_DECODER_ERROR CChannelElement_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const AUDIO_OBJECT_TYPE aot, SamplingRateInfo *pSamplingRateInfo, + const UINT flags, const UINT elFlags, const UINT frame_length, + const UCHAR numberOfChannels, const SCHAR epConfig, + HANDLE_TRANSPORTDEC pTpDec); + +#endif /* #ifndef CHANNEL_H */ diff --git a/fdk-aac/libAACdec/src/channelinfo.cpp b/fdk-aac/libAACdec/src/channelinfo.cpp new file mode 100644 index 0000000..79add5b --- /dev/null +++ b/fdk-aac/libAACdec/src/channelinfo.cpp @@ -0,0 +1,297 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: individual channel stream info + +*******************************************************************************/ + +#include "channelinfo.h" +#include "aac_rom.h" +#include "aac_ram.h" +#include "FDK_bitstream.h" + +AAC_DECODER_ERROR IcsReadMaxSfb(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + int nbits; + + if (IsLongBlock(pIcsInfo)) { + nbits = 6; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Long; + } else { + nbits = 4; + pIcsInfo->TotalSfBands = pSamplingRateInfo->NumberOfScaleFactorBands_Short; + } + pIcsInfo->MaxSfBands = (UCHAR)FDKreadBits(bs, nbits); + + if (pIcsInfo->MaxSfBands > pIcsInfo->TotalSfBands) { + ErrorStatus = AAC_DEC_PARSE_ERROR; + } + + return ErrorStatus; +} + +AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo, + const UINT flags) { + AAC_DECODER_ERROR ErrorStatus = AAC_DEC_OK; + + pIcsInfo->Valid = 0; + + if (flags & AC_ELD) { + pIcsInfo->WindowSequence = BLOCK_LONG; + pIcsInfo->WindowShape = 0; + } else { + if (!(flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA))) { + FDKreadBits(bs, 1); + } + pIcsInfo->WindowSequence = (BLOCK_TYPE)FDKreadBits(bs, 2); + pIcsInfo->WindowShape = (UCHAR)FDKreadBits(bs, 1); + if (flags & AC_LD) { + if (pIcsInfo->WindowShape) { + pIcsInfo->WindowShape = 2; /* select low overlap instead of KBD */ + } + } + } + + /* Sanity check */ + if ((flags & (AC_ELD | AC_LD)) && pIcsInfo->WindowSequence != BLOCK_LONG) { + pIcsInfo->WindowSequence = BLOCK_LONG; + ErrorStatus = AAC_DEC_PARSE_ERROR; + goto bail; + } + + ErrorStatus = IcsReadMaxSfb(bs, pIcsInfo, pSamplingRateInfo); + if (ErrorStatus != AAC_DEC_OK) { + goto bail; + } + + if (IsLongBlock(pIcsInfo)) { + if (!(flags & (AC_ELD | AC_SCALABLE | AC_BSAC | AC_USAC | AC_RSVD50 | + AC_RSV603DA))) /* If not ELD nor Scalable nor BSAC nor USAC + syntax then ... */ + { + if ((UCHAR)FDKreadBits(bs, 1) != 0) /* UCHAR PredictorDataPresent */ + { + ErrorStatus = AAC_DEC_UNSUPPORTED_PREDICTION; + goto bail; + } + } + + pIcsInfo->WindowGroups = 1; + pIcsInfo->WindowGroupLength[0] = 1; + } else { + INT i; + UINT mask; + + pIcsInfo->ScaleFactorGrouping = (UCHAR)FDKreadBits(bs, 7); + + pIcsInfo->WindowGroups = 0; + + for (i = 0; i < (8 - 1); i++) { + mask = 1 << (6 - i); + pIcsInfo->WindowGroupLength[i] = 1; + + if (pIcsInfo->ScaleFactorGrouping & mask) { + pIcsInfo->WindowGroupLength[pIcsInfo->WindowGroups]++; + } else { + pIcsInfo->WindowGroups++; + } + } + + /* loop runs to i < 7 only */ + pIcsInfo->WindowGroupLength[8 - 1] = 1; + pIcsInfo->WindowGroups++; + } + +bail: + if (ErrorStatus == AAC_DEC_OK) pIcsInfo->Valid = 1; + + return ErrorStatus; +} + +/* + interleave codebooks the following way + + 9 (84w) | 1 (51w) + 10 (82w) | 2 (39w) + SCL (65w) | 4 (38w) + 3 (39w) | 5 (41w) + | 6 (40w) + | 7 (31w) + | 8 (31w) + (270w) (271w) +*/ + +/* + Table entries are sorted as following: + | num_swb_long_window | sfbands_long | num_swb_short_window | sfbands_short | +*/ +AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, + UINT samplingRateIndex, + UINT samplingRate) { + int index = 0; + + /* Search closest samplerate according to ISO/IEC 13818-7:2005(E) 8.2.4 (Table + * 38): */ + if ((samplingRateIndex >= 15) || (samplesPerFrame == 768)) { + const UINT borders[] = {(UINT)-1, 92017, 75132, 55426, 46009, 37566, + 27713, 23004, 18783, 13856, 11502, 9391}; + UINT i, samplingRateSearch = samplingRate; + + if (samplesPerFrame == 768) { + samplingRateSearch = (samplingRate * 4) / 3; + } + + for (i = 0; i < 11; i++) { + if (borders[i] > samplingRateSearch && + samplingRateSearch >= borders[i + 1]) { + break; + } + } + samplingRateIndex = i; + } + + t->samplingRateIndex = samplingRateIndex; + t->samplingRate = samplingRate; + + switch (samplesPerFrame) { + case 1024: + index = 0; + break; + case 960: + index = 1; + break; + case 768: + index = 2; + break; + case 512: + index = 3; + break; + case 480: + index = 4; + break; + + default: + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + t->ScaleFactorBands_Long = + sfbOffsetTables[index][samplingRateIndex].sfbOffsetLong; + t->ScaleFactorBands_Short = + sfbOffsetTables[index][samplingRateIndex].sfbOffsetShort; + t->NumberOfScaleFactorBands_Long = + sfbOffsetTables[index][samplingRateIndex].numberOfSfbLong; + t->NumberOfScaleFactorBands_Short = + sfbOffsetTables[index][samplingRateIndex].numberOfSfbShort; + + if (t->ScaleFactorBands_Long == NULL || + t->NumberOfScaleFactorBands_Long == 0) { + t->samplingRate = 0; + return AAC_DEC_UNSUPPORTED_FORMAT; + } + + FDK_ASSERT((UINT)t->ScaleFactorBands_Long[t->NumberOfScaleFactorBands_Long] == + samplesPerFrame); + FDK_ASSERT( + t->ScaleFactorBands_Short == NULL || + (UINT)t->ScaleFactorBands_Short[t->NumberOfScaleFactorBands_Short] * 8 == + samplesPerFrame); + + return AAC_DEC_OK; +} diff --git a/fdk-aac/libAACdec/src/channelinfo.h b/fdk-aac/libAACdec/src/channelinfo.h new file mode 100644 index 0000000..4523400 --- /dev/null +++ b/fdk-aac/libAACdec/src/channelinfo.h @@ -0,0 +1,564 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: individual channel stream info + +*******************************************************************************/ + +#ifndef CHANNELINFO_H +#define CHANNELINFO_H + +#include "common_fix.h" + +#include "aac_rom.h" +#include "aacdecoder_lib.h" +#include "FDK_bitstream.h" +#include "overlapadd.h" + +#include "mdct.h" +#include "stereo.h" +#include "pulsedata.h" +#include "aacdec_tns.h" + +#include "aacdec_pns.h" + +#include "aacdec_hcr_types.h" +#include "rvlc_info.h" + +#include "usacdec_acelp.h" +#include "usacdec_const.h" +#include "usacdec_rom.h" + +#include "ac_arith_coder.h" + +#include "conceal_types.h" + +#include "aacdec_drc_types.h" + +#define WB_SECTION_SIZE (1024 * 2) + +#define DRM_BS_BUFFER_SIZE \ + (512) /* size of the dynamic buffer which is used to reverse the bits of \ + the DRM SBR payload */ + +/* Output rendering mode */ +typedef enum { + AACDEC_RENDER_INVALID = 0, + AACDEC_RENDER_IMDCT, + AACDEC_RENDER_ELDFB, + AACDEC_RENDER_LPD, + AACDEC_RENDER_INTIMDCT +} AACDEC_RENDER_MODE; + +enum { MAX_QUANTIZED_VALUE = 8191 }; + +typedef enum { FD_LONG, FD_SHORT, LPD } USAC_COREMODE; + +typedef struct { + const SHORT *ScaleFactorBands_Long; + const SHORT *ScaleFactorBands_Short; + UCHAR NumberOfScaleFactorBands_Long; + UCHAR NumberOfScaleFactorBands_Short; + UINT samplingRateIndex; + UINT samplingRate; +} SamplingRateInfo; + +typedef struct { + UCHAR CommonWindow; + UCHAR GlobalGain; + +} CRawDataInfo; + +typedef struct { + UCHAR WindowGroupLength[8]; + UCHAR WindowGroups; + UCHAR Valid; + + UCHAR WindowShape; /* 0: sine window, 1: KBD, 2: low overlap */ + BLOCK_TYPE WindowSequence; /* mdct.h; 0: long, 1: start, 2: short, 3: stop */ + UCHAR MaxSfBands; + UCHAR max_sfb_ste; + UCHAR ScaleFactorGrouping; + + UCHAR TotalSfBands; + +} CIcsInfo; + +enum { + ZERO_HCB = 0, + ESCBOOK = 11, + NSPECBOOKS = ESCBOOK + 1, + BOOKSCL = NSPECBOOKS, + NOISE_HCB = 13, + INTENSITY_HCB2 = 14, + INTENSITY_HCB = 15, + LAST_HCB +}; + +/* This struct holds the persistent data shared by both channels of a CPE. + It needs to be allocated for each CPE. */ +typedef struct { + CJointStereoPersistentData jointStereoPersistentData; +} CpePersistentData; + +/* + * This struct must be allocated one for every channel and must be persistent. + */ +typedef struct { + FIXP_DBL *pOverlapBuffer; + mdct_t IMdct; + + CArcoData *hArCo; + + INT pnsCurrentSeed; + + /* LPD memory */ + FIXP_DBL old_synth[PIT_MAX_MAX - L_SUBFR]; + INT old_T_pf[SYN_SFD]; + FIXP_DBL old_gain_pf[SYN_SFD]; + FIXP_DBL mem_bpf[L_FILT + L_SUBFR]; + UCHAR + old_bpf_control_info; /* (1: enable, 0: disable) bpf for past superframe + */ + + USAC_COREMODE last_core_mode; /* core mode used by the decoder in previous + frame. (not signalled by the bitstream, see + CAacDecoderChannelInfo::core_mode_last !! ) + */ + UCHAR last_lpd_mode; /* LPD mode used by the decoder in last LPD subframe + (not signalled by the bitstream, see + CAacDecoderChannelInfo::lpd_mode_last !! ) */ + UCHAR last_last_lpd_mode; /* LPD mode used in second last LPD subframe + (not signalled by the bitstream) */ + UCHAR last_lpc_lost; /* Flag indicating that the previous LPC is lost */ + + FIXP_LPC + lpc4_lsf[M_LP_FILTER_ORDER]; /* Last LPC4 coefficients in LSF domain. */ + FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER]; /* Adaptive mean of LPC + coefficients in LSF domain + for concealment. */ + FIXP_LPC lp_coeff_old[2][M_LP_FILTER_ORDER]; /* Last LPC coefficients in LP + domain. lp_coeff_old[0] is lpc4 (coeffs for + right folding point of last tcx frame), + lp_coeff_old[1] are coeffs for left folding + point of last tcx frame */ + INT lp_coeff_old_exp[2]; + + FIXP_SGL + oldStability; /* LPC coeff stability value from last frame (required for + TCX concealment). */ + UINT numLostLpdFrames; /* Number of consecutive lost subframes. */ + + /* TCX memory */ + FIXP_DBL last_tcx_gain; + INT last_tcx_gain_e; + FIXP_DBL last_alfd_gains[32]; /* Scaled by one bit. */ + SHORT last_tcx_pitch; + UCHAR last_tcx_noise_factor; + + /* ACELP memory */ + CAcelpStaticMem acelp; + + ULONG nfRandomSeed; /* seed value for USAC noise filling random generator */ + + CDrcChannelData drcData; + CConcealmentInfo concealmentInfo; + + CpePersistentData *pCpeStaticData; + +} CAacDecoderStaticChannelInfo; + +/* + * This union must be allocated for every element (up to 2 channels). + */ +typedef struct { + /* Common bit stream data */ + SHORT aScaleFactor[( + 8 * 16)]; /* Spectral scale factors for each sfb in each window. */ + SHORT aSfbScale[(8 * 16)]; /* could be free after ApplyTools() */ + UCHAR + aCodeBook[(8 * 16)]; /* section data: codebook for each window and sfb. */ + UCHAR band_is_noise[(8 * 16)]; + CTnsData TnsData; + CRawDataInfo RawDataInfo; + + shouldBeUnion { + struct { + CPulseData PulseData; + SHORT aNumLineInSec4Hcr[MAX_SFB_HCR]; /* needed once for all channels + except for Drm syntax */ + UCHAR + aCodeBooks4Hcr[MAX_SFB_HCR]; /* needed once for all channels except for + Drm syntax. Same as "aCodeBook" ? */ + SHORT lenOfReorderedSpectralData; + SCHAR lenOfLongestCodeword; + SCHAR numberSection; + SCHAR rvlcCurrentScaleFactorOK; + SCHAR rvlcIntensityUsed; + } aac; + struct { + UCHAR fd_noise_level_and_offset; + UCHAR tns_active; + UCHAR tns_on_lr; + UCHAR tcx_noise_factor[4]; + UCHAR tcx_global_gain[4]; + } usac; + } + specificTo; + +} CAacDecoderDynamicData; + +typedef shouldBeUnion { + UCHAR DrmBsBuffer[DRM_BS_BUFFER_SIZE]; + + /* Common signal data, can be used once the bit stream data from above is not + * used anymore. */ + FIXP_DBL mdctOutTemp[1024]; + + FIXP_DBL synth_buf[(PIT_MAX_MAX + SYN_DELAY + L_FRAME_PLUS)]; + + FIXP_DBL workBuffer[WB_SECTION_SIZE]; +} +CWorkBufferCore1; + +/* Common data referenced by all channels */ +typedef struct { + CAacDecoderDynamicData pAacDecoderDynamicData[2]; + + CPnsInterChannelData pnsInterChannelData; + INT pnsRandomSeed[(8 * 16)]; + + CJointStereoData jointStereoData; /* One for one element */ + + shouldBeUnion { + struct { + CErHcrInfo erHcrInfo; + CErRvlcInfo erRvlcInfo; + SHORT aRvlcScfEsc[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfFwd[RVLC_MAX_SFB]; /* needed once for all channels */ + SHORT aRvlcScfBwd[RVLC_MAX_SFB]; /* needed once for all channels */ + } aac; + } + overlay; + +} CAacDecoderCommonData; + +typedef struct { + CWorkBufferCore1 *pWorkBufferCore1; + CCplxPredictionData *cplxPredictionData; +} CAacDecoderCommonStaticData; + +/* + * This struct must be allocated one for every channel of every element and must + * be persistent. Among its members, the following memory areas can be + * overwritten under the given conditions: + * - pSpectralCoefficient The memory pointed to can be overwritten after time + * signal rendering. + * - data can be overwritten after time signal rendering. + * - pDynData memory pointed to can be overwritten after each + * CChannelElement_Decode() call. + * - pComData->overlay memory pointed to can be overwritten after each + * CChannelElement_Decode() call.. + */ +typedef struct { + shouldBeUnion { + struct { + FIXP_DBL fac_data0[LFAC]; + SCHAR fac_data_e[4]; + FIXP_DBL + *fac_data[4]; /* Pointers to unused parts of pSpectralCoefficient */ + + UCHAR core_mode; /* current core mode */ + USAC_COREMODE + core_mode_last; /* previous core mode, signalled in the bitstream + (not done by the decoder, see + CAacDecoderStaticChannelInfo::last_core_mode !!)*/ + UCHAR lpd_mode_last; /* previous LPD mode, signalled in the bitstream + (not done by the decoder, see + CAacDecoderStaticChannelInfo::last_core_mode !!)*/ + UCHAR mod[4]; + UCHAR bpf_control_info; /* (1: enable, 0: disable) bpf for current + superframe */ + + FIXP_LPC lsp_coeff[5][M_LP_FILTER_ORDER]; /* linear prediction + coefficients in LSP domain */ + FIXP_LPC + lp_coeff[5][M_LP_FILTER_ORDER]; /* linear prediction coefficients in + LP domain */ + INT lp_coeff_exp[5]; + FIXP_LPC lsf_adaptive_mean_cand + [M_LP_FILTER_ORDER]; /* concealment: is copied to + CAacDecoderStaticChannelInfo->lsf_adaptive_mean once frame is + assumed to be correct*/ + FIXP_SGL aStability[4]; /* LPC coeff stability values required for ACELP + and TCX (concealment) */ + + CAcelpChannelData acelp[4]; + + FIXP_DBL tcx_gain[4]; + SCHAR tcx_gain_e[4]; + } usac; + + struct { + CPnsData PnsData; /* Not required for USAC */ + } aac; + } + data; + + SPECTRAL_PTR pSpectralCoefficient; /* Spectral coefficients of each window */ + SHORT specScale[8]; /* Scale shift values of each spectrum window */ + CIcsInfo icsInfo; + INT granuleLength; /* Size of smallest spectrum piece */ + UCHAR ElementInstanceTag; + + AACDEC_RENDER_MODE renderMode; /* Output signal rendering mode */ + + CAacDecoderDynamicData * + pDynData; /* Data required for one element and discarded after decoding */ + CAacDecoderCommonData + *pComData; /* Data required for one channel at a time during decode */ + CAacDecoderCommonStaticData *pComStaticData; /* Persistent data required for + one channel at a time during + decode */ + + int currAliasingSymmetry; /* required for RSVD60 MCT */ + +} CAacDecoderChannelInfo; + +/* channelinfo.cpp */ + +AAC_DECODER_ERROR getSamplingRateInfo(SamplingRateInfo *t, UINT samplesPerFrame, + UINT samplingRateIndex, + UINT samplingRate); + +/** + * \brief Read max SFB from bit stream and assign TotalSfBands according + * to the window sequence and sample rate. + * \param hBs bit stream handle as data source + * \param pIcsInfo IcsInfo structure to read the window sequence and store + * MaxSfBands and TotalSfBands + * \param pSamplingRateInfo read only + */ +AAC_DECODER_ERROR IcsReadMaxSfb(HANDLE_FDK_BITSTREAM hBs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *pSamplingRateInfo); + +AAC_DECODER_ERROR IcsRead(HANDLE_FDK_BITSTREAM bs, CIcsInfo *pIcsInfo, + const SamplingRateInfo *SamplingRateInfoTable, + const UINT flags); + +/* stereo.cpp, only called from this file */ + +/*! + \brief Applies MS stereo. + + The function applies MS stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmittedL number of transmitted scalefactor bands in + left channel. \param scaleFactorBandsTransmittedR number of transmitted + scalefactor bands in right channel. May differ from + scaleFactorBandsTransmittedL only for USAC. \return none +*/ +void CJointStereo_ApplyMS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale, + SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR, + const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength, + const int windowGroups, const int max_sfb_ste_outside, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev, + SHORT *store_dmx_re_prev_e, const int mainband_flag); + +/*! + \brief Applies intensity stereo + + The function applies intensity stereo. + + \param pAacDecoderChannelInfo aac channel info. + \param pScaleFactorBandOffsets pointer to scalefactor band offsets. + \param pWindowGroupLength pointer to window group length array. + \param windowGroups number of window groups. + \param scaleFactorBandsTransmitted number of transmitted scalefactor bands. + \return none +*/ +void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const short *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted); + +/* aacdec_pns.cpp */ +int CPns_IsPnsUsed(const CPnsData *pPnsData, const int group, const int band); + +void CPns_SetCorrelation(CPnsData *pPnsData, const int group, const int band, + const int outofphase); + +/****************** inline functions ******************/ + +inline UCHAR IsValid(const CIcsInfo *pIcsInfo) { return pIcsInfo->Valid; } + +inline UCHAR IsLongBlock(const CIcsInfo *pIcsInfo) { + return (pIcsInfo->WindowSequence != BLOCK_SHORT); +} + +inline UCHAR GetWindowShape(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowShape; +} + +inline BLOCK_TYPE GetWindowSequence(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowSequence; +} + +inline const SHORT *GetScaleFactorBandOffsets( + const CIcsInfo *pIcsInfo, const SamplingRateInfo *samplingRateInfo) { + if (IsLongBlock(pIcsInfo)) { + return samplingRateInfo->ScaleFactorBands_Long; + } else { + return samplingRateInfo->ScaleFactorBands_Short; + } +} + +inline UCHAR GetNumberOfScaleFactorBands( + const CIcsInfo *pIcsInfo, const SamplingRateInfo *samplingRateInfo) { + if (IsLongBlock(pIcsInfo)) { + return samplingRateInfo->NumberOfScaleFactorBands_Long; + } else { + return samplingRateInfo->NumberOfScaleFactorBands_Short; + } +} + +inline int GetWindowsPerFrame(const CIcsInfo *pIcsInfo) { + return (pIcsInfo->WindowSequence == BLOCK_SHORT) ? 8 : 1; +} + +inline UCHAR GetWindowGroups(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowGroups; +} + +inline UCHAR GetWindowGroupLength(const CIcsInfo *pIcsInfo, const INT index) { + return pIcsInfo->WindowGroupLength[index]; +} + +inline const UCHAR *GetWindowGroupLengthTable(const CIcsInfo *pIcsInfo) { + return pIcsInfo->WindowGroupLength; +} + +inline UCHAR GetScaleFactorBandsTransmitted(const CIcsInfo *pIcsInfo) { + return pIcsInfo->MaxSfBands; +} + +inline UCHAR GetScaleMaxFactorBandsTransmitted(const CIcsInfo *pIcsInfo0, + const CIcsInfo *pIcsInfo1) { + return fMax(pIcsInfo0->MaxSfBands, pIcsInfo1->MaxSfBands); +} + +inline UCHAR GetScaleFactorBandsTotal(const CIcsInfo *pIcsInfo) { + return pIcsInfo->TotalSfBands; +} + +/* Note: This function applies to AAC-LC only ! */ +inline UCHAR GetMaximumTnsBands(const CIcsInfo *pIcsInfo, + const int samplingRateIndex) { + return tns_max_bands_tbl[samplingRateIndex][!IsLongBlock(pIcsInfo)]; +} + +#endif /* #ifndef CHANNELINFO_H */ diff --git a/fdk-aac/libAACdec/src/conceal.cpp b/fdk-aac/libAACdec/src/conceal.cpp new file mode 100644 index 0000000..5895cb8 --- /dev/null +++ b/fdk-aac/libAACdec/src/conceal.cpp @@ -0,0 +1,2095 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: independent channel concealment + +*******************************************************************************/ + +/*! + \page concealment AAC core concealment + + This AAC core implementation includes a concealment function, which can be + enabled using the several defines during compilation. + + There are various tests inside the core, starting with simple CRC tests and + ending in a variety of plausibility checks. If such a check indicates an + invalid bitstream, then concealment is applied. + + Concealment is also applied when the calling main program indicates a + distorted or missing data frame using the frameOK flag. This is used for error + detection on the transport layer. (See below) + + There are three concealment-modes: + + 1) Muting: The spectral data is simply set to zero in case of an detected + error. + + 2) Noise substitution: In case of an detected error, concealment copies the + last frame and adds attenuates the spectral data. For this mode you have to + set the #CONCEAL_NOISE define. Noise substitution adds no additional delay. + + 3) Interpolation: The interpolation routine swaps the spectral data from the + previous and the current frame just before the final frequency to time + conversion. In case a single frame is corrupted, concealmant interpolates + between the last good and the first good frame to create the spectral data for + the missing frame. If multiple frames are corrupted, concealment implements + first a fade out based on slightly modified spectral values from the last good + frame. As soon as good frames are available, concealmant fades in the new + spectral data. For this mode you have to set the #CONCEAL_INTER define. Note + that in this case, you also need to set #SBR_BS_DELAY_ENABLE, which basically + adds approriate delay in the SBR decoder. Note that the + Interpolating-Concealment increases the delay of your decoder by one frame and + that it does require additional resources such as memory and computational + complexity. + +

How concealment can be used with errors on the transport layer

+ + Many errors can or have to be detected on the transport layer. For example in + IP based systems packet loss can occur. The transport protocol used should + indicate such packet loss by inserting an empty frame with frameOK=0. +*/ + +#include "conceal.h" + +#include "aac_rom.h" +#include "genericStds.h" + +/* PNS (of block) */ +#include "aacdec_pns.h" +#include "block.h" + +#define CONCEAL_DFLT_COMF_NOISE_LEVEL (0x100000) + +#define CONCEAL_NOT_DEFINED ((UCHAR)-1) + +/* default settings */ +#define CONCEAL_DFLT_FADEOUT_FRAMES (6) +#define CONCEAL_DFLT_FADEIN_FRAMES (5) +#define CONCEAL_DFLT_MUTE_RELEASE_FRAMES (0) + +#define CONCEAL_DFLT_FADE_FACTOR (0.707106781186548f) /* 1/sqrt(2) */ + +/* some often used constants: */ +#define FIXP_ZERO FL2FXCONST_DBL(0.0f) +#define FIXP_ONE FL2FXCONST_DBL(1.0f) +#define FIXP_FL_CORRECTION FL2FXCONST_DBL(0.53333333333333333f) + +/* For parameter conversion */ +#define CONCEAL_PARAMETER_BITS (8) +#define CONCEAL_MAX_QUANT_FACTOR ((1 << CONCEAL_PARAMETER_BITS) - 1) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_025 ( FL2FXCONST_DBL(0.971627951577106174) )*/ /* -0.25 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_025_LD \ + FL2FXCONST_DBL(-0.041524101186092029596853445212299) +/*#define CONCEAL_MIN_ATTENUATION_FACTOR_050 ( FL2FXCONST_DBL(0.944060876285923380) )*/ /* -0.50 dB */ +#define CONCEAL_MIN_ATTENUATION_FACTOR_050_LD \ + FL2FXCONST_DBL(-0.083048202372184059253597008145293) + +typedef enum { + CConcealment_NoExpand, + CConcealment_Expand, + CConcealment_Compress +} CConcealmentExpandType; + +static const FIXP_SGL facMod4Table[4] = { + FL2FXCONST_SGL(0.500000000f), /* FIXP_SGL(0x4000), 2^-(1-0,00) */ + FL2FXCONST_SGL(0.594603558f), /* FIXP_SGL(0x4c1b), 2^-(1-0,25) */ + FL2FXCONST_SGL(0.707106781f), /* FIXP_SGL(0x5a82), 2^-(1-0,50) */ + FL2FXCONST_SGL(0.840896415f) /* FIXP_SGL(0x6ba2) 2^-(1-0,75) */ +}; + +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType ex, int *sfbEnergy); + +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrev, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset); + +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active); + +static int CConcealment_ApplyNoise( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags); + +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +static void CConcealment_ApplyRandomSign(int iRandomPhase, FIXP_DBL *spec, + int samplesPerFrame); + +/* TimeDomainFading */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, FIXP_PCM *pcmdata); +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType); +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps); + +/* Streamline the state machine */ +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +static int CConcealment_TDNoise_Random(ULONG *seed); +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, FIXP_PCM *const pcmdata); + +static BLOCK_TYPE CConcealment_GetWinSeq(int prevWinSeq) { + BLOCK_TYPE newWinSeq = BLOCK_LONG; + + /* Try to have only long blocks */ + if (prevWinSeq == BLOCK_START || prevWinSeq == BLOCK_SHORT) { + newWinSeq = BLOCK_STOP; + } + + return (newWinSeq); +} + +/*! + \brief Init common concealment information data + + \param pConcealCommonData Pointer to the concealment common data structure. +*/ +void CConcealment_InitCommonData(CConcealParams *pConcealCommonData) { + if (pConcealCommonData != NULL) { + int i; + + /* Set default error concealment technique */ + pConcealCommonData->method = ConcealMethodInter; + + pConcealCommonData->numFadeOutFrames = CONCEAL_DFLT_FADEOUT_FRAMES; + pConcealCommonData->numFadeInFrames = CONCEAL_DFLT_FADEIN_FRAMES; + pConcealCommonData->numMuteReleaseFrames = CONCEAL_DFLT_MUTE_RELEASE_FRAMES; + + pConcealCommonData->comfortNoiseLevel = + (FIXP_DBL)CONCEAL_DFLT_COMF_NOISE_LEVEL; + + /* Init fade factors (symetric) */ + pConcealCommonData->fadeOutFactor[0] = + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR); + pConcealCommonData->fadeInFactor[0] = pConcealCommonData->fadeOutFactor[0]; + + for (i = 1; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + pConcealCommonData->fadeOutFactor[i] = + FX_DBL2FX_SGL(fMult(pConcealCommonData->fadeOutFactor[i - 1], + FL2FXCONST_SGL(CONCEAL_DFLT_FADE_FACTOR))); + pConcealCommonData->fadeInFactor[i] = + pConcealCommonData->fadeOutFactor[i]; + } + } +} + +/*! + \brief Get current concealment method. + + \param pConcealCommonData Pointer to common concealment data (for all + channels) +*/ +CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData) { + CConcealmentMethod method = ConcealMethodNone; + + if (pConcealCommonData != NULL) { + method = pConcealCommonData->method; + } + + return (method); +} + +/*! + \brief Init concealment information for each channel + + \param pConcealChannelInfo Pointer to the channel related concealment info + structure to be initialized. \param pConcealCommonData Pointer to common + concealment data (for all channels) \param initRenderMode Initial render + mode to be set for the current channel. \param samplesPerFrame The number + of samples per frame. +*/ +void CConcealment_InitChannelData(CConcealmentInfo *pConcealChannelInfo, + CConcealParams *pConcealCommonData, + AACDEC_RENDER_MODE initRenderMode, + int samplesPerFrame) { + int i; + pConcealChannelInfo->TDNoiseSeed = 0; + FDKmemclear(pConcealChannelInfo->TDNoiseStates, + sizeof(pConcealChannelInfo->TDNoiseStates)); + pConcealChannelInfo->TDNoiseCoef[0] = FL2FXCONST_SGL(0.05f); + pConcealChannelInfo->TDNoiseCoef[1] = FL2FXCONST_SGL(0.5f); + pConcealChannelInfo->TDNoiseCoef[2] = FL2FXCONST_SGL(0.45f); + + pConcealChannelInfo->pConcealParams = pConcealCommonData; + + pConcealChannelInfo->lastRenderMode = initRenderMode; + + pConcealChannelInfo->windowShape = CONCEAL_NOT_DEFINED; + pConcealChannelInfo->windowSequence = BLOCK_LONG; /* default type */ + pConcealChannelInfo->lastWinGrpLen = 1; + + pConcealChannelInfo->concealState = ConcealState_Ok; + + FDKmemclear(pConcealChannelInfo->spectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); + + for (i = 0; i < 8; i++) { + pConcealChannelInfo->specScale[i] = 0; + } + + pConcealChannelInfo->iRandomPhase = 0; + + pConcealChannelInfo->prevFrameOk[0] = 1; + pConcealChannelInfo->prevFrameOk[1] = 1; + + pConcealChannelInfo->cntFadeFrames = 0; + pConcealChannelInfo->cntValidFrames = 0; + pConcealChannelInfo->fade_old = (FIXP_DBL)MAXVAL_DBL; + pConcealChannelInfo->winGrpOffset[0] = 0; + pConcealChannelInfo->winGrpOffset[1] = 0; + pConcealChannelInfo->attGrpOffset[0] = 0; + pConcealChannelInfo->attGrpOffset[1] = 0; +} + +/*! + \brief Set error concealment parameters + + \param concealParams + \param method + \param fadeOutSlope + \param fadeInSlope + \param muteRelease + \param comfNoiseLevel +*/ +AAC_DECODER_ERROR +CConcealment_SetParams(CConcealParams *concealParams, int method, + int fadeOutSlope, int fadeInSlope, int muteRelease, + FIXP_DBL comfNoiseLevel) { + /* set concealment technique */ + if (method != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + switch ((CConcealmentMethod)method) { + case ConcealMethodMute: + case ConcealMethodNoise: + case ConcealMethodInter: + /* Be sure to enable delay adjustment of SBR decoder! */ + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->method = (CConcealmentMethod)method; + } + break; + + default: + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-out slope */ + if (fadeOutSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((fadeOutSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeOutSlope >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeOutFrames = fadeOutSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of frames for fade-in slope */ + if (fadeInSlope != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((fadeInSlope < CONCEAL_MAX_NUM_FADE_FACTORS) && (fadeInSlope >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numFadeInFrames = fadeInSlope; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set number of error-free frames after which the muting will be released */ + if (muteRelease != AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((muteRelease < (CONCEAL_MAX_NUM_FADE_FACTORS << 1)) && + (muteRelease >= 0)) { + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + /* set param */ + concealParams->numMuteReleaseFrames = muteRelease; + } + } else { + return AAC_DEC_SET_PARAM_FAIL; + } + } + + /* set confort noise level which will be inserted while in state 'muting' */ + if (comfNoiseLevel != (FIXP_DBL)AACDEC_CONCEAL_PARAM_NOT_SPECIFIED) { + if ((comfNoiseLevel < (FIXP_DBL)0) || + (comfNoiseLevel > (FIXP_DBL)MAXVAL_DBL)) { + return AAC_DEC_SET_PARAM_FAIL; + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } else { + concealParams->comfortNoiseLevel = (FIXP_DBL)comfNoiseLevel; + } + } + + return (AAC_DEC_OK); +} + +/*! + \brief Set fade-out/in attenuation factor vectors + + \param concealParams + \param fadeOutAttenuationVector + \param fadeInAttenuationVector + + \return 0 if OK all other values indicate errors +*/ +AAC_DECODER_ERROR +CConcealment_SetAttenuation(CConcealParams *concealParams, + const SHORT *fadeOutAttenuationVector, + const SHORT *fadeInAttenuationVector) { + if ((fadeOutAttenuationVector == NULL) && (fadeInAttenuationVector == NULL)) { + return AAC_DEC_SET_PARAM_FAIL; + } + + /* Fade-out factors */ + if (fadeOutAttenuationVector != NULL) { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeOutAttenuationVector[i] < 0) || + (fadeOutAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + concealParams->fadeOutFactor[i] = + FX_DBL2FX_SGL(fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FL2FXCONST_DBL(1.0 / 2.0) >> + (CONCEAL_PARAMETER_BITS - 1)) * + (INT)fadeOutAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); + } + } + + /* Fade-in factors */ + if (fadeInAttenuationVector != NULL) { + int i; + + /* check quantized factors first */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + if ((fadeInAttenuationVector[i] < 0) || + (fadeInAttenuationVector[i] > CONCEAL_MAX_QUANT_FACTOR)) { + return AAC_DEC_SET_PARAM_FAIL; + } + } + if (concealParams == NULL) { + return AAC_DEC_INVALID_HANDLE; + } + + /* now dequantize factors */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + concealParams->fadeInFactor[i] = FX_DBL2FX_SGL( + fLdPow(CONCEAL_MIN_ATTENUATION_FACTOR_025_LD, 0, + (FIXP_DBL)((INT)(FIXP_ONE >> CONCEAL_PARAMETER_BITS) * + (INT)fadeInAttenuationVector[i]), + CONCEAL_PARAMETER_BITS)); + } + } + + return (AAC_DEC_OK); +} + +/*! + \brief Get state of concealment module. + + \param pConcealChannelInfo + + \return Concealment state. +*/ +CConcealmentState CConcealment_GetState(CConcealmentInfo *pConcealChannelInfo) { + CConcealmentState state = ConcealState_Ok; + + if (pConcealChannelInfo != NULL) { + state = pConcealChannelInfo->concealState; + } + + return (state); +} + +/*! + \brief Store data for concealment techniques applied later + + Interface function to store data for different concealment strategies + */ +void CConcealment_Store( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + UCHAR nbDiv = NB_DIV; + + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderChannelInfo->data.usac.mod[nbDiv - 1] == 0)) + + { + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + SHORT tSpecScale[8]; + UCHAR tWindowShape; + BLOCK_TYPE tWindowSequence; + + /* store old window infos for swapping */ + tWindowSequence = hConcealmentInfo->windowSequence; + tWindowShape = hConcealmentInfo->windowShape; + + /* store old scale factors for swapping */ + FDKmemcpy(tSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); + + /* store new window infos */ + hConcealmentInfo->windowSequence = GetWindowSequence(pIcsInfo); + hConcealmentInfo->windowShape = GetWindowShape(pIcsInfo); + hConcealmentInfo->lastWinGrpLen = + *(GetWindowGroupLengthTable(pIcsInfo) + GetWindowGroups(pIcsInfo) - 1); + + /* store new scale factors */ + FDKmemcpy(hConcealmentInfo->specScale, pSpecScale, 8 * sizeof(SHORT)); + + if (hConcealmentInfo->pConcealParams->method < ConcealMethodInter) { + /* store new spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpectralCoefficient, + 1024 * sizeof(FIXP_CNCL)); +#else + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + int i; + for (i = 1024; i != 0; i--) { + *pCncl-- = FX_DBL2FX_CNCL(*pSpec--); + } +#endif + } else { + /* swap spectral data */ +#if (FIXP_CNCL == FIXP_DBL) + C_ALLOC_SCRATCH_START(pSpecTmp, FIXP_DBL, 1024); + FDKmemcpy(pSpecTmp, pSpectralCoefficient, 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); + FDKmemcpy(hConcealmentInfo->spectralCoefficient, pSpecTmp, + 1024 * sizeof(FIXP_DBL)); + C_ALLOC_SCRATCH_END(pSpecTmp, FIXP_DBL, 1024); +#else + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + FIXP_DBL tSpec; + + for (int i = 1024; i != 0; i--) { + tSpec = *pSpec; + *pSpec-- = FX_CNCL2FX_DBL(*pCncl); + *pCncl-- = FX_DBL2FX_CNCL(tSpec); + } +#endif + + /* complete swapping of window infos */ + pIcsInfo->WindowSequence = tWindowSequence; + pIcsInfo->WindowShape = tWindowShape; + + /* complete swapping of scale factors */ + FDKmemcpy(pSpecScale, tSpecScale, 8 * sizeof(SHORT)); + } + } + + if (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD) { + /* Store LSF4 */ + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(hConcealmentInfo->lsf4)); + /* Store TCX gain */ + hConcealmentInfo->last_tcx_gain = + pAacDecoderStaticChannelInfo->last_tcx_gain; + hConcealmentInfo->last_tcx_gain_e = + pAacDecoderStaticChannelInfo->last_tcx_gain_e; + } +} + +/*! + \brief Apply concealment + + Interface function to different concealment strategies + */ +int CConcealment_Apply( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UCHAR lastLpdMode, const int frameOk, const UINT flags) { + int appliedProcessing = 0; + const int mute_release_active = + frameOk && (hConcealmentInfo->concealState >= ConcealState_Mute) && + (hConcealmentInfo->cntValidFrames + 1 <= + hConcealmentInfo->pConcealParams->numMuteReleaseFrames); + + if (hConcealmentInfo->windowShape == CONCEAL_NOT_DEFINED) { + /* Initialize window_shape with same value as in the current (parsed) frame. + Because section 4.6.11.3.2 (Windowing and block switching) of ISO/IEC + 14496-3:2009 says: For the first raw_data_block() to be decoded the + window_shape of the left and right half of the window are identical. */ + hConcealmentInfo->windowShape = pAacDecoderChannelInfo->icsInfo.WindowShape; + } + + if (frameOk && !mute_release_active) { + /* Update render mode if frameOk except for ongoing mute release state. */ + hConcealmentInfo->lastRenderMode = + (SCHAR)pAacDecoderChannelInfo->renderMode; + + /* Rescue current data for concealment in future frames */ + CConcealment_Store(hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + /* Reset index to random sign vector to make sign calculation frame agnostic + (only depends on number of subsequently concealed spectral blocks) */ + hConcealmentInfo->iRandomPhase = 0; + } else { + if (hConcealmentInfo->lastRenderMode == AACDEC_RENDER_INVALID) { + hConcealmentInfo->lastRenderMode = AACDEC_RENDER_IMDCT; + } + pAacDecoderChannelInfo->renderMode = + (AACDEC_RENDER_MODE)hConcealmentInfo->lastRenderMode; + } + + /* hand current frame status to the state machine */ + CConcealment_UpdateState(hConcealmentInfo, frameOk, + pAacDecoderStaticChannelInfo, samplesPerFrame, + pAacDecoderChannelInfo); + + { + if (!frameOk && pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_IMDCT) { + /* LPC extrapolation */ + CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + hConcealmentInfo->lastRenderMode == AACDEC_RENDER_IMDCT); + FDKmemcpy(hConcealmentInfo->lsf4, pAacDecoderStaticChannelInfo->lpc4_lsf, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + } + + /* Create data for signal rendering according to the selected concealment + * method and decoder operating mode. */ + + if ((!frameOk || mute_release_active) && + (pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD)) { + /* Restore old LSF4 */ + FDKmemcpy(pAacDecoderStaticChannelInfo->lpc4_lsf, hConcealmentInfo->lsf4, + sizeof(pAacDecoderStaticChannelInfo->lpc4_lsf)); + /* Restore old TCX gain */ + pAacDecoderStaticChannelInfo->last_tcx_gain = + hConcealmentInfo->last_tcx_gain; + pAacDecoderStaticChannelInfo->last_tcx_gain_e = + hConcealmentInfo->last_tcx_gain_e; + } + + if (!(pAacDecoderChannelInfo->renderMode == AACDEC_RENDER_LPD && + pAacDecoderStaticChannelInfo->last_lpd_mode == 0)) { + switch (hConcealmentInfo->pConcealParams->method) { + default: + case ConcealMethodMute: + if (!frameOk) { + /* Mute spectral data in case of errors */ + FDKmemclear(pAacDecoderChannelInfo->pSpectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); + /* Set last window shape */ + pAacDecoderChannelInfo->icsInfo.WindowShape = + hConcealmentInfo->windowShape; + appliedProcessing = 1; + } + break; + + case ConcealMethodNoise: + /* Noise substitution error concealment technique */ + appliedProcessing = CConcealment_ApplyNoise( + hConcealmentInfo, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, pSamplingRateInfo, samplesPerFrame, + flags); + break; + + case ConcealMethodInter: + /* Energy interpolation concealment based on 3GPP */ + appliedProcessing = CConcealment_ApplyInter( + hConcealmentInfo, pAacDecoderChannelInfo, pSamplingRateInfo, + samplesPerFrame, 0, /* don't use tonal improvement */ + frameOk, mute_release_active); + break; + } + } else if (!frameOk || mute_release_active) { + /* simply restore the buffer */ + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; +#if (CNCL_FRACT_BITS != DFRACT_BITS) + FIXP_CNCL *RESTRICT pCncl = + &hConcealmentInfo->spectralCoefficient[1024 - 1]; + FIXP_DBL *RESTRICT pSpec = &pSpectralCoefficient[1024 - 1]; + int i; +#endif + + /* restore window infos (gri) do we need that? */ + pIcsInfo->WindowSequence = hConcealmentInfo->windowSequence; + pIcsInfo->WindowShape = hConcealmentInfo->windowShape; + + if (hConcealmentInfo->concealState != ConcealState_Mute) { + /* restore scale factors */ + FDKmemcpy(pSpecScale, hConcealmentInfo->specScale, 8 * sizeof(SHORT)); + + /* restore spectral bins */ +#if (CNCL_FRACT_BITS == DFRACT_BITS) + FDKmemcpy(pSpectralCoefficient, hConcealmentInfo->spectralCoefficient, + 1024 * sizeof(FIXP_DBL)); +#else + for (i = 1024; i != 0; i--) { + *pSpec-- = FX_CNCL2FX_DBL(*pCncl--); + } +#endif + } else { + /* clear scale factors */ + FDKmemclear(pSpecScale, 8 * sizeof(SHORT)); + + /* clear buffer */ + FDKmemclear(pSpectralCoefficient, 1024 * sizeof(FIXP_CNCL)); + } + } + } + /* update history */ + hConcealmentInfo->prevFrameOk[0] = hConcealmentInfo->prevFrameOk[1]; + hConcealmentInfo->prevFrameOk[1] = frameOk; + + return mute_release_active ? -1 : appliedProcessing; +} + +/*! +\brief Apply concealment noise substitution + + In case of frame lost this function produces a noisy frame with respect to the + energies values of past frame. + */ +static int CConcealment_ApplyNoise( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UINT flags) { + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + + int appliedProcessing = 0; + + FDK_ASSERT(pConcealmentInfo != NULL); + FDK_ASSERT((samplesPerFrame >= 120) && (samplesPerFrame <= 1024)); + + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + /* Nothing to do here! */ + break; + + case ConcealState_Single: + case ConcealState_FadeOut: + appliedProcessing = CConcealment_ApplyFadeOut( + /*mode =*/1, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + break; + + case ConcealState_Mute: { + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + FDKmemclear(pConcealmentInfo->spectralCoefficient, + samplesPerFrame * sizeof(FIXP_DBL)); + + appliedProcessing = 1; + } break; + + case ConcealState_FadeIn: { + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + default: + /* we shouldn't come here anyway */ + FDK_ASSERT(0); + break; + } + + return appliedProcessing; +} + +/*! + \brief Apply concealment interpolation + + The function swaps the data from the current and the previous frame. If an + error has occured, frame interpolation is performed to restore the missing + frame. In case of multiple faulty frames, fade-in and fade-out is applied. +*/ +static int CConcealment_ApplyInter( + CConcealmentInfo *pConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const int improveTonal, const int frameOk, const int mute_release_active) { +#if defined(FDK_ASSERT_ENABLE) + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; +#endif + + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + int sfbEnergyPrev[64]; + int sfbEnergyAct[64]; + + int i, appliedProcessing = 0; + + /* clear/init */ + FDKmemclear(sfbEnergyPrev, 64 * sizeof(int)); + FDKmemclear(sfbEnergyAct, 64 * sizeof(int)); + + if (!frameOk || mute_release_active) { + /* Restore last frame from concealment buffer */ + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + /* Restore spectral data */ + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = + FX_CNCL2FX_DBL(pConcealmentInfo->spectralCoefficient[i]); + } + + /* Restore scale factors */ + FDKmemcpy(pSpecScale, pConcealmentInfo->specScale, 8 * sizeof(SHORT)); + } + + /* if previous frame was not ok */ + if (!pConcealmentInfo->prevFrameOk[1] || mute_release_active) { + /* if current frame (f_n) is ok and the last but one frame (f_(n-2)) + was ok, too, then interpolate both frames in order to generate + the current output frame (f_(n-1)). Otherwise, use the last stored + frame (f_(n-2) or f_(n-3) or ...). */ + if (frameOk && pConcealmentInfo->prevFrameOk[0] && !mute_release_active) { + appliedProcessing = 1; + + /* Interpolate both frames in order to generate the current output frame + * (f_(n-1)). */ + if (pIcsInfo->WindowSequence == BLOCK_SHORT) { + /* f_(n-2) == BLOCK_SHORT */ + /* short--??????--short, short--??????--long interpolation */ + /* short--short---short, short---long---long interpolation */ + + int wnd; + + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ + /* short--short---short interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_SHORT; + + for (wnd = 0; wnd < 8; wnd++) { + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyPrev); + + CConcealment_CalcBandEnergy( + &pConcealmentInfo->spectralCoefficient[wnd * (samplesPerFrame / + 8)], /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_NoExpand, + sfbEnergyAct); + + CConcealment_InterpolateBuffer( + &pSpectralCoefficient[wnd * + (samplesPerFrame / 8)], /* spec_(n-1) */ + &pSpecScale[wnd], &pConcealmentInfo->specScale[wnd], + &pSpecScale[wnd], sfbEnergyPrev, sfbEnergyAct, + scaleFactorBandsTotal, pSfbOffset); + } + } else { /* f_n != BLOCK_SHORT */ + /* short---long---long interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleOut; + + CConcealment_CalcBandEnergy( + &pSpectralCoefficient[samplesPerFrame - + (samplesPerFrame / + 8)], /* [wnd] spec_(n-2) */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, + sfbEnergyAct); + + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyPrev); + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = BLOCK_STOP; + + for (i = 0; i < samplesPerFrame; i++) { + pSpectralCoefficient[i] = + pConcealmentInfo->spectralCoefficient[i]; /* spec_n */ + } + + for (i = 0; i < 8; i++) { /* search for max(specScale) */ + if (pSpecScale[i] > pSpecScale[0]) { + pSpecScale[0] = pSpecScale[i]; + } + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pConcealmentInfo->specScale[0], &pSpecScale[0], &specScaleOut, + sfbEnergyPrev, sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); + + pSpecScale[0] = specScaleOut; + } + } else { + /* long--??????--short, long--??????--long interpolation */ + /* long---long---short, long---long---long interpolation */ + + int scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + const SHORT *pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + SHORT specScaleAct = pConcealmentInfo->specScale[0]; + + CConcealment_CalcBandEnergy(pSpectralCoefficient, /* spec_(n-2) */ + pSamplingRateInfo, BLOCK_LONG, + CConcealment_NoExpand, sfbEnergyPrev); + + if (pConcealmentInfo->windowSequence == + BLOCK_SHORT) { /* f_n == BLOCK_SHORT */ + /* long---long---short interpolation */ + + pIcsInfo->WindowShape = (samplesPerFrame <= 512) ? 2 : 1; + pIcsInfo->WindowSequence = BLOCK_START; + + for (i = 1; i < 8; i++) { /* search for max(specScale) */ + if (pConcealmentInfo->specScale[i] > specScaleAct) { + specScaleAct = pConcealmentInfo->specScale[i]; + } + } + + /* Expand first short spectrum */ + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_SHORT, CConcealment_Expand, /* !!! */ + sfbEnergyAct); + } else { + /* long---long---long interpolation */ + + pIcsInfo->WindowShape = 0; + pIcsInfo->WindowSequence = BLOCK_LONG; + + CConcealment_CalcBandEnergy( + pConcealmentInfo->spectralCoefficient, /* spec_n */ + pSamplingRateInfo, BLOCK_LONG, CConcealment_NoExpand, + sfbEnergyAct); + } + + CConcealment_InterpolateBuffer( + pSpectralCoefficient, /* spec_(n-1) */ + &pSpecScale[0], &specScaleAct, &pSpecScale[0], sfbEnergyPrev, + sfbEnergyAct, scaleFactorBandsTotal, pSfbOffset); + } + } + + /* Noise substitution of sign of the output spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, + pSpectralCoefficient, samplesPerFrame); + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } + + /* scale spectrum according to concealment state */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Single: + appliedProcessing = 1; + break; + + case ConcealState_FadeOut: { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeOutFrames); + + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + case ConcealState_FadeIn: { + FDK_ASSERT(pConcealmentInfo->cntFadeFrames >= 0); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + CONCEAL_MAX_NUM_FADE_FACTORS); + FDK_ASSERT(pConcealmentInfo->cntFadeFrames < + pConcealCommonData->numFadeInFrames); + + /* TimeDomainFading: */ + /* Attenuation of signal is done in CConcealment_TDFading() */ + + appliedProcessing = 1; + } break; + + case ConcealState_Mute: { + /* set dummy window parameters */ + pIcsInfo->Valid = 0; /* Trigger the generation of a consitent IcsInfo */ + pIcsInfo->WindowShape = + pConcealmentInfo->windowShape; /* Prevent an invalid WindowShape + (required for F/T transform) */ + pIcsInfo->WindowSequence = + CConcealment_GetWinSeq(pConcealmentInfo->windowSequence); + pConcealmentInfo->windowSequence = + pIcsInfo->WindowSequence; /* Store for next frame + (spectrum in concealment + buffer can't be used at + all) */ + + /* mute spectral data */ + FDKmemclear(pSpectralCoefficient, samplesPerFrame * sizeof(FIXP_DBL)); + + appliedProcessing = 1; + } break; + + default: + /* nothing to do here */ + break; + } + + return appliedProcessing; +} + +/*! + \brief Calculate the spectral energy + + The function calculates band-wise the spectral energy. This is used for + frame interpolation. +*/ +static void CConcealment_CalcBandEnergy( + FIXP_DBL *spectrum, const SamplingRateInfo *pSamplingRateInfo, + const int blockType, CConcealmentExpandType expandType, int *sfbEnergy) { + const SHORT *pSfbOffset; + int line, sfb, scaleFactorBandsTotal = 0; + + /* In the following calculations, enAccu is initialized with LSB-value in + * order to avoid zero energy-level */ + + line = 0; + + switch (blockType) { + case BLOCK_LONG: + case BLOCK_START: + case BLOCK_STOP: + + if (expandType == CConcealment_NoExpand) { + /* standard long calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } else { + /* compress long to short */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1] << 3; line++) { + enAccu += + (enAccu + (fPow2Div2(*(spectrum + line)) >> sfbScale)) >> 3; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + + case BLOCK_SHORT: + + if (expandType == CConcealment_NoExpand) { + /* standard short calculation */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Short; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Short; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + line)) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } else { + /* expand short to long spectrum */ + scaleFactorBandsTotal = + pSamplingRateInfo->NumberOfScaleFactorBands_Long; + pSfbOffset = pSamplingRateInfo->ScaleFactorBands_Long; + + for (sfb = 0; sfb < scaleFactorBandsTotal; sfb++) { + FIXP_DBL enAccu = (FIXP_DBL)(LONG)1; + int sfbScale = + (sizeof(LONG) << 3) - + CntLeadingZeros(pSfbOffset[sfb + 1] - pSfbOffset[sfb]) - 1; + /* scaling depends on sfb width. */ + for (; line < pSfbOffset[sfb + 1]; line++) { + enAccu += fPow2Div2(*(spectrum + (line >> 3))) >> sfbScale; + } + *(sfbEnergy + sfb) = CntLeadingZeros(enAccu) - 1; + } + } + break; + } +} + +/*! + \brief Interpolate buffer + + The function creates the interpolated spectral data according to the + energy of the last good frame and the current (good) frame. +*/ +static void CConcealment_InterpolateBuffer(FIXP_DBL *spectrum, + SHORT *pSpecScalePrv, + SHORT *pSpecScaleAct, + SHORT *pSpecScaleOut, int *enPrv, + int *enAct, int sfbCnt, + const SHORT *pSfbOffset) { + int sfb, line = 0; + int fac_shift; + int fac_mod; + FIXP_DBL accu; + + for (sfb = 0; sfb < sfbCnt; sfb++) { + fac_shift = + enPrv[sfb] - enAct[sfb] + ((*pSpecScaleAct - *pSpecScalePrv) << 1); + fac_mod = fac_shift & 3; + fac_shift = (fac_shift >> 2) + 1; + fac_shift += *pSpecScalePrv - fixMax(*pSpecScalePrv, *pSpecScaleAct); + + for (; line < pSfbOffset[sfb + 1]; line++) { + accu = fMult(*(spectrum + line), facMod4Table[fac_mod]); + if (fac_shift < 0) { + accu >>= -fac_shift; + } else { + accu <<= fac_shift; + } + *(spectrum + line) = accu; + } + } + *pSpecScaleOut = fixMax(*pSpecScalePrv, *pSpecScaleAct); +} + +/*! + \brief Find next fading frame in case of changing fading direction + + \param pConcealCommonData Pointer to the concealment common data structure. + \param actFadeIndex Last index used for fading + \param direction Direction of change: 0 : change from FADE-OUT to FADE-IN, 1 + : change from FADE-IN to FADE-OUT + + This function determines the next fading index to be used for the fading + direction to be changed to. +*/ + +static INT findEquiFadeFrame(CConcealParams *pConcealCommonData, + INT actFadeIndex, int direction) { + FIXP_SGL *pFactor; + FIXP_SGL referenceVal; + FIXP_SGL minDiff = (FIXP_SGL)MAXVAL_SGL; + + INT nextFadeIndex = 0; + + int i; + + /* init depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeOutFactor[actFadeIndex] >> 1; + } + pFactor = pConcealCommonData->fadeInFactor; + } else { /* FADE-IN => FADE-OUT */ + if (actFadeIndex < 0) { + referenceVal = (FIXP_SGL)MAXVAL_SGL; + } else { + referenceVal = pConcealCommonData->fadeInFactor[actFadeIndex] >> 1; + } + pFactor = pConcealCommonData->fadeOutFactor; + } + + /* search for minimum difference */ + for (i = 0; i < CONCEAL_MAX_NUM_FADE_FACTORS; i++) { + FIXP_SGL diff = fixp_abs((pFactor[i] >> 1) - referenceVal); + if (diff < minDiff) { + minDiff = diff; + nextFadeIndex = i; + } + } + + /* check and adjust depending on direction */ + if (direction == 0) { /* FADE-OUT => FADE-IN */ + if (nextFadeIndex > pConcealCommonData->numFadeInFrames) { + nextFadeIndex = fMax(pConcealCommonData->numFadeInFrames - 1, 0); + } + if (((pFactor[nextFadeIndex] >> 1) <= referenceVal) && + (nextFadeIndex > 0)) { + nextFadeIndex -= 1; + } + } else { /* FADE-IN => FADE-OUT */ + if (((pFactor[nextFadeIndex] >> 1) >= referenceVal) && + (nextFadeIndex < CONCEAL_MAX_NUM_FADE_FACTORS - 1)) { + nextFadeIndex += 1; + } + } + + return (nextFadeIndex); +} + +/*! + \brief Update the concealment state + + The function updates the state of the concealment state-machine. The + states are: mute, fade-in, fade-out, interpolate and frame-ok. +*/ +static void CConcealment_UpdateState( + CConcealmentInfo *pConcealmentInfo, int frameOk, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CConcealParams *pConcealCommonData = pConcealmentInfo->pConcealParams; + + switch (pConcealCommonData->method) { + case ConcealMethodNoise: { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if (frameOk) { + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for Noise Substitution -- */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!frameOk) { + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state SINGLE-FRAME-LOSS */ + pConcealmentInfo->concealState = ConcealState_Single; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Single: /* Just a pre-stage before fade-out begins. + Stay here only one frame! */ + if (frameOk) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } else { + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } + } + break; + + case ConcealState_FadeOut: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } else /* Stay in FADE-OUT */ + { + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (frameOk) { + /* we have good frame information but stay fully in concealment - + * reset winGrpOffset/attGrpOffset */ + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= 1; + if (frameOk) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + pConcealmentInfo->winGrpOffset[0] = 0; + pConcealmentInfo->winGrpOffset[1] = 0; + pConcealmentInfo->attGrpOffset[0] = 0; + pConcealmentInfo->attGrpOffset[1] = 0; + + pConcealmentInfo + ->cntFadeFrames--; /* decrease because + CConcealment_ApplyFadeOut() will + increase, accordingly */ + /* mode 0 just updates the Fading counter */ + CConcealment_ApplyFadeOut( + /*mode =*/0, pConcealmentInfo, pAacDecoderStaticChannelInfo, + samplesPerFrame, pAacDecoderChannelInfo); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + default: + FDK_ASSERT(0); + break; + } + } break; + + case ConcealMethodInter: + case ConcealMethodTonal: { + if (pConcealmentInfo->concealState != ConcealState_Ok) { + /* count the valid frames during concealment process */ + if (pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk)) { + /* The frame is OK even if it can be estimated by the energy + * interpolation algorithm */ + pConcealmentInfo->cntValidFrames += 1; + } else { + pConcealmentInfo->cntValidFrames = 0; + } + } + + /* -- STATE MACHINE for energy interpolation -- */ + switch (pConcealmentInfo->concealState) { + case ConcealState_Ok: + if (!(pConcealmentInfo->prevFrameOk[1] || + (pConcealmentInfo->prevFrameOk[0] && + !pConcealmentInfo->prevFrameOk[1] && frameOk))) { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* Fade out only if the energy interpolation algorithm can not be + * applied! */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + pConcealmentInfo->cntFadeFrames = 0; + pConcealmentInfo->cntValidFrames = 0; + } + break; + + case ConcealState_Single: + pConcealmentInfo->concealState = ConcealState_Ok; + break; + + case ConcealState_FadeOut: + pConcealmentInfo->cntFadeFrames += 1; + + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames - 1, + 0 /* FadeOut -> FadeIn */); + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealmentInfo->cntFadeFrames >= + pConcealCommonData->numFadeOutFrames) { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + + case ConcealState_Mute: + if (pConcealmentInfo->cntValidFrames > + pConcealCommonData->numMuteReleaseFrames) { + if (pConcealCommonData->numFadeInFrames > 0) { + /* change to state FADE-IN */ + pConcealmentInfo->concealState = ConcealState_FadeIn; + pConcealmentInfo->cntFadeFrames = + pConcealCommonData->numFadeInFrames - 1; + } else { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } + break; + + case ConcealState_FadeIn: + pConcealmentInfo->cntFadeFrames -= + 1; /* used to address the fade-in factors */ + + if (frameOk || pConcealmentInfo->prevFrameOk[1]) { + if (pConcealmentInfo->cntFadeFrames < 0) { + /* change to state OK */ + pConcealmentInfo->concealState = ConcealState_Ok; + } + } else { + if (pConcealCommonData->numFadeOutFrames > 0) { + /* change to state FADE-OUT */ + pConcealmentInfo->concealState = ConcealState_FadeOut; + pConcealmentInfo->cntFadeFrames = findEquiFadeFrame( + pConcealCommonData, pConcealmentInfo->cntFadeFrames + 1, + 1 /* FadeIn -> FadeOut */); + } else { + /* change to state MUTE */ + pConcealmentInfo->concealState = ConcealState_Mute; + } + } + break; + } /* End switch(pConcealmentInfo->concealState) */ + } break; + + default: + /* Don't need a state machine for other concealment methods. */ + break; + } +} + +/*! +\brief Randomizes the sign of the spectral data + + The function toggles the sign of the spectral data randomly. This is + useful to ensure the quality of the concealed frames. + */ +static void CConcealment_ApplyRandomSign(int randomPhase, FIXP_DBL *spec, + int samplesPerFrame) { + int i; + USHORT packedSign = 0; + + /* random table 512x16bit has been reduced to 512 packed sign bits = 32x16 bit + */ + + /* read current packed sign word */ + packedSign = AacDec_randomSign[randomPhase >> 4]; + packedSign >>= (randomPhase & 0xf); + + for (i = 0; i < samplesPerFrame; i++) { + if ((randomPhase & 0xf) == 0) { + packedSign = AacDec_randomSign[randomPhase >> 4]; + } + + if (packedSign & 0x1) { + spec[i] = -spec[i]; + } + packedSign >>= 1; + + randomPhase = (randomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + } +} + +/*! + \brief Get fadeing factor for current concealment state. + + The function returns the state (ok or not) of the previous frame. + If called before the function CConcealment_Apply() set the fBeforeApply + flag to get the correct value. + + \return Frame OK flag of previous frame. + */ +int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply) { + int prevFrameOk = 1; + + if (hConcealmentInfo != NULL) { + prevFrameOk = hConcealmentInfo->prevFrameOk[fBeforeApply & 0x1]; + } + + return prevFrameOk; +} + +/*! + \brief Get the number of delay frames introduced by concealment technique. + + \return Number of delay frames. + */ +UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData) { + UINT frameDelay = 0; + + if (pConcealCommonData != NULL) { + switch (pConcealCommonData->method) { + case ConcealMethodTonal: + case ConcealMethodInter: + frameDelay = 1; + break; + default: + break; + } + } + + return frameDelay; +} + +static int CConcealment_ApplyFadeOut( + int mode, CConcealmentInfo *pConcealmentInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const int samplesPerFrame, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + /* mode 1 = apply RandomSign and mute spectral coefficients if necessary, * + * mode 0 = Update cntFadeFrames */ + + /* restore frequency coefficients from buffer with a specific muting */ + int srcWin, dstWin, numWindows = 1; + int windowLen = samplesPerFrame; + int srcGrpStart = 0; + int winIdxStride = 1; + int numWinGrpPerFac, attIdx, attIdxStride; + int i; + int appliedProcessing = 0; + + CIcsInfo *pIcsInfo = &pAacDecoderChannelInfo->icsInfo; + FIXP_DBL *pSpectralCoefficient = + SPEC_LONG(pAacDecoderChannelInfo->pSpectralCoefficient); + SHORT *pSpecScale = pAacDecoderChannelInfo->specScale; + + /* set old window parameters */ + if (pConcealmentInfo->lastRenderMode == AACDEC_RENDER_LPD) { + switch (pAacDecoderStaticChannelInfo->last_lpd_mode) { + case 1: + numWindows = 4; + srcGrpStart = 3; + windowLen = samplesPerFrame >> 2; + break; + case 2: + numWindows = 2; + srcGrpStart = 1; + windowLen = samplesPerFrame >> 1; + winIdxStride = 2; + break; + case 3: + numWindows = 1; + srcGrpStart = 0; + windowLen = samplesPerFrame; + winIdxStride = 4; + break; + } + pConcealmentInfo->lastWinGrpLen = 1; + } else { + pIcsInfo->WindowShape = pConcealmentInfo->windowShape; + pIcsInfo->WindowSequence = pConcealmentInfo->windowSequence; + + if (pConcealmentInfo->windowSequence == BLOCK_SHORT) { + /* short block handling */ + numWindows = 8; + windowLen = samplesPerFrame >> 3; + srcGrpStart = numWindows - pConcealmentInfo->lastWinGrpLen; + } + } + + attIdxStride = + fMax(1, (int)(numWindows / (pConcealmentInfo->lastWinGrpLen + 1))); + + /* load last state */ + attIdx = pConcealmentInfo->cntFadeFrames; + numWinGrpPerFac = pConcealmentInfo->attGrpOffset[mode]; + srcWin = srcGrpStart + pConcealmentInfo->winGrpOffset[mode]; + + FDK_ASSERT((srcGrpStart * windowLen + windowLen) <= samplesPerFrame); + FDK_ASSERT((srcWin * windowLen + windowLen) <= 1024); + + for (dstWin = 0; dstWin < numWindows; dstWin += 1) { + FIXP_CNCL *pCncl = + pConcealmentInfo->spectralCoefficient + (srcWin * windowLen); + FIXP_DBL *pOut = pSpectralCoefficient + (dstWin * windowLen); + + if (mode == 1) { + /* mute if attIdx gets large enaugh */ + if (attIdx > pConcealmentInfo->pConcealParams->numFadeOutFrames) { + FDKmemclear(pCncl, sizeof(FIXP_DBL) * windowLen); + } + + /* restore frequency coefficients from buffer - attenuation is done later + */ + for (i = 0; i < windowLen; i++) { + pOut[i] = pCncl[i]; + } + + /* apply random change of sign for spectral coefficients */ + CConcealment_ApplyRandomSign(pConcealmentInfo->iRandomPhase, pOut, + windowLen); + + /* Increment random phase index to avoid repetition artifacts. */ + pConcealmentInfo->iRandomPhase = + (pConcealmentInfo->iRandomPhase + 1) & (AAC_NF_NO_RANDOM_VAL - 1); + + /* set old scale factors */ + pSpecScale[dstWin * winIdxStride] = + pConcealmentInfo->specScale[srcWin * winIdxStride]; + } + + srcWin += 1; + + if (srcWin >= numWindows) { + /* end of sequence -> rewind to first window of group */ + srcWin = srcGrpStart; + numWinGrpPerFac += 1; + if (numWinGrpPerFac >= attIdxStride) { + numWinGrpPerFac = 0; + attIdx += 1; + } + } + } + + /* store current state */ + + pConcealmentInfo->winGrpOffset[mode] = srcWin - srcGrpStart; + FDK_ASSERT((pConcealmentInfo->winGrpOffset[mode] >= 0) && + (pConcealmentInfo->winGrpOffset[mode] < 8)); + pConcealmentInfo->attGrpOffset[mode] = numWinGrpPerFac; + FDK_ASSERT((pConcealmentInfo->attGrpOffset[mode] >= 0) && + (pConcealmentInfo->attGrpOffset[mode] < attIdxStride)); + + if (mode == 0) { + pConcealmentInfo->cntFadeFrames = attIdx; + } + + appliedProcessing = 1; + + return appliedProcessing; +} + +/*! + \brief Do Time domain fading (TDFading) in concealment case + + In case of concealment, this function takes care of the fading, after time +domain signal has been rendered by the respective signal rendering functions. + The fading out in case of ACELP decoding is not done by this function but by +the ACELP decoder for the first concealed frame if CONCEAL_CORE_IGNORANT_FADE is +not set. + + TimeDomain fading never creates jumps in energy / discontinuities, it always +does a continuous fading. To achieve this, fading is always done from a starting +point to a target point, while the starting point is always determined to be the +last target point. By varying the target point of a fading, the fading slope can +be controlled. + + This principle is applied to the fading within a frame and the fading from +frame to frame. + + One frame is divided into 8 subframes to obtain 8 parts of fading slopes +within a frame, each maybe with its own gradient. + + Workflow: + 1.) Determine Fading behavior and end-of-frame target fading level, based on +concealmentState (determined by CConcealment_UpdateState()) and the core mode. + - By _DEFAULT_, + The target fading level is determined by fadeOutFactor[cntFadeFrames] +in case of fadeOut, or fadeInFactor[cntFadeFrames] in case of fadeIn. + --> fading type is FADE_TIMEDOMAIN in this case. Target fading level +is determined by fading index cntFadeFrames. + + - If concealmentState is signalling a _MUTED SIGNAL_, + TDFading decays to 0 within 1/8th of a frame if numFadeOutFrames == 0. + --> fading type is FADE_TIMEDOMAIN_TOSPECTRALMUTE in this case. + + - If concealmentState is signalling the _END OF MUTING_, + TDFading fades to target fading level within 1/8th of a frame if +numFadeInFrames == 0. + --> fading type is FADE_TIMEDOMAIN_FROMSPECTRALMUTE in this case. +Target fading level is determined by fading index cntFadeFrames. + +#ifndef CONCEAL_CORE_IGNORANT_FADE + - In case of an _ACELP FADEOUT_, + TDFading leaves fading control to ACELP decoder for 1/2 frame. + --> fading type is FADE_ACELPDOMAIN in this case. +#endif + + 2.) Render fading levels within current frame and do the final fading: + Map Fading slopes to fading levels and apply to time domain signal. + + +*/ + +INT CConcealment_TDFading( + int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, + FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1) { + /* + Do the fading in Time domain based on concealment states and core mode + */ + FIXP_DBL fadeStop, attMute = (FIXP_DBL)0; + int idx = 0, ii; + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo = + *ppAacDecoderStaticChannelInfo; + CConcealmentInfo *pConcealmentInfo = + &pAacDecoderStaticChannelInfo->concealmentInfo; + CConcealParams *pConcealParams = pConcealmentInfo->pConcealParams; + const CConcealmentState concealState = pConcealmentInfo->concealState; + TDfadingType fadingType; + FIXP_DBL fadingStations[9] = {0}; + int fadingSteps[8] = {0}; + const FIXP_DBL fadeStart = + pConcealmentInfo + ->fade_old; /* start fading at last end-of-frame attenuation */ + FIXP_SGL *fadeFactor = pConcealParams->fadeOutFactor; + const INT cntFadeFrames = pConcealmentInfo->cntFadeFrames; + int TDFadeOutStopBeforeMute = 1; + int TDFadeInStopBeforeFullLevel = 1; + + /* + determine Fading behaviour (end-of-frame attenuation and fading type) (1.) + */ + + switch (concealState) { + case ConcealState_Single: + case ConcealState_Mute: + case ConcealState_FadeOut: + idx = (pConcealParams->method == ConcealMethodNoise) ? cntFadeFrames - 1 + : cntFadeFrames; + fadingType = FADE_TIMEDOMAIN; + + if (concealState == ConcealState_Mute || + (cntFadeFrames + TDFadeOutStopBeforeMute) > + pConcealmentInfo->pConcealParams->numFadeOutFrames) { + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; + } + + break; + case ConcealState_FadeIn: + idx = cntFadeFrames; + idx -= TDFadeInStopBeforeFullLevel; + FDK_FALLTHROUGH; + case ConcealState_Ok: + fadeFactor = pConcealParams->fadeInFactor; + idx = (concealState == ConcealState_Ok) ? -1 : idx; + fadingType = (pConcealmentInfo->concealState_old == ConcealState_Mute) + ? FADE_TIMEDOMAIN_FROMSPECTRALMUTE + : FADE_TIMEDOMAIN; + break; + default: + FDK_ASSERT(0); + fadingType = FADE_TIMEDOMAIN_TOSPECTRALMUTE; + break; + } + + /* determine Target end-of-frame fading level and fading slope */ + switch (fadingType) { + case FADE_TIMEDOMAIN_FROMSPECTRALMUTE: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + if (pConcealmentInfo->pConcealParams->numFadeInFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN: + fadeStop = + (idx < 0) ? (FIXP_DBL)MAXVAL_DBL : FX_SGL2FX_DBL(fadeFactor[idx]); + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + case FADE_TIMEDOMAIN_TOSPECTRALMUTE: + fadeStop = attMute; + if (pConcealmentInfo->pConcealParams->numFadeOutFrames == 0) { + /* do step as fast as possible */ + fadingSteps[0] = 1; + break; + } + CConcealment_TDFading_doLinearFadingSteps(&fadingSteps[0]); + break; + } + + /* + Render fading levels within current frame and do the final fading (2.) + */ + + len >>= 3; + CConcealment_TDFadeFillFadingStations(fadingStations, fadingSteps, fadeStop, + fadeStart, fadingType); + + if ((fadingStations[8] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[7] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[6] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[5] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[4] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[3] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[2] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[1] != (FIXP_DBL)MAXVAL_DBL) || + (fadingStations[0] != + (FIXP_DBL)MAXVAL_DBL)) /* if there's something to fade */ + { + int start = 0; + for (ii = 0; ii < 8; ii++) { + CConcealment_TDFadePcmAtt(start, len, fadingStations[ii], + fadingStations[ii + 1], pcmdata); + start += len; + } + } + CConcealment_TDNoise_Apply(pConcealmentInfo, len, pcmdata); + + /* Save end-of-frame attenuation and fading type */ + pConcealmentInfo->lastFadingType = fadingType; + pConcealmentInfo->fade_old = fadeStop; + pConcealmentInfo->concealState_old = concealState; + + return 1; +} + +/* attenuate pcmdata in Time Domain Fading process */ +static void CConcealment_TDFadePcmAtt(int start, int len, FIXP_DBL fadeStart, + FIXP_DBL fadeStop, FIXP_PCM *pcmdata) { + int i; + FIXP_DBL dStep; + FIXP_DBL dGain; + FIXP_DBL dGain_apply; + int bitshift = (DFRACT_BITS - SAMPLE_BITS); + + /* set start energy */ + dGain = fadeStart; + /* determine energy steps from sample to sample */ + dStep = (FIXP_DBL)((int)((fadeStart >> 1) - (fadeStop >> 1)) / len) << 1; + + for (i = start; i < (start + len); i++) { + dGain -= dStep; + /* prevent gain from getting negative due to possible fixpoint inaccuracies + */ + dGain_apply = fMax((FIXP_DBL)0, dGain); + /* finally, attenuate samples */ + pcmdata[i] = (FIXP_PCM)((fMult(pcmdata[i], (dGain_apply))) >> bitshift); + } +} + +/* +\brief Fill FadingStations + +The fadingstations are the attenuation factors, being applied to its dedicated +portions of pcm data. They are calculated using the fadingsteps. One fadingstep +is the weighted contribution to the fading slope within its dedicated portion of +pcm data. + +*Fadingsteps : 0 0 0 1 0 1 2 0 + + |<- 1 Frame pcm data ->| + fadeStart-->|__________ | + ^ ^ ^ ^ \____ | + Attenuation : | | | | ^ ^\__ | + | | | | | | ^\ | + | | | | | | | \___|<-- fadeStop + | | | | | | | ^ ^ + | | | | | | | | | +Fadingstations: [0][1][2][3][4][5][6][7][8] + +(Fadingstations "[0]" is "[8] from previous frame", therefore its not meaningful +to be edited) + +*/ +static void CConcealment_TDFadeFillFadingStations(FIXP_DBL *fadingStations, + int *fadingSteps, + FIXP_DBL fadeStop, + FIXP_DBL fadeStart, + TDfadingType fadingType) { + int i; + INT fadingSteps_sum = 0; + INT fadeDiff; + + fadingSteps_sum = fadingSteps[0] + fadingSteps[1] + fadingSteps[2] + + fadingSteps[3] + fadingSteps[4] + fadingSteps[5] + + fadingSteps[6] + fadingSteps[7]; + fadeDiff = ((INT)(fadeStop - fadeStart) / fMax(fadingSteps_sum, (INT)1)); + fadingStations[0] = fadeStart; + for (i = 1; i < 8; i++) { + fadingStations[i] = + fadingStations[i - 1] + (FIXP_DBL)(fadeDiff * fadingSteps[i - 1]); + } + fadingStations[8] = fadeStop; +} + +static void CConcealment_TDFading_doLinearFadingSteps(int *fadingSteps) { + fadingSteps[0] = fadingSteps[1] = fadingSteps[2] = fadingSteps[3] = + fadingSteps[4] = fadingSteps[5] = fadingSteps[6] = fadingSteps[7] = 1; +} + +/* end of TimeDomainFading functions */ + +/* derived from int UsacRandomSign() */ +static int CConcealment_TDNoise_Random(ULONG *seed) { + *seed = (ULONG)(((UINT64)(*seed) * 69069) + 5); + return (int)(*seed); +} + +static void CConcealment_TDNoise_Apply(CConcealmentInfo *const pConcealmentInfo, + const int len, FIXP_PCM *const pcmdata) { + FIXP_PCM *states = pConcealmentInfo->TDNoiseStates; + FIXP_PCM noiseVal; + FIXP_DBL noiseValLong; + FIXP_SGL *coef = pConcealmentInfo->TDNoiseCoef; + FIXP_DBL TDNoiseAtt; + ULONG seed = pConcealmentInfo->TDNoiseSeed = + (ULONG)CConcealment_TDNoise_Random(&pConcealmentInfo->TDNoiseSeed) + 1; + + TDNoiseAtt = pConcealmentInfo->pConcealParams->comfortNoiseLevel; + + int ii; + + if ((pConcealmentInfo->concealState != ConcealState_Ok || + pConcealmentInfo->concealState_old != ConcealState_Ok) && + TDNoiseAtt != (FIXP_DBL)0) { + for (ii = 0; ii < (len << 3); ii++) { + /* create filtered noise */ + states[2] = states[1]; + states[1] = states[0]; + states[0] = ((FIXP_PCM)CConcealment_TDNoise_Random(&seed)); + noiseValLong = fMult(states[0], coef[0]) + fMult(states[1], coef[1]) + + fMult(states[2], coef[2]); + noiseVal = FX_DBL2FX_PCM(fMult(noiseValLong, TDNoiseAtt)); + + /* add filtered noise - check for clipping, before */ + if (noiseVal > (FIXP_PCM)0 && + pcmdata[ii] > (FIXP_PCM)MAXVAL_FIXP_PCM - noiseVal) { + noiseVal = noiseVal * (FIXP_PCM)-1; + } else if (noiseVal < (FIXP_PCM)0 && + pcmdata[ii] < (FIXP_PCM)MINVAL_FIXP_PCM - noiseVal) { + noiseVal = noiseVal * (FIXP_PCM)-1; + } + + pcmdata[ii] += noiseVal; + } + } +} diff --git a/fdk-aac/libAACdec/src/conceal.h b/fdk-aac/libAACdec/src/conceal.h new file mode 100644 index 0000000..e01a796 --- /dev/null +++ b/fdk-aac/libAACdec/src/conceal.h @@ -0,0 +1,152 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: independent channel concealment + +*******************************************************************************/ + +#ifndef CONCEAL_H +#define CONCEAL_H + +#include "channelinfo.h" + +#define AACDEC_CONCEAL_PARAM_NOT_SPECIFIED (0xFFFE) + +void CConcealment_InitCommonData(CConcealParams *pConcealCommonData); + +void CConcealment_InitChannelData(CConcealmentInfo *hConcealmentInfo, + CConcealParams *pConcealCommonData, + AACDEC_RENDER_MODE initRenderMode, + int samplesPerFrame); + +CConcealmentMethod CConcealment_GetMethod(CConcealParams *pConcealCommonData); + +UINT CConcealment_GetDelay(CConcealParams *pConcealCommonData); + +AAC_DECODER_ERROR +CConcealment_SetParams(CConcealParams *concealParams, int method, + int fadeOutSlope, int fadeInSlope, int muteRelease, + FIXP_DBL comfNoiseLevel); + +CConcealmentState CConcealment_GetState(CConcealmentInfo *hConcealmentInfo); + +AAC_DECODER_ERROR +CConcealment_SetAttenuation(CConcealParams *concealParams, + const SHORT *fadeOutAttenuationVector, + const SHORT *fadeInAttenuationVector); + +void CConcealment_Store( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +int CConcealment_Apply( + CConcealmentInfo *hConcealmentInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, const int samplesPerFrame, + const UCHAR lastLpdMode, const int FrameOk, const UINT flags); + +int CConcealment_GetLastFrameOk(CConcealmentInfo *hConcealmentInfo, + const int fBeforeApply); + +INT CConcealment_TDFading( + int len, CAacDecoderStaticChannelInfo **ppAacDecoderStaticChannelInfo, + FIXP_PCM *pcmdata, FIXP_PCM *pcmdata_1); + +#endif /* #ifndef CONCEAL_H */ diff --git a/fdk-aac/libAACdec/src/conceal_types.h b/fdk-aac/libAACdec/src/conceal_types.h new file mode 100644 index 0000000..d90374e --- /dev/null +++ b/fdk-aac/libAACdec/src/conceal_types.h @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Christian Griebel + + Description: Error concealment structs and types + +*******************************************************************************/ + +#ifndef CONCEAL_TYPES_H +#define CONCEAL_TYPES_H + +#include "machine_type.h" +#include "common_fix.h" + +#include "rvlc_info.h" + +#include "usacdec_lpc.h" + +#define CONCEAL_MAX_NUM_FADE_FACTORS (32) + +#define FIXP_CNCL FIXP_DBL +#define FL2FXCONST_CNCL FL2FXCONST_DBL +#define FX_DBL2FX_CNCL +#define FX_CNCL2FX_DBL +#define CNCL_FRACT_BITS DFRACT_BITS + +/* Warning: Do not ever change these values. */ +typedef enum { + ConcealMethodNone = -1, + ConcealMethodMute = 0, + ConcealMethodNoise = 1, + ConcealMethodInter = 2, + ConcealMethodTonal = 3 + +} CConcealmentMethod; + +typedef enum { + ConcealState_Ok, + ConcealState_Single, + ConcealState_FadeIn, + ConcealState_Mute, + ConcealState_FadeOut + +} CConcealmentState; + +typedef struct { + FIXP_SGL fadeOutFactor[CONCEAL_MAX_NUM_FADE_FACTORS]; + FIXP_SGL fadeInFactor[CONCEAL_MAX_NUM_FADE_FACTORS]; + + CConcealmentMethod method; + + int numFadeOutFrames; + int numFadeInFrames; + int numMuteReleaseFrames; + FIXP_DBL comfortNoiseLevel; + +} CConcealParams; + +typedef enum { + FADE_TIMEDOMAIN_TOSPECTRALMUTE = 1, + FADE_TIMEDOMAIN_FROMSPECTRALMUTE, + FADE_TIMEDOMAIN +} TDfadingType; + +typedef struct { + CConcealParams *pConcealParams; + + FIXP_CNCL spectralCoefficient[1024]; + SHORT specScale[8]; + + INT iRandomPhase; + INT prevFrameOk[2]; + INT cntValidFrames; + INT cntFadeFrames; /* State for signal fade-in/out */ + /* States for signal fade-out of frames with more than one window/subframe - + [0] used by Update CntFadeFrames mode of CConcealment_ApplyFadeOut, [1] used + by FadeOut mode */ + int winGrpOffset[2]; /* State for signal fade-out of frames with more than one + window/subframe */ + int attGrpOffset[2]; /* State for faster signal fade-out of frames with + transient signal parts */ + + SCHAR lastRenderMode; + + UCHAR windowShape; + BLOCK_TYPE windowSequence; + UCHAR lastWinGrpLen; + + CConcealmentState concealState; + CConcealmentState concealState_old; + FIXP_DBL fade_old; /* last fading factor */ + TDfadingType lastFadingType; /* last fading type */ + + SHORT aRvlcPreviousScaleFactor[RVLC_MAX_SFB]; /* needed once per channel */ + UCHAR aRvlcPreviousCodebook[RVLC_MAX_SFB]; /* needed once per channel */ + SCHAR rvlcPreviousScaleFactorOK; + SCHAR rvlcPreviousBlockType; + + FIXP_LPC lsf4[M_LP_FILTER_ORDER]; + FIXP_DBL last_tcx_gain; + INT last_tcx_gain_e; + ULONG TDNoiseSeed; + FIXP_PCM TDNoiseStates[3]; + FIXP_SGL TDNoiseCoef[3]; + FIXP_SGL TDNoiseAtt; + +} CConcealmentInfo; + +#endif /* #ifndef CONCEAL_TYPES_H */ diff --git a/fdk-aac/libAACdec/src/ldfiltbank.cpp b/fdk-aac/libAACdec/src/ldfiltbank.cpp new file mode 100644 index 0000000..c7d2928 --- /dev/null +++ b/fdk-aac/libAACdec/src/ldfiltbank.cpp @@ -0,0 +1,276 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: low delay filterbank + +*******************************************************************************/ + +#include "ldfiltbank.h" + +#include "aac_rom.h" +#include "dct.h" +#include "FDK_tools_rom.h" +#include "mdct.h" + +#define LDFB_HEADROOM 2 + +#if defined(__arm__) +#endif + +static void multE2_DinvF_fdk(FIXP_PCM *output, FIXP_DBL *x, const FIXP_WTB *fb, + FIXP_DBL *z, const int N) { + int i; + + /* scale for FIXP_DBL -> INT_PCM conversion. */ + const int scale = (DFRACT_BITS - SAMPLE_BITS) - LDFB_HEADROOM; +#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) + FIXP_DBL rnd_val_wts0 = (FIXP_DBL)0; + FIXP_DBL rnd_val_wts1 = (FIXP_DBL)0; + if (-WTS0 - 1 + scale) + rnd_val_wts0 = (FIXP_DBL)(1 << (-WTS0 - 1 + scale - 1)); + if (-WTS1 - 1 + scale) + rnd_val_wts1 = (FIXP_DBL)(1 << (-WTS1 - 1 + scale - 1)); +#endif + + for (i = 0; i < N / 4; i++) { + FIXP_DBL z0, z2, tmp; + + z2 = x[N / 2 + i]; + z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)); + + z[N / 2 + i] = x[N / 2 - 1 - i] + + (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)); + + tmp = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N + N / 2 + i])); + +#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) + FDK_ASSERT((-WTS1 - 1 + scale) >= 0); + FDK_ASSERT(tmp <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts1)); /* rounding must not cause overflow */ + output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + tmp + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS1 + 1 - scale) >= 0); + output[(N * 3 / 4 - 1 - i)] = + (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp, WTS1 + 1 - scale, PCM_OUT_BITS); +#endif + + z[i] = z0; + z[N + i] = z2; + } + + for (i = N / 4; i < N / 2; i++) { + FIXP_DBL z0, z2, tmp0, tmp1; + + z2 = x[N / 2 + i]; + z0 = z2 + (fMultDiv2(z[N / 2 + i], fb[2 * N + i]) >> (-WTS2 - 1)); + + z[N / 2 + i] = x[N / 2 - 1 - i] + + (fMultDiv2(z[N + i], fb[2 * N + N / 2 + i]) >> (-WTS2 - 1)); + + tmp0 = (fMultDiv2(z[N / 2 + i], fb[N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N / 2 + i])); + tmp1 = (fMultDiv2(z[N / 2 + i], fb[N + N / 2 - 1 - i]) + + fMultDiv2(z[i], fb[N + N / 2 + i])); + +#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) + FDK_ASSERT((-WTS0 - 1 + scale) >= 0); + FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts0)); /* rounding must not cause overflow */ + FDK_ASSERT(tmp1 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts1)); /* rounding must not cause overflow */ + output[(i - N / 4)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); + output[(N * 3 / 4 - 1 - i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + tmp1 + rnd_val_wts1, -WTS1 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS0 + 1 - scale) >= 0); + output[(i - N / 4)] = + (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); + output[(N * 3 / 4 - 1 - i)] = + (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp1, WTS1 + 1 - scale, PCM_OUT_BITS); +#endif + z[i] = z0; + z[N + i] = z2; + } + + /* Exchange quarter parts of x to bring them in the "right" order */ + for (i = 0; i < N / 4; i++) { + FIXP_DBL tmp0 = fMultDiv2(z[i], fb[N / 2 + i]); + +#if ((DFRACT_BITS - SAMPLE_BITS - LDFB_HEADROOM) > 0) + FDK_ASSERT((-WTS0 - 1 + scale) >= 0); + FDK_ASSERT(tmp0 <= ((FIXP_DBL)0x7FFFFFFF - + rnd_val_wts0)); /* rounding must not cause overflow */ + output[(N * 3 / 4 + i)] = (FIXP_PCM)SATURATE_RIGHT_SHIFT( + tmp0 + rnd_val_wts0, -WTS0 - 1 + scale, PCM_OUT_BITS); +#else + FDK_ASSERT((WTS0 + 1 - scale) >= 0); + output[(N * 3 / 4 + i)] = + (FIXP_PCM)SATURATE_LEFT_SHIFT(tmp0, WTS0 + 1 - scale, PCM_OUT_BITS); +#endif + } +} + +int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctData, const int mdctData_e, + FIXP_PCM *output, FIXP_DBL *fs_buffer, + const int N) { + const FIXP_WTB *coef; + FIXP_DBL gain = (FIXP_DBL)0; + int scale = mdctData_e + MDCT_OUT_HEADROOM - + LDFB_HEADROOM; /* The LDFB_HEADROOM is compensated inside + multE2_DinvF_fdk() below */ + int i; + + /* Select LD window slope */ + switch (N) { + case 256: + coef = LowDelaySynthesis256; + break; + case 240: + coef = LowDelaySynthesis240; + break; + case 160: + coef = LowDelaySynthesis160; + break; + case 128: + coef = LowDelaySynthesis128; + break; + case 120: + coef = LowDelaySynthesis120; + break; + case 512: + coef = LowDelaySynthesis512; + break; + case 480: + default: + coef = LowDelaySynthesis480; + break; + } + + /* + Apply exponent and 1/N factor. + Note: "scale" is off by one because for LD_MDCT the window length is twice + the window length of a regular MDCT. This is corrected inside + multE2_DinvF_fdk(). Refer to ISO/IEC 14496-3:2009 page 277, + chapter 4.6.20.2 "Low Delay Window". + */ + imdct_gain(&gain, &scale, N); + + dct_IV(mdctData, N, &scale); + + if (N == 256 || N == 240 || N == 160) { + scale -= 1; + } else if (N == 128 || N == 120) { + scale -= 2; + } + + if (gain != (FIXP_DBL)0) { + for (i = 0; i < N; i++) { + mdctData[i] = fMult(mdctData[i], gain); + } + } + scaleValuesSaturate(mdctData, N, scale); + + /* Since all exponent and factors have been applied, current exponent is zero. + */ + multE2_DinvF_fdk(output, mdctData, coef, fs_buffer, N); + + return (1); +} diff --git a/fdk-aac/libAACdec/src/ldfiltbank.h b/fdk-aac/libAACdec/src/ldfiltbank.h new file mode 100644 index 0000000..b63da6b --- /dev/null +++ b/fdk-aac/libAACdec/src/ldfiltbank.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: low delay filterbank interface + +*******************************************************************************/ + +#ifndef LDFILTBANK_H +#define LDFILTBANK_H + +#include "common_fix.h" + +int InvMdctTransformLowDelay_fdk(FIXP_DBL *mdctdata_m, const int mdctdata_e, + FIXP_PCM *mdctOut, FIXP_DBL *fs_buffer, + const int frameLength); + +#endif diff --git a/fdk-aac/libAACdec/src/overlapadd.h b/fdk-aac/libAACdec/src/overlapadd.h new file mode 100644 index 0000000..49eecd8 --- /dev/null +++ b/fdk-aac/libAACdec/src/overlapadd.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: + +*******************************************************************************/ + +#ifndef OVERLAPADD_H +#define OVERLAPADD_H + +#include "common_fix.h" + +/* ELD uses different overlap which is twice the frame size: */ +#define OverlapBufferSize (768) + +typedef FIXP_DBL SPECTRUM[1024]; +typedef FIXP_DBL* SPECTRAL_PTR; + +#define SPEC_LONG(ptr) (ptr) +#define SPEC(ptr, w, gl) ((ptr) + ((w) * (gl))) + +#define SPEC_TCX(ptr, f, gl, fb) \ + ((ptr) + ((f) * (gl * 2) * (((fb) == 0) ? 1 : 2))) + +#endif /* #ifndef OVERLAPADD_H */ diff --git a/fdk-aac/libAACdec/src/pulsedata.cpp b/fdk-aac/libAACdec/src/pulsedata.cpp new file mode 100644 index 0000000..eb6d5bc --- /dev/null +++ b/fdk-aac/libAACdec/src/pulsedata.cpp @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: pulse data tool + +*******************************************************************************/ + +#include "pulsedata.h" + +#include "channelinfo.h" + +INT CPulseData_Read(HANDLE_FDK_BITSTREAM bs, CPulseData *const PulseData, + const SHORT *sfb_startlines, const void *pIcsInfo, + const SHORT frame_length) { + int i, k = 0; + const UINT MaxSfBands = + GetScaleFactorBandsTransmitted((const CIcsInfo *)pIcsInfo); + + /* reset pulse data flag */ + PulseData->PulseDataPresent = 0; + + if ((PulseData->PulseDataPresent = (UCHAR)FDKreadBit(bs)) != 0) { + if (!IsLongBlock((const CIcsInfo *)pIcsInfo)) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + PulseData->NumberPulse = (UCHAR)FDKreadBits(bs, 2); + PulseData->PulseStartBand = (UCHAR)FDKreadBits(bs, 6); + + if (PulseData->PulseStartBand >= MaxSfBands) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + + k = sfb_startlines[PulseData->PulseStartBand]; + + for (i = 0; i <= PulseData->NumberPulse; i++) { + PulseData->PulseOffset[i] = (UCHAR)FDKreadBits(bs, 5); + PulseData->PulseAmp[i] = (UCHAR)FDKreadBits(bs, 4); + k += PulseData->PulseOffset[i]; + } + + if (k >= frame_length) { + return AAC_DEC_DECODE_FRAME_ERROR; + } + } + + return 0; +} + +void CPulseData_Apply( + CPulseData *PulseData, /*!< pointer to pulse data side info */ + const short + *pScaleFactorBandOffsets, /*!< pointer to scalefactor band offsets */ + FIXP_DBL *coef) /*!< pointer to spectrum */ +{ + int i, k; + + if (PulseData->PulseDataPresent) { + k = pScaleFactorBandOffsets[PulseData->PulseStartBand]; + + for (i = 0; i <= PulseData->NumberPulse; i++) { + k += PulseData->PulseOffset[i]; + if (coef[k] > (FIXP_DBL)0) + coef[k] += (FIXP_DBL)(int)PulseData->PulseAmp[i]; + else + coef[k] -= (FIXP_DBL)(int)PulseData->PulseAmp[i]; + } + } +} diff --git a/fdk-aac/libAACdec/src/pulsedata.h b/fdk-aac/libAACdec/src/pulsedata.h new file mode 100644 index 0000000..15ae11c --- /dev/null +++ b/fdk-aac/libAACdec/src/pulsedata.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: pulse data tool + +*******************************************************************************/ + +#ifndef PULSEDATA_H +#define PULSEDATA_H + +#include "common_fix.h" +#include "FDK_bitstream.h" + +#define N_MAX_LINES 4 + +typedef struct { + UCHAR PulseDataPresent; + UCHAR NumberPulse; + UCHAR PulseStartBand; + UCHAR PulseOffset[N_MAX_LINES]; + UCHAR PulseAmp[N_MAX_LINES]; +} CPulseData; + +/** + * \brief Read pulse data from bitstream + * + * The function reads the elements for pulse data from + * the bitstream. + * + * \param bs bit stream handle data source. + * \param PulseData pointer to a CPulseData were the decoded data is stored + * into. + * \param MaxSfBands max number of scale factor bands. + * \return 0 on success, != 0 on parse error. + */ +INT CPulseData_Read(const HANDLE_FDK_BITSTREAM bs, CPulseData *const PulseData, + const SHORT *sfb_startlines, const void *pIcsInfo, + const SHORT frame_length); + +/** + * \brief Apply pulse data to spectral lines + * + * The function applies the pulse data to the + * specified spectral lines. + * + * \param PulseData pointer to the previously decoded pulse data. + * \param pScaleFactorBandOffsets scale factor band line offset table. + * \param coef pointer to the spectral data were pulse data should be applied + * to. + * \return none + */ +void CPulseData_Apply(CPulseData *PulseData, + const short *pScaleFactorBandOffsets, FIXP_DBL *coef); + +#endif /* #ifndef PULSEDATA_H */ diff --git a/fdk-aac/libAACdec/src/rvlc.cpp b/fdk-aac/libAACdec/src/rvlc.cpp new file mode 100644 index 0000000..b7a9be1 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlc.cpp @@ -0,0 +1,1217 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief RVLC Decoder + \author Robert Weidner +*/ + +#include "rvlc.h" + +#include "block.h" + +#include "aac_rom.h" +#include "rvlcbit.h" +#include "rvlcconceal.h" +#include "aacdec_hcr.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcInit + + description: init RVLC by data from channelinfo, which was decoded +previously and set up pointers +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcInit(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + /* RVLC common initialization part 2 of 2 */ + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScaleFactor = pAacDecoderChannelInfo->pDynData->aScaleFactor; + int bnds; + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = 0; + + pRvlc->numDecodedEscapeWordsEsc = 0; + pRvlc->numDecodedEscapeWordsFwd = 0; + pRvlc->numDecodedEscapeWordsBwd = 0; + + pRvlc->intensity_used = 0; + pRvlc->errorLogRvlc = 0; + + pRvlc->conceal_max = CONCEAL_MAX_INIT; + pRvlc->conceal_min = CONCEAL_MIN_INIT; + + pRvlc->conceal_max_esc = CONCEAL_MAX_INIT; + pRvlc->conceal_min_esc = CONCEAL_MIN_INIT; + + pRvlc->pHuffTreeRvlcEscape = aHuffTreeRvlcEscape; + pRvlc->pHuffTreeRvlCodewds = aHuffTreeRvlCodewds; + + /* init scf arrays (for savety (in case of there are only zero codebooks)) */ + for (bnds = 0; bnds < RVLC_MAX_SFB; bnds++) { + pScfFwd[bnds] = 0; + pScfBwd[bnds] = 0; + pScfEsc[bnds] = 0; + pScaleFactor[bnds] = 0; + } + + /* set base bitstream ptr to the RVL-coded part (start of RVLC data (ESC 2)) + */ + FDKsyncCache(bs); + pRvlc->bsAnchor = (INT)FDKgetValidBits(bs); + + pRvlc->bitstreamIndexRvlFwd = + 0; /* first bit within RVL coded block as start address for forward + decoding */ + pRvlc->bitstreamIndexRvlBwd = + pRvlc->length_of_rvlc_sf - 1; /* last bit within RVL coded block as start + address for backward decoding */ + + /* skip RVLC-bitstream-part -- pointing now to escapes (if present) or to TNS + * data (if present) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_sf); + + if (pRvlc->sf_escapes_present != 0) { + /* locate internal bitstream ptr at escapes (which is the second part) */ + FDKsyncCache(bs); + pRvlc->bitstreamIndexEsc = pRvlc->bsAnchor - (INT)FDKgetValidBits(bs); + + /* skip escapeRVLC-bitstream-part -- pointing to TNS data (if present) to + * make decoder continue */ + /* decoding of RVLC should work despite this second pushFor during + * initialization because */ + /* bitstream initialization is valid for both ESC2 data parts (RVL-coded + * values and ESC-coded values) */ + FDKpushFor(bs, pRvlc->length_of_rvlc_escapes); + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcCheckIntensityCb + + description: Check if a intensity codebook is used in the current channel. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + output: - intensity_used: 0 no intensity codebook is used + 1 intensity codebook is used +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcCheckIntensityCb( + CErRvlcInfo *pRvlc, CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + int group, band, bnds; + + pRvlc->intensity_used = 0; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + if ((pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB) || + (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds] == + INTENSITY_HCB2)) { + pRvlc->intensity_used = 1; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapeWord + + description: Decode a huffman coded RVLC Escape-word. This value is part +of a DPCM coded scalefactor. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a single RVLC-Escape value which had to be applied to a +DPCM value (which has a absolute value of 7) +-------------------------------------------------------------------------------------------- +*/ + +static SCHAR rvlcDecodeEscapeWord(CErRvlcInfo *pRvlc, HANDLE_FDK_BITSTREAM bs) { + int i; + SCHAR value; + UCHAR carryBit; + UINT treeNode; + UINT branchValue; + UINT branchNode; + + INT *pBitstreamIndexEsc; + const UINT *pEscTree; + + pEscTree = pRvlc->pHuffTreeRvlcEscape; + pBitstreamIndexEsc = &(pRvlc->bitstreamIndexEsc); + treeNode = *pEscTree; /* init at starting node */ + + for (i = MAX_LEN_RVLC_ESCAPE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstreamIndexEsc, FWD); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a RVLC-escape-word is + completely decoded */ + value = (SCHAR)branchNode & CLR_BIT_10; + pRvlc->length_of_rvlc_escapes -= (MAX_LEN_RVLC_ESCAPE_WORD - i); + + if (pRvlc->length_of_rvlc_escapes < 0) { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + value = -1; + } + + return value; + } else { + treeNode = *( + pEscTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + + return -1; /* should not be reached */ +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeEscapes + + description: Decodes all huffman coded RVLC Escape Words. + Here a difference to the pseudo-code-implementation from +standard can be found. A while loop (and not two nested for loops) is used for +two reasons: + + 1. The plain huffman encoded escapes are decoded before the +RVL-coded scalefactors. Therefore the escapes are present in the second step + when decoding the RVL-coded-scalefactor values in forward +and backward direction. + + When the RVL-coded scalefactors are decoded and there a +escape is needed, then it is just taken out of the array in ascending order. + + 2. It's faster. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - 0 ok the decoded escapes seem to be valid + - 1 error there was a error detected during decoding escapes + --> all escapes are invalid +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeEscapes(CErRvlcInfo *pRvlc, SHORT *pEsc, + HANDLE_FDK_BITSTREAM bs) { + SCHAR escWord; + SCHAR escCnt = 0; + SHORT *pEscBitCntSum; + + pEscBitCntSum = &(pRvlc->length_of_rvlc_escapes); + + /* Decode all RVLC-Escape words with a plain Huffman-Decoder */ + while (*pEscBitCntSum > 0) { + escWord = rvlcDecodeEscapeWord(pRvlc, bs); + + if (escWord >= 0) { + pEsc[escCnt] = escWord; + escCnt++; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID; + pRvlc->numDecodedEscapeWordsEsc = escCnt; + + return; + } + } /* all RVLC escapes decoded */ + + pRvlc->numDecodedEscapeWordsEsc = escCnt; +} + +/*--------------------------------------------------------------------------------------------- + function: decodeRVLCodeword + + description: Decodes a RVL-coded dpcm-word (-part). +----------------------------------------------------------------------------------------------- + input: - FDK bitstream handle + - pointer rvlc structure +----------------------------------------------------------------------------------------------- + return: - a dpcm value which is within range [0,1,..,14] in case of +no errors. The offset of 7 must be subtracted to get a valid dpcm scalefactor +value. In case of errors a forbidden codeword is detected --> returning -1 +-------------------------------------------------------------------------------------------- +*/ + +SCHAR decodeRVLCodeword(HANDLE_FDK_BITSTREAM bs, CErRvlcInfo *pRvlc) { + int i; + SCHAR value; + UCHAR carryBit; + UINT branchValue; + UINT branchNode; + + const UINT *pRvlCodeTree = pRvlc->pHuffTreeRvlCodewds; + UCHAR direction = pRvlc->direction; + INT *pBitstrIndxRvl = pRvlc->pBitstrIndxRvl_RVL; + UINT treeNode = *pRvlCodeTree; + + for (i = MAX_LEN_RVLC_CODE_WORD - 1; i >= 0; i--) { + carryBit = + rvlcReadBitFromBitstream(bs, /* get next bit */ + pRvlc->bsAnchor, pBitstrIndxRvl, direction); + + CarryBitToBranchValue(carryBit, /* huffman decoding, do a single step in + huffman decoding tree */ + treeNode, &branchValue, &branchNode); + + if ((branchNode & TEST_BIT_10) == + TEST_BIT_10) { /* test bit 10 ; if set --> a + RVLC-codeword is completely decoded + */ + value = (SCHAR)(branchNode & CLR_BIT_10); + *pRvlc->pRvlBitCnt_RVL -= (MAX_LEN_RVLC_CODE_WORD - i); + + /* check available bits for decoding */ + if (*pRvlc->pRvlBitCnt_RVL < 0) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD; + } + value = -1; /* signalize an error in return value, because too many bits + was decoded */ + } + + /* check max value of dpcm value */ + if (value > MAX_ALLOWED_DPCM_INDEX) { + if (direction == FWD) { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD; + } else { + pRvlc->errorLogRvlc |= RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD; + } + value = -1; /* signalize an error in return value, because a forbidden + cw was detected*/ + } + + return value; /* return a dpcm value with offset +7 or an error status */ + } else { + treeNode = *( + pRvlCodeTree + + branchValue); /* update treeNode for further step in decoding tree */ + } + } + + return -1; +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeForward + + description: Decode RVL-coded codewords in forward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle to FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeForward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + int band = 0; + int group = 0; + int bnds = 0; + + SHORT dpcm; + + SHORT factor = + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + SHORT position = -SF_OFFSET; + SHORT noisenrg = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + + SHORT *pScfFwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscFwdCnt = &(pRvlc->numDecodedEscapeWordsFwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_fwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlFwd); + + *pEscFwdCnt = 0; + pRvlc->direction = FWD; + pRvlc->noise_used = 0; + pRvlc->sf_used = 0; + pRvlc->lastScf = 0; + pRvlc->lastNrg = 0; + pRvlc->lastIs = 0; + + rvlcCheckIntensityCb(pRvlc, pAacDecoderChannelInfo); + + /* main loop fwd long */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfFwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + position += dpcm; + pScfFwd[bnds] = position; + pRvlc->lastIs = position; + break; + + case NOISE_HCB: + if (pRvlc->noise_used == 0) { + pRvlc->noise_used = 1; + pRvlc->first_noise_band = bnds; + noisenrg += pRvlc->dpcm_noise_nrg; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + noisenrg += dpcm; + pScfFwd[bnds] = 100 + noisenrg; + pRvlc->lastNrg = noisenrg; + } + pAacDecoderChannelInfo->data.aac.PnsData.pnsUsed[bnds] = 1; + break; + + default: + pRvlc->sf_used = 1; + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + factor += dpcm; + pScfFwd[bnds] = factor; + pRvlc->lastScf = factor; + break; + } + } + } + + /* postfetch fwd long */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->conceal_max = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_max = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc++; + } else { + dpcm += *pScfEsc++; + } + (*pEscFwdCnt)++; + if (pRvlc->conceal_max_esc == CONCEAL_MAX_INIT) { + pRvlc->conceal_max_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcDecodeBackward + + description: Decode RVL-coded codewords in backward direction. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - handle FDK bitstream +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcDecodeBackward(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + SHORT band, group, dpcm, offset; + SHORT bnds = pRvlc->maxSfbTransmitted - 1; + + SHORT factor = pRvlc->rev_global_gain - SF_OFFSET; + SHORT position = pRvlc->dpcm_is_last_position - SF_OFFSET; + SHORT noisenrg = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - + SF_OFFSET - 90 - 256; + + SHORT *pScfBwd = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd; + SHORT *pScfEsc = pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc; + UCHAR *pEscEscCnt = &(pRvlc->numDecodedEscapeWordsEsc); + UCHAR *pEscBwdCnt = &(pRvlc->numDecodedEscapeWordsBwd); + + pRvlc->pRvlBitCnt_RVL = &(pRvlc->length_of_rvlc_sf_bwd); + pRvlc->pBitstrIndxRvl_RVL = &(pRvlc->bitstreamIndexRvlBwd); + + *pEscBwdCnt = 0; + pRvlc->direction = BWD; + pScfEsc += *pEscEscCnt - 1; /* set pScfEsc to last entry */ + pRvlc->firstScf = 0; + pRvlc->firstNrg = 0; + pRvlc->firstIs = 0; + + /* prefetch long BWD */ + if (pRvlc->intensity_used) { + dpcm = decodeRVLCodeword(bs, pRvlc); /* dpcm_is_last_position */ + if (dpcm < 0) { + pRvlc->dpcm_is_last_position = 0; + pRvlc->conceal_min = bnds; + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pRvlc->conceal_min = bnds; + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = bnds; + } + } + } + pRvlc->dpcm_is_last_position = dpcm; + } + + /* main loop long BWD */ + for (group = pRvlc->numWindowGroups - 1; group >= 0; group--) { + for (band = pRvlc->maxSfbTransmitted - 1; band >= 0; band--) { + bnds = 16 * group + band; + if ((band == 0) && (pRvlc->numWindowGroups != 1)) + offset = 16 - pRvlc->maxSfbTransmitted + 1; + else + offset = 1; + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pScfBwd[bnds] = 0; + break; + + case INTENSITY_HCB2: + case INTENSITY_HCB: + /* store dpcm_is_position */ + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = position; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = position; + position -= dpcm; + pRvlc->firstIs = position; + break; + + case NOISE_HCB: + if (bnds == pRvlc->first_noise_band) { + pScfBwd[bnds] = + pRvlc->dpcm_noise_nrg + + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + pRvlc->firstNrg = pScfBwd[bnds]; + } else { + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = noisenrg; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = noisenrg; + noisenrg -= dpcm; + pRvlc->firstNrg = noisenrg; + } + break; + + default: + dpcm = decodeRVLCodeword(bs, pRvlc); + if (dpcm < 0) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } + dpcm -= TABLE_OFFSET; + if ((dpcm == MIN_RVL) || (dpcm == MAX_RVL)) { + if (pRvlc->length_of_rvlc_escapes) { + pScfBwd[bnds] = factor; + pRvlc->conceal_min = fMax(0, bnds - offset); + return; + } else { + if (dpcm == MIN_RVL) { + dpcm -= *pScfEsc--; + } else { + dpcm += *pScfEsc--; + } + (*pEscBwdCnt)++; + if (pRvlc->conceal_min_esc == CONCEAL_MIN_INIT) { + pRvlc->conceal_min_esc = fMax(0, bnds - offset); + } + } + } + pScfBwd[bnds] = factor; + factor -= dpcm; + pRvlc->firstScf = factor; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: rvlcFinalErrorDetection + + description: Call RVLC concealment if error was detected in decoding +process +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void rvlcFinalErrorDetection( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + UCHAR ErrorStatusComplete = 0; + UCHAR ErrorStatusLengthFwd = 0; + UCHAR ErrorStatusLengthBwd = 0; + UCHAR ErrorStatusLengthEscapes = 0; + UCHAR ErrorStatusFirstScf = 0; + UCHAR ErrorStatusLastScf = 0; + UCHAR ErrorStatusFirstNrg = 0; + UCHAR ErrorStatusLastNrg = 0; + UCHAR ErrorStatusFirstIs = 0; + UCHAR ErrorStatusLastIs = 0; + UCHAR ErrorStatusForbiddenCwFwd = 0; + UCHAR ErrorStatusForbiddenCwBwd = 0; + UCHAR ErrorStatusNumEscapesFwd = 0; + UCHAR ErrorStatusNumEscapesBwd = 0; + UCHAR ConcealStatus = 1; + UCHAR currentBlockType; /* short: 0, not short: 1*/ + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 1; + + /* invalid escape words, bit counter unequal zero, forbidden codeword detected + */ + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD) + ErrorStatusForbiddenCwFwd = 1; + + if (pRvlc->errorLogRvlc & RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD) + ErrorStatusForbiddenCwBwd = 1; + + /* bit counter forward unequal zero */ + if (pRvlc->length_of_rvlc_sf_fwd) ErrorStatusLengthFwd = 1; + + /* bit counter backward unequal zero */ + if (pRvlc->length_of_rvlc_sf_bwd) ErrorStatusLengthBwd = 1; + + /* bit counter escape sequences unequal zero */ + if (pRvlc->sf_escapes_present) + if (pRvlc->length_of_rvlc_escapes) ErrorStatusLengthEscapes = 1; + + if (pRvlc->sf_used) { + /* first decoded scf does not match to global gain in backward direction */ + if (pRvlc->firstScf != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET)) + ErrorStatusFirstScf = 1; + + /* last decoded scf does not match to rev global gain in forward direction + */ + if (pRvlc->lastScf != (pRvlc->rev_global_gain - SF_OFFSET)) + ErrorStatusLastScf = 1; + } + + if (pRvlc->noise_used) { + /* first decoded nrg does not match to dpcm_noise_nrg in backward direction + */ + if (pRvlc->firstNrg != + (pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain + + pRvlc->dpcm_noise_nrg - SF_OFFSET - 90 - 256)) + ErrorStatusFirstNrg = 1; + + /* last decoded nrg does not match to dpcm_noise_last_position in forward + * direction */ + if (pRvlc->lastNrg != + (pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - SF_OFFSET - + 90 - 256)) + ErrorStatusLastNrg = 1; + } + + if (pRvlc->intensity_used) { + /* first decoded is position does not match in backward direction */ + if (pRvlc->firstIs != (-SF_OFFSET)) ErrorStatusFirstIs = 1; + + /* last decoded is position does not match in forward direction */ + if (pRvlc->lastIs != (pRvlc->dpcm_is_last_position - SF_OFFSET)) + ErrorStatusLastIs = 1; + } + + /* decoded escapes and used escapes in forward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_max == CONCEAL_MAX_INIT)) { + ErrorStatusNumEscapesFwd = 1; + } + + /* decoded escapes and used escapes in backward direction do not fit */ + if ((pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + ErrorStatusNumEscapesBwd = 1; + } + + if (ErrorStatusLengthEscapes || + (((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + (pRvlc->numDecodedEscapeWordsFwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusLastScf || ErrorStatusLastNrg || ErrorStatusLastIs)) + + && + + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + (pRvlc->numDecodedEscapeWordsBwd != pRvlc->numDecodedEscapeWordsEsc) && + (ErrorStatusFirstScf || ErrorStatusFirstNrg || ErrorStatusFirstIs))) || + ((pRvlc->conceal_max == CONCEAL_MAX_INIT) && + ((pRvlc->rev_global_gain - SF_OFFSET - pRvlc->lastScf) < -15)) || + ((pRvlc->conceal_min == CONCEAL_MIN_INIT) && + ((pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET - + pRvlc->firstScf) < -15))) { + if ((pRvlc->conceal_max == CONCEAL_MAX_INIT) || + (pRvlc->conceal_min == CONCEAL_MIN_INIT)) { + pRvlc->conceal_max = 0; + pRvlc->conceal_min = fMax( + 0, (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1); + } else { + pRvlc->conceal_max = fMin(pRvlc->conceal_max, pRvlc->conceal_max_esc); + pRvlc->conceal_min = fMax(pRvlc->conceal_min, pRvlc->conceal_min_esc); + } + } + + ErrorStatusComplete = ErrorStatusLastScf || ErrorStatusFirstScf || + ErrorStatusLastNrg || ErrorStatusFirstNrg || + ErrorStatusLastIs || ErrorStatusFirstIs || + ErrorStatusForbiddenCwFwd || + ErrorStatusForbiddenCwBwd || ErrorStatusLengthFwd || + ErrorStatusLengthBwd || ErrorStatusLengthEscapes || + ErrorStatusNumEscapesFwd || ErrorStatusNumEscapesBwd; + + currentBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) ? 0 + : 1; + + if (!ErrorStatusComplete) { + int band; + int group; + int bnds; + int lastSfbIndex; + + lastSfbIndex = (pRvlc->numWindowGroups > 1) ? 16 : 64; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + } + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = + pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]; + } + for (; band < lastSfbIndex; band++) { + bnds = 16 * group + band; + FDK_ASSERT(bnds >= 0 && bnds < RVLC_MAX_SFB); + pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] = ZERO_HCB; + } + } + } else { + int band; + int group; + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward decoding, backward decoding and previous frame. + */ + if (((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + (pRvlc->conceal_min <= pRvlc->conceal_max) && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && ConcealStatus) { + BidirectionalEstimation_UseScfOfPrevFrameAsReference( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* A single bit error was detected in decoding of dpcm values. It also could + be an error with more bits in decoding of escapes and dpcm values whereby + an illegal codeword followed not directly after the corrupted bits but + just after decoding some more (wrong) scalefactors. Use the smaller + scalefactor from forward and backward decoding. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((pRvlc->conceal_min != CONCEAL_MIN_INIT) || + (pRvlc->conceal_max != CONCEAL_MAX_INIT)) && + !(pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousBlockType == currentBlockType)) && + ConcealStatus) { + BidirectionalEstimation_UseLowerScfOfCurrentFrame(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* No errors were detected in decoding of escapes and dpcm values however + the first and last value of a group (is,nrg,sf) is incorrect */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + ((ErrorStatusLastScf && ErrorStatusFirstScf) || + (ErrorStatusLastNrg && ErrorStatusFirstNrg) || + (ErrorStatusLastIs && ErrorStatusFirstIs)) && + !(ErrorStatusForbiddenCwFwd || ErrorStatusForbiddenCwBwd || + ErrorStatusLengthEscapes) && + ConcealStatus) { + StatisticalEstimation(pAacDecoderChannelInfo); + ConcealStatus = 0; + } + + /* A error with more bits in decoding of escapes and dpcm values was + detected. Use the smaller scalefactor from forward decoding, backward + decoding and previous frame. */ + if ((pRvlc->conceal_min <= pRvlc->conceal_max) && + pAacDecoderStaticChannelInfo->concealmentInfo + .rvlcPreviousScaleFactorOK && + pRvlc->sf_concealment && + (pAacDecoderStaticChannelInfo->concealmentInfo.rvlcPreviousBlockType == + currentBlockType) && + ConcealStatus) { + PredictiveInterpolation(pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo); + ConcealStatus = 0; + } + + /* Call frame concealment, because no better strategy was found. Setting the + scalefactors to zero is done for debugging purposes */ + if (ConcealStatus) { + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + pAacDecoderChannelInfo->pDynData->aScaleFactor[16 * group + band] = 0; + } + } + pAacDecoderChannelInfo->pDynData->specificTo.aac + .rvlcCurrentScaleFactorOK = 0; + } + } +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Read + + description: Read RVLC ESC1 data (side info) from bitstream. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + + int group, band; + + /* RVLC long specific initialization Init part 1 of 2 */ + pRvlc->numWindowGroups = GetWindowGroups(&pAacDecoderChannelInfo->icsInfo); + pRvlc->maxSfbTransmitted = + GetScaleFactorBandsTransmitted(&pAacDecoderChannelInfo->icsInfo); + pRvlc->noise_used = 0; /* noise detection */ + pRvlc->dpcm_noise_nrg = 0; /* only for debugging */ + pRvlc->dpcm_noise_last_position = 0; /* only for debugging */ + pRvlc->length_of_rvlc_escapes = + -1; /* default value is used for error detection and concealment */ + + /* read only error sensitivity class 1 data (ESC 1 - data) */ + pRvlc->sf_concealment = FDKreadBits(bs, 1); /* #1 */ + pRvlc->rev_global_gain = FDKreadBits(bs, 8); /* #2 */ + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 11); /* #3 */ + } else { + pRvlc->length_of_rvlc_sf = FDKreadBits(bs, 9); /* #3 */ + } + + /* check if noise codebook is used */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + if (pAacDecoderChannelInfo->pDynData->aCodeBook[16 * group + band] == + NOISE_HCB) { + pRvlc->noise_used = 1; + break; + } + } + } + + if (pRvlc->noise_used) + pRvlc->dpcm_noise_nrg = FDKreadBits(bs, 9); /* #4 PNS */ + + pRvlc->sf_escapes_present = FDKreadBits(bs, 1); /* #5 */ + + if (pRvlc->sf_escapes_present) { + pRvlc->length_of_rvlc_escapes = FDKreadBits(bs, 8); /* #6 */ + } + + if (pRvlc->noise_used) { + pRvlc->dpcm_noise_last_position = FDKreadBits(bs, 9); /* #7 PNS */ + pRvlc->length_of_rvlc_sf -= 9; + } + + pRvlc->length_of_rvlc_sf_fwd = pRvlc->length_of_rvlc_sf; + pRvlc->length_of_rvlc_sf_bwd = pRvlc->length_of_rvlc_sf; +} + +/*--------------------------------------------------------------------------------------------- + function: CRvlc_Decode + + description: Decode rvlc data + The function reads both the escape sequences and the +scalefactors in forward and backward direction. If an error occured during +decoding process which can not be concealed with the rvlc concealment frame +concealment will be initiated. Then the element "rvlcCurrentScaleFactorOK" in +the decoder channel info is set to 0 otherwise it is set to 1. +----------------------------------------------------------------------------------------------- + input: - pointer rvlc structure + - pointer channel info structure + - pointer to persistent channel info structure + - pointer bitstream structure +----------------------------------------------------------------------------------------------- + return: ErrorStatus = AAC_DEC_OK +-------------------------------------------------------------------------------------------- +*/ + +void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + INT bitCntOffst; + INT saveBitCnt; + + rvlcInit(pRvlc, pAacDecoderChannelInfo, bs); + + /* save bitstream position */ + saveBitCnt = (INT)FDKgetValidBits(bs); + + if (pRvlc->sf_escapes_present) + rvlcDecodeEscapes( + pRvlc, pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfEsc, bs); + + rvlcDecodeForward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcDecodeBackward(pRvlc, pAacDecoderChannelInfo, bs); + rvlcFinalErrorDetection(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo); + + pAacDecoderChannelInfo->pDynData->specificTo.aac.rvlcIntensityUsed = + pRvlc->intensity_used; + pAacDecoderChannelInfo->data.aac.PnsData.PnsActive = pRvlc->noise_used; + + /* restore bitstream position */ + bitCntOffst = (INT)FDKgetValidBits(bs) - saveBitCnt; + if (bitCntOffst) { + FDKpushBiDirectional(bs, bitCntOffst); + } +} + +void CRvlc_ElementCheck( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, const INT elChannels) { + int ch; + + /* Required for MPS residuals. */ + if (pAacDecoderStaticChannelInfo == NULL) { + return; + } + + /* RVLC specific sanity checks */ + if ((flags & AC_ER_RVLC) && (elChannels == 2)) { /* to be reviewed */ + if (((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) || + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0)) && + pAacDecoderChannelInfo[0]->pComData->jointStereoData.MsMaskPresent) { + pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + + if ((pAacDecoderChannelInfo[0] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 0) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK == 1) && + (pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcIntensityUsed == 1)) { + pAacDecoderChannelInfo[1] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK = 0; + } + } + + for (ch = 0; ch < elChannels; ch++) { + pAacDecoderStaticChannelInfo[ch]->concealmentInfo.rvlcPreviousBlockType = + (GetWindowSequence(&pAacDecoderChannelInfo[ch]->icsInfo) == BLOCK_SHORT) + ? 0 + : 1; + if (flags & AC_ER_RVLC) { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = + pAacDecoderChannelInfo[ch] + ->pDynData->specificTo.aac.rvlcCurrentScaleFactorOK; + } else { + pAacDecoderStaticChannelInfo[ch] + ->concealmentInfo.rvlcPreviousScaleFactorOK = 0; + } + } +} diff --git a/fdk-aac/libAACdec/src/rvlc.h b/fdk-aac/libAACdec/src/rvlc.h new file mode 100644 index 0000000..9c60d51 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlc.h @@ -0,0 +1,153 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Defines structures and prototypes for RVLC + \author Robert Weidner +*/ + +#ifndef RVLC_H +#define RVLC_H + +#include "aacdecoder.h" +#include "channel.h" +#include "rvlc_info.h" + +/* ------------------------------------------------------------------- */ +/* errorLogRvlc: A word of 32 bits used for logging possible errors */ +/* within RVLC in case of distorted bitstreams. */ +/* ------------------------------------------------------------------- */ +#define RVLC_ERROR_ALL_ESCAPE_WORDS_INVALID \ + 0x80000000 /* ESC-Dec During RVLC-Escape-decoding there have been more \ + bits decoded as there are available */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_FWD \ + 0x40000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding \ + (long+shrt) */ +#define RVLC_ERROR_RVL_SUM_BIT_COUNTER_BELOW_ZERO_BWD \ + 0x20000000 /* RVL-Dec negative sum-bitcounter during RVL-fwd-decoding \ + (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_FWD \ + 0x08000000 /* RVL-Dec forbidden codeword detected fwd (long+shrt) */ +#define RVLC_ERROR_FORBIDDEN_CW_DETECTED_BWD \ + 0x04000000 /* RVL-Dec forbidden codeword detected bwd (long+shrt) */ + +void CRvlc_Read(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +void CRvlc_Decode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + HANDLE_FDK_BITSTREAM bs); + +/** + * \brief performe sanity checks to the channel data corresponding to one + * channel element. + * \param pAacDecoderChannelInfo + * \param pAacDecoderStaticChannelInfo + * \param elChannels amount of channels of the channel element. + */ +void CRvlc_ElementCheck( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[], + const UINT flags, const INT elChannels); + +#endif /* RVLC_H */ diff --git a/fdk-aac/libAACdec/src/rvlc_info.h b/fdk-aac/libAACdec/src/rvlc_info.h new file mode 100644 index 0000000..e7b3b99 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlc_info.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Defines structures for RVLC + \author Robert Weidner +*/ +#ifndef RVLC_INFO_H +#define RVLC_INFO_H + +#define FWD 0 /* bitstream decoding direction forward (RVL coded part) */ +#define BWD 1 /* bitstream decoding direction backward (RVL coded part) */ + +#define MAX_RVL 7 /* positive RVLC escape */ +#define MIN_RVL -7 /* negative RVLC escape */ +#define MAX_ALLOWED_DPCM_INDEX \ + 14 /* the maximum allowed index of a decoded dpcm value (offset \ + 'TABLE_OFFSET' incl --> must be subtracted) */ +#define TABLE_OFFSET \ + 7 /* dpcm offset of valid output values of rvl table decoding, the rvl table \ + ouly returns positive values, therefore the offset */ +#define MAX_LEN_RVLC_CODE_WORD 9 /* max length of a RVL codeword in bits */ +#define MAX_LEN_RVLC_ESCAPE_WORD \ + 20 /* max length of huffman coded RVLC escape word in bits */ + +#define DPCM_NOISE_NRG_BITS 9 +#define SF_OFFSET 100 /* offset for correcting scf value */ + +#define CONCEAL_MAX_INIT 1311 /* arbitrary value */ +#define CONCEAL_MIN_INIT -1311 /* arbitrary value */ + +#define RVLC_MAX_SFB ((8) * (16)) + +/* sideinfo of RVLC */ +typedef struct { + /* ------- ESC 1 Data: --------- */ /* order of RVLC-bitstream components in + bitstream (RVLC-initialization), every + component appears only once in + bitstream */ + INT sf_concealment; /* 1 */ + INT rev_global_gain; /* 2 */ + SHORT length_of_rvlc_sf; /* 3 */ /* original value, gets modified + (subtract 9) in case of noise + (PNS); is kept for later use */ + INT dpcm_noise_nrg; /* 4 optional */ + INT sf_escapes_present; /* 5 */ + SHORT length_of_rvlc_escapes; /* 6 optional */ + INT dpcm_noise_last_position; /* 7 optional */ + + INT dpcm_is_last_position; + + SHORT length_of_rvlc_sf_fwd; /* length_of_rvlc_sf used for forward decoding */ + SHORT + length_of_rvlc_sf_bwd; /* length_of_rvlc_sf used for backward decoding */ + + /* for RVL-Codeword decoder to distinguish between fwd and bwd decoding */ + SHORT *pRvlBitCnt_RVL; + INT *pBitstrIndxRvl_RVL; + + UCHAR numWindowGroups; + UCHAR maxSfbTransmitted; + UCHAR first_noise_group; + UCHAR first_noise_band; + UCHAR direction; + + /* bitstream indices */ + INT bsAnchor; /* hcr bit buffer reference index */ + INT bitstreamIndexRvlFwd; /* base address of RVL-coded-scalefactor data (ESC + 2) for forward decoding */ + INT bitstreamIndexRvlBwd; /* base address of RVL-coded-scalefactor data (ESC + 2) for backward decoding */ + INT bitstreamIndexEsc; /* base address where RVLC-escapes start (ESC 2) */ + + /* decoding trees */ + const UINT *pHuffTreeRvlCodewds; + const UINT *pHuffTreeRvlcEscape; + + /* escape counters */ + UCHAR numDecodedEscapeWordsFwd; /* when decoding RVL-codes forward */ + UCHAR numDecodedEscapeWordsBwd; /* when decoding RVL-codes backward */ + UCHAR numDecodedEscapeWordsEsc; /* when decoding the escape-Words */ + + SCHAR noise_used; + SCHAR intensity_used; + SCHAR sf_used; + + SHORT firstScf; + SHORT lastScf; + SHORT firstNrg; + SHORT lastNrg; + SHORT firstIs; + SHORT lastIs; + + /* ------ RVLC error detection ------ */ + UINT errorLogRvlc; /* store RVLC errors */ + SHORT conceal_min; /* is set at backward decoding */ + SHORT conceal_max; /* is set at forward decoding */ + SHORT conceal_min_esc; /* is set at backward decoding */ + SHORT conceal_max_esc; /* is set at forward decoding */ +} CErRvlcInfo; + +typedef CErRvlcInfo RVLC_INFO; /* temp */ + +#endif /* RVLC_INFO_H */ diff --git a/fdk-aac/libAACdec/src/rvlcbit.cpp b/fdk-aac/libAACdec/src/rvlcbit.cpp new file mode 100644 index 0000000..b0c4596 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlcbit.cpp @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief RVLC bitstream reading + \author Robert Weidner +*/ + +#include "rvlcbit.h" + +/*--------------------------------------------------------------------------------------------- + function: rvlcReadBitFromBitstream + + description: This function returns a bit from the bitstream according to +read direction. It is called very often, therefore it makes sense to inline it +(runtime). +----------------------------------------------------------------------------------------------- + input: - bitstream + - pPosition + - readDirection +----------------------------------------------------------------------------------------------- + return: - bit from bitstream +-------------------------------------------------------------------------------------------- +*/ + +UCHAR rvlcReadBitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pPosition, UCHAR readDirection) { + UINT bit; + INT readBitOffset = (INT)FDKgetValidBits(bs) - bsAnchor + *pPosition; + + if (readBitOffset) { + FDKpushBiDirectional(bs, readBitOffset); + } + + if (readDirection == FWD) { + bit = FDKreadBits(bs, 1); + + *pPosition += 1; + } else { + /* to be replaced with a brother function of FDKreadBits() */ + bit = FDKreadBits(bs, 1); + FDKpushBack(bs, 2); + + *pPosition -= 1; + } + + return (bit); +} diff --git a/fdk-aac/libAACdec/src/rvlcbit.h b/fdk-aac/libAACdec/src/rvlcbit.h new file mode 100644 index 0000000..2578453 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlcbit.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Robert Weidner (DSP Solutions) + + Description: RVLC Decoder: Bitstream reading + +*******************************************************************************/ + +#ifndef RVLCBIT_H +#define RVLCBIT_H + +#include "rvlc.h" + +UCHAR rvlcReadBitFromBitstream(HANDLE_FDK_BITSTREAM bs, const INT bsAnchor, + INT *pPosition, UCHAR readDirection); + +#endif /* RVLCBIT_H */ diff --git a/fdk-aac/libAACdec/src/rvlcconceal.cpp b/fdk-aac/libAACdec/src/rvlcconceal.cpp new file mode 100644 index 0000000..77fda68 --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlcconceal.cpp @@ -0,0 +1,787 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#include "rvlcconceal.h" + +#include "block.h" +#include "rvlc.h" + +/*--------------------------------------------------------------------------------------------- + function: calcRefValFwd + + description: The function determines the scalefactor which is closed to the +scalefactorband conceal_min. The same is done for intensity data and noise +energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void calcRefValFwd(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsFwd, int *refNrgFwd, int *refScfFwd) { + int band, bnds, group, startBand; + int idIs, idNrg, idScf; + int conceal_min, conceal_group_min; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + + /* calculate first reference value for approach in forward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsFwd = -SF_OFFSET; + *refNrgFwd = pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - + SF_OFFSET - 90 - 256; + *refScfFwd = + pAacDecoderChannelInfo->pDynData->RawDataInfo.GlobalGain - SF_OFFSET; + + startBand = conceal_min - 1; + for (group = conceal_group_min; group >= 0; group--) { + for (band = startBand; band >= 0; band--) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idIs = 0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idNrg = 0; /* reference value has been set */ + } + break; + default: + if (idScf) { + *refScfFwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + idScf = 0; /* reference value has been set */ + } + break; + } + } + startBand = pRvlc->maxSfbTransmitted - 1; + } +} + +/*--------------------------------------------------------------------------------------------- + function: calcRefValBwd + + description: The function determines the scalefactor which is closed to the +scalefactorband conceal_max. The same is done for intensity data and noise +energies. +----------------------------------------------------------------------------------------------- + output: - reference value scf + - reference value internsity data + - reference value noise energy +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +static void calcRefValBwd(CErRvlcInfo *pRvlc, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + int *refIsBwd, int *refNrgBwd, int *refScfBwd) { + int band, bnds, group, startBand; + int idIs, idNrg, idScf; + int conceal_max, conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) + MaximumScaleFactorBands = 16; + else + MaximumScaleFactorBands = 64; + + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + /* calculate first reference value for approach in backward direction */ + idIs = idNrg = idScf = 1; + + /* set reference values */ + *refIsBwd = pRvlc->dpcm_is_last_position - SF_OFFSET; + *refNrgBwd = pRvlc->rev_global_gain + pRvlc->dpcm_noise_last_position - + SF_OFFSET - 90 - 256 + pRvlc->dpcm_noise_nrg; + *refScfBwd = pRvlc->rev_global_gain - SF_OFFSET; + + startBand = conceal_max + 1; + + /* if needed, re-set reference values */ + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (idIs) { + *refIsBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idIs = 0; /* reference value has been set */ + } + break; + case NOISE_HCB: + if (idNrg) { + *refNrgBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idNrg = 0; /* reference value has been set */ + } + break; + default: + if (idScf) { + *refScfBwd = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + idScf = 0; /* reference value has been set */ + } + break; + } + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseLowerScfOfCurrentFrame + + description: This approach by means of bidirectional estimation is generally +performed when a single bit error has been detected, the bit error can be +isolated between 'conceal_min' and 'conceal_max' and the 'sf_concealment' flag +is not set. The sets of scalefactors decoded in forward and backward direction +are compared with each other. The smaller scalefactor will be considered as the +correct one respectively. The reconstruction of the scalefactors with this +approach archieve good results in audio quality. The strategy must be applied to +scalefactors, intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between +conceal_min and conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame( + CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, startBand, endBand, group; + int conceal_min, conceal_max; + int conceal_group_min, conceal_group_max; + int MaximumScaleFactorBands; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + MaximumScaleFactorBands = 16; + } else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the + corresponding border for concealment to a appropriate scalefactor band. The + border is set to first or last sfb respectively, because the error will + possibly not follow directly after the corrupt bit but just after decoding + some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = + (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + if (pRvlc->conceal_min == pRvlc->conceal_max) { + int refIsFwd, refNrgFwd, refScfFwd; + int refIsBwd, refNrgBwd, refScfBwd; + + bnds = pRvlc->conceal_min; + calcRefValFwd(pRvlc, pAacDecoderChannelInfo, &refIsFwd, &refNrgFwd, + &refScfFwd); + calcRefValBwd(pRvlc, pAacDecoderChannelInfo, &refIsBwd, &refNrgBwd, + &refScfBwd); + + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (refIsFwd < refIsBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refIsBwd; + break; + case NOISE_HCB: + if (refNrgFwd < refNrgBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refNrgBwd; + break; + default: + if (refScfFwd < refScfBwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfFwd; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = refScfBwd; + break; + } + } else { + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_max] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_min] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the + * correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted - 1; + + for (group = conceal_group_min; group <= conceal_group_max; group++) { + for (band = startBand; band <= endBand; band++) { + bnds = 16 * group + band; + if (pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds] < + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + if ((group + 1) == conceal_group_max) endBand = conceal_max; + } + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group = 0; group <= conceal_group_min; group++) { + for (band = 0; band < endBand; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group + 1) == conceal_group_min) endBand = conceal_min; + } + + startBand = conceal_max + 1; + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: BidirectionalEstimation_UseScfOfPrevFrameAsReference + + description: This approach by means of bidirectional estimation is generally +performed when a single bit error has been detected, the bit error can be +isolated between 'conceal_min' and 'conceal_max', the 'sf_concealment' flag is +set and the previous frame has the same block type as the current frame. The +scalefactor decoded in forward and backward direction and the scalefactor of the +previous frame are compared with each other. The smaller scalefactor will be +considered as the correct one. At this the codebook of the previous and current +frame must be of the same set (scf, nrg, is) in each scalefactorband. Otherwise +the scalefactor of the previous frame is not considered in the minimum +calculation. The reconstruction of the scalefactors with this approach archieve +good results in audio quality. The strategy must be applied to scalefactors, +intensity data and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data between +conceal_min and conceal_max +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, startBand, endBand, group; + int conceal_min, conceal_max; + int conceal_group_min, conceal_group_max; + int MaximumScaleFactorBands; + SHORT commonMin; + + if (GetWindowSequence(&pAacDecoderChannelInfo->icsInfo) == BLOCK_SHORT) { + MaximumScaleFactorBands = 16; + } else { + MaximumScaleFactorBands = 64; + } + + /* If an error was detected just in forward or backward direction, set the + corresponding border for concealment to a appropriate scalefactor band. The + border is set to first or last sfb respectively, because the error will + possibly not follow directly after the corrupt bit but just after decoding + some more (wrong) scalefactors. */ + if (pRvlc->conceal_min == CONCEAL_MIN_INIT) pRvlc->conceal_min = 0; + + if (pRvlc->conceal_max == CONCEAL_MAX_INIT) + pRvlc->conceal_max = + (pRvlc->numWindowGroups - 1) * 16 + pRvlc->maxSfbTransmitted - 1; + + conceal_min = pRvlc->conceal_min % MaximumScaleFactorBands; + conceal_group_min = pRvlc->conceal_min / MaximumScaleFactorBands; + conceal_max = pRvlc->conceal_max % MaximumScaleFactorBands; + conceal_group_max = pRvlc->conceal_max / MaximumScaleFactorBands; + + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_max] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_max]; + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[pRvlc->conceal_min] = + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfFwd[pRvlc->conceal_min]; + + /* consider the smaller of the forward and backward decoded value as the + * correct one */ + startBand = conceal_min; + if (conceal_group_min == conceal_group_max) + endBand = conceal_max; + else + endBand = pRvlc->maxSfbTransmitted - 1; + + for (group = conceal_group_min; group <= conceal_group_max; group++) { + for (band = startBand; band <= endBand; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB) || + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + + case NOISE_HCB: + if (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == NOISE_HCB) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + + default: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != ZERO_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != NOISE_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + } + break; + } + } + startBand = 0; + if ((group + 1) == conceal_group_max) endBand = conceal_max; + } + + /* now copy all data to the output buffer which needs not to be concealed */ + if (conceal_group_min == 0) + endBand = conceal_min; + else + endBand = pRvlc->maxSfbTransmitted; + for (group = 0; group <= conceal_group_min; group++) { + for (band = 0; band < endBand; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + } + if ((group + 1) == conceal_group_min) endBand = conceal_min; + } + + startBand = conceal_max + 1; + for (group = conceal_group_max; group < pRvlc->numWindowGroups; group++) { + for (band = startBand; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + } + startBand = 0; + } +} + +/*--------------------------------------------------------------------------------------------- + function: StatisticalEstimation + + description: This approach by means of statistical estimation is generally +performed when both the start value and the end value are different and no +further errors have been detected. Considering the forward and backward decoded +scalefactors, the set with the lower scalefactors in sum will be considered as +the correct one. The scalefactors are differentially encoded. Normally it would +reach to compare one pair of the forward and backward decoded scalefactors to +specify the lower set. But having detected no further errors does not +necessarily mean the absence of errors. Therefore all scalefactors decoded in +forward and backward direction are summed up seperately. The set with the lower +sum will be used. The strategy must be applied to scalefactors, intensity data +and noise energy seperately. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void StatisticalEstimation(CAacDecoderChannelInfo *pAacDecoderChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, group; + int sumIsFwd, sumIsBwd; /* sum of intensity data forward/backward */ + int sumNrgFwd, sumNrgBwd; /* sum of noise energy data forward/backward */ + int sumScfFwd, sumScfBwd; /* sum of scalefactor data forward/backward */ + int useIsFwd, useNrgFwd, useScfFwd; /* the flags signals the elements which + are used for the final result */ + + sumIsFwd = sumIsBwd = sumNrgFwd = sumNrgBwd = sumScfFwd = sumScfBwd = 0; + useIsFwd = useNrgFwd = useScfFwd = 0; + + /* calculate sum of each group (scf,nrg,is) of forward and backward direction + */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + sumIsFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumIsBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + sumNrgFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumNrgBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + default: + sumScfFwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + sumScfBwd += + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } + + /* find for each group (scf,nrg,is) the correct direction */ + if (sumIsFwd < sumIsBwd) useIsFwd = 1; + + if (sumNrgFwd < sumNrgBwd) useNrgFwd = 1; + + if (sumScfFwd < sumScfBwd) useScfFwd = 1; + + /* conceal each group (scf,nrg,is) */ + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if (useIsFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + case NOISE_HCB: + if (useNrgFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + + default: + if (useScfFwd) + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds]; + else + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfBwd[bnds]; + break; + } + } + } +} + +/*--------------------------------------------------------------------------------------------- + description: Approach by means of predictive interpolation + This approach by means of predictive estimation is generally +performed when the error cannot be isolated between 'conceal_min' and +'conceal_max', the 'sf_concealment' flag is set and the previous frame has the +same block type as the current frame. Check for each scalefactorband if the same +type of data (scalefactor, internsity data, noise energies) is transmitted. If +so use the scalefactor (intensity data, noise energy) in the current frame. +Otherwise set the scalefactor (intensity data, noise energy) for this +scalefactorband to zero. +----------------------------------------------------------------------------------------------- + output: Concealed scalefactor, noise energy and intensity data +----------------------------------------------------------------------------------------------- + return: - +-------------------------------------------------------------------------------------------- +*/ + +void PredictiveInterpolation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo) { + CErRvlcInfo *pRvlc = + &pAacDecoderChannelInfo->pComData->overlay.aac.erRvlcInfo; + int band, bnds, group; + SHORT commonMin; + + for (group = 0; group < pRvlc->numWindowGroups; group++) { + for (band = 0; band < pRvlc->maxSfbTransmitted; band++) { + bnds = 16 * group + band; + switch (pAacDecoderChannelInfo->pDynData->aCodeBook[bnds]) { + case ZERO_HCB: + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + break; + + case INTENSITY_HCB: + case INTENSITY_HCB2: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB) || + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + case NOISE_HCB: + if (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] == NOISE_HCB) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = -110; + } + break; + + default: + if ((pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != ZERO_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != NOISE_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB) && + (pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousCodebook[bnds] != INTENSITY_HCB2)) { + commonMin = fMin( + pAacDecoderChannelInfo->pComData->overlay.aac.aRvlcScfFwd[bnds], + pAacDecoderChannelInfo->pComData->overlay.aac + .aRvlcScfBwd[bnds]); + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = + fMin(commonMin, pAacDecoderStaticChannelInfo->concealmentInfo + .aRvlcPreviousScaleFactor[bnds]); + } else { + pAacDecoderChannelInfo->pDynData->aScaleFactor[bnds] = 0; + } + break; + } + } + } +} diff --git a/fdk-aac/libAACdec/src/rvlcconceal.h b/fdk-aac/libAACdec/src/rvlcconceal.h new file mode 100644 index 0000000..8e2062e --- /dev/null +++ b/fdk-aac/libAACdec/src/rvlcconceal.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rvlc concealment + \author Josef Hoepfl +*/ + +#ifndef RVLCCONCEAL_H +#define RVLCCONCEAL_H + +#include "rvlc.h" + +void BidirectionalEstimation_UseLowerScfOfCurrentFrame( + CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void BidirectionalEstimation_UseScfOfPrevFrameAsReference( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +void StatisticalEstimation(CAacDecoderChannelInfo *pAacDecoderChannelInfo); + +void PredictiveInterpolation( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +#endif /* RVLCCONCEAL_H */ diff --git a/fdk-aac/libAACdec/src/stereo.cpp b/fdk-aac/libAACdec/src/stereo.cpp new file mode 100644 index 0000000..eed826b --- /dev/null +++ b/fdk-aac/libAACdec/src/stereo.cpp @@ -0,0 +1,1250 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: joint stereo processing + +*******************************************************************************/ + +#include "stereo.h" + +#include "aac_rom.h" +#include "FDK_bitstream.h" +#include "channelinfo.h" +#include "FDK_audio.h" + +enum { L = 0, R = 1 }; + +#include "block.h" + +int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs, + CJointStereoData *pJointStereoData, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const int max_sfb_ste_clear, + CJointStereoPersistentData *pJointStereoPersistentData, + CCplxPredictionData *cplxPredictionData, + int cplxPredictionActiv, int scaleFactorBandsTotal, + int windowSequence, const UINT flags) { + int group, band; + + pJointStereoData->MsMaskPresent = (UCHAR)FDKreadBits(bs, 2); + + FDKmemclear(pJointStereoData->MsUsed, + scaleFactorBandsTransmitted * sizeof(UCHAR)); + + pJointStereoData->cplx_pred_flag = 0; + if (cplxPredictionActiv) { + cplxPredictionData->pred_dir = 0; + cplxPredictionData->complex_coef = 0; + cplxPredictionData->use_prev_frame = 0; + cplxPredictionData->igf_pred_dir = 0; + } + + switch (pJointStereoData->MsMaskPresent) { + case 0: /* no M/S */ + /* all flags are already cleared */ + break; + + case 1: /* read ms_used */ + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group); + } + } + break; + + case 2: /* full spectrum M/S */ + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] = 255; /* set all flags to 1 */ + } + break; + + case 3: + /* M/S coding is disabled, complex stereo prediction is enabled */ + if (flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) { + if (cplxPredictionActiv) { /* 'if (stereoConfigIndex == 0)' */ + + pJointStereoData->cplx_pred_flag = 1; + + /* cplx_pred_data() cp. ISO/IEC FDIS 23003-3:2011(E) Table 26 */ + int cplx_pred_all = 0; /* local use only */ + cplx_pred_all = FDKreadBits(bs, 1); + + if (cplx_pred_all) { + for (group = 0; group < windowGroups; group++) { + UCHAR groupmask = ((UCHAR)1 << group); + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + pJointStereoData->MsUsed[band] |= groupmask; + } + } + } else { + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; + band += SFB_PER_PRED_BAND) { + pJointStereoData->MsUsed[band] |= (FDKreadBits(bs, 1) << group); + if ((band + 1) < scaleFactorBandsTotal) { + pJointStereoData->MsUsed[band + 1] |= + (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)); + } + } + } + } + } else { + return -1; + } + } + break; + } + + if (cplxPredictionActiv) { + /* If all sfb are MS-ed then no complex prediction */ + if (pJointStereoData->MsMaskPresent == 3) { + if (pJointStereoData->cplx_pred_flag) { + int delta_code_time = 0; + + /* set pointer to Huffman codebooks */ + const CodeBookDescription *hcb = &AACcodeBookDescriptionTable[BOOKSCL]; + /* set predictors to zero in case of a transition from long to short + * window sequences and vice versa */ + if (((windowSequence == BLOCK_SHORT) && + (pJointStereoPersistentData->winSeqPrev != BLOCK_SHORT)) || + ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) && + (windowSequence != BLOCK_SHORT))) { + FDKmemclear(pJointStereoPersistentData->alpha_q_re_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + FDKmemclear(pJointStereoPersistentData->alpha_q_im_prev, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + } + { + FDKmemclear(cplxPredictionData->alpha_q_re, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + FDKmemclear(cplxPredictionData->alpha_q_im, + JointStereoMaximumGroups * JointStereoMaximumBands * + sizeof(SHORT)); + } + + /* 0 = mid->side prediction, 1 = side->mid prediction */ + cplxPredictionData->pred_dir = FDKreadBits(bs, 1); + cplxPredictionData->complex_coef = FDKreadBits(bs, 1); + + if (cplxPredictionData->complex_coef) { + if (flags & AC_INDEP) { + cplxPredictionData->use_prev_frame = 0; + } else { + cplxPredictionData->use_prev_frame = FDKreadBits(bs, 1); + } + } + + if (flags & AC_INDEP) { + delta_code_time = 0; + } else { + delta_code_time = FDKreadBits(bs, 1); + } + + { + int last_alpha_q_re = 0, last_alpha_q_im = 0; + + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < scaleFactorBandsTransmitted; + band += SFB_PER_PRED_BAND) { + if (delta_code_time == 1) { + if (group > 0) { + last_alpha_q_re = + cplxPredictionData->alpha_q_re[group - 1][band]; + last_alpha_q_im = + cplxPredictionData->alpha_q_im[group - 1][band]; + } else if ((windowSequence == BLOCK_SHORT) && + (pJointStereoPersistentData->winSeqPrev == + BLOCK_SHORT)) { + /* Included for error-robustness */ + if (pJointStereoPersistentData->winGroupsPrev == 0) return -1; + + last_alpha_q_re = + pJointStereoPersistentData->alpha_q_re_prev + [pJointStereoPersistentData->winGroupsPrev - 1][band]; + last_alpha_q_im = + pJointStereoPersistentData->alpha_q_im_prev + [pJointStereoPersistentData->winGroupsPrev - 1][band]; + } else { + last_alpha_q_re = + pJointStereoPersistentData->alpha_q_re_prev[group][band]; + last_alpha_q_im = + pJointStereoPersistentData->alpha_q_im_prev[group][band]; + } + + } else { + if (band > 0) { + last_alpha_q_re = + cplxPredictionData->alpha_q_re[group][band - 1]; + last_alpha_q_im = + cplxPredictionData->alpha_q_im[group][band - 1]; + } else { + last_alpha_q_re = 0; + last_alpha_q_im = 0; + } + + } /* if (delta_code_time == 1) */ + + if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) { + int dpcm_alpha_re, dpcm_alpha_im; + + dpcm_alpha_re = CBlock_DecodeHuffmanWord(bs, hcb); + dpcm_alpha_re -= 60; + dpcm_alpha_re *= -1; + + cplxPredictionData->alpha_q_re[group][band] = + dpcm_alpha_re + last_alpha_q_re; + + if (cplxPredictionData->complex_coef) { + dpcm_alpha_im = CBlock_DecodeHuffmanWord(bs, hcb); + dpcm_alpha_im -= 60; + dpcm_alpha_im *= -1; + + cplxPredictionData->alpha_q_im[group][band] = + dpcm_alpha_im + last_alpha_q_im; + } else { + cplxPredictionData->alpha_q_im[group][band] = 0; + } + + } else { + cplxPredictionData->alpha_q_re[group][band] = 0; + cplxPredictionData->alpha_q_im[group][band] = 0; + } /* if (pJointStereoData->MsUsed[band] & ((UCHAR)1 << group)) */ + + if ((band + 1) < + scaleFactorBandsTransmitted) { /* <= this should be the + correct way (cp. + ISO_IEC_FDIS_23003-0(E) */ + /* 7.7.2.3.2 Decoding of prediction coefficients) */ + cplxPredictionData->alpha_q_re[group][band + 1] = + cplxPredictionData->alpha_q_re[group][band]; + cplxPredictionData->alpha_q_im[group][band + 1] = + cplxPredictionData->alpha_q_im[group][band]; + } /* if ((band+1)alpha_q_re_prev[group][band] = + cplxPredictionData->alpha_q_re[group][band]; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = + cplxPredictionData->alpha_q_im[group][band]; + } + + for (band = scaleFactorBandsTransmitted; band < max_sfb_ste_clear; + band++) { + cplxPredictionData->alpha_q_re[group][band] = 0; + cplxPredictionData->alpha_q_im[group][band] = 0; + pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0; + } + } + } + } + } else { + for (group = 0; group < windowGroups; group++) { + for (band = 0; band < max_sfb_ste_clear; band++) { + pJointStereoPersistentData->alpha_q_re_prev[group][band] = 0; + pJointStereoPersistentData->alpha_q_im_prev[group][band] = 0; + } + } + } + + pJointStereoPersistentData->winGroupsPrev = windowGroups; + } + + return 0; +} + +static void CJointStereo_filterAndAdd( + FIXP_DBL *in, int len, int windowLen, const FIXP_FILT *coeff, FIXP_DBL *out, + UCHAR isCurrent /* output values with even index get a + positve addon (=1) or a negative addon + (=0) */ +) { + int i, j; + + int indices_1[] = {2, 1, 0, 1, 2, 3}; + int indices_2[] = {1, 0, 0, 2, 3, 4}; + int indices_3[] = {0, 0, 1, 3, 4, 5}; + + int subtr_1[] = {6, 5, 4, 2, 1, 1}; + int subtr_2[] = {5, 4, 3, 1, 1, 2}; + int subtr_3[] = {4, 3, 2, 1, 2, 3}; + + if (isCurrent == 1) { + /* exploit the symmetry of the table: coeff[6] = - coeff[0], + coeff[5] = - coeff[1], + coeff[4] = - coeff[2], + coeff[3] = 0 + */ + + for (i = 0; i < 3; i++) { + out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]]) >> SR_FNA_OUT; + out[0] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[1] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]]) >> SR_FNA_OUT; + out[1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]]) >> SR_FNA_OUT; + out[2] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]]) >> SR_FNA_OUT; + } + + for (j = 3; j < (len - 3); j++) { + for (i = 0; i < 3; i++) { + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i]) >> SR_FNA_OUT; + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i]) >> SR_FNA_OUT; + } + } + + for (i = 0; i < 3; i++) { + out[len - 3] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]]) >> SR_FNA_OUT; + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]]) >> SR_FNA_OUT; + out[len - 2] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]]) >> SR_FNA_OUT; + } + + for (i = 0; i < 3; i++) { + out[len - 1] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]]) >> SR_FNA_OUT; + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]]) >> SR_FNA_OUT; + } + + } else { + /* exploit the symmetry of the table: coeff[6] = coeff[0], + coeff[5] = coeff[1], + coeff[4] = coeff[2] + */ + + for (i = 0; i < 3; i++) { + out[0] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[i]] >> SR_FNA_OUT); + out[0] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_1[5 - i]] >> SR_FNA_OUT); + } + out[0] -= (FIXP_DBL)fMultDiv2(coeff[3], in[0] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[1] += (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[i]] >> SR_FNA_OUT); + out[1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_2[5 - i]] >> SR_FNA_OUT); + } + out[1] += (FIXP_DBL)fMultDiv2(coeff[3], in[1] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[2] -= (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[i]] >> SR_FNA_OUT); + out[2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[indices_3[5 - i]] >> SR_FNA_OUT); + } + out[2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[2] >> SR_FNA_OUT); + + for (j = 3; j < (len - 4); j++) { + for (i = 0; i < 3; i++) { + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT); + out[j] += (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT); + } + out[j] += (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT); + + j++; + + for (i = 0; i < 3; i++) { + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j - 3 + i] >> SR_FNA_OUT); + out[j] -= (FIXP_DBL)fMultDiv2(coeff[i], in[j + 3 - i] >> SR_FNA_OUT); + } + out[j] -= (FIXP_DBL)fMultDiv2(coeff[3], in[j] >> SR_FNA_OUT); + } + + for (i = 0; i < 3; i++) { + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[i]] >> SR_FNA_OUT); + out[len - 3] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_1[5 - i]] >> SR_FNA_OUT); + } + out[len - 3] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 3] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[i]] >> SR_FNA_OUT); + out[len - 2] -= + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_2[5 - i]] >> SR_FNA_OUT); + } + out[len - 2] -= (FIXP_DBL)fMultDiv2(coeff[3], in[len - 2] >> SR_FNA_OUT); + + for (i = 0; i < 3; i++) { + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[i]] >> SR_FNA_OUT); + out[len - 1] += + (FIXP_DBL)fMultDiv2(coeff[i], in[len - subtr_3[5 - i]] >> SR_FNA_OUT); + } + out[len - 1] += (FIXP_DBL)fMultDiv2(coeff[3], in[len - 1] >> SR_FNA_OUT); + } +} + +static inline void CJointStereo_GenerateMSOutput(FIXP_DBL *pSpecLCurrBand, + FIXP_DBL *pSpecRCurrBand, + UINT leftScale, + UINT rightScale, + UINT nSfbBands) { + unsigned int i; + + FIXP_DBL leftCoefficient0; + FIXP_DBL leftCoefficient1; + FIXP_DBL leftCoefficient2; + FIXP_DBL leftCoefficient3; + + FIXP_DBL rightCoefficient0; + FIXP_DBL rightCoefficient1; + FIXP_DBL rightCoefficient2; + FIXP_DBL rightCoefficient3; + + for (i = nSfbBands; i > 0; i -= 4) { + leftCoefficient0 = pSpecLCurrBand[i - 4]; + leftCoefficient1 = pSpecLCurrBand[i - 3]; + leftCoefficient2 = pSpecLCurrBand[i - 2]; + leftCoefficient3 = pSpecLCurrBand[i - 1]; + + rightCoefficient0 = pSpecRCurrBand[i - 4]; + rightCoefficient1 = pSpecRCurrBand[i - 3]; + rightCoefficient2 = pSpecRCurrBand[i - 2]; + rightCoefficient3 = pSpecRCurrBand[i - 1]; + + /* MS output generation */ + leftCoefficient0 >>= leftScale; + leftCoefficient1 >>= leftScale; + leftCoefficient2 >>= leftScale; + leftCoefficient3 >>= leftScale; + + rightCoefficient0 >>= rightScale; + rightCoefficient1 >>= rightScale; + rightCoefficient2 >>= rightScale; + rightCoefficient3 >>= rightScale; + + pSpecLCurrBand[i - 4] = leftCoefficient0 + rightCoefficient0; + pSpecLCurrBand[i - 3] = leftCoefficient1 + rightCoefficient1; + pSpecLCurrBand[i - 2] = leftCoefficient2 + rightCoefficient2; + pSpecLCurrBand[i - 1] = leftCoefficient3 + rightCoefficient3; + + pSpecRCurrBand[i - 4] = leftCoefficient0 - rightCoefficient0; + pSpecRCurrBand[i - 3] = leftCoefficient1 - rightCoefficient1; + pSpecRCurrBand[i - 2] = leftCoefficient2 - rightCoefficient2; + pSpecRCurrBand[i - 1] = leftCoefficient3 - rightCoefficient3; + } +} + +void CJointStereo_ApplyMS( + CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo[2], + FIXP_DBL *spectrumL, FIXP_DBL *spectrumR, SHORT *SFBleftScale, + SHORT *SFBrightScale, SHORT *specScaleL, SHORT *specScaleR, + const SHORT *pScaleFactorBandOffsets, const UCHAR *pWindowGroupLength, + const int windowGroups, const int max_sfb_ste_outside, + const int scaleFactorBandsTransmittedL, + const int scaleFactorBandsTransmittedR, FIXP_DBL *store_dmx_re_prev, + SHORT *store_dmx_re_prev_e, const int mainband_flag) { + int window, group, band; + UCHAR groupMask; + CJointStereoData *pJointStereoData = + &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + CCplxPredictionData *cplxPredictionData = + pAacDecoderChannelInfo[L]->pComStaticData->cplxPredictionData; + + int max_sfb_ste = + fMax(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR); + int min_sfb_ste = + fMin(scaleFactorBandsTransmittedL, scaleFactorBandsTransmittedR); + int scaleFactorBandsTransmitted = min_sfb_ste; + + if (pJointStereoData->cplx_pred_flag) { + int windowLen, groupwin, frameMaxScale; + CJointStereoPersistentData *pJointStereoPersistentData = + &pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData; + FIXP_DBL *const staticSpectralCoeffsL = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[L]; + FIXP_DBL *const staticSpectralCoeffsR = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.spectralCoeffs[R]; + SHORT *const staticSpecScaleL = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.specScale[L]; + SHORT *const staticSpecScaleR = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.specScale[R]; + + FIXP_DBL *dmx_re = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer; + FIXP_DBL *dmx_re_prev = + pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData.scratchBuffer + + 1024; + + /* When MS is applied over the main band this value gets computed. Otherwise + * (for the tiles) it uses the assigned value */ + SHORT dmx_re_prev_e = *store_dmx_re_prev_e; + + const FIXP_FILT *pCoeff; + const FIXP_FILT *pCoeffPrev; + int coeffPointerOffset; + + int previousShape = (int)pJointStereoPersistentData->winShapePrev; + int currentShape = (int)pAacDecoderChannelInfo[L]->icsInfo.WindowShape; + + /* complex stereo prediction */ + + /* 0. preparations */ + + /* 0.0. get scratch buffer for downmix MDST */ + C_AALLOC_SCRATCH_START(dmx_im, FIXP_DBL, 1024); + + /* 0.1. window lengths */ + + /* get length of short window for current configuration */ + windowLen = + pAacDecoderChannelInfo[L]->granuleLength; /* framelength 768 => 96, + framelength 1024 => 128 */ + + /* if this is no short-block set length for long-block */ + if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != BLOCK_SHORT) { + windowLen *= 8; + } + + /* 0.2. set pointer to filter-coefficients for MDST excitation including + * previous frame portions */ + /* cp. ISO/IEC FDIS 23003-3:2011(E) table 125 */ + + /* set pointer to default-position */ + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + + if (cplxPredictionData->complex_coef == 1) { + switch (pAacDecoderChannelInfo[L] + ->icsInfo.WindowSequence) { /* current window sequence */ + case BLOCK_SHORT: + case BLOCK_LONG: + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + break; + + case BLOCK_START: + if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) || + (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) { + /* a stop-start-sequence can only follow on an eight-short-sequence + * or a start-sequence */ + pCoeffPrev = mdst_filt_coef_prev[2 + previousShape]; + } else { + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + } + break; + + case BLOCK_STOP: + pCoeffPrev = mdst_filt_coef_prev[2 + previousShape]; + break; + + default: + pCoeffPrev = mdst_filt_coef_prev[previousShape]; + break; + } + } + + /* 0.3. set pointer to filter-coefficients for MDST excitation */ + + /* define offset of pointer to filter-coefficients for MDST exitation + * employing only the current frame */ + if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_SINE)) { + coeffPointerOffset = 0; + } else if ((previousShape == SHAPE_SINE) && (currentShape == SHAPE_KBD)) { + coeffPointerOffset = 2; + } else if ((previousShape == SHAPE_KBD) && (currentShape == SHAPE_KBD)) { + coeffPointerOffset = 1; + } else /* if ( (previousShape == SHAPE_KBD) && (currentShape == SHAPE_SINE) + ) */ + { + coeffPointerOffset = 3; + } + + /* set pointer to filter-coefficient table cp. ISO/IEC FDIS 23003-3:2011(E) + * table 124 */ + switch (pAacDecoderChannelInfo[L] + ->icsInfo.WindowSequence) { /* current window sequence */ + case BLOCK_SHORT: + case BLOCK_LONG: + pCoeff = mdst_filt_coef_curr[coeffPointerOffset]; + break; + + case BLOCK_START: + if ((pJointStereoPersistentData->winSeqPrev == BLOCK_SHORT) || + (pJointStereoPersistentData->winSeqPrev == BLOCK_START)) { + /* a stop-start-sequence can only follow on an eight-short-sequence or + * a start-sequence */ + pCoeff = mdst_filt_coef_curr[12 + coeffPointerOffset]; + } else { + pCoeff = mdst_filt_coef_curr[4 + coeffPointerOffset]; + } + break; + + case BLOCK_STOP: + pCoeff = mdst_filt_coef_curr[8 + coeffPointerOffset]; + break; + + default: + pCoeff = mdst_filt_coef_curr[coeffPointerOffset]; + } + + /* 0.4. find maximum common (l/r) band-scaling-factor for whole sequence + * (all windows) */ + frameMaxScale = 0; + for (window = 0, group = 0; group < windowGroups; group++) { + for (groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + SHORT *leftScale = &SFBleftScale[window * 16]; + SHORT *rightScale = &SFBrightScale[window * 16]; + int windowMaxScale = 0; + + /* find maximum scaling factor of all bands in this window */ + for (band = 0; band < min_sfb_ste; band++) { + int lScale = leftScale[band]; + int rScale = rightScale[band]; + int commonScale = ((lScale > rScale) ? lScale : rScale); + windowMaxScale = + (windowMaxScale < commonScale) ? commonScale : windowMaxScale; + } + if (scaleFactorBandsTransmittedL > + min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedL == max_sfb_ste + */ + for (; band < max_sfb_ste; band++) { + int lScale = leftScale[band]; + windowMaxScale = + (windowMaxScale < lScale) ? lScale : windowMaxScale; + } + } else { + if (scaleFactorBandsTransmittedR > + min_sfb_ste) { /* i.e. scaleFactorBandsTransmittedR == max_sfb_ste + */ + for (; band < max_sfb_ste; band++) { + int rScale = rightScale[band]; + windowMaxScale = + (windowMaxScale < rScale) ? rScale : windowMaxScale; + } + } + } + + /* find maximum common SF of all windows */ + frameMaxScale = + (frameMaxScale < windowMaxScale) ? windowMaxScale : frameMaxScale; + } + } + + /* add some headroom for overflow protection during filter and add operation + */ + frameMaxScale += 2; + + /* process on window-basis (i.e. iterate over all groups and corresponding + * windows) */ + for (window = 0, group = 0; group < windowGroups; group++) { + groupMask = 1 << group; + + for (groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + /* initialize the MDST with zeros */ + FDKmemclear(&dmx_im[windowLen * window], windowLen * sizeof(FIXP_DBL)); + + /* 1. calculate the previous downmix MDCT. We do this once just for the + * Main band. */ + if (cplxPredictionData->complex_coef == 1) { + if ((cplxPredictionData->use_prev_frame == 1) && (mainband_flag)) { + /* if this is a long-block or the first window of a short-block + calculate the downmix MDCT of the previous frame. + use_prev_frame is assumed not to change during a frame! + */ + + /* first determine shiftfactors to scale left and right channel */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != + BLOCK_SHORT) || + (window == 0)) { + int index_offset = 0; + int srLeftChan = 0; + int srRightChan = 0; + if (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) { + /* use the last window of the previous frame for MDCT + * calculation if this is a short-block. */ + index_offset = windowLen * 7; + if (staticSpecScaleL[7] > staticSpecScaleR[7]) { + srRightChan = staticSpecScaleL[7] - staticSpecScaleR[7]; + dmx_re_prev_e = staticSpecScaleL[7]; + } else { + srLeftChan = staticSpecScaleR[7] - staticSpecScaleL[7]; + dmx_re_prev_e = staticSpecScaleR[7]; + } + } else { + if (staticSpecScaleL[0] > staticSpecScaleR[0]) { + srRightChan = staticSpecScaleL[0] - staticSpecScaleR[0]; + dmx_re_prev_e = staticSpecScaleL[0]; + } else { + srLeftChan = staticSpecScaleR[0] - staticSpecScaleL[0]; + dmx_re_prev_e = staticSpecScaleR[0]; + } + } + + /* now scale channels and determine downmix MDCT of previous frame + */ + if (pAacDecoderStaticChannelInfo[L] + ->pCpeStaticData->jointStereoPersistentData + .clearSpectralCoeffs == 1) { + FDKmemclear(dmx_re_prev, windowLen * sizeof(FIXP_DBL)); + dmx_re_prev_e = 0; + } else { + if (cplxPredictionData->pred_dir == 0) { + for (int i = 0; i < windowLen; i++) { + dmx_re_prev[i] = + ((staticSpectralCoeffsL[index_offset + i] >> + srLeftChan) + + (staticSpectralCoeffsR[index_offset + i] >> + srRightChan)) >> + 1; + } + } else { + for (int i = 0; i < windowLen; i++) { + dmx_re_prev[i] = + ((staticSpectralCoeffsL[index_offset + i] >> + srLeftChan) - + (staticSpectralCoeffsR[index_offset + i] >> + srRightChan)) >> + 1; + } + } + } + + /* In case that we use INF we have to preserve the state of the + "dmx_re_prev" (original or computed). This is necessary because we + have to apply MS over the separate IGF tiles. */ + FDKmemcpy(store_dmx_re_prev, &dmx_re_prev[0], + windowLen * sizeof(FIXP_DBL)); + + /* Particular exponent of the computed/original "dmx_re_prev" must + * be kept for the tile MS calculations if necessary.*/ + *store_dmx_re_prev_e = dmx_re_prev_e; + + } /* if ( (pAacDecoderChannelInfo[L]->icsInfo.WindowSequence != + BLOCK_SHORT) || (window == 0) ) */ + + } /* if ( pJointStereoData->use_prev_frame == 1 ) */ + + } /* if ( pJointStereoData->complex_coef == 1 ) */ + + /* 2. calculate downmix MDCT of current frame */ + + /* set pointer to scale-factor-bands of current window */ + SHORT *leftScale = &SFBleftScale[window * 16]; + SHORT *rightScale = &SFBrightScale[window * 16]; + + specScaleL[window] = specScaleR[window] = frameMaxScale; + + /* adapt scaling-factors to previous frame */ + if (cplxPredictionData->use_prev_frame == 1) { + if (window == 0) { + if (dmx_re_prev_e < frameMaxScale) { + if (mainband_flag == 0) { + scaleValues(dmx_re_prev, store_dmx_re_prev, windowLen, + -(frameMaxScale - dmx_re_prev_e)); + } else { + for (int i = 0; i < windowLen; i++) { + dmx_re_prev[i] >>= (frameMaxScale - dmx_re_prev_e); + } + } + } else { + if (mainband_flag == 0) { + FDKmemcpy(dmx_re_prev, store_dmx_re_prev, + windowLen * sizeof(FIXP_DBL)); + } + specScaleL[0] = dmx_re_prev_e; + specScaleR[0] = dmx_re_prev_e; + } + } else { /* window != 0 */ + FDK_ASSERT(pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT); + if (specScaleL[window - 1] < frameMaxScale) { + for (int i = 0; i < windowLen; i++) { + dmx_re[windowLen * (window - 1) + i] >>= + (frameMaxScale - specScaleL[window - 1]); + } + } else { + specScaleL[window] = specScaleL[window - 1]; + specScaleR[window] = specScaleR[window - 1]; + } + } + } /* if ( pJointStereoData->use_prev_frame == 1 ) */ + + /* scaling factors of both channels ought to be equal now */ + FDK_ASSERT(specScaleL[window] == specScaleR[window]); + + /* rescale signal and calculate downmix MDCT */ + for (band = 0; band < max_sfb_ste; band++) { + /* first adapt scaling of current band to scaling of current window => + * shift signal right */ + int lScale = leftScale[band]; + int rScale = rightScale[band]; + + lScale = fMin(DFRACT_BITS - 1, specScaleL[window] - lScale); + rScale = fMin(DFRACT_BITS - 1, + specScaleL[window] - rScale); /* L or R doesn't + matter, + specScales are + equal at this + point */ + + /* Write back to sfb scale to cover the case when max_sfb_ste < + * max_sfb */ + leftScale[band] = rightScale[band] = specScaleL[window]; + + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + spectrumL[windowLen * window + i] >>= lScale; + spectrumR[windowLen * window + i] >>= rScale; + } + + /* now calculate downmix MDCT */ + if (pJointStereoData->MsUsed[band] & groupMask) { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + spectrumL[windowLen * window + i]; + } + } else { + if (cplxPredictionData->pred_dir == 0) { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + (spectrumL[windowLen * window + i] + + spectrumR[windowLen * window + i]) >> + 1; + } + } else { + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + dmx_re[windowLen * window + i] = + (spectrumL[windowLen * window + i] - + spectrumR[windowLen * window + i]) >> + 1; + } + } + } + + } /* for ( band=0; bandcomplex_coef == 1) { + { + /* 3.1 move pointer in filter-coefficient table in case of short + * window sequence */ + /* (other coefficients are utilized for the last 7 short + * windows) */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) && + (window != 0)) { + pCoeff = mdst_filt_coef_curr[currentShape]; + pCoeffPrev = mdst_filt_coef_prev[currentShape]; + } + + /* The length of the filter processing must be extended because of + * filter boundary problems */ + int extended_band = fMin( + pScaleFactorBandOffsets[max_sfb_ste_outside] + 7, windowLen); + + /* 3.2. estimate downmix MDST from current frame downmix MDCT */ + if ((pAacDecoderChannelInfo[L]->icsInfo.WindowSequence == + BLOCK_SHORT) && + (window != 0)) { + CJointStereo_filterAndAdd(&dmx_re[windowLen * window], + extended_band, windowLen, pCoeff, + &dmx_im[windowLen * window], 1); + + CJointStereo_filterAndAdd(&dmx_re[windowLen * (window - 1)], + extended_band, windowLen, pCoeffPrev, + &dmx_im[windowLen * window], 0); + } else { + CJointStereo_filterAndAdd(dmx_re, extended_band, windowLen, + pCoeff, dmx_im, 1); + + if (cplxPredictionData->use_prev_frame == 1) { + CJointStereo_filterAndAdd(dmx_re_prev, extended_band, windowLen, + pCoeffPrev, + &dmx_im[windowLen * window], 0); + } + } + + } /* if(pAacDecoderChannelInfo[L]->transform_splitting_active) */ + } /* if ( pJointStereoData->complex_coef == 1 ) */ + + /* 4. upmix process */ + INT pred_dir = cplxPredictionData->pred_dir ? -1 : 1; + /* 0.1 in Q-3.34 */ + const FIXP_DBL pointOne = 0x66666666; /* 0.8 */ + /* Shift value for the downmix */ + const INT shift_dmx = SF_FNA_COEFFS + 1; + + for (band = 0; band < max_sfb_ste_outside; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + FIXP_SGL tempRe = + (FIXP_SGL)cplxPredictionData->alpha_q_re[group][band]; + FIXP_SGL tempIm = + (FIXP_SGL)cplxPredictionData->alpha_q_im[group][band]; + + /* Find the minimum common headroom for alpha_re and alpha_im */ + int alpha_re_headroom = CountLeadingBits((INT)tempRe) - 16; + if (tempRe == (FIXP_SGL)0) alpha_re_headroom = 15; + int alpha_im_headroom = CountLeadingBits((INT)tempIm) - 16; + if (tempIm == (FIXP_SGL)0) alpha_im_headroom = 15; + int val = fMin(alpha_re_headroom, alpha_im_headroom); + + /* Multiply alpha by 0.1 with maximum precision */ + FDK_ASSERT(val >= 0); + FIXP_DBL alpha_re_tmp = fMult((FIXP_SGL)(tempRe << val), pointOne); + FIXP_DBL alpha_im_tmp = fMult((FIXP_SGL)(tempIm << val), pointOne); + + /* Calculate alpha exponent */ + /* (Q-3.34 * Q15.0) shifted left by "val" */ + int alpha_re_exp = -3 + 15 - val; + + int help3_shift = alpha_re_exp + 1; + + FIXP_DBL *p2CoeffL = &( + spectrumL[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2CoeffR = &( + spectrumR[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2dmxIm = + &(dmx_im[windowLen * window + pScaleFactorBandOffsets[band]]); + FIXP_DBL *p2dmxRe = + &(dmx_re[windowLen * window + pScaleFactorBandOffsets[band]]); + + for (int i = pScaleFactorBandOffsets[band]; + i < pScaleFactorBandOffsets[band + 1]; i++) { + /* Calculating helper term: + side = specR[i] - alpha_re[i] * dmx_re[i] - alpha_im[i] * + dmx_im[i]; + + Here "dmx_re" may be the same as "specL" or alternatively keep + the downmix. "dmx_re" and "specL" are two different pointers + pointing to separate arrays, which may or may not contain the + same data (with different scaling). + */ + + /* help1: alpha_re[i] * dmx_re[i] */ + FIXP_DBL help1 = fMultDiv2(alpha_re_tmp, *p2dmxRe++); + + /* tmp: dmx_im[i] */ + FIXP_DBL tmp = (*p2dmxIm++) << shift_dmx; + + /* help2: alpha_im[i] * dmx_im[i] */ + FIXP_DBL help2 = fMultDiv2(alpha_im_tmp, tmp); + + /* help3: alpha_re[i] * dmx_re[i] + alpha_im[i] * dmx_im[i] */ + FIXP_DBL help3 = help1 + help2; + + /* side (= help4) = specR[i] - (dmx_re[i] * specL[i] + alpha_im[i] + * * dmx_im[i]) */ + FIXP_DBL help4 = *p2CoeffR - scaleValue(help3, help3_shift); + + /* We calculate the left and right output by using the helper + * function */ + /* specR[i] = -/+ (specL[i] - side); */ + *p2CoeffR = + (FIXP_DBL)((LONG)(*p2CoeffL - help4) * (LONG)pred_dir); + p2CoeffR++; + + /* specL[i] = specL[i] + side; */ + *p2CoeffL = *p2CoeffL + help4; + p2CoeffL++; + } + } + + } /* for ( band=0; band < max_sfb_ste; band++ ) */ + } /* for ( groupwin=0; groupwingranuleLength); + rightSpectrum = + SPEC(spectrumR, window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band = 0; band < max_sfb_ste_outside; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + int lScale = leftScale[band]; + int rScale = rightScale[band]; + int commonScale = lScale > rScale ? lScale : rScale; + unsigned int offsetCurrBand, offsetNextBand; + + /* ISO/IEC 14496-3 Chapter 4.6.8.1.1 : + M/S joint channel coding can only be used if common_window is 1. + */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + commonScale++; + leftScale[band] = commonScale; + rightScale[band] = commonScale; + + lScale = fMin(DFRACT_BITS - 1, commonScale - lScale); + rScale = fMin(DFRACT_BITS - 1, commonScale - rScale); + + FDK_ASSERT(lScale >= 0 && rScale >= 0); + + offsetCurrBand = pScaleFactorBandOffsets[band]; + offsetNextBand = pScaleFactorBandOffsets[band + 1]; + + CJointStereo_GenerateMSOutput(&(leftSpectrum[offsetCurrBand]), + &(rightSpectrum[offsetCurrBand]), + lScale, rScale, + offsetNextBand - offsetCurrBand); + } + } + if (scaleFactorBandsTransmittedL > scaleFactorBandsTransmitted) { + for (; band < scaleFactorBandsTransmittedL; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + rightScale[band] = leftScale[band]; + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + FIXP_DBL leftCoefficient = leftSpectrum[index]; + /* FIXP_DBL rightCoefficient = (FIXP_DBL)0; */ + rightSpectrum[index] = leftCoefficient; + } + } + } + } else if (scaleFactorBandsTransmittedR > scaleFactorBandsTransmitted) { + for (; band < scaleFactorBandsTransmittedR; band++) { + if (pJointStereoData->MsUsed[band] & groupMask) { + leftScale[band] = rightScale[band]; + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + /* FIXP_DBL leftCoefficient = (FIXP_DBL)0; */ + FIXP_DBL rightCoefficient = rightSpectrum[index]; + + leftSpectrum[index] = rightCoefficient; + rightSpectrum[index] = -rightCoefficient; + } + } + } + } + } + } + + /* Reset MsUsed flags if no explicit signalling was transmitted. Necessary + for intensity coding. PNS correlation signalling was mapped before + calling CJointStereo_ApplyMS(). */ + if (pJointStereoData->MsMaskPresent == 2) { + FDKmemclear(pJointStereoData->MsUsed, + JointStereoMaximumBands * sizeof(UCHAR)); + } + } +} + +void CJointStereo_ApplyIS(CAacDecoderChannelInfo *pAacDecoderChannelInfo[2], + const SHORT *pScaleFactorBandOffsets, + const UCHAR *pWindowGroupLength, + const int windowGroups, + const int scaleFactorBandsTransmitted) { + CJointStereoData *pJointStereoData = + &pAacDecoderChannelInfo[L]->pComData->jointStereoData; + + for (int window = 0, group = 0; group < windowGroups; group++) { + UCHAR *CodeBook; + SHORT *ScaleFactor; + UCHAR groupMask = 1 << group; + + CodeBook = &pAacDecoderChannelInfo[R]->pDynData->aCodeBook[group * 16]; + ScaleFactor = + &pAacDecoderChannelInfo[R]->pDynData->aScaleFactor[group * 16]; + + for (int groupwin = 0; groupwin < pWindowGroupLength[group]; + groupwin++, window++) { + FIXP_DBL *leftSpectrum, *rightSpectrum; + SHORT *leftScale = + &pAacDecoderChannelInfo[L]->pDynData->aSfbScale[window * 16]; + SHORT *rightScale = + &pAacDecoderChannelInfo[R]->pDynData->aSfbScale[window * 16]; + int band; + + leftSpectrum = SPEC(pAacDecoderChannelInfo[L]->pSpectralCoefficient, + window, pAacDecoderChannelInfo[L]->granuleLength); + rightSpectrum = SPEC(pAacDecoderChannelInfo[R]->pSpectralCoefficient, + window, pAacDecoderChannelInfo[R]->granuleLength); + + for (band = 0; band < scaleFactorBandsTransmitted; band++) { + if ((CodeBook[band] == INTENSITY_HCB) || + (CodeBook[band] == INTENSITY_HCB2)) { + int bandScale = -(ScaleFactor[band] + 100); + + int msb = bandScale >> 2; + int lsb = bandScale & 0x03; + + /* exponent of MantissaTable[lsb][0] is 1, thus msb+1 below. */ + FIXP_DBL scale = MantissaTable[lsb][0]; + + /* ISO/IEC 14496-3 Chapter 4.6.8.2.3 : + The use of intensity stereo coding is signaled by the use of the + pseudo codebooks INTENSITY_HCB and INTENSITY_HCB2 (15 and 14) only + in the right channel of a channel_pair_element() having a common + ics_info() (common_window == 1). */ + FDK_ASSERT(GetWindowSequence(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowSequence(&pAacDecoderChannelInfo[R]->icsInfo)); + FDK_ASSERT(GetWindowShape(&pAacDecoderChannelInfo[L]->icsInfo) == + GetWindowShape(&pAacDecoderChannelInfo[R]->icsInfo)); + + rightScale[band] = leftScale[band] + msb + 1; + + if (pJointStereoData->MsUsed[band] & groupMask) { + if (CodeBook[band] == INTENSITY_HCB) /* _NOT_ in-phase */ + { + scale = -scale; + } + } else { + if (CodeBook[band] == INTENSITY_HCB2) /* out-of-phase */ + { + scale = -scale; + } + } + + for (int index = pScaleFactorBandOffsets[band]; + index < pScaleFactorBandOffsets[band + 1]; index++) { + rightSpectrum[index] = fMult(leftSpectrum[index], scale); + } + } + } + } + } +} diff --git a/fdk-aac/libAACdec/src/stereo.h b/fdk-aac/libAACdec/src/stereo.h new file mode 100644 index 0000000..af7a74f --- /dev/null +++ b/fdk-aac/libAACdec/src/stereo.h @@ -0,0 +1,211 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Josef Hoepfl + + Description: joint stereo processing + +*******************************************************************************/ + +#ifndef STEREO_H +#define STEREO_H + +#include "machine_type.h" +#include "FDK_bitstream.h" +#include "common_fix.h" + +#define SFB_PER_PRED_BAND 2 + +#define SR_FNA_OUT \ + 0 /* Additional scaling of the CJointStereo_filterAndAdd()-output to avoid \ + overflows. */ + /* The scaling factor can be set to 0 if the coefficients are prescaled + * appropriately. */ +/* Prescaling via factor SF_FNA_COEFFS is done at compile-time but should only + * be */ +/* utilized if the coefficients are stored as FIXP_DBL. (cp. aac_rom.cpp/.h) */ + +/* The NO_CPLX_PRED_BUGFIX-switch was introduced to enable decoding of + conformance-streams in way that they are comparable to buggy + reference-streams. This is established by storing the prediction direction + for computation of the "downmix MDCT of previous frame". This is not standard + compliant. Once correct reference-streams for complex-stereo-prediction are + available this switch becomes obsolete. +*/ +/*#define NO_CPLX_PRED_BUGFIX*/ + +enum { JointStereoMaximumGroups = 8, JointStereoMaximumBands = 64 }; + +typedef struct { + UCHAR pred_dir; // 0 = prediction from mid to side channel, 1 = vice versa + UCHAR + igf_pred_dir; // 0 = prediction from mid to side channel, 1 = vice versa + UCHAR complex_coef; // 0 = alpha_q_im[x] is 0 for all prediction bands, 1 = + // alpha_q_im[x] is transmitted via bitstream + UCHAR use_prev_frame; // 0 = use current frame for MDST estimation, 1 = use + // current and previous frame + + SHORT alpha_q_re[JointStereoMaximumGroups][JointStereoMaximumBands]; + SHORT alpha_q_im[JointStereoMaximumGroups][JointStereoMaximumBands]; +} CCplxPredictionData; + +/* joint stereo scratch memory (valid for this frame) */ +typedef struct { + UCHAR MsMaskPresent; + UCHAR MsUsed[JointStereoMaximumBands]; /*!< every arry element contains flags + for up to 8 groups. this array is + also utilized for complex stereo + prediction. */ + UCHAR IGF_MsMaskPresent; + + UCHAR cplx_pred_flag; /* stereo complex prediction was signalled for this + frame */ + UCHAR igf_cplx_pred_flag; + + /* The following array and variable are needed for the case when INF is + * active */ + FIXP_DBL store_dmx_re_prev[1024]; + SHORT store_dmx_re_prev_e; + +} CJointStereoData; + +/* joint stereo persistent memory */ +typedef struct { + UCHAR clearSpectralCoeffs; /* indicates that the spectral coeffs must be + cleared because the transform splitting active + flag of the left and right channel was different + */ + + FIXP_DBL *scratchBuffer; /* pointer to scratch buffer */ + + FIXP_DBL + *spectralCoeffs[2]; /* spectral coefficients of this channel utilized by + complex stereo prediction */ + SHORT *specScale[2]; + + SHORT alpha_q_re_prev[JointStereoMaximumGroups][JointStereoMaximumBands]; + SHORT alpha_q_im_prev[JointStereoMaximumGroups][JointStereoMaximumBands]; + + UCHAR winSeqPrev; + UCHAR winShapePrev; + UCHAR winGroupsPrev; + +} CJointStereoPersistentData; + +/*! + \brief Read joint stereo data from bitstream + + The function reads joint stereo data from bitstream. + + \param bs bit stream handle data source. + \param pJointStereoData pointer to stereo data structure to receive decoded + data. \param windowGroups number of window groups. \param + scaleFactorBandsTransmitted number of transmitted scalefactor bands. \param + flags decoder flags + + \return 0 on success, -1 on error. +*/ +int CJointStereo_Read(HANDLE_FDK_BITSTREAM bs, + CJointStereoData *pJointStereoData, + const int windowGroups, + const int scaleFactorBandsTransmitted, + const int max_sfb_ste_clear, + CJointStereoPersistentData *pJointStereoPersistentData, + CCplxPredictionData *cplxPredictionData, + int cplxPredictionActiv, int scaleFactorBandsTotal, + int windowSequence, const UINT flags); + +#endif /* #ifndef STEREO_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp b/fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp new file mode 100644 index 0000000..43e06cd --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_ace_d4t64.cpp @@ -0,0 +1,439 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: ACELP + +*******************************************************************************/ + +#include "usacdec_ace_d4t64.h" + +#define L_SUBFR 64 /* Subframe size */ + +/* + * D_ACELP_add_pulse + * + * Parameters: + * pos I: position of pulse + * nb_pulse I: number of pulses + * track I: track + * code O: fixed codebook + * + * Function: + * Add pulses to fixed codebook + * + * Returns: + * void + */ +static void D_ACELP_add_pulse(SHORT pos[], SHORT nb_pulse, SHORT track, + FIXP_COD code[]) { + SHORT i, k; + for (k = 0; k < nb_pulse; k++) { + /* i = ((pos[k] & (16-1))*NB_TRACK) + track; */ + i = ((pos[k] & (16 - 1)) << 2) + track; + if ((pos[k] & 16) == 0) { + code[i] = code[i] + (FIXP_COD)(512 << (COD_BITS - FRACT_BITS)); + } else { + code[i] = code[i] - (FIXP_COD)(512 << (COD_BITS - FRACT_BITS)); + } + } + return; +} +/* + * D_ACELP_decode_1p_N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 1 pulse with N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_1p_N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT pos1; + LONG i, mask; + + mask = ((1 << N) - 1); + /* + * Decode 1 pulse with N+1 bits + */ + pos1 = (SHORT)((index & mask) + offset); + i = ((index >> N) & 1); + if (i == 1) { + pos1 += 16; + } + pos[0] = pos1; + return; +} +/* + * D_ACELP_decode_2p_2N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 2 pulses with 2*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_2p_2N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT pos1, pos2; + LONG mask, i; + mask = ((1 << N) - 1); + /* + * Decode 2 pulses with 2*N+1 bits + */ + pos1 = (SHORT)(((index >> N) & mask) + offset); + i = (index >> (2 * N)) & 1; + pos2 = (SHORT)((index & mask) + offset); + if ((pos2 - pos1) < 0) { + if (i == 1) { + pos1 += 16; + } else { + pos2 += 16; + } + } else { + if (i == 1) { + pos1 += 16; + pos2 += 16; + } + } + pos[0] = pos1; + pos[1] = pos2; + return; +} +/* + * D_ACELP_decode_3p_3N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 3 pulses with 3*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_3p_3N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j; + LONG mask, idx; + + /* + * Decode 3 pulses with 3*N+1 bits + */ + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + if (((index >> ((2 * N) - 1)) & 1) == 1) { + j += (1 << (N - 1)); + } + D_ACELP_decode_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << (N + 1)) - 1); + idx = (index >> (2 * N)) & mask; + D_ACELP_decode_1p_N1(idx, N, offset, pos + 2); + return; +} +/* + * D_ACELP_decode_4p_4N1 + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 4 pulses with 4*N+1 bits + * + * Returns: + * void + */ +static void D_ACELP_decode_4p_4N1(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j; + LONG mask, idx; + /* + * Decode 4 pulses with 4*N+1 bits + */ + mask = ((1 << ((2 * N) - 1)) - 1); + idx = index & mask; + j = offset; + if (((index >> ((2 * N) - 1)) & 1) == 1) { + j += (1 << (N - 1)); + } + D_ACELP_decode_2p_2N1(idx, N - 1, j, pos); + mask = ((1 << ((2 * N) + 1)) - 1); + idx = (index >> (2 * N)) & mask; + D_ACELP_decode_2p_2N1(idx, N, offset, pos + 2); + return; +} +/* + * D_ACELP_decode_4p_4N + * + * Parameters: + * index I: pulse index + * N I: number of bits for position + * offset I: offset + * pos O: position of the pulse + * + * Function: + * Decode 4 pulses with 4*N bits + * + * Returns: + * void + */ +static void D_ACELP_decode_4p_4N(LONG index, SHORT N, SHORT offset, + SHORT pos[]) { + SHORT j, n_1; + /* + * Decode 4 pulses with 4*N bits + */ + n_1 = N - 1; + j = offset + (1 << n_1); + switch ((index >> ((4 * N) - 2)) & 3) { + case 0: + if (((index >> ((4 * n_1) + 1)) & 1) == 0) { + D_ACELP_decode_4p_4N1(index, n_1, offset, pos); + } else { + D_ACELP_decode_4p_4N1(index, n_1, j, pos); + } + break; + case 1: + D_ACELP_decode_1p_N1((index >> ((3 * n_1) + 1)), n_1, offset, pos); + D_ACELP_decode_3p_3N1(index, n_1, j, pos + 1); + break; + case 2: + D_ACELP_decode_2p_2N1((index >> ((2 * n_1) + 1)), n_1, offset, pos); + D_ACELP_decode_2p_2N1(index, n_1, j, pos + 2); + break; + case 3: + D_ACELP_decode_3p_3N1((index >> (n_1 + 1)), n_1, offset, pos); + D_ACELP_decode_1p_N1(index, n_1, j, pos + 3); + break; + } + return; +} + +/* + * D_ACELP_decode_4t + * + * Parameters: + * index I: index + * mode I: speech mode + * code I: (Q9) algebraic (fixed) codebook excitation + * + * Function: + * 20, 36, 44, 52, 64, 72, 88 bits algebraic codebook. + * 4 tracks x 16 positions per track = 64 samples. + * + * 20 bits 5+5+5+5 --> 4 pulses in a frame of 64 samples. + * 36 bits 9+9+9+9 --> 8 pulses in a frame of 64 samples. + * 44 bits 13+9+13+9 --> 10 pulses in a frame of 64 samples. + * 52 bits 13+13+13+13 --> 12 pulses in a frame of 64 samples. + * 64 bits 2+2+2+2+14+14+14+14 --> 16 pulses in a frame of 64 samples. + * 72 bits 10+2+10+2+10+14+10+14 --> 18 pulses in a frame of 64 samples. + * 88 bits 11+11+11+11+11+11+11+11 --> 24 pulses in a frame of 64 samples. + * + * All pulses can have two (2) possible amplitudes: +1 or -1. + * Each pulse can sixteen (16) possible positions. + * + * codevector length 64 + * number of track 4 + * number of position 16 + * + * Returns: + * void + */ +void D_ACELP_decode_4t64(SHORT index[], int nbits, FIXP_COD code[]) { + LONG L_index; + SHORT k, pos[6]; + + FDKmemclear(code, L_SUBFR * sizeof(FIXP_COD)); + + /* decode the positions and signs of pulses and build the codeword */ + switch (nbits) { + case 12: + for (k = 0; k < 4; k += 2) { + L_index = index[2 * (k / 2) + 1]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, 2 * (index[2 * (k / 2)]) + k / 2, code); + } + break; + case 16: { + int i = 0; + int offset = index[i++]; + offset = (offset == 0) ? 1 : 3; + for (k = 0; k < 4; k++) { + if (k != offset) { + L_index = index[i++]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + } + } break; + case 20: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + break; + case 28: + for (k = 0; k < 4 - 2; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + for (k = 2; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_1p_N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 1, k, code); + } + break; + case 36: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + break; + case 44: + for (k = 0; k < 4 - 2; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_3p_3N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 3, k, code); + } + for (k = 2; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_2p_2N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 2, k, code); + } + break; + case 52: + for (k = 0; k < 4; k++) { + L_index = (LONG)index[k]; + D_ACELP_decode_3p_3N1(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 3, k, code); + } + break; + case 64: + for (k = 0; k < 4; k++) { + L_index = (((LONG)index[k] << 14) + (LONG)index[k + 4]); + D_ACELP_decode_4p_4N(L_index, 4, 0, pos); + D_ACELP_add_pulse(pos, 4, k, code); + } + break; + default: + FDK_ASSERT(0); + } + return; +} diff --git a/fdk-aac/libAACdec/src/usacdec_ace_d4t64.h b/fdk-aac/libAACdec/src/usacdec_ace_d4t64.h new file mode 100644 index 0000000..76bc3d9 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_ace_d4t64.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): + + Description: ACELP + +*******************************************************************************/ + +#ifndef USACDEC_ACE_D4T64_H +#define USACDEC_ACE_D4T64_H + +#include "common_fix.h" + +/* Data type definition for the fixed codebook vector */ +#define FIXP_COD FIXP_SGL +#define FX_COD2FX_DBL(x) (FX_SGL2FX_DBL(x)) +#define FX_DBL2FX_COD(x) FX_DBL2FX_SGL((x) + (FIXP_DBL)0x8000) +#define FX_SGL2FX_COD(x) (x) +#define COD_BITS FRACT_BITS + +void D_ACELP_decode_4t64(SHORT index[], int nbits, FIXP_COD code[]); + +#endif /* USACDEC_ACE_D4T64_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp b/fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp new file mode 100644 index 0000000..5964b49 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_ace_ltp.cpp @@ -0,0 +1,229 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP LTP filter + +*******************************************************************************/ + +#include "usacdec_ace_ltp.h" + +#include "genericStds.h" +#include "common_fix.h" + +#define UP_SAMP 4 +#define L_INTERPOL2 16 +#define L_SUBFR 64 + +#define A2 FL2FX_SGL(2 * 0.18f) +#define B FL2FX_SGL(0.64f) + +static const LONG Pred_lt4_inter4_2[UP_SAMP][L_INTERPOL2] = { + {(LONG)0x0000FFFC, (LONG)0x0008FFFC, (LONG)0xFFEB004C, (LONG)0xFF50014A, + (LONG)0xFDD90351, (LONG)0xFB2A06CD, (LONG)0xF6920D46, (LONG)0xEBB42B35, + (LONG)0x6D9EEF39, (LONG)0x0618FE0F, (LONG)0xFFE00131, (LONG)0xFE5501C5, + (LONG)0xFE5E015D, (LONG)0xFEF700B6, (LONG)0xFF920037, (LONG)0xFFEC0003}, + {(LONG)0x0002FFF2, (LONG)0x0026FFBD, (LONG)0x005DFF98, (LONG)0x0055FFEF, + (LONG)0xFF89015F, (LONG)0xFD3A04E5, (LONG)0xF7D90DAA, (LONG)0xE67A50EE, + (LONG)0x50EEE67A, (LONG)0x0DAAF7D9, (LONG)0x04E5FD3A, (LONG)0x015FFF89, + (LONG)0xFFEF0055, (LONG)0xFF98005D, (LONG)0xFFBD0026, (LONG)0xFFF20002}, + {(LONG)0x0003FFEC, (LONG)0x0037FF92, (LONG)0x00B6FEF7, (LONG)0x015DFE5E, + (LONG)0x01C5FE55, (LONG)0x0131FFE0, (LONG)0xFE0F0618, (LONG)0xEF396D9E, + (LONG)0x2B35EBB4, (LONG)0x0D46F692, (LONG)0x06CDFB2A, (LONG)0x0351FDD9, + (LONG)0x014AFF50, (LONG)0x004CFFEB, (LONG)0xFFFC0008, (LONG)0xFFFC0000}, + {(LONG)0x0002FFF2, (LONG)0x002BFF9E, (LONG)0x00B9FECE, (LONG)0x01CFFD75, + (LONG)0x035EFBC1, (LONG)0x0521FA0C, (LONG)0x06AAF8C9, (LONG)0x07907852, + (LONG)0x0790F8C9, (LONG)0x06AAFA0C, (LONG)0x0521FBC1, (LONG)0x035EFD75, + (LONG)0x01CFFECE, (LONG)0x00B9FF9E, (LONG)0x002BFFF2, (LONG)0x00020000}}; + +void Pred_lt4(FIXP_DBL exc[], /* in/out: excitation buffer */ + int T0, /* input : integer pitch lag */ + int frac /* input : fraction of lag in range 0..3 */ +) { + int j; + FIXP_DBL *x; + const LONG *interpol; + FIXP_DBL L_sumb, L_sumt; + + x = &exc[-T0 - L_INTERPOL2 + 1]; + + /* remap frac and x: + 0 -> 3 x (unchanged) + 1 -> 0 x-- + 2 -> 1 x-- + 3 -> 2 x-- + */ + + if (--frac < 0) + frac += UP_SAMP; + else + x--; + + j = L_SUBFR + 1; + do { + LONG filt; + FIXP_DBL x0, x1; + FIXP_DBL *xi = x++; + interpol = Pred_lt4_inter4_2[frac]; + int i = 3; + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultDiv2(x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultDiv2(x1, (FIXP_SGL)((SHORT)filt)); + do { + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + + filt = *interpol++; + x0 = *xi++; + x1 = *xi++; + L_sumt = fMultAddDiv2(L_sumt, x0, (FIXP_SGL)((SHORT)(filt >> 16))); + L_sumb = fMultAddDiv2(L_sumb, x1, (FIXP_SGL)((SHORT)filt)); + } while (--i != 0); + + L_sumb <<= 1; + L_sumb = fAddSaturate(L_sumt << 1, L_sumb); + *exc++ = L_sumb; + } while (--j != 0); + return; +} + +void Pred_lt4_postfilter(FIXP_DBL exc[] /* in/out: excitation buffer */ +) { + /* + exc[i] = A*exc[i-1] + B*exc[i] + A*exc[i+1] + exc[i+1] = A*exc[i] + B*exc[i+1] + A*exc[i+2] ; i = 0:2:62 + */ + int i; + FIXP_DBL sum0, sum1, a_exc0, a_exc1; + a_exc0 = fMultDiv2(A2, exc[-1]); + a_exc1 = fMultDiv2(A2, exc[0]); + + /* ARM926: 22 cycles/iteration */ + for (i = 0; i < L_SUBFR; i += 2) { + sum0 = a_exc0 + fMult(B, exc[i]); + sum1 = a_exc1 + fMult(B, exc[i + 1]); + a_exc0 = fMultDiv2(A2, exc[i + 1]); + a_exc1 = fMultDiv2(A2, exc[i + 2]); + exc[i] = sum0 + a_exc0; + exc[i + 1] = sum1 + a_exc1; + } + return; +} diff --git a/fdk-aac/libAACdec/src/usacdec_ace_ltp.h b/fdk-aac/libAACdec/src/usacdec_ace_ltp.h new file mode 100644 index 0000000..5128acd --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_ace_ltp.h @@ -0,0 +1,128 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP LTP filter + +*******************************************************************************/ + +#ifndef USACDEC_ACE_LTP_H +#define USACDEC_ACE_LTP_H + +#include "common_fix.h" + +/** + * \brief Compute the initial adaptive codebook excitation v'(n) by + * interpolating the past excitation vector u'(n). + * \param exc points to adaptive codebook of current subframe (input/output) + * \param T0 integer part of decoded pitch lag (input) + * \param frac fractional part of decoded pitch lag (0..3) (input) + */ +void Pred_lt4(FIXP_DBL exc[], /* in/out: excitation buffer */ + int T0, /* input : integer pitch lag */ + int frac /* input : fraction of lag */ +); + +/** + * \brief Compute the adaptive codebook excitation v(n) in case of + * ltp_filtering_flag == 0. + * \param exc points to adaptive codebook of current subframe (input/output) + */ +void Pred_lt4_postfilter(FIXP_DBL exc[] /* in/out: excitation buffer */ +); + +#endif /* USACDEC_ACE_LTP_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_acelp.cpp b/fdk-aac/libAACdec/src/usacdec_acelp.cpp new file mode 100644 index 0000000..a606459 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_acelp.cpp @@ -0,0 +1,1296 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP frame decoder + +*******************************************************************************/ + +#include "usacdec_acelp.h" + +#include "usacdec_ace_d4t64.h" +#include "usacdec_ace_ltp.h" +#include "usacdec_rom.h" +#include "usacdec_lpc.h" +#include "genericStds.h" + +#define PIT_FR2_12k8 128 /* Minimum pitch lag with resolution 1/2 */ +#define PIT_FR1_12k8 160 /* Minimum pitch lag with resolution 1 */ +#define TILT_CODE2 \ + FL2FXCONST_SGL(0.3f * 2.0f) /* ACELP code pre-emphasis factor ( *2 ) */ +#define PIT_SHARP \ + FL2FXCONST_SGL(0.85f) /* pitch sharpening factor */ +#define PREEMPH_FAC \ + FL2FXCONST_SGL(0.68f) /* ACELP synth pre-emphasis factor */ + +#define ACELP_HEADROOM 1 +#define ACELP_OUTSCALE (MDCT_OUT_HEADROOM - ACELP_HEADROOM) + +/** + * \brief Calculate pre-emphasis (1 - mu z^-1) on input signal. + * \param[in] in pointer to input signal; in[-1] is also needed. + * \param[out] out pointer to output signal. + * \param[in] L length of filtering. + */ +/* static */ +void E_UTIL_preemph(const FIXP_DBL *in, FIXP_DBL *out, INT L) { + int i; + + for (i = 0; i < L; i++) { + out[i] = in[i] - fMult(PREEMPH_FAC, in[i - 1]); + } + + return; +} + +/** + * \brief Calculate de-emphasis 1/(1 - TILT_CODE z^-1) on innovative codebook + * vector. + * \param[in,out] x innovative codebook vector. + */ +static void Preemph_code( + FIXP_COD x[] /* (i/o) : input signal overwritten by the output */ +) { + int i; + FIXP_DBL L_tmp; + + /* ARM926: 12 cycles per sample */ + for (i = L_SUBFR - 1; i > 0; i--) { + L_tmp = FX_COD2FX_DBL(x[i]); + L_tmp -= fMultDiv2(x[i - 1], TILT_CODE2); + x[i] = FX_DBL2FX_COD(L_tmp); + } +} + +/** + * \brief Apply pitch sharpener to the innovative codebook vector. + * \param[in,out] x innovative codebook vector. + * \param[in] pit_lag decoded pitch lag. + */ +static void Pit_shrp( + FIXP_COD x[], /* in/out: impulse response (or algebraic code) */ + int pit_lag /* input : pitch lag */ +) { + int i; + FIXP_DBL L_tmp; + + for (i = pit_lag; i < L_SUBFR; i++) { + L_tmp = FX_COD2FX_DBL(x[i]); + L_tmp += fMult(x[i - pit_lag], PIT_SHARP); + x[i] = FX_DBL2FX_COD(L_tmp); + } + + return; +} + + /** + * \brief Calculate Quantized codebook gain, Quantized pitch gain and unbiased + * Innovative code vector energy. + * \param[in] index index of quantizer. + * \param[in] code innovative code vector with exponent = SF_CODE. + * \param[out] gain_pit Quantized pitch gain g_p with exponent = SF_GAIN_P. + * \param[out] gain_code Quantized codebook gain g_c. + * \param[in] mean_ener mean_ener defined in open-loop (2 bits), exponent = 7. + * \param[out] E_code unbiased innovative code vector energy. + * \param[out] E_code_e exponent of unbiased innovative code vector energy. + */ + +#define SF_MEAN_ENER_LG10 9 + +/* pow(10.0, {18, 30, 42, 54}/20.0) /(float)(1<>= 1; + } else { + ener_code_e -= 6; + } + gcode_inov = invSqrtNorm2(ener_code, &gcode0_e); + gcode_inov_e = gcode0_e - (ener_code_e >> 1); + + if (bfi) { + FIXP_DBL tgcode; + FIXP_SGL tgpit; + + tgpit = *past_gpit; + + if (tgpit > FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P))) { + tgpit = FL2FXCONST_SGL(0.95f / (1 << SF_GAIN_P)); + } else if (tgpit < FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P))) { + tgpit = FL2FXCONST_SGL(0.5f / (1 << SF_GAIN_P)); + } + *gain_pit = tgpit; + tgpit = FX_DBL2FX_SGL(fMult(tgpit, FL2FXCONST_DBL(0.95f))); + *past_gpit = tgpit; + + tgpit = FL2FXCONST_SGL(1.4f / (1 << SF_GAIN_P)) - tgpit; + tgcode = fMult(*past_gcode, tgpit) << SF_GAIN_P; + *gain_code = scaleValue(fMult(tgcode, gcode_inov), gcode_inov_e); + *past_gcode = tgcode; + + return; + } + + /*-------------- Decode gains ---------------*/ + /* + gcode0 = pow(10.0, (float)mean_ener/20.0); + gcode0 = gcode0 / sqrt(ener_code/L_SUBFR); + */ + gcode0 = pow_10_mean_energy[mean_ener_bits]; + gcode0 = fMultDiv2(gcode0, gcode_inov); + gcode0_e = gcode0_e + SF_MEAN_ENER_LG10 - (ener_code_e >> 1) + 1; + + i = index << 1; + *gain_pit = fdk_t_qua_gain7b[i]; /* adaptive codebook gain */ + /* t_qua_gain[ind2p1] : fixed codebook gain correction factor */ + Ltmp = fMult(fdk_t_qua_gain7b[i + 1], gcode0); + *gain_code = scaleValue(Ltmp, gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B); + + /* update bad frame handler */ + *past_gpit = *gain_pit; + + /*-------------------------------------------------------- + past_gcode = gain_code/gcode_inov + --------------------------------------------------------*/ + { + FIXP_DBL gcode_m; + INT gcode_e; + + gcode_m = fDivNormHighPrec(Ltmp, gcode_inov, &gcode_e); + gcode_e += (gcode0_e - SF_GAIN_C + SF_QUA_GAIN7B) - (gcode_inov_e); + *past_gcode = scaleValue(gcode_m, gcode_e); + } +} + +/** + * \brief Calculate period/voicing factor r_v + * \param[in] exc pitch excitation. + * \param[in] gain_pit gain of pitch g_p. + * \param[in] gain_code gain of code g_c. + * \param[in] gain_code_e exponent of gain of code. + * \param[in] ener_code unbiased innovative code vector energy. + * \param[in] ener_code_e exponent of unbiased innovative code vector energy. + * \return period/voice factor r_v (-1=unvoiced to 1=voiced), exponent SF_PFAC. + */ +static FIXP_DBL calc_period_factor(FIXP_DBL exc[], FIXP_SGL gain_pit, + FIXP_DBL gain_code, FIXP_DBL ener_code, + int ener_code_e) { + int ener_exc_e, L_tmp_e, s = 0; + FIXP_DBL ener_exc, L_tmp; + FIXP_DBL period_fac; + + /* energy of pitch excitation */ + ener_exc = (FIXP_DBL)0; + for (int i = 0; i < L_SUBFR; i++) { + ener_exc += fPow2Div2(exc[i]) >> s; + if (ener_exc >= FL2FXCONST_DBL(0.5f)) { + ener_exc >>= 1; + s++; + } + } + + ener_exc_e = fNorm(ener_exc); + ener_exc = fMult(ener_exc << ener_exc_e, fPow2(gain_pit)); + if (ener_exc != (FIXP_DBL)0) { + ener_exc_e = 2 * SF_EXC + 1 + 2 * SF_GAIN_P - ener_exc_e + s; + } else { + ener_exc_e = 0; + } + + /* energy of innovative code excitation */ + /* L_tmp = ener_code * gain_code*gain_code; */ + L_tmp_e = fNorm(gain_code); + L_tmp = fPow2(gain_code << L_tmp_e); + L_tmp = fMult(ener_code, L_tmp); + L_tmp_e = 2 * SF_GAIN_C + ener_code_e - 2 * L_tmp_e; + + /* Find common exponent */ + { + FIXP_DBL num, den; + int exp_diff; + + exp_diff = ener_exc_e - L_tmp_e; + if (exp_diff >= 0) { + ener_exc >>= 1; + if (exp_diff <= DFRACT_BITS - 2) { + L_tmp >>= exp_diff + 1; + } else { + L_tmp = (FIXP_DBL)0; + } + den = ener_exc + L_tmp; + if (ener_exc_e < DFRACT_BITS - 1) { + den += scaleValue(FL2FXCONST_DBL(0.01f), -ener_exc_e - 1); + } + } else { + if (exp_diff >= -(DFRACT_BITS - 2)) { + ener_exc >>= 1 - exp_diff; + } else { + ener_exc = (FIXP_DBL)0; + } + L_tmp >>= 1; + den = ener_exc + L_tmp; + if (L_tmp_e < DFRACT_BITS - 1) { + den += scaleValue(FL2FXCONST_DBL(0.01f), -L_tmp_e - 1); + } + } + num = (ener_exc - L_tmp); + num >>= SF_PFAC; + + if (den > (FIXP_DBL)0) { + if (ener_exc > L_tmp) { + period_fac = schur_div(num, den, 16); + } else { + period_fac = -schur_div(-num, den, 16); + } + } else { + period_fac = (FIXP_DBL)MAXVAL_DBL; + } + } + + /* exponent = SF_PFAC */ + return period_fac; +} + +/*------------------------------------------------------------* + * noise enhancer * + * ~~~~~~~~~~~~~~ * + * - Enhance excitation on noise. (modify gain of code) * + * If signal is noisy and LPC filter is stable, move gain * + * of code 1.5 dB toward gain of code threshold. * + * This decrease by 3 dB noise energy variation. * + *------------------------------------------------------------*/ +/** + * \brief Enhance excitation on noise. (modify gain of code) + * \param[in] gain_code Quantized codebook gain g_c, exponent = SF_GAIN_C. + * \param[in] period_fac periodicity factor, exponent = SF_PFAC. + * \param[in] stab_fac stability factor, exponent = SF_STAB. + * \param[in,out] p_gc_threshold modified gain of previous subframe. + * \return gain_code smoothed gain of code g_sc, exponent = SF_GAIN_C. + */ +static FIXP_DBL +noise_enhancer(/* (o) : smoothed gain g_sc SF_GAIN_C */ + FIXP_DBL gain_code, /* (i) : Quantized codebook gain SF_GAIN_C */ + FIXP_DBL period_fac, /* (i) : periodicity factor (-1=unvoiced to + 1=voiced), SF_PFAC */ + FIXP_SGL stab_fac, /* (i) : stability factor (0 <= ... < 1.0) + SF_STAB */ + FIXP_DBL + *p_gc_threshold) /* (io): gain of code threshold SF_GAIN_C */ +{ + FIXP_DBL fac, L_tmp, gc_thres; + + gc_thres = *p_gc_threshold; + + L_tmp = gain_code; + if (L_tmp < gc_thres) { + L_tmp += fMultDiv2(gain_code, + FL2FXCONST_SGL(2.0 * 0.19f)); /* +1.5dB => *(1.0+0.19) */ + if (L_tmp > gc_thres) { + L_tmp = gc_thres; + } + } else { + L_tmp = fMult(gain_code, + FL2FXCONST_SGL(1.0f / 1.19f)); /* -1.5dB => *10^(-1.5/20) */ + if (L_tmp < gc_thres) { + L_tmp = gc_thres; + } + } + *p_gc_threshold = L_tmp; + + /* voicing factor lambda = 0.5*(1-period_fac) */ + /* gain smoothing factor S_m = lambda*stab_fac (=fac) + = 0.5(stab_fac - stab_fac * period_fac) */ + fac = (FX_SGL2FX_DBL(stab_fac) >> (SF_PFAC + 1)) - + fMultDiv2(stab_fac, period_fac); + /* fac_e = SF_PFAC + SF_STAB */ + FDK_ASSERT(fac >= (FIXP_DBL)0); + + /* gain_code = (float)((fac*tmp) + ((1.0-fac)*gain_code)); */ + gain_code = fMult(fac, L_tmp) - + fMult(FL2FXCONST_DBL(-1.0f / (1 << (SF_PFAC + SF_STAB))) + fac, + gain_code); + gain_code <<= (SF_PFAC + SF_STAB); + + return gain_code; +} + +/** + * \brief Update adaptive codebook u'(n) (exc) + * Enhance pitch of c(n) and build post-processed excitation u(n) (exc2) + * \param[in] code innovative codevector c(n), exponent = SF_CODE. + * \param[in,out] exc filtered adaptive codebook v(n), exponent = SF_EXC. + * \param[in] gain_pit adaptive codebook gain, exponent = SF_GAIN_P. + * \param[in] gain_code innovative codebook gain g_c, exponent = SF_GAIN_C. + * \param[in] gain_code_smoothed smoothed innov. codebook gain g_sc, exponent = + * SF_GAIN_C. + * \param[in] period_fac periodicity factor r_v, exponent = SF_PFAC. + * \param[out] exc2 post-processed excitation u(n), exponent = SF_EXC. + */ +void BuildAdaptiveExcitation( + FIXP_COD code[], /* (i) : algebraic codevector c(n) Q9 */ + FIXP_DBL exc[], /* (io): filtered adaptive codebook v(n) Q15 */ + FIXP_SGL gain_pit, /* (i) : adaptive codebook gain g_p Q14 */ + FIXP_DBL gain_code, /* (i) : innovative codebook gain g_c Q16 */ + FIXP_DBL gain_code_smoothed, /* (i) : smoothed innov. codebook gain g_sc + Q16 */ + FIXP_DBL period_fac, /* (i) : periodicity factor r_v Q15 */ + FIXP_DBL exc2[] /* (o) : post-processed excitation u(n) Q15 */ +) { +/* Note: code[L_SUBFR] and exc2[L_SUBFR] share the same memory! + If exc2[i] is written, code[i] will be destroyed! +*/ +#define SF (SF_CODE + SF_GAIN_C + 1 - SF_EXC) + + int i; + FIXP_DBL tmp, cpe, code_smooth_prev, code_smooth; + + FIXP_COD code_i; + FIXP_DBL cpe_code_smooth, cpe_code_smooth_prev; + + /* cpe = (1+r_v)/8 * 2 ; ( SF = -1) */ + cpe = (period_fac >> (2 - SF_PFAC)) + FL2FXCONST_DBL(0.25f); + + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1); /* v(0)*g_p */ + *exc++ = tmp + (fMultDiv2(code[0], gain_code) << SF); + + /* u(n) */ + code_smooth_prev = fMultDiv2(*code++, gain_code_smoothed) + << SF; /* c(0) * g_sc */ + code_i = *code++; + code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; /* c(1) * g_sc */ + tmp += code_smooth_prev; /* tmp = v(0)*g_p + c(0)*g_sc */ + cpe_code_smooth = fMultDiv2(cpe, code_smooth); + *exc2++ = tmp - cpe_code_smooth; + cpe_code_smooth_prev = fMultDiv2(cpe, code_smooth_prev); + + i = L_SUBFR - 2; + do /* ARM926: 22 cycles per iteration */ + { + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1); + *exc++ = tmp + (fMultDiv2(code_i, gain_code) << SF); + /* u(n) */ + tmp += code_smooth; /* += g_sc * c(i) */ + tmp -= cpe_code_smooth_prev; + cpe_code_smooth_prev = cpe_code_smooth; + code_i = *code++; + code_smooth = fMultDiv2(code_i, gain_code_smoothed) << SF; + cpe_code_smooth = fMultDiv2(cpe, code_smooth); + *exc2++ = tmp - cpe_code_smooth; /* tmp - c_pe * g_sc * c(i+1) */ + } while (--i != 0); + + /* u'(n) */ + tmp = fMultDiv2(*exc, gain_pit) << (SF_GAIN_P + 1); + *exc = tmp + (fMultDiv2(code_i, gain_code) << SF); + /* u(n) */ + tmp += code_smooth; + tmp -= cpe_code_smooth_prev; + *exc2++ = tmp; + + return; +} + +/** + * \brief Interpolate LPC vector in LSP domain for current subframe and convert + * to LP domain + * \param[in] lsp_old LPC vector (LSP domain) corresponding to the beginning of + * current ACELP frame. + * \param[in] lsp_new LPC vector (LSP domain) corresponding to the end of + * current ACELP frame. + * \param[in] subfr_nr number of current ACELP subframe 0..3. + * \param[in] nb_subfr total number of ACELP subframes in this frame. + * \param[out] A LP filter coefficients for current ACELP subframe, exponent = + * SF_A_COEFFS. + */ +/* static */ +void int_lpc_acelp( + const FIXP_LPC lsp_old[], /* input : LSPs from past frame */ + const FIXP_LPC lsp_new[], /* input : LSPs from present frame */ + int subfr_nr, int nb_subfr, + FIXP_LPC + A[], /* output: interpolated LP coefficients for current subframe */ + INT *A_exp) { + int i; + FIXP_LPC lsp_interpol[M_LP_FILTER_ORDER]; + FIXP_SGL fac_old, fac_new; + + FDK_ASSERT((nb_subfr == 3) || (nb_subfr == 4)); + + fac_old = lsp_interpol_factor[nb_subfr & 0x1][(nb_subfr - 1) - subfr_nr]; + fac_new = lsp_interpol_factor[nb_subfr & 0x1][subfr_nr]; + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp_interpol[i] = FX_DBL2FX_LPC( + (fMultDiv2(lsp_old[i], fac_old) + fMultDiv2(lsp_new[i], fac_new)) << 1); + } + + E_LPC_f_lsp_a_conversion(lsp_interpol, A, A_exp); + + return; +} + +/** + * \brief Perform LP synthesis by filtering the post-processed excitation u(n) + * through the LP synthesis filter 1/A(z) + * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS. + * \param[in] length length of input/output signal. + * \param[in] x post-processed excitation u(n). + * \param[in,out] y LP synthesis signal and filter memory + * y[-M_LP_FILTER_ORDER..-1]. + */ + +/* static */ +void Syn_filt(const FIXP_LPC a[], /* (i) : a[m] prediction coefficients Q12 */ + const INT a_exp, + INT length, /* (i) : length of input/output signal (64|128) */ + FIXP_DBL x[], /* (i) : input signal Qx */ + FIXP_DBL y[] /* (i/o) : filter states / output signal Qx-s*/ +) { + int i, j; + FIXP_DBL L_tmp; + + for (i = 0; i < length; i++) { + L_tmp = (FIXP_DBL)0; + + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + L_tmp -= fMultDiv2(a[j], y[i - (j + 1)]) >> (LP_FILTER_SCALE - 1); + } + + L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE); + y[i] = fAddSaturate(L_tmp, x[i]); + } + + return; +} + +/** + * \brief Calculate de-emphasis 1/(1 - mu z^-1) on input signal. + * \param[in] x input signal. + * \param[out] y output signal. + * \param[in] L length of signal. + * \param[in,out] mem memory (signal[-1]). + */ +/* static */ +void Deemph(FIXP_DBL *x, FIXP_DBL *y, int L, FIXP_DBL *mem) { + int i; + FIXP_DBL yi = *mem; + + for (i = 0; i < L; i++) { + FIXP_DBL xi = x[i] >> 1; + xi = fMultAddDiv2(xi, PREEMPH_FAC, yi); + yi = SATURATE_LEFT_SHIFT(xi, 1, 32); + y[i] = yi; + } + *mem = yi; + return; +} + +/** + * \brief Compute the LP residual by filtering the input speech through the + * analysis filter A(z). + * \param[in] a LP filter coefficients, exponent = SF_A_COEFFS + * \param[in] x input signal (note that values x[-m..-1] are needed), exponent = + * SF_SYNTH + * \param[out] y output signal (residual), exponent = SF_EXC + * \param[in] l length of filtering + */ +/* static */ +void E_UTIL_residu(const FIXP_LPC *a, const INT a_exp, FIXP_DBL *x, FIXP_DBL *y, + INT l) { + FIXP_DBL s; + INT i, j; + + /* (note that values x[-m..-1] are needed) */ + for (i = 0; i < l; i++) { + s = (FIXP_DBL)0; + + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + s += fMultDiv2(a[j], x[i - j - 1]) >> (LP_FILTER_SCALE - 1); + } + + s = scaleValue(s, a_exp + LP_FILTER_SCALE); + y[i] = fAddSaturate(s, x[i]); + } + + return; +} + +/* use to map subfr number to number of bits used for acb_index */ +static const UCHAR num_acb_idx_bits_table[2][NB_SUBFR] = { + {9, 6, 9, 6}, /* coreCoderFrameLength == 1024 */ + {9, 6, 6, 0} /* coreCoderFrameLength == 768 */ +}; + +static int DecodePitchLag(HANDLE_FDK_BITSTREAM hBs, + const UCHAR num_acb_idx_bits, + const int PIT_MIN, /* TMIN */ + const int PIT_FR2, /* TFR2 */ + const int PIT_FR1, /* TFR1 */ + const int PIT_MAX, /* TMAX */ + int *pT0, int *pT0_frac, int *pT0_min, int *pT0_max) { + int acb_idx; + int error = 0; + int T0, T0_frac; + + FDK_ASSERT((num_acb_idx_bits == 9) || (num_acb_idx_bits == 6)); + + acb_idx = FDKreadBits(hBs, num_acb_idx_bits); + + if (num_acb_idx_bits == 6) { + /* When the pitch value is encoded on 6 bits, a pitch resolution of 1/4 is + always used in the range [T1-8, T1+7.75], where T1 is nearest integer to + the fractional pitch lag of the previous subframe. + */ + T0 = *pT0_min + acb_idx / 4; + T0_frac = acb_idx & 0x3; + } else { /* num_acb_idx_bits == 9 */ + /* When the pitch value is encoded on 9 bits, a fractional pitch delay is + used with resolutions 0.25 in the range [TMIN, TFR2-0.25], resolutions + 0.5 in the range [TFR2, TFR1-0.5], and integers only in the range [TFR1, + TMAX]. NOTE: for small sampling rates TMAX can get smaller than TFR1. + */ + int T0_min, T0_max; + + if (acb_idx < (PIT_FR2 - PIT_MIN) * 4) { + /* first interval with 0.25 pitch resolution */ + T0 = PIT_MIN + (acb_idx / 4); + T0_frac = acb_idx & 0x3; + } else if (acb_idx < ((PIT_FR2 - PIT_MIN) * 4 + (PIT_FR1 - PIT_FR2) * 2)) { + /* second interval with 0.5 pitch resolution */ + acb_idx -= (PIT_FR2 - PIT_MIN) * 4; + T0 = PIT_FR2 + (acb_idx / 2); + T0_frac = (acb_idx & 0x1) * 2; + } else { + /* third interval with 1.0 pitch resolution */ + T0 = acb_idx + PIT_FR1 - ((PIT_FR2 - PIT_MIN) * 4) - + ((PIT_FR1 - PIT_FR2) * 2); + T0_frac = 0; + } + /* find T0_min and T0_max for subframe 1 or 3 */ + T0_min = T0 - 8; + if (T0_min < PIT_MIN) { + T0_min = PIT_MIN; + } + T0_max = T0_min + 15; + if (T0_max > PIT_MAX) { + T0_max = PIT_MAX; + T0_min = T0_max - 15; + } + *pT0_min = T0_min; + *pT0_max = T0_max; + } + *pT0 = T0; + *pT0_frac = T0_frac; + + return error; +} +static void ConcealPitchLag(CAcelpStaticMem *acelp_mem, const int PIT_MAX, + int *pT0, int *pT0_frac) { + USHORT *pold_T0 = &acelp_mem->old_T0; + UCHAR *pold_T0_frac = &acelp_mem->old_T0_frac; + + if ((int)*pold_T0 >= PIT_MAX) { + *pold_T0 = (UCHAR)(PIT_MAX - 5); + } + *pT0 = (int)*pold_T0; + *pT0_frac = (int)*pold_T0_frac; +} + +static UCHAR tab_coremode2nbits[8] = {20, 28, 36, 44, 52, 64, 12, 16}; + +static int MapCoreMode2NBits(int core_mode) { + return (int)tab_coremode2nbits[core_mode]; +} + +void CLpd_AcelpDecode(CAcelpStaticMem *acelp_mem, INT i_offset, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + FIXP_SGL stab_fac, CAcelpChannelData *pAcelpData, + INT numLostSubframes, int lastLpcLost, int frameCnt, + FIXP_DBL synth[], int pT[], FIXP_DBL *pit_gain, + INT coreCoderFrameLength) { + int i_subfr, subfr_nr, l_div, T; + int T0 = -1, T0_frac = -1; /* mark invalid */ + + int pit_gain_index = 0; + + const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset); /* maximum pitch lag */ + + FIXP_COD *code; + FIXP_DBL *exc2; + FIXP_DBL *syn; + FIXP_DBL *exc; + FIXP_LPC A[M_LP_FILTER_ORDER]; + INT A_exp; + + FIXP_DBL period_fac; + FIXP_SGL gain_pit; + FIXP_DBL gain_code, gain_code_smooth, Ener_code; + int Ener_code_e; + int n; + int bfi = (numLostSubframes > 0) ? 1 : 0; + + C_ALLOC_SCRATCH_START( + exc_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + L_DIV + 1); /* 411 + 17 + 256 + 1 = 685 */ + C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL, + M_LP_FILTER_ORDER + L_DIV); /* 16 + 256 = 272 */ + /* use same memory for code[L_SUBFR] and exc2[L_SUBFR] */ + C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_SUBFR); /* 64 */ + /* make sure they don't overlap if they are accessed alternatingly in + * BuildAdaptiveExcitation() */ +#if (COD_BITS == FRACT_BITS) + code = (FIXP_COD *)(tmp_buf + L_SUBFR / 2); +#elif (COD_BITS == DFRACT_BITS) + code = (FIXP_COD *)tmp_buf; +#endif + exc2 = (FIXP_DBL *)tmp_buf; + + syn = syn_buf + M_LP_FILTER_ORDER; + exc = exc_buf + PIT_MAX_MAX + L_INTERPOL; + + FDKmemcpy(syn_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemcpy(exc_buf, acelp_mem->old_exc_mem, + (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + + FDKmemclear(exc_buf + (PIT_MAX_MAX + L_INTERPOL), + (L_DIV + 1) * sizeof(FIXP_DBL)); + + l_div = coreCoderFrameLength / NB_DIV; + + for (i_subfr = 0, subfr_nr = 0; i_subfr < l_div; + i_subfr += L_SUBFR, subfr_nr++) { + /*-------------------------------------------------* + * - Decode pitch lag (T0 and T0_frac) * + *-------------------------------------------------*/ + if (bfi) { + ConcealPitchLag(acelp_mem, PIT_MAX, &T0, &T0_frac); + } else { + T0 = (int)pAcelpData->T0[subfr_nr]; + T0_frac = (int)pAcelpData->T0_frac[subfr_nr]; + } + + /*-------------------------------------------------* + * - Find the pitch gain, the interpolation filter * + * and the adaptive codebook vector. * + *-------------------------------------------------*/ + Pred_lt4(&exc[i_subfr], T0, T0_frac); + + if ((!bfi && pAcelpData->ltp_filtering_flag[subfr_nr] == 0) || + (bfi && numLostSubframes == 1 && stab_fac < FL2FXCONST_SGL(0.25f))) { + /* find pitch excitation with lp filter: v'(n) => v(n) */ + Pred_lt4_postfilter(&exc[i_subfr]); + } + + /*-------------------------------------------------------* + * - Decode innovative codebook. * + * - Add the fixed-gain pitch contribution to code[]. * + *-------------------------------------------------------*/ + if (bfi) { + for (n = 0; n < L_SUBFR; n++) { + code[n] = + FX_SGL2FX_COD((FIXP_SGL)E_UTIL_random(&acelp_mem->seed_ace)) >> 4; + } + } else { + int nbits = MapCoreMode2NBits((int)pAcelpData->acelp_core_mode); + D_ACELP_decode_4t64(pAcelpData->icb_index[subfr_nr], nbits, &code[0]); + } + + T = T0; + if (T0_frac > 2) { + T += 1; + } + + Preemph_code(code); + Pit_shrp(code, T); + + /* Output pitch lag for bass post-filter */ + if (T > PIT_MAX) { + pT[subfr_nr] = PIT_MAX; + } else { + pT[subfr_nr] = T; + } + D_gain2_plus( + pAcelpData->gains[subfr_nr], + code, /* (i) : Innovative code vector, exponent = SF_CODE */ + &gain_pit, /* (o) : Quantized pitch gain, exponent = SF_GAIN_P */ + &gain_code, /* (o) : Quantized codebook gain */ + pAcelpData + ->mean_energy, /* (i) : mean_ener defined in open-loop (2 bits) */ + bfi, &acelp_mem->past_gpit, &acelp_mem->past_gcode, + &Ener_code, /* (o) : Innovative code vector energy */ + &Ener_code_e); /* (o) : Innovative code vector energy exponent */ + + pit_gain[pit_gain_index++] = FX_SGL2FX_DBL(gain_pit); + + /* calc periodicity factor r_v */ + period_fac = + calc_period_factor(/* (o) : factor (-1=unvoiced to 1=voiced) */ + &exc[i_subfr], /* (i) : pitch excitation, exponent = + SF_EXC */ + gain_pit, /* (i) : gain of pitch, exponent = + SF_GAIN_P */ + gain_code, /* (i) : gain of code */ + Ener_code, /* (i) : Energy of code[] */ + Ener_code_e); /* (i) : Exponent of energy of code[] + */ + + if (lastLpcLost && frameCnt == 0) { + if (gain_pit > FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P))) { + gain_pit = FL2FXCONST_SGL(1.0f / (1 << SF_GAIN_P)); + } + } + + gain_code_smooth = + noise_enhancer(/* (o) : smoothed gain g_sc exponent = SF_GAIN_C */ + gain_code, /* (i) : Quantized codebook gain */ + period_fac, /* (i) : periodicity factor (-1=unvoiced to + 1=voiced) */ + stab_fac, /* (i) : stability factor (0 <= ... < 1), + exponent = 1 */ + &acelp_mem->gc_threshold); + + /* Compute adaptive codebook update u'(n), pitch enhancement c'(n) and + * post-processed excitation u(n). */ + BuildAdaptiveExcitation(code, exc + i_subfr, gain_pit, gain_code, + gain_code_smooth, period_fac, exc2); + + /* Interpolate filter coeffs for current subframe in lsp domain and convert + * to LP domain */ + int_lpc_acelp(lsp_old, /* input : LSPs from past frame */ + lsp_new, /* input : LSPs from present frame */ + subfr_nr, /* input : ACELP subframe index */ + coreCoderFrameLength / L_DIV, + A, /* output: LP coefficients of this subframe */ + &A_exp); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + exc2, /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + } /* end of subframe loop */ + + /* update pitch value for bfi procedure */ + acelp_mem->old_T0_frac = T0_frac; + acelp_mem->old_T0 = T0; + + /* save old excitation and old synthesis memory for next ACELP frame */ + FDKmemcpy(acelp_mem->old_exc_mem, exc + l_div - (PIT_MAX_MAX + L_INTERPOL), + sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL)); + FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + l_div, + sizeof(FIXP_DBL) * M_LP_FILTER_ORDER); + + Deemph(syn, synth, l_div, + &acelp_mem->de_emph_mem); /* ref soft: mem = synth[-1] */ + + scaleValues(synth, l_div, -ACELP_OUTSCALE); + acelp_mem->deemph_mem_wsyn = acelp_mem->de_emph_mem; + + C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_SUBFR); + C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV); + C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV + 1); + return; +} + +void CLpd_AcelpReset(CAcelpStaticMem *acelp) { + acelp->gc_threshold = (FIXP_DBL)0; + + acelp->past_gpit = (FIXP_SGL)0; + acelp->past_gcode = (FIXP_DBL)0; + acelp->old_T0 = 64; + acelp->old_T0_frac = 0; + acelp->deemph_mem_wsyn = (FIXP_DBL)0; + acelp->wsyn_rms = (FIXP_DBL)0; + acelp->seed_ace = 0; +} + +/* TCX time domain concealment */ +/* Compare to figure 13a on page 54 in 3GPP TS 26.290 */ +void CLpd_TcxTDConceal(CAcelpStaticMem *acelp_mem, SHORT *pitch, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + const FIXP_SGL stab_fac, INT nLostSf, FIXP_DBL synth[], + INT coreCoderFrameLength, UCHAR last_tcx_noise_factor) { + /* repeat past excitation with pitch from previous decoded TCX frame */ + C_ALLOC_SCRATCH_START( + exc_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + L_DIV); /* 411 + 17 + 256 + 1 = */ + C_ALLOC_SCRATCH_START(syn_buf, FIXP_DBL, + M_LP_FILTER_ORDER + L_DIV); /* 256 + 16 = */ + /* += */ + FIXP_DBL ns_buf[L_DIV + 1]; + FIXP_DBL *syn = syn_buf + M_LP_FILTER_ORDER; + FIXP_DBL *exc = exc_buf + PIT_MAX_MAX + L_INTERPOL; + FIXP_DBL *ns = ns_buf + 1; + FIXP_DBL tmp, fact_exc; + INT T = fMin(*pitch, (SHORT)PIT_MAX_MAX); + int i, i_subfr, subfr_nr; + int lDiv = coreCoderFrameLength / NB_DIV; + + FDKmemcpy(syn_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemcpy(exc_buf, acelp_mem->old_exc_mem, + (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + + /* if we lost all packets (i.e. 1 packet of TCX-20 ms, 2 packets of + the TCX-40 ms or 4 packets of the TCX-80ms), we lost the whole + coded frame extrapolation strategy: repeat lost excitation and + use extrapolated LSFs */ + + /* AMR-WB+ like TCX TD concealment */ + + /* number of lost frame cmpt */ + if (nLostSf < 2) { + fact_exc = FL2FXCONST_DBL(0.8f); + } else { + fact_exc = FL2FXCONST_DBL(0.4f); + } + + /* repeat past excitation */ + for (i = 0; i < lDiv; i++) { + exc[i] = fMult(fact_exc, exc[i - T]); + } + + tmp = fMult(fact_exc, acelp_mem->wsyn_rms); + acelp_mem->wsyn_rms = tmp; + + /* init deemph_mem_wsyn */ + acelp_mem->deemph_mem_wsyn = exc[-1]; + + ns[-1] = acelp_mem->deemph_mem_wsyn; + + for (i_subfr = 0, subfr_nr = 0; i_subfr < lDiv; + i_subfr += L_SUBFR, subfr_nr++) { + FIXP_DBL tRes[L_SUBFR]; + FIXP_LPC A[M_LP_FILTER_ORDER]; + INT A_exp; + + /* interpolate LPC coefficients */ + int_lpc_acelp(lsp_old, lsp_new, subfr_nr, lDiv / L_SUBFR, A, &A_exp); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + &exc[i_subfr], /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + E_LPC_a_weight( + A, A, + M_LP_FILTER_ORDER); /* overwrite A as it is not needed any longer */ + + E_UTIL_residu(A, A_exp, &syn[i_subfr], tRes, L_SUBFR); + + Deemph(tRes, &ns[i_subfr], L_SUBFR, &acelp_mem->deemph_mem_wsyn); + + /* Amplitude limiter (saturate at wsyn_rms) */ + for (i = i_subfr; i < i_subfr + L_SUBFR; i++) { + if (ns[i] > tmp) { + ns[i] = tmp; + } else { + if (ns[i] < -tmp) { + ns[i] = -tmp; + } + } + } + + E_UTIL_preemph(&ns[i_subfr], tRes, L_SUBFR); + + Syn_filt(A, /* (i) : a[m] prediction coefficients */ + A_exp, L_SUBFR, /* (i) : length */ + tRes, /* (i) : input signal */ + &syn[i_subfr] /* (i/o) : filter states / output signal */ + ); + + FDKmemmove(&synth[i_subfr], &syn[i_subfr], L_SUBFR * sizeof(FIXP_DBL)); + } + + /* save old excitation and old synthesis memory for next ACELP frame */ + FDKmemcpy(acelp_mem->old_exc_mem, exc + lDiv - (PIT_MAX_MAX + L_INTERPOL), + sizeof(FIXP_DBL) * (PIT_MAX_MAX + L_INTERPOL)); + FDKmemcpy(acelp_mem->old_syn_mem, syn_buf + lDiv, + sizeof(FIXP_DBL) * M_LP_FILTER_ORDER); + acelp_mem->de_emph_mem = acelp_mem->deemph_mem_wsyn; + + C_ALLOC_SCRATCH_END(syn_buf, FIXP_DBL, M_LP_FILTER_ORDER + L_DIV); + C_ALLOC_SCRATCH_END(exc_buf, FIXP_DBL, PIT_MAX_MAX + L_INTERPOL + L_DIV); +} + +void Acelp_PreProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, FIXP_DBL *pit_gain, + FIXP_DBL *old_gain_pf, INT samplingRate, INT *i_offset, + INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr) { + int n; + + /* init beginning of synth_buf with old synthesis from previous frame */ + FDKmemcpy(synth_buf, old_synth, sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY)); + + /* calculate pitch lag offset for ACELP decoder */ + *i_offset = + (samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM - + PIT_MIN_12k8; + + /* for bass postfilter */ + for (n = 0; n < synSfd; n++) { + pitch[n] = old_T_pf[n]; + pit_gain[n] = old_gain_pf[n]; + } + for (n = 0; n < nbSubfrSuperfr; n++) { + pitch[n + synSfd] = L_SUBFR; + pit_gain[n + synSfd] = (FIXP_DBL)0; + } +} + +void Acelp_PostProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr) { + int n; + + /* store last part of synth_buf (which is not handled by the IMDCT overlap) + * for next frame */ + FDKmemcpy(old_synth, synth_buf + coreCoderFrameLength, + sizeof(FIXP_DBL) * (PIT_MAX_MAX - BPF_DELAY)); + + /* for bass postfilter */ + for (n = 0; n < synSfd; n++) { + old_T_pf[n] = pitch[nbSubfrSuperfr + n]; + } +} + +#define L_FAC_ZIR (LFAC) + +void CLpd_Acelp_Zir(const FIXP_LPC A[], const INT A_exp, + CAcelpStaticMem *acelp_mem, const INT length, + FIXP_DBL zir[], int doDeemph) { + C_ALLOC_SCRATCH_START(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER); + FDK_ASSERT(length <= L_FAC_ZIR); + + FDKmemcpy(tmp_buf, acelp_mem->old_syn_mem, + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + FDKmemset(tmp_buf + M_LP_FILTER_ORDER, 0, L_FAC_ZIR * sizeof(FIXP_DBL)); + + Syn_filt(A, A_exp, length, &tmp_buf[M_LP_FILTER_ORDER], + &tmp_buf[M_LP_FILTER_ORDER]); + if (!doDeemph) { + /* if last lpd mode was TD concealment, then bypass deemph */ + FDKmemcpy(zir, tmp_buf, length * sizeof(*zir)); + } else { + Deemph(&tmp_buf[M_LP_FILTER_ORDER], &zir[0], length, + &acelp_mem->de_emph_mem); + scaleValues(zir, length, -ACELP_OUTSCALE); + } + C_ALLOC_SCRATCH_END(tmp_buf, FIXP_DBL, L_FAC_ZIR + M_LP_FILTER_ORDER); +} + +void CLpd_AcelpPrepareInternalMem(const FIXP_DBL *synth, UCHAR last_lpd_mode, + UCHAR last_last_lpd_mode, + const FIXP_LPC *A_new, const INT A_new_exp, + const FIXP_LPC *A_old, const INT A_old_exp, + CAcelpStaticMem *acelp_mem, + INT coreCoderFrameLength, INT clearOldExc, + UCHAR lpd_mode) { + int l_div = + coreCoderFrameLength / NB_DIV; /* length of one ACELP/TCX20 frame */ + int l_div_partial; + FIXP_DBL *syn, *old_exc_mem; + + C_ALLOC_SCRATCH_START(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + syn = &synth_buf[M_LP_FILTER_ORDER]; + + l_div_partial = PIT_MAX_MAX + L_INTERPOL - l_div; + old_exc_mem = acelp_mem->old_exc_mem; + + if (lpd_mode == 4) { + /* Bypass Domain conversion. TCXTD Concealment does no deemphasis in the + * end. */ + FDKmemcpy( + synth_buf, &synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)], + (PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER) * sizeof(FIXP_DBL)); + /* Set deemphasis memory state for TD concealment */ + acelp_mem->deemph_mem_wsyn = scaleValueSaturate(synth[-1], ACELP_OUTSCALE); + } else { + /* convert past [PIT_MAX_MAX+L_INTERPOL+M_LP_FILTER_ORDER] synthesis to + * preemph domain */ + E_UTIL_preemph(&synth[-(PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER)], + synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + scaleValuesSaturate(synth_buf, PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER, + ACELP_OUTSCALE); + } + + /* Set deemphasis memory state */ + acelp_mem->de_emph_mem = scaleValueSaturate(synth[-1], ACELP_OUTSCALE); + + /* update acelp synth filter memory */ + FDKmemcpy(acelp_mem->old_syn_mem, + &syn[PIT_MAX_MAX + L_INTERPOL - M_LP_FILTER_ORDER], + M_LP_FILTER_ORDER * sizeof(FIXP_DBL)); + + if (clearOldExc) { + FDKmemclear(old_exc_mem, (PIT_MAX_MAX + L_INTERPOL) * sizeof(FIXP_DBL)); + C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + return; + } + + /* update past [PIT_MAX_MAX+L_INTERPOL] samples of exc memory */ + if (last_lpd_mode == 1) { /* last frame was TCX20 */ + if (last_last_lpd_mode == 0) { /* ACELP -> TCX20 -> ACELP transition */ + /* Delay valid part of excitation buffer (from previous ACELP frame) by + * l_div samples */ + FDKmemmove(old_exc_mem, old_exc_mem + l_div, + sizeof(FIXP_DBL) * l_div_partial); + } else if (last_last_lpd_mode > 0) { /* TCX -> TCX20 -> ACELP transition */ + E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, l_div_partial); + } + E_UTIL_residu(A_new, A_new_exp, syn + l_div_partial, + old_exc_mem + l_div_partial, l_div); + } else { /* prev frame was FD, TCX40 or TCX80 */ + int exc_A_new_length = (coreCoderFrameLength / 2 > PIT_MAX_MAX + L_INTERPOL) + ? PIT_MAX_MAX + L_INTERPOL + : coreCoderFrameLength / 2; + int exc_A_old_length = PIT_MAX_MAX + L_INTERPOL - exc_A_new_length; + E_UTIL_residu(A_old, A_old_exp, syn, old_exc_mem, exc_A_old_length); + E_UTIL_residu(A_new, A_new_exp, &syn[exc_A_old_length], + &old_exc_mem[exc_A_old_length], exc_A_new_length); + } + C_ALLOC_SCRATCH_END(synth_buf, FIXP_DBL, + PIT_MAX_MAX + L_INTERPOL + M_LP_FILTER_ORDER); + + return; +} + +FIXP_DBL *CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem *acelp_mem, INT length) { + FDK_ASSERT(length <= PIT_MAX_MAX + L_INTERPOL); + return acelp_mem->old_exc_mem; +} + +INT CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs, CAcelpChannelData *acelp, + INT acelp_core_mode, INT coreCoderFrameLength, + INT i_offset) { + int nb_subfr = coreCoderFrameLength / L_DIV; + const UCHAR *num_acb_index_bits = + (nb_subfr == 4) ? num_acb_idx_bits_table[0] : num_acb_idx_bits_table[1]; + int nbits; + int error = 0; + + const int PIT_MIN = PIT_MIN_12k8 + i_offset; + const int PIT_FR2 = PIT_FR2_12k8 - i_offset; + const int PIT_FR1 = PIT_FR1_12k8; + const int PIT_MAX = PIT_MAX_12k8 + (6 * i_offset); + int T0, T0_frac, T0_min = 0, T0_max; + + if (PIT_MAX > PIT_MAX_MAX) { + error = AAC_DEC_DECODE_FRAME_ERROR; + goto bail; + } + + acelp->acelp_core_mode = acelp_core_mode; + + nbits = MapCoreMode2NBits(acelp_core_mode); + + /* decode mean energy with 2 bits : 18, 30, 42 or 54 dB */ + acelp->mean_energy = FDKreadBits(hBs, 2); + + for (int sfr = 0; sfr < nb_subfr; sfr++) { + /* read ACB index and store T0 and T0_frac for each ACELP subframe. */ + error = DecodePitchLag(hBs, num_acb_index_bits[sfr], PIT_MIN, PIT_FR2, + PIT_FR1, PIT_MAX, &T0, &T0_frac, &T0_min, &T0_max); + if (error) { + goto bail; + } + acelp->T0[sfr] = (USHORT)T0; + acelp->T0_frac[sfr] = (UCHAR)T0_frac; + acelp->ltp_filtering_flag[sfr] = FDKreadBits(hBs, 1); + switch (nbits) { + case 12: /* 12 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 16: /* 16 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 1); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 20: /* 20 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 28: /* 28 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 5); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 5); + break; + case 36: /* 36 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9); + break; + case 44: /* 44 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 9); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 9); + break; + case 52: /* 52 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 13); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 13); + break; + case 64: /* 64 bits AMR-WB codebook is used */ + acelp->icb_index[sfr][0] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][1] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][2] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][3] = FDKreadBits(hBs, 2); + acelp->icb_index[sfr][4] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][5] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][6] = FDKreadBits(hBs, 14); + acelp->icb_index[sfr][7] = FDKreadBits(hBs, 14); + break; + default: + FDK_ASSERT(0); + break; + } + acelp->gains[sfr] = FDKreadBits(hBs, 7); + } + +bail: + return error; +} diff --git a/fdk-aac/libAACdec/src/usacdec_acelp.h b/fdk-aac/libAACdec/src/usacdec_acelp.h new file mode 100644 index 0000000..9de41ff --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_acelp.h @@ -0,0 +1,281 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: USAC ACELP frame decoder + +*******************************************************************************/ + +#ifndef USACDEC_ACELP_H +#define USACDEC_ACELP_H + +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "usacdec_const.h" +#include "usacdec_rom.h" + +//#define ENHANCED_TCX_TD_CONCEAL_ENABLE + +/** Structure which holds the ACELP internal persistent memory */ +typedef struct { + FIXP_DBL old_exc_mem[PIT_MAX_MAX + L_INTERPOL]; + FIXP_DBL old_syn_mem[M_LP_FILTER_ORDER]; /* synthesis filter states */ + FIXP_SGL A[M_LP_FILTER_ORDER]; + INT A_exp; + FIXP_DBL gc_threshold; + FIXP_DBL de_emph_mem; + FIXP_SGL past_gpit; + FIXP_DBL past_gcode; + USHORT old_T0; + UCHAR old_T0_frac; + FIXP_DBL deemph_mem_wsyn; + FIXP_DBL wsyn_rms; + SHORT seed_ace; +} CAcelpStaticMem; + +/** Structure which holds the parameter data needed to decode one ACELP frame. + */ +typedef struct { + UCHAR + acelp_core_mode; /**< mean excitation energy index for whole ACELP frame + */ + UCHAR mean_energy; /**< acelp core mode for whole ACELP frame */ + USHORT T0[NB_SUBFR]; + UCHAR T0_frac[NB_SUBFR]; + UCHAR ltp_filtering_flag[NB_SUBFR]; /**< controlls whether LTP postfilter is + active for each ACELP subframe */ + SHORT icb_index[NB_SUBFR] + [8]; /**< innovative codebook index for each ACELP subframe */ + UCHAR gains[NB_SUBFR]; /**< gain index for each ACELP subframe */ +} CAcelpChannelData; + +/** + * \brief Read the acelp_coding() bitstream part. + * \param[in] hBs bitstream handle to read data from. + * \param[out] acelpData pointer to structure to store the parsed data of one + * ACELP frame. + * \param[in] acelp_core_mode the ACELP core mode index. + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +INT CLpd_AcelpRead(HANDLE_FDK_BITSTREAM hBs, CAcelpChannelData *acelpData, + INT acelp_core_mode, INT i_offset, INT coreCoderFrameLength); +/** + * \brief Initialization of memory before one LPD frame is decoded + * \param[out] synth_buf synthesis buffer to be initialized, exponent = SF_SYNTH + * \param[in] old_synth past synthesis of previous LPD frame, exponent = + * SF_SYNTH + * \param[out] synth_buf_fb fullband synthesis buffer to be initialized, + * exponent = SF_SYNTH + * \param[in] old_synth_fb past fullband synthesis of previous LPD frame, + * exponent = SF_SYNTH + * \param[out] pitch vector where decoded pitch lag values are stored + * \param[in] old_T_pf past pitch lag values of previous LPD frame + * \param[in] samplingRate sampling rate for pitch lag offset calculation + * \param[out] i_offset pitch lag offset for the decoding of the pitch lag + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void Acelp_PreProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, FIXP_DBL *pit_gain, + FIXP_DBL *old_gain_pf, INT samplingRate, INT *i_offset, + INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr); + +/** + * \brief Save tail of buffers for the initialization of the next LPD frame + * \param[in] synth_buf synthesis of current LPD frame, exponent = SF_SYNTH + * \param[out] old_synth memory where tail of fullband synth_buf is stored, + * exponent = SF_SYNTH + * \param[in] synth_buf_fb fullband synthesis of current LPD frame, exponent = + * SF_SYNTH + * \param[out] old_synth_fb memory where tail of fullband synth_buf is stored, + * exponent = SF_SYNTH + * \param[in] pitch decoded pitch lag values of current LPD frame + * \param[out] old_T_pf memory where last SYN_SFD pitch lag values are stored + */ +void Acelp_PostProcessing(FIXP_DBL *synth_buf, FIXP_DBL *old_synth, INT *pitch, + INT *old_T_pf, INT coreCoderFrameLength, INT synSfd, + INT nbSubfrSuperfr); + +/** + * \brief Decode one ACELP frame (three or four ACELP subframes with 64 samples + * each) + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] i_offset pitch lag offset + * \param[in] lsp_old LPC filter in LSP domain corresponding to previous frame + * \param[in] lsp_new LPC filter in LSP domain corresponding to current frame + * \param[in] stab_fac stability factor constrained by 0<=stab_fac<=1.0, + * exponent = SF_STAB + * \param[in] acelpData pointer to struct with data which is needed for decoding + * one ACELP frame + * \param[out] synth ACELP output signal + * \param[out] pT four decoded pitch lag values + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void CLpd_AcelpDecode(CAcelpStaticMem *acelp_mem, INT i_offset, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + FIXP_SGL stab_fac, CAcelpChannelData *acelpData, + INT numLostSubframes, int lastLpcLost, int frameCnt, + FIXP_DBL synth[], int pT[], FIXP_DBL *pit_gain, + INT coreCoderFrameLength); + +/** + * \brief Reset ACELP internal memory. + * \param[out] acelp_mem pointer to ACELP memory structure + */ +void CLpd_AcelpReset(CAcelpStaticMem *acelp_mem); + +/** + * \brief Initialize ACELP internal memory in case of FAC before ACELP decoder + * is called + * \param[in] synth points to end+1 of past valid synthesis signal, exponent = + * SF_SYNTH + * \param[in] last_lpd_mode last lpd mode + * \param[in] last_last_lpd_mode lpd mode before last_lpd_mode + * \param[in] A_new LP synthesis filter coeffs corresponding to last frame, + * exponent = SF_A_COEFFS + * \param[in] A_old LP synthesis filter coeffs corresponding to the frame before + * last frame, exponent = SF_A_COEFFS + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] coreCoderFrameLength length of core coder frame (1024|768) + */ +void CLpd_AcelpPrepareInternalMem(const FIXP_DBL *synth, UCHAR last_lpd_mode, + UCHAR last_last_lpd_mode, + const FIXP_LPC *A_new, const INT A_new_exp, + const FIXP_LPC *A_old, const INT A_old_exp, + CAcelpStaticMem *acelp_mem, + INT coreCoderFrameLength, INT clearOldExc, + UCHAR lpd_mode); + +/** + * \brief Calculate zero input response (zir) of the acelp synthesis filter + * \param[in] A LP synthesis filter coefficients, exponent = SF_A_COEFFS + * \param[in,out] acelp_mem pointer to ACELP memory structure + * \param[in] length length of zir + * \param[out] zir pointer to zir output buffer, exponent = SF_SYNTH + */ +void CLpd_Acelp_Zir(const FIXP_LPC A[], const INT A_exp, + CAcelpStaticMem *acelp_mem, const INT length, + FIXP_DBL zir[], int doDeemph); + +/** + * \brief Borrow static excitation memory from ACELP decoder + * \param[in] acelp_mem pointer to ACELP memory structure + * \param[in] length number of requested FIXP_DBL values + * \return pointer to requested memory + * + * The caller has to take care not to overwrite valid memory areas. + * During TCX/FAC calculations and before CLpd_AcelpPrepareInternalMem() is + * called, the following memory size is available: + * - 256 samples in case of ACELP -> TCX20 -> ACELP transition + * - PIT_MAX_MAX+L_INTERPOL samples in all other cases + */ +FIXP_DBL *CLpd_ACELP_GetFreeExcMem(CAcelpStaticMem *acelp_mem, INT length); + +void CLpd_TcxTDConceal(CAcelpStaticMem *acelp_mem, SHORT *pitch, + const FIXP_LPC lsp_old[M_LP_FILTER_ORDER], + const FIXP_LPC lsp_new[M_LP_FILTER_ORDER], + const FIXP_SGL stab_fac, INT numLostSubframes, + FIXP_DBL synth[], INT coreCoderFrameLength, + UCHAR last_tcx_noise_factor); + +inline SHORT E_UTIL_random(SHORT *seed) { + *seed = (SHORT)((((LONG)*seed * (LONG)31821) >> 1) + (LONG)13849); + return (*seed); +} + +#endif /* USACDEC_ACELP_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_const.h b/fdk-aac/libAACdec/src/usacdec_const.h new file mode 100644 index 0000000..f68e808 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_const.h @@ -0,0 +1,203 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC related constants + +*******************************************************************************/ + +#ifndef USACDEC_CONST_H +#define USACDEC_CONST_H + +/* scale factors */ +#define SF_CODE 6 /* exponent of code[], fixed codebook vector */ +#define SF_GAIN_C 16 /* exponent of gain code and smoothed gain code */ +#define SF_EXC 16 /* exponent of exc[] and exc2[], excitation buffer */ +#define SF_GAIN_P 1 /* exponent of gain_pit */ +#define SF_PFAC 0 /* exponent of period/voicing factor */ +#define SF_SYNTH SF_EXC /* exponent of synthesis buffer */ +#define SF_A_COEFFS 3 /* exponent of LP domain synthesis filter coefficient */ +#define SF_STAB 1 /* exponent of stability factor */ + +/* definitions which are independent of coreCoderFrameLength */ +#define M_LP_FILTER_ORDER 16 /* LP filter order */ +#define LP_FILTER_SCALE 4 /* LP filter scale */ + +#define PIT_MIN_12k8 34 /* Minimum pitch lag with resolution 1/4 */ +#define PIT_MAX_12k8 231 /* Maximum pitch lag for fs=12.8kHz */ +#define FSCALE_DENOM 12800 /* Frequency scale denominator */ +#define FAC_FSCALE_MIN \ + 6000 /* Minimum allowed frequency scale for acelp decoder */ + +#if !defined(LPD_MAX_CORE_SR) +#define LPD_MAX_CORE_SR 24000 /* Default value from ref soft */ +#endif +#define FAC_FSCALE_MAX \ + LPD_MAX_CORE_SR /* Maximum allowed frequency scale for acelp decoder */ + +/* Maximum pitch lag (= 411 for fs_max = 24000) */ +#define PIT_MAX_TMP \ + (PIT_MAX_12k8 + \ + (6 * \ + ((((FAC_FSCALE_MAX * PIT_MIN_12k8) + (FSCALE_DENOM / 2)) / FSCALE_DENOM) - \ + PIT_MIN_12k8))) +#if (PIT_MAX_TMP < \ + 256) /* cannot be smaller because of tcx time domain concealment */ +#define PIT_MAX_MAX 256 +#else +#define PIT_MAX_MAX PIT_MAX_TMP +#endif + +#define NB_DIV 4 /* number of division (20ms) per 80ms frame */ +#define L_SUBFR 64 /* subframe size (5ms) */ +#define BPF_SFD 1 /* bass postfilter delay (subframe) */ +#define BPF_DELAY (BPF_SFD * L_SUBFR) /* bass postfilter delay (samples) */ + +#define L_FILT 12 /* Delay of up-sampling filter (bass post-filter) */ +#define L_EXTRA 96 /* for bass post-filter */ +#define L_INTERPOL \ + (16 + 1) /* Length of filter for interpolation (acelp decoder) */ + +/* definitions for coreCoderFrameLength = 1024 */ +#define L_FRAME_PLUS_1024 1024 /* length of one 80ms superframe */ +#define L_DIV_1024 \ + (L_FRAME_PLUS_1024 / NB_DIV) /* length of one acelp or tcx20 frame */ +#define NB_SUBFR_1024 \ + (L_DIV_1024 / L_SUBFR) /* number of 5ms subframe per division */ +#define NB_SUBFR_SUPERFR_1024 \ + (L_FRAME_PLUS_1024 / L_SUBFR) /* number of 5ms subframe per 80ms frame */ +#define AAC_SFD_1024 (NB_SUBFR_SUPERFR_1024 / 2) /* AAC delay (subframe) */ +#define AAC_DELAY_1024 (AAC_SFD_1024 * L_SUBFR) /* AAC delay (samples) */ +#define SYN_SFD_1024 (AAC_SFD_1024 - BPF_SFD) /* synthesis delay (subframe) */ +#define SYN_DELAY_1024 \ + (SYN_SFD_1024 * L_SUBFR) /* synthesis delay (samples) \ + */ +#define LFAC_1024 (L_DIV_1024 / 2) /* FAC frame length */ +#define LFAC_SHORT_1024 \ + (L_DIV_1024 / 4) /* for transitions EIGHT_SHORT FD->LPD and vv. */ +#define FDNS_NPTS_1024 64 /* FD noise shaping resolution (64=100Hz/point) */ + +/* definitions for coreCoderFrameLength = 768 */ +#define L_FRAME_PLUS_768 768 +#define L_DIV_768 \ + (L_FRAME_PLUS_768 / NB_DIV) /* length of one acelp or tcx20 frame */ +#define NB_SUBFR_768 \ + (L_DIV_768 / L_SUBFR) /* number of 5ms subframe per division */ +#define NB_SUBFR_SUPERFR_768 \ + (L_FRAME_PLUS_768 / L_SUBFR) /* number of 5ms subframe per 80ms frame */ +#define AAC_SFD_768 (NB_SUBFR_SUPERFR_768 / 2) /* AAC delay (subframe) */ +#define AAC_DELAY_768 (AAC_SFD_768 * L_SUBFR) /* AAC delay (samples) */ +#define SYN_SFD_768 (AAC_SFD_768 - BPF_SFD) /* synthesis delay (subframe) */ +#define SYN_DELAY_768 (SYN_SFD_768 * L_SUBFR) /* synthesis delay (samples) */ +#define LFAC_768 (L_DIV_768 / 2) /* FAC frame length */ +#define LFAC_SHORT_768 \ + (L_DIV_768 / 4) /* for transitions EIGHT_SHORT FD->LPD and vv. */ + +/* maximum (used for memory allocation) */ +#define L_FRAME_PLUS L_FRAME_PLUS_1024 +#define L_DIV L_DIV_1024 +#define NB_SUBFR NB_SUBFR_1024 +#define NB_SUBFR_SUPERFR NB_SUBFR_SUPERFR_1024 +#define AAC_SFD AAC_SFD_1024 +#define AAC_DELAY AAC_DELAY_1024 +#define SYN_SFD SYN_SFD_1024 +#define SYN_DELAY SYN_DELAY_1024 +#define LFAC LFAC_1024 +#define LFAC_SHORT LFAC_SHORT_1024 +#define FDNS_NPTS FDNS_NPTS_1024 + +#endif /* USACDEC_CONST_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_fac.cpp b/fdk-aac/libAACdec/src/usacdec_fac.cpp new file mode 100644 index 0000000..0d3d844 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_fac.cpp @@ -0,0 +1,745 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC FAC + +*******************************************************************************/ + +#include "usacdec_fac.h" + +#include "usacdec_const.h" +#include "usacdec_lpc.h" +#include "usacdec_acelp.h" +#include "usacdec_rom.h" +#include "dct.h" +#include "FDK_tools_rom.h" +#include "mdct.h" + +#define SPEC_FAC(ptr, i, gl) ((ptr) + ((i) * (gl))) + +FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR mod[NB_DIV], int *pState) { + FIXP_DBL *ptr; + int i; + int k = 0; + int max_windows = 8; + + FDK_ASSERT(*pState >= 0 && *pState < max_windows); + + /* Look for free space to store FAC data. 2 FAC data blocks fit into each TCX + * spectral data block. */ + for (i = *pState; i < max_windows; i++) { + if (mod[i >> 1] == 0) { + break; + } + } + + *pState = i + 1; + + if (i == max_windows) { + ptr = pAacDecoderChannelInfo->data.usac.fac_data0; + } else { + FDK_ASSERT(mod[(i >> 1)] == 0); + ptr = SPEC_FAC(pAacDecoderChannelInfo->pSpectralCoefficient, i, + pAacDecoderChannelInfo->granuleLength << k); + } + + return ptr; +} + +int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale, + int length, int use_gain, int frame) { + FIXP_DBL fac_gain; + int fac_gain_e = 0; + + if (use_gain) { + CLpd_DecodeGain(&fac_gain, &fac_gain_e, FDKreadBits(hBs, 7)); + } + + if (CLpc_DecodeAVQ(hBs, pFac, 1, 1, length) != 0) { + return -1; + } + + { + int scale; + + scale = getScalefactor(pFac, length); + scaleValues(pFac, length, scale); + pFacScale[frame] = DFRACT_BITS - 1 - scale; + } + + if (use_gain) { + int i; + + pFacScale[frame] += fac_gain_e; + + for (i = 0; i < length; i++) { + pFac[i] = fMult(pFac[i], fac_gain); + } + } + return 0; +} + +/** + * \brief Apply synthesis filter with zero input to x. The overall filter gain + * is 1.0. + * \param a LPC filter coefficients. + * \param length length of the input/output data vector x. + * \param x input/output vector, where the synthesis filter is applied in place. + */ +static void Syn_filt_zero(const FIXP_LPC a[], const INT a_exp, INT length, + FIXP_DBL x[]) { + int i, j; + FIXP_DBL L_tmp; + + for (i = 0; i < length; i++) { + L_tmp = (FIXP_DBL)0; + + for (j = 0; j < fMin(i, M_LP_FILTER_ORDER); j++) { + L_tmp -= fMultDiv2(a[j], x[i - (j + 1)]) >> (LP_FILTER_SCALE - 1); + } + + L_tmp = scaleValue(L_tmp, a_exp + LP_FILTER_SCALE); + x[i] = fAddSaturate(x[i], L_tmp); + } +} + +/* Table is also correct for coreCoderFrameLength = 768. Factor 3/4 is canceled + out: gainFac = 0.5 * sqrt(fac_length/lFrame) +*/ +static const FIXP_DBL gainFac[4] = {0x40000000, 0x2d413ccd, 0x20000000, + 0x16a09e66}; + +void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length, + const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[], + const INT mod) { + FIXP_DBL facFactor; + int i; + + FDK_ASSERT((fac_length == 128) || (fac_length == 96)); + + /* 2) Apply gain factor to FAC data */ + facFactor = fMult(gainFac[mod], tcx_gain); + for (i = 0; i < fac_length; i++) { + fac_data[i] = fMult(fac_data[i], facFactor); + } + + /* 3) Apply spectrum deshaping using alfd_gains */ + for (i = 0; i < fac_length / 4; i++) { + int k; + + k = i >> (3 - mod); + fac_data[i] = fMult(fac_data[i], alfd_gains[k]) + << 1; /* alfd_gains is scaled by one bit. */ + } +} + +static void CFac_CalcFacSignal(FIXP_DBL *pOut, FIXP_DBL *pFac, + const int fac_scale, const int fac_length, + const FIXP_LPC A[M_LP_FILTER_ORDER], + const INT A_exp, const int fAddZir, + const int isFdFac) { + FIXP_LPC wA[M_LP_FILTER_ORDER]; + FIXP_DBL tf_gain = (FIXP_DBL)0; + int wlength; + int scale = fac_scale; + + /* obtain tranform gain. */ + imdct_gain(&tf_gain, &scale, isFdFac ? 0 : fac_length); + + /* 4) Compute inverse DCT-IV of FAC data. Output scale of DCT IV is 16 bits. + */ + dct_IV(pFac, fac_length, &scale); + /* dct_IV scale = log2(fac_length). "- 7" is a factor of 2/128 */ + if (tf_gain != (FIXP_DBL)0) { /* non-radix 2 transform gain */ + int i; + + for (i = 0; i < fac_length; i++) { + pFac[i] = fMult(tf_gain, pFac[i]); + } + } + scaleValuesSaturate(pOut, pFac, fac_length, + scale); /* Avoid overflow issues and saturate. */ + + E_LPC_a_weight(wA, A, M_LP_FILTER_ORDER); + + /* We need the output of the IIR filter to be longer than "fac_length". + For this reason we run it with zero input appended to the end of the input + sequence, i.e. we generate its ZIR and extend the output signal.*/ + FDKmemclear(pOut + fac_length, fac_length * sizeof(FIXP_DBL)); + wlength = 2 * fac_length; + + /* 5) Apply weighted synthesis filter to FAC data, including optional Zir (5. + * item 4). */ + Syn_filt_zero(wA, A_exp, wlength, pOut); +} + +INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac, + const int fac_scale, FIXP_LPC *A, INT A_exp, + INT nrOutSamples, const INT fac_length, + const INT isFdFac, UCHAR prevWindowShape) { + FIXP_DBL *pOvl; + FIXP_DBL *pOut0; + const FIXP_WTP *pWindow; + int i, fl, nrSamples = 0; + + FDK_ASSERT(fac_length <= 1024 / (4 * 2)); + + fl = fac_length * 2; + + pWindow = FDKgetWindowSlope(fl, prevWindowShape); + + /* Adapt window slope length in case of frame loss. */ + if (hMdct->prev_fr != fl) { + int nl = 0; + imdct_adapt_parameters(hMdct, &fl, &nl, fac_length, pWindow, nrOutSamples); + FDK_ASSERT(nl == 0); + } + + if (nrSamples < nrOutSamples) { + pOut0 = output; + nrSamples += hMdct->ov_offset; + /* Purge buffered output. */ + FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); + hMdct->ov_offset = 0; + } + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + + if (nrSamples >= nrOutSamples) { + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + pOut0 = output + nrSamples; + nrSamples += hMdct->prev_nr + fl / 2; + } + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } else { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = (*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } + hMdct->prev_nr = 0; + + { + if (pFac != NULL) { + /* Note: The FAC gain might have been applied directly after bit stream + * parse in this case. */ + CFac_CalcFacSignal(pOut0, pFac, fac_scale, fac_length, A, A_exp, 0, + isFdFac); + } else { + /* Clear buffer because of the overlap and ADD! */ + FDKmemclear(pOut0, fac_length * sizeof(FIXP_DBL)); + } + } + + i = 0; + + if (hMdct->prevPrevAliasSymmetry == 0) { + for (; i < fl / 2; i++) { + FIXP_DBL x0; + + /* Overlap Add */ + x0 = -fMult(*pOvl--, pWindow[i].v.re); + + *pOut0 += IMDCT_SCALE_DBL(x0); + pOut0++; + } + } else { + for (; i < fl / 2; i++) { + FIXP_DBL x0; + + /* Overlap Add */ + x0 = fMult(*pOvl--, pWindow[i].v.re); + + *pOut0 += IMDCT_SCALE_DBL(x0); + pOut0++; + } + } + if (hMdct->pFacZir != + 0) { /* this should only happen for ACELP -> TCX20 -> ACELP transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; /* fl/2 == fac_length */ + for (i = 0; i < fl / 2; i++) { + pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); + } + hMdct->pFacZir = NULL; + } + + hMdct->prev_fr = 0; + hMdct->prev_nr = 0; + hMdct->prev_tl = 0; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + + return nrSamples; +} + +INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *_pSpec, + const SHORT spec_scale[], const int nSpec, + FIXP_DBL *pFac, const int fac_scale, + const INT fac_length, INT noOutSamples, const INT tl, + const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], + INT A_exp, CAcelpStaticMem *acelp_mem, + const FIXP_DBL gain, const int last_frame_lost, + const int isFdFac, const UCHAR last_lpd_mode, + const int k, int currAliasingSymmetry) { + FIXP_DBL *pCurr, *pOvl, *pSpec; + const FIXP_WTP *pWindow; + const FIXP_WTB *FacWindowZir_conceal; + UCHAR doFacZirConceal = 0; + int doDeemph = 1; + const FIXP_WTB *FacWindowZir, *FacWindowSynth; + FIXP_DBL *pOut0 = output, *pOut1; + int w, i, fl, nl, nr, f_len, nrSamples = 0, s = 0, scale, total_gain_e; + FIXP_DBL *pF, *pFAC_and_FAC_ZIR = NULL; + FIXP_DBL total_gain = gain; + + FDK_ASSERT(fac_length <= 1024 / (4 * 2)); + switch (fac_length) { + /* coreCoderFrameLength = 1024 */ + case 128: + pWindow = SineWindow256; + FacWindowZir = FacWindowZir128; + FacWindowSynth = FacWindowSynth128; + break; + case 64: + pWindow = SineWindow128; + FacWindowZir = FacWindowZir64; + FacWindowSynth = FacWindowSynth64; + break; + case 32: + pWindow = SineWindow64; + FacWindowZir = FacWindowZir32; + FacWindowSynth = FacWindowSynth32; + break; + /* coreCoderFrameLength = 768 */ + case 96: + pWindow = SineWindow192; + FacWindowZir = FacWindowZir96; + FacWindowSynth = FacWindowSynth96; + break; + case 48: + pWindow = SineWindow96; + FacWindowZir = FacWindowZir48; + FacWindowSynth = FacWindowSynth48; + break; + default: + FDK_ASSERT(0); + return 0; + } + + FacWindowZir_conceal = FacWindowSynth; + /* Derive NR and NL */ + fl = fac_length * 2; + nl = (tl - fl) >> 1; + nr = (tl - fr) >> 1; + + if (noOutSamples > nrSamples) { + /* Purge buffered output. */ + FDKmemcpy(pOut0, hMdct->overlap.time, hMdct->ov_offset * sizeof(pOut0[0])); + nrSamples = hMdct->ov_offset; + hMdct->ov_offset = 0; + } + + if (nrSamples >= noOutSamples) { + pOut1 = hMdct->overlap.time + hMdct->ov_offset; + if (hMdct->ov_offset < fac_length) { + pOut0 = output + nrSamples; + } else { + pOut0 = pOut1; + } + hMdct->ov_offset += fac_length + nl; + } else { + pOut1 = output + nrSamples; + pOut0 = output + nrSamples; + } + + { + pFAC_and_FAC_ZIR = CLpd_ACELP_GetFreeExcMem(acelp_mem, 2 * fac_length); + { + const FIXP_DBL *pTmp1, *pTmp2; + + doFacZirConceal |= ((last_frame_lost != 0) && (k == 0)); + doDeemph &= (last_lpd_mode != 4); + if (doFacZirConceal) { + /* ACELP contribution in concealment case: + Use ZIR with a modified ZIR window to preserve some more energy. + Dont use FAC, which contains wrong information for concealed frame + Dont use last ACELP samples, but double ZIR, instead (afterwards) */ + FDKmemclear(pFAC_and_FAC_ZIR, 2 * fac_length * sizeof(FIXP_DBL)); + FacWindowSynth = (FIXP_WTB *)pFAC_and_FAC_ZIR; + FacWindowZir = FacWindowZir_conceal; + } else { + CFac_CalcFacSignal(pFAC_and_FAC_ZIR, pFac, fac_scale + s, fac_length, A, + A_exp, 1, isFdFac); + } + /* 6) Get windowed past ACELP samples and ACELP ZIR signal */ + + /* + * Get ACELP ZIR (pFac[]) and ACELP past samples (pOut0[]) and add them + * to the FAC synth signal contribution on pOut1[]. + */ + { + { + CLpd_Acelp_Zir(A, A_exp, acelp_mem, fac_length, pFac, doDeemph); + + pTmp1 = pOut0; + pTmp2 = pFac; + } + + for (i = 0, w = 0; i < fac_length; i++) { + FIXP_DBL x; + /* Div2 is compensated by table scaling */ + x = fMultDiv2(pTmp2[i], FacWindowZir[w]); + x += fMultDiv2(pTmp1[-i - 1], FacWindowSynth[w]); + x += pFAC_and_FAC_ZIR[i]; + pOut1[i] = x; + + w++; + } + } + + if (doFacZirConceal) { + /* ZIR is the only ACELP contribution, so double it */ + scaleValues(pOut1, fac_length, 1); + } + } + } + + if (nrSamples < noOutSamples) { + nrSamples += fac_length + nl; + } + + /* Obtain transform gain */ + total_gain = gain; + total_gain_e = 0; + imdct_gain(&total_gain, &total_gain_e, tl); + + /* IMDCT overlap add */ + scale = total_gain_e; + pSpec = _pSpec; + + /* Note:when comming from an LPD frame (TCX/ACELP) the previous alisaing + * symmetry must always be 0 */ + if (currAliasingSymmetry == 0) { + dct_IV(pSpec, tl, &scale); + } else { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dst_III(pSpec, tmp, tl, &scale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum */ + if (total_gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], total_gain); + } + } + int loc_scale = fixmin_I(spec_scale[0] + scale, (INT)DFRACT_BITS - 1); + scaleValuesSaturate(pSpec, tl, loc_scale); + + pOut1 += fl / 2 - 1; + pCurr = pSpec + tl - fl / 2; + + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x1; + + /* FAC signal is already on pOut1, because of that the += operator. */ + x1 = fMult(*pCurr++, pWindow[i].v.re); + FDK_ASSERT((pOut1 >= hMdct->overlap.time && + pOut1 < hMdct->overlap.time + hMdct->ov_size) || + (pOut1 >= output && pOut1 < output + 1024)); + *pOut1 += IMDCT_SCALE_DBL(-x1); + pOut1--; + } + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + + pFAC_and_FAC_ZIR += fac_length; /* set pointer to beginning of FAC ZIR */ + + if (nl == 0) { + /* save pointer to write FAC ZIR data later */ + hMdct->pFacZir = pFAC_and_FAC_ZIR; + } else { + FDK_ASSERT(nl >= fac_length); + /* FAC ZIR will be added now ... */ + hMdct->pFacZir = NULL; + } + + pF = pFAC_and_FAC_ZIR; + f_len = fac_length; + + pCurr = pSpec + tl - fl / 2 - 1; + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + /* 5) (item 4) Synthesis filter Zir component, FAC ZIR (another one). */ + if (i < f_len) { + x += *pF++; + } + + FDK_ASSERT((pOut1 >= hMdct->overlap.time && + pOut1 < hMdct->overlap.time + hMdct->ov_size) || + (pOut1 >= output && pOut1 < output + 1024)); + *pOut1 = IMDCT_SCALE_DBL(x); + pOut1++; + } + + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_wrs = wrs; + hMdct->prev_tl = tl; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasingSymmetry; + fl = fr; + nl = nr; + + pOvl = pSpec + tl / 2 - 1; + pOut0 = pOut1; + + for (w = 1; w < nSpec; w++) /* for ACELP -> FD short */ + { + const FIXP_WTP *pWindow_prev; + + /* Setup window pointers */ + pWindow_prev = hMdct->prev_wrs; + + /* Current spectrum */ + pSpec = _pSpec + w * tl; + + scale = total_gain_e; + + /* For the second, third, etc. short frames the alisaing symmetry is equal, + * either (0,0) or (1,1) */ + if (currAliasingSymmetry == 0) { + /* DCT IV of current spectrum */ + dct_IV(pSpec, tl, &scale); + } else { + dst_IV(pSpec, tl, &scale); + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum + */ + /* and de-scale current spectrum signal (time domain, no yet windowed) */ + if (total_gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], total_gain); + } + } + loc_scale = fixmin_I(spec_scale[w] + scale, (INT)DFRACT_BITS - 1); + scaleValuesSaturate(pSpec, tl, loc_scale); + + if (noOutSamples <= nrSamples) { + /* Divert output first half to overlap buffer if we already got enough + * output samples. */ + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + /* Account output samples */ + nrSamples += hMdct->prev_nr + fl / 2; + } + + /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + + if (noOutSamples <= nrSamples) { + /* Divert output second half to overlap buffer if we already got enough + * output samples. */ + pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; + hMdct->ov_offset += fl / 2 + nl; + } else { + pOut1 = pOut0 + (fl - 1); + nrSamples += fl / 2 + nl; + } + + /* output samples before window crossing point NR .. TL/2. + * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ + /* output samples after window crossing point TL/2 .. TL/2+FL/2. + * -overlap[0..FL/2] - current[TL/2..FL/2] */ + pCurr = pSpec + tl - fl / 2; + if (currAliasingSymmetry == 0) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL(x0); + *pOut1 = IMDCT_SCALE_DBL(-x1); + pOut0++; + pOut1--; + } + } else { + if (hMdct->prevPrevAliasSymmetry == 0) { + /* Jump DST II -> DST IV for the second window */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMult(&x1, &x0, *pCurr++, -*pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL(x0); + *pOut1 = IMDCT_SCALE_DBL(x1); + pOut0++; + pOut1--; + } + } else { + /* Jump DST IV -> DST IV from the second window on */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + + cplxMult(&x1, &x0, *pCurr++, *pOvl--, pWindow_prev[i]); + *pOut0 = IMDCT_SCALE_DBL(x0); + *pOut1 = IMDCT_SCALE_DBL(x1); + pOut0++; + pOut1--; + } + } + } + + if (hMdct->pFacZir != 0) { + /* add FAC ZIR of previous ACELP -> mdct transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; + FDK_ASSERT(fl / 2 <= 128); + for (i = 0; i < fl / 2; i++) { + pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); + } + hMdct->pFacZir = NULL; + } + pOut0 += (fl / 2); + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + pCurr = pSpec + tl - fl / 2 - 1; + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + *pOut1 = IMDCT_SCALE_DBL(x); + pOut1++; + } + + /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ + pOvl = pSpec + tl / 2 - 1; + + /* Previous window values. */ + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + hMdct->prev_wrs = pWindow_prev; + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasingSymmetry; + } + + /* Save overlap */ + + pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; + FDK_ASSERT(pOvl >= hMdct->overlap.time + hMdct->ov_offset); + FDK_ASSERT(tl / 2 <= hMdct->ov_size); + for (i = 0; i < tl / 2; i++) { + pOvl[i] = _pSpec[i + (w - 1) * tl]; + } + + return nrSamples; +} diff --git a/fdk-aac/libAACdec/src/usacdec_fac.h b/fdk-aac/libAACdec/src/usacdec_fac.h new file mode 100644 index 0000000..100a6fa --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_fac.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC FAC + +*******************************************************************************/ + +#ifndef USACDEC_FAC_H +#define USACDEC_FAC_H + +#include "channelinfo.h" +#include "FDK_bitstream.h" + +/** + * \brief Get the address of a memory area of the spectral data memory were the + * FAC data can be stored into. + * \param spec SPECTRAL_PTR pointing to the current spectral data. + * \param mod the current LPD mod array. + * \param pState pointer to a private state variable which must be 0 for the + * first call and not changed externally. + * \param isFullbandLPD is 1 if fullband LPD mode is on, otherwise it is 0. + */ +FIXP_DBL *CLpd_FAC_GetMemory(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + UCHAR mod[NB_SUBFR], int *pState); + +/** + * \brief read a fac bitstream data block. + * \param hBs a bit stream handle, where the fac bitstream data is located. + * \param pFac pointer to were the FAC data will be stored into. + * \param pFacScale pointer to were the FAC data scale value will be stored + * into. + * \param tcx_gain value to be used as FAC gain. If zero, read fac_gain from + * bitstream. + * \param tcx_gain_e exponen value of tcx_gain. + * \param frame the subframe to be considered from the current superframe. + * Always 0 for FD case. + * \return 0 on success, -1 on error. + */ +int CLpd_FAC_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pFac, SCHAR *pFacScale, + int length, int use_gain, int frame); + +/** + * \brief Apply TCX and ALFD gains to FAC data. + * \param fac_data pointer to FAC data. + * \param fac_length FAC length (128 or 96). + * \param tcx_gain TCX gain + * \param alfd_gains pointer to alfd gains. + * \param mod mod value (1,2,3) of TCX frame where the FAC signal needs to be + * applied. + */ +void CFac_ApplyGains(FIXP_DBL fac_data[LFAC], const INT fac_length, + const FIXP_DBL tcx_gain, const FIXP_DBL alfd_gains[], + const INT mod); + +/** + * \brief Do FAC transition from frequency domain to ACELP domain. + */ +INT CLpd_FAC_Mdct2Acelp(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pFac_data, + const int fac_data_e, FIXP_LPC *A, INT A_exp, + INT nrOutSamples, const INT fac_length, + const INT isFdFac, UCHAR prevWindowShape); + +/** + * \brief Do FAC transition from ACELP domain to frequency domain. + * \param hMdct MDCT context. + * \param output pointer for time domain output. + * \param pSpec pointer to MDCT spectrum input. + * \param spec_scale MDCT spectrum exponents. + * \param nSpec amount of contiguos MDCT spectra. + * \param pFac pointer to FAC MDCT domain data. + * \param fac_scale exponent of FAC data. + * \param fac_length length of FAC data. + * \param nrSamples room in samples in output buffer. + * \param tl MDCT transform length of pSpec. + * \param wrs right MDCT window slope. + * \param fr right MDCT window slope length. + * \param A LP domain filter coefficients. + * \param deemph_mem deemphasis filter state. + * \param gain gain to be applied to FAC data before overlap add. + * \param old_syn_mem Synthesis filter state. + * \param isFdFac indicates fac processing from or to FD. + * \param pFacData fac data stored for fullband LPD. + * \param elFlags element specific parser guidance flags. + * \param isFacForFullband indicates that fac is processed for fullband LPD. + */ +INT CLpd_FAC_Acelp2Mdct(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *pSpec, + const SHORT spec_scale[], const int nSpec, + FIXP_DBL *pFac_data, const int fac_data_e, + const INT fac_length, INT nrSamples, const INT tl, + const FIXP_WTP *wrs, const INT fr, FIXP_LPC A[16], + INT A_exp, CAcelpStaticMem *acelp_mem, + const FIXP_DBL gain, const int last_frame_lost, + const int isFdFac, const UCHAR last_lpd, const int k, + int currAliasingSymmetry); + +#endif /* USACDEC_FAC_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_lpc.cpp b/fdk-aac/libAACdec/src/usacdec_lpc.cpp new file mode 100644 index 0000000..271463f --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_lpc.cpp @@ -0,0 +1,1194 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand, Manuel Jander + + Description: USAC LPC/AVQ decode + +*******************************************************************************/ + +#include "usacdec_lpc.h" + +#include "usacdec_rom.h" +#include "FDK_trigFcts.h" + +#define NQ_MAX 36 + +/* + * Helper functions. + */ + +/** + * \brief Read unary code. + * \param hBs bitstream handle as data source. + * \return decoded value. + */ +static int get_vlclbf(HANDLE_FDK_BITSTREAM hBs) { + int result = 0; + + while (FDKreadBits(hBs, 1) && result <= NQ_MAX) { + result++; + } + return result; +} + +/** + * \brief Read bit count limited unary code. + * \param hBs bitstream handle as data source + * \param n max amount of bits to be read. + * \return decoded value. + */ +static int get_vlclbf_n(HANDLE_FDK_BITSTREAM hBs, int n) { + int result = 0; + + while (FDKreadBits(hBs, 1)) { + result++; + n--; + if (n <= 0) { + break; + } + } + + return result; +} + +/* + * Algebraic Vector Quantizer + */ + +/* ZF_SCALE must be greater than (number of FIXP_ZF)/2 + because the loss of precision caused by fPow2Div2 in RE8_PPV() */ +//#define ZF_SCALE ((NQ_MAX-3)>>1) +#define ZF_SCALE ((DFRACT_BITS / 2)) +#define FIXP_ZF FIXP_DBL +#define INT2ZF(x, s) (FIXP_ZF)((x) << (ZF_SCALE - (s))) +#define ZF2INT(x) (INT)((x) >> ZF_SCALE) + +/* 1.0 in ZF format format */ +#define ONEZF ((FIXP_ZF)INT2ZF(1, 0)) + +/* static */ +void nearest_neighbor_2D8(FIXP_ZF x[8], int y[8]) { + FIXP_ZF s, em, e[8]; + int i, j, sum; + + /* round x into 2Z^8 i.e. compute y=(y1,...,y8) such that yi = 2[xi/2] + where [.] is the nearest integer operator + in the mean time, compute sum = y1+...+y8 + */ + sum = 0; + for (i = 0; i < 8; i++) { + FIXP_ZF tmp; + /* round to ..., -2, 0, 2, ... ([-1..1[ --> 0) */ + if (x[i] < (FIXP_ZF)0) { + tmp = ONEZF - x[i]; + y[i] = -2 * ((ZF2INT(tmp)) >> 1); + } else { + tmp = ONEZF + x[i]; + y[i] = 2 * ((ZF2INT(tmp)) >> 1); + } + sum += y[i]; + } + /* check if y1+...+y8 is a multiple of 4 + if not, y is not round xj in the wrong way where j is defined by + j = arg max_i | xi -yi| + (this is called the Wagner rule) + */ + if (sum % 4) { + /* find j = arg max_i | xi -yi| */ + em = (FIXP_SGL)0; + j = 0; + for (i = 0; i < 8; i++) { + /* compute ei = xi-yi */ + e[i] = x[i] - INT2ZF(y[i], 0); + } + for (i = 0; i < 8; i++) { + /* compute |ei| = | xi-yi | */ + if (e[i] < (FIXP_ZF)0) { + s = -e[i]; + } else { + s = e[i]; + } + /* check if |ei| is maximal, if so, set j=i */ + if (em < s) { + em = s; + j = i; + } + } + /* round xj in the "wrong way" */ + if (e[j] < (FIXP_ZF)0) { + y[j] -= 2; + } else { + y[j] += 2; + } + } +} + +/*-------------------------------------------------------------- + RE8_PPV(x,y) + NEAREST NEIGHBOR SEARCH IN INFINITE LATTICE RE8 + the algorithm is based on the definition of RE8 as + RE8 = (2D8) U (2D8+[1,1,1,1,1,1,1,1]) + it applies the coset decoding of Sloane and Conway + (i) x: point in R^8 in 32-ZF_SCALE.ZF_SCALE format + (o) y: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------- +*/ +/* static */ +void RE8_PPV(FIXP_ZF x[], SHORT y[], int r) { + int i, y0[8], y1[8]; + FIXP_ZF x1[8], tmp; + FIXP_DBL e; + + /* find the nearest neighbor y0 of x in 2D8 */ + nearest_neighbor_2D8(x, y0); + /* find the nearest neighbor y1 of x in 2D8+(1,...,1) (by coset decoding) */ + for (i = 0; i < 8; i++) { + x1[i] = x[i] - ONEZF; + } + nearest_neighbor_2D8(x1, y1); + for (i = 0; i < 8; i++) { + y1[i] += 1; + } + + /* compute e0=||x-y0||^2 and e1=||x-y1||^2 */ + e = (FIXP_DBL)0; + for (i = 0; i < 8; i++) { + tmp = x[i] - INT2ZF(y0[i], 0); + e += fPow2Div2( + tmp << r); /* shift left to ensure that no fract part bits get lost. */ + tmp = x[i] - INT2ZF(y1[i], 0); + e -= fPow2Div2(tmp << r); + } + /* select best candidate y0 or y1 to minimize distortion */ + if (e < (FIXP_DBL)0) { + for (i = 0; i < 8; i++) { + y[i] = y0[i]; + } + } else { + for (i = 0; i < 8; i++) { + y[i] = y1[i]; + } + } +} + +/* table look-up of unsigned value: find i where index >= table[i] + Note: range must be >= 2, index must be >= table[0] */ +static int table_lookup(const USHORT *table, unsigned int index, int range) { + int i; + + for (i = 4; i < range; i += 4) { + if (index < table[i]) { + break; + } + } + if (i > range) { + i = range; + } + + if (index < table[i - 2]) { + i -= 2; + } + if (index < table[i - 1]) { + i--; + } + i--; + + return (i); /* index >= table[i] */ +} + +/*-------------------------------------------------------------------------- + re8_decode_rank_of_permutation(rank, xs, x) + DECODING OF THE RANK OF THE PERMUTATION OF xs + (i) rank: index (rank) of a permutation + (i) xs: signed leader in RE8 (8-dimensional integer vector) + (o) x: point in RE8 (8-dimensional integer vector) + -------------------------------------------------------------------------- + */ +static void re8_decode_rank_of_permutation(int rank, int *xs, SHORT x[8]) { + INT a[8], w[8], B, fac, fac_B, target; + int i, j; + + /* --- pre-processing based on the signed leader xs --- + - compute the alphabet a=[a[0] ... a[q-1]] of x (q elements) + such that a[0]!=...!=a[q-1] + it is assumed that xs is sorted in the form of a signed leader + which can be summarized in 2 requirements: + a) |xs[0]| >= |xs[1]| >= |xs[2]| >= ... >= |xs[7]| + b) if |xs[i]|=|xs[i-1]|, xs[i]>=xs[i+1] + where |.| indicates the absolute value operator + - compute q (the number of symbols in the alphabet) + - compute w[0..q-1] where w[j] counts the number of occurences of + the symbol a[j] in xs + - compute B = prod_j=0..q-1 (w[j]!) where .! is the factorial */ + /* xs[i], xs[i-1] and ptr_w/a*/ + j = 0; + w[j] = 1; + a[j] = xs[0]; + B = 1; + for (i = 1; i < 8; i++) { + if (xs[i] != xs[i - 1]) { + j++; + w[j] = 1; + a[j] = xs[i]; + } else { + w[j]++; + B *= w[j]; + } + } + + /* --- actual rank decoding --- + the rank of x (where x is a permutation of xs) is based on + Schalkwijk's formula + it is given by rank=sum_{k=0..7} (A_k * fac_k/B_k) + the decoding of this rank is sequential and reconstructs x[0..7] + element by element from x[0] to x[7] + [the tricky part is the inference of A_k for each k...] + */ + + if (w[0] == 8) { + for (i = 0; i < 8; i++) { + x[i] = a[0]; /* avoid fac of 40320 */ + } + } else { + target = rank * B; + fac_B = 1; + /* decode x element by element */ + for (i = 0; i < 8; i++) { + fac = fac_B * fdk_dec_tab_factorial[i]; /* fac = 1..5040 */ + j = -1; + do { + target -= w[++j] * fac; + } while (target >= 0); /* max of 30 tests / SV */ + x[i] = a[j]; + /* update rank, denominator B (B_k) and counter w[j] */ + target += w[j] * fac; /* target = fac_B*B*rank */ + fac_B *= w[j]; + w[j]--; + } + } +} + +/*-------------------------------------------------------------------------- + re8_decode_base_index(n, I, y) + DECODING OF AN INDEX IN Qn (n=0,2,3 or 4) + (i) n: codebook number (*n is an integer defined in {0,2,3,4}) + (i) I: index of c (pointer to unsigned 16-bit word) + (o) y: point in RE8 (8-dimensional integer vector) + note: the index I is defined as a 32-bit word, but only + 16 bits are required (long can be replaced by unsigned integer) + -------------------------------------------------------------------------- + */ +static void re8_decode_base_index(int *n, UINT index, SHORT y[8]) { + int i, im, t, sign_code, ka, ks, rank, leader[8]; + + if (*n < 2) { + for (i = 0; i < 8; i++) { + y[i] = 0; + } + } else { + // index = (unsigned int)*I; + /* search for the identifier ka of the absolute leader (table-lookup) + Q2 is a subset of Q3 - the two cases are considered in the same branch + */ + switch (*n) { + case 2: + case 3: + i = table_lookup(fdk_dec_I3, index, NB_LDQ3); + ka = fdk_dec_A3[i]; + break; + case 4: + i = table_lookup(fdk_dec_I4, index, NB_LDQ4); + ka = fdk_dec_A4[i]; + break; + default: + FDK_ASSERT(0); + return; + } + /* reconstruct the absolute leader */ + for (i = 0; i < 8; i++) { + leader[i] = fdk_dec_Da[ka][i]; + } + /* search for the identifier ks of the signed leader (table look-up) + (this search is focused based on the identifier ka of the absolute + leader)*/ + t = fdk_dec_Ia[ka]; + im = fdk_dec_Ns[ka]; + ks = table_lookup(fdk_dec_Is + t, index, im); + + /* reconstruct the signed leader from its sign code */ + sign_code = 2 * fdk_dec_Ds[t + ks]; + for (i = 7; i >= 0; i--) { + leader[i] *= (1 - (sign_code & 2)); + sign_code >>= 1; + } + + /* compute and decode the rank of the permutation */ + rank = index - fdk_dec_Is[t + ks]; /* rank = index - cardinality offset */ + + re8_decode_rank_of_permutation(rank, leader, y); + } + return; +} + +/* re8_y2k(y,m,k) + VORONOI INDEXING (INDEX DECODING) k -> y + (i) k: Voronoi index k[0..7] + (i) m: Voronoi modulo (m = 2^r = 1<=2) + (i) r: Voronoi order (m = 2^r = 1<=2) + (o) y: 8-dimensional point y[0..7] in RE8 + */ +static void re8_k2y(int *k, int r, SHORT *y) { + int i, tmp, sum; + SHORT v[8]; + FIXP_ZF zf[8]; + + FDK_ASSERT(r <= ZF_SCALE); + + /* compute y = k M and z=(y-a)/m, where + M = [4 ] + [2 2 ] + [| \ ] + [2 2 ] + [1 1 _ 1 1] + a=(2,0,...,0) + m = 1<= 1; i--) { + tmp = 2 * k[i]; + sum += tmp; + y[i] += tmp; + zf[i] = INT2ZF(y[i], r); + } + y[0] += (4 * k[0] + sum); + zf[0] = INT2ZF(y[0] - 2, r); + /* find nearest neighbor v of z in infinite RE8 */ + RE8_PPV(zf, v, r); + /* compute y -= m v */ + for (i = 0; i < 8; i++) { + y[i] -= (SHORT)(v[i] << r); + } +} + +/*-------------------------------------------------------------------------- + RE8_dec(n, I, k, y) + MULTI-RATE INDEXING OF A POINT y in THE LATTICE RE8 (INDEX DECODING) + (i) n: codebook number (*n is an integer defined in {0,2,3,4,..,n_max}). n_max + = 36 (i) I: index of c (pointer to unsigned 16-bit word) (i) k: index of v + (8-dimensional vector of binary indices) = Voronoi index (o) y: point in RE8 + (8-dimensional integer vector) note: the index I is defined as a 32-bit word, + but only 16 bits are required (long can be replaced by unsigned integer) + + return 0 on success, -1 on error. + -------------------------------------------------------------------------- + */ +static int RE8_dec(int n, int I, int *k, FIXP_DBL *y) { + SHORT v[8]; + SHORT _y[8]; + UINT r; + int i; + + /* Check bound of codebook qn */ + if (n > NQ_MAX) { + return -1; + } + + /* decode the sub-indices I and kv[] according to the codebook number n: + if n=0,2,3,4, decode I (no Voronoi extension) + if n>4, Voronoi extension is used, decode I and kv[] */ + if (n <= 4) { + re8_decode_base_index(&n, I, _y); + for (i = 0; i < 8; i++) { + y[i] = (LONG)_y[i]; + } + } else { + /* compute the Voronoi modulo m = 2^r where r is extension order */ + r = ((n - 3) >> 1); + + while (n > 4) { + n -= 2; + } + /* decode base codebook index I into c (c is an element of Q3 or Q4) + [here c is stored in y to save memory] */ + re8_decode_base_index(&n, I, _y); + /* decode Voronoi index k[] into v */ + re8_k2y(k, r, v); + /* reconstruct y as y = m c + v (with m=2^r, r integer >=1) */ + for (i = 0; i < 8; i++) { + y[i] = (LONG)((_y[i] << r) + v[i]); + } + } + return 0; +} + +/**************************/ +/* start LPC decode stuff */ +/**************************/ +//#define M 16 +#define FREQ_MAX 6400.0f +#define FREQ_DIV 400.0f +#define LSF_GAP 50.0f + +/** + * \brief calculate inverse weighting factor and add non-weighted residual + * LSF vector to first stage LSF approximation + * \param lsfq first stage LSF approximation values. + * \param xq weighted residual LSF vector + * \param nk_mode code book number coding mode. + */ +static void lsf_weight_2st(FIXP_LPC *lsfq, FIXP_DBL *xq, int nk_mode) { + FIXP_LPC d[M_LP_FILTER_ORDER + 1]; + FIXP_SGL factor; + LONG w; /* inverse weight factor */ + int i; + + /* compute lsf distance */ + d[0] = lsfq[0]; + d[M_LP_FILTER_ORDER] = + FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - lsfq[M_LP_FILTER_ORDER - 1]; + for (i = 1; i < M_LP_FILTER_ORDER; i++) { + d[i] = lsfq[i] - lsfq[i - 1]; + } + + switch (nk_mode) { + case 0: + factor = FL2FXCONST_SGL(2.0f * 60.0f / FREQ_DIV); + break; /* abs */ + case 1: + factor = FL2FXCONST_SGL(2.0f * 65.0f / FREQ_DIV); + break; /* mid */ + case 2: + factor = FL2FXCONST_SGL(2.0f * 64.0f / FREQ_DIV); + break; /* rel1 */ + default: + factor = FL2FXCONST_SGL(2.0f * 63.0f / FREQ_DIV); + break; /* rel2 */ + } + /* add non-weighted residual LSF vector to LSF1st */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + w = (LONG)fMultDiv2(factor, sqrtFixp(fMult(d[i], d[i + 1]))); + lsfq[i] = fAddSaturate(lsfq[i], FX_DBL2FX_LPC((FIXP_DBL)(w * (LONG)xq[i]))); + } + + return; +} + +/** + * \brief decode nqn amount of code book numbers. These values determine the + * amount of following bits for nqn AVQ RE8 vectors. + * \param nk_mode quantization mode. + * \param nqn amount code book number to read. + * \param qn pointer to output buffer to hold decoded code book numbers qn. + */ +static void decode_qn(HANDLE_FDK_BITSTREAM hBs, int nk_mode, int nqn, + int qn[]) { + int n; + + if (nk_mode == 1) { /* nk mode 1 */ + /* Unary code for mid LPC1/LPC3 */ + /* Q0=0, Q2=10, Q3=110, ... */ + for (n = 0; n < nqn; n++) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) { + qn[n]++; + } + } + } else { /* nk_mode 0, 3 and 2 */ + /* 2 bits to specify Q2,Q3,Q4,ext */ + for (n = 0; n < nqn; n++) { + qn[n] = 2 + FDKreadBits(hBs, 2); + } + if (nk_mode == 2) { + /* Unary code for rel LPC1/LPC3 */ + /* Q0 = 0, Q5=10, Q6=110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + if (qn[n] > 0) qn[n] += 4; + } + } + } else { /* nk_mode == (0 and 3) */ + /* Unary code for abs and rel LPC0/LPC2 */ + /* Q5 = 0, Q6=10, Q0=110, Q7=1110, ... */ + for (n = 0; n < nqn; n++) { + if (qn[n] > 4) { + qn[n] = get_vlclbf(hBs); + switch (qn[n]) { + case 0: + qn[n] = 5; + break; + case 1: + qn[n] = 6; + break; + case 2: + qn[n] = 0; + break; + default: + qn[n] += 4; + break; + } + } + } + } + } +} + +/** + * \brief reorder LSF coefficients to minimum distance. + * \param lsf pointer to buffer containing LSF coefficients and where reordered + * LSF coefficients will be stored into, scaled by LSF_SCALE. + * \param min_dist min distance scaled by LSF_SCALE + * \param n number of LSF/LSP coefficients. + */ +static void reorder_lsf(FIXP_LPC *lsf, FIXP_LPC min_dist, int n) { + FIXP_LPC lsf_min; + int i; + + lsf_min = min_dist; + for (i = 0; i < n; i++) { + if (lsf[i] < lsf_min) { + lsf[i] = lsf_min; + } + lsf_min = fAddSaturate(lsf[i], min_dist); + } + + /* reverse */ + lsf_min = FL2FXCONST_LPC(FREQ_MAX / (1 << LSF_SCALE)) - min_dist; + for (i = n - 1; i >= 0; i--) { + if (lsf[i] > lsf_min) { + lsf[i] = lsf_min; + } + + lsf_min = lsf[i] - min_dist; + } +} + +/** + * \brief First stage approximation + * \param hBs bitstream handle as data source + * \param lsfq pointer to output buffer to hold LPC coefficients scaled by + * LSF_SCALE. + */ +static void vlpc_1st_dec( + HANDLE_FDK_BITSTREAM hBs, /* input: codebook index */ + FIXP_LPC *lsfq /* i/o: i:prediction o:quantized lsf */ +) { + const FIXP_LPC *p_dico; + int i, index; + + index = FDKreadBits(hBs, 8); + p_dico = &fdk_dec_dico_lsf_abs_8b[index * M_LP_FILTER_ORDER]; + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsfq[i] = p_dico[i]; + } +} + +/** + * \brief Do first stage approximation weighting and multiply with AVQ + * refinement. + * \param hBs bitstream handle data ssource. + * \param lsfq buffer holding 1st stage approx, 2nd stage approx is added to + * this values. + * \param nk_mode quantization mode. + * \return 0 on success, -1 on error. + */ +static int vlpc_2st_dec( + HANDLE_FDK_BITSTREAM hBs, + FIXP_LPC *lsfq, /* i/o: i:1st stage o:1st+2nd stage */ + int nk_mode /* input: 0=abs, >0=rel */ +) { + int err; + FIXP_DBL xq[M_LP_FILTER_ORDER]; /* weighted residual LSF vector */ + + /* Decode AVQ refinement */ + { err = CLpc_DecodeAVQ(hBs, xq, nk_mode, 2, 8); } + if (err != 0) { + return -1; + } + + /* add non-weighted residual LSF vector to LSF1st */ + lsf_weight_2st(lsfq, xq, nk_mode); + + /* reorder */ + reorder_lsf(lsfq, FL2FXCONST_LPC(LSF_GAP / (1 << LSF_SCALE)), + M_LP_FILTER_ORDER); + + return 0; +} + +/* + * Externally visible functions + */ + +int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *pOutput, int nk_mode, + int no_qn, int length) { + int i, l; + + for (i = 0; i < length; i += 8 * no_qn) { + int qn[2], nk, n, I; + int kv[8] = {0}; + + decode_qn(hBs, nk_mode, no_qn, qn); + + for (l = 0; l < no_qn; l++) { + if (qn[l] == 0) { + FDKmemclear(&pOutput[i + l * 8], 8 * sizeof(FIXP_DBL)); + } + + /* Voronoi extension order ( nk ) */ + nk = 0; + n = qn[l]; + if (qn[l] > 4) { + nk = (qn[l] - 3) >> 1; + n = qn[l] - nk * 2; + } + + /* Base codebook index, in reverse bit group order (!) */ + I = FDKreadBits(hBs, 4 * n); + + if (nk > 0) { + int j; + + for (j = 0; j < 8; j++) { + kv[j] = FDKreadBits(hBs, nk); + } + } + + if (RE8_dec(qn[l], I, kv, &pOutput[i + l * 8]) != 0) { + return -1; + } + } + } + return 0; +} + +int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER], + FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag, + int last_lpc_lost, int last_frame_ok) { + int i, k, err; + int mode_lpc_bin = 0; /* mode_lpc bitstream representation */ + int lpc_present[5] = {0, 0, 0, 0, 0}; + int lpc0_available = 1; + int s = 0; + int l = 3; + const int nbDiv = NB_DIV; + + lpc_present[4 >> s] = 1; /* LPC4 */ + + /* Decode LPC filters in the following order: LPC 4,0,2,1,3 */ + + /*** Decode LPC4 ***/ + vlpc_1st_dec(hBs, lsp[4 >> s]); + err = vlpc_2st_dec(hBs, lsp[4 >> s], 0); /* nk_mode = 0 */ + if (err != 0) { + return err; + } + + /*** Decode LPC0 and LPC2 ***/ + k = 0; + if (!first_lpd_flag) { + lpc_present[0] = 1; + lpc0_available = !last_lpc_lost; + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + /* skip LPC0 and continue with LPC2 */ + k = 2; + } + + for (; k < l; k += 2) { + int nk_mode = 0; + + if ((k == 2) && (mod[0] == 3)) { + break; /* skip LPC2 */ + } + + lpc_present[k >> s] = 1; + + mode_lpc_bin = FDKreadBit(hBs); + + if (mode_lpc_bin == 0) { + /* LPC0/LPC2: Abs */ + vlpc_1st_dec(hBs, lsp[k >> s]); + } else { + /* LPC0/LPC2: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[k >> s][i] = lsp[4 >> s][i]; + } + nk_mode = 3; + } + + err = vlpc_2st_dec(hBs, lsp[k >> s], nk_mode); + if (err != 0) { + return err; + } + } + + /*** Decode LPC1 ***/ + if (mod[0] < 2) { /* else: skip LPC1 */ + lpc_present[1] = 1; + mode_lpc_bin = get_vlclbf_n(hBs, 2); + + switch (mode_lpc_bin) { + case 1: + /* LPC1: abs */ + vlpc_1st_dec(hBs, lsp[1]); + err = vlpc_2st_dec(hBs, lsp[1], 0); + if (err != 0) { + return err; + } + break; + case 2: + /* LPC1: mid0 (no second stage AVQ quantizer in this case) */ + if (lpc0_available) { /* LPC0/lsf[0] might be zero some times */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = (lsp[0][i] >> 1) + (lsp[2][i] >> 1); + } + } else { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + } + break; + case 0: + /* LPC1: RelR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[1][i] = lsp[2][i]; + } + err = vlpc_2st_dec(hBs, lsp[1], 2 << s); + if (err != 0) { + return err; + } + break; + } + } + + /*** Decode LPC3 ***/ + if ((mod[2] < 2)) { /* else: skip LPC3 */ + int nk_mode = 0; + lpc_present[3] = 1; + + mode_lpc_bin = get_vlclbf_n(hBs, 3); + + switch (mode_lpc_bin) { + case 1: + /* LPC3: abs */ + vlpc_1st_dec(hBs, lsp[3]); + break; + case 0: + /* LPC3: mid */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = (lsp[2][i] >> 1) + (lsp[4][i] >> 1); + } + nk_mode = 1; + break; + case 2: + /* LPC3: relL */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[2][i]; + } + nk_mode = 2; + break; + case 3: + /* LPC3: relR */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[3][i] = lsp[4][i]; + } + nk_mode = 2; + break; + } + err = vlpc_2st_dec(hBs, lsp[3], nk_mode); + if (err != 0) { + return err; + } + } + + if (!lpc0_available && !last_frame_ok) { + /* LPC(0) was lost. Use next available LPC(k) instead */ + for (k = 1; k < (nbDiv + 1); k++) { + if (lpc_present[k]) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { +#define LSF_INIT_TILT (0.25f) + if (mod[0] > 0) { + lsp[0][i] = FX_DBL2FX_LPC( + fMult(lsp[k][i], FL2FXCONST_SGL(1.0f - LSF_INIT_TILT)) + + fMult(fdk_dec_lsf_init[i], FL2FXCONST_SGL(LSF_INIT_TILT))); + } else { + lsp[0][i] = lsp[k][i]; + } + } + break; + } + } + } + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4 >> s][i]; + } + + { + FIXP_DBL divFac; + int last, numLpc = 0; + + i = nbDiv; + do { + numLpc += lpc_present[i--]; + } while (i >= 0 && numLpc < 3); + + last = i; + + switch (numLpc) { + case 3: + divFac = FL2FXCONST_DBL(1.0f / 3.0f); + break; + case 2: + divFac = FL2FXCONST_DBL(1.0f / 2.0f); + break; + default: + divFac = FL2FXCONST_DBL(1.0f); + break; + } + + /* get the adaptive mean for the next (bad) frame */ + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + FIXP_DBL tmp = (FIXP_DBL)0; + for (i = nbDiv; i > last; i--) { + if (lpc_present[i]) { + tmp = fMultAdd(tmp >> 1, lsp[i][k], divFac); + } + } + lsf_adaptive_mean_cand[k] = FX_DBL2FX_LPC(tmp); + } + } + + /* calculate stability factor Theta. Needed for ACELP decoder and concealment + */ + { + FIXP_LPC *lsf_prev, *lsf_curr; + k = 0; + + FDK_ASSERT(lpc_present[0] == 1 && lpc_present[4 >> s] == 1); + lsf_prev = lsp[0]; + for (i = 1; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + FIXP_DBL tmp = (FIXP_DBL)0; + int j; + lsf_curr = lsp[i]; + + /* sum = tmp * 2^(LSF_SCALE*2 + 4) */ + for (j = 0; j < M_LP_FILTER_ORDER; j++) { + tmp += fPow2Div2((FIXP_SGL)(lsf_curr[j] - lsf_prev[j])) >> 3; + } + + /* tmp = (float)(FL2FXCONST_DBL(1.25f) - fMult(tmp, + * FL2FXCONST_DBL(1/400000.0f))); */ + tmp = FL2FXCONST_DBL(1.25f / (1 << LSF_SCALE)) - + fMult(tmp, FL2FXCONST_DBL((1 << (LSF_SCALE + 4)) / 400000.0f)); + if (tmp >= FL2FXCONST_DBL(1.0f / (1 << LSF_SCALE))) { + pStability[k] = FL2FXCONST_SGL(1.0f / 2.0f); + } else if (tmp < FL2FXCONST_DBL(0.0f)) { + pStability[k] = FL2FXCONST_SGL(0.0f); + } else { + pStability[k] = FX_DBL2FX_SGL(tmp << (LSF_SCALE - 1)); + } + + lsf_prev = lsf_curr; + k = i; + } else { + /* Mark stability value as undefined. */ + pStability[i] = (FIXP_SGL)-1; + } + } + } + + /* convert into LSP domain */ + for (i = 0; i < (nbDiv + 1); i++) { + if (lpc_present[i]) { + for (k = 0; k < M_LP_FILTER_ORDER; k++) { + lsp[i][k] = FX_DBL2FX_LPC( + fixp_cos(fMult(lsp[i][k], + FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } + } + + return 0; +} + +void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean[M_LP_FILTER_ORDER], + const int first_lpd_flag) { + int i, j; + +#define BETA (FL2FXCONST_SGL(0.25f)) +#define ONE_BETA (FL2FXCONST_SGL(0.75f)) +#define BFI_FAC (FL2FXCONST_SGL(0.90f)) +#define ONE_BFI_FAC (FL2FXCONST_SGL(0.10f)) + + /* Frame loss concealment (could be improved) */ + + if (first_lpd_flag) { + /* Reset past LSF values */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i] = fdk_dec_lsf_init[i]; + } + } else { + /* old LPC4 is new LPC0 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[0][i] = lpc4_lsf[i]; + } + } + + /* LPC1 */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + FIXP_LPC lsf_mean = FX_DBL2FX_LPC(fMult(BETA, fdk_dec_lsf_init[i]) + + fMult(ONE_BETA, lsf_adaptive_mean[i])); + + lsp[1][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lpc4_lsf[i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + + /* LPC2 - LPC4 */ + for (j = 2; j <= 4; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + /* lsf_mean[i] = FX_DBL2FX_LPC(fMult((FIXP_LPC)(BETA + j * + FL2FXCONST_LPC(0.1f)), fdk_dec_lsf_init[i]) + + fMult((FIXP_LPC)(ONE_BETA - j * + FL2FXCONST_LPC(0.1f)), lsf_adaptive_mean[i])); */ + + FIXP_LPC lsf_mean = FX_DBL2FX_LPC( + fMult((FIXP_SGL)(BETA + (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + (FIXP_SGL)fdk_dec_lsf_init[i]) + + fMult( + (FIXP_SGL)(ONE_BETA - (FIXP_SGL)(j * (INT)FL2FXCONST_SGL(0.1f))), + lsf_adaptive_mean[i])); + + lsp[j][i] = FX_DBL2FX_LPC(fMult(BFI_FAC, lsp[j - 1][i]) + + fMult(ONE_BFI_FAC, lsf_mean)); + } + } + + /* Update past values for the future */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lpc4_lsf[i] = lsp[4][i]; + } + + /* convert into LSP domain */ + for (j = 0; j < 5; j++) { + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + lsp[j][i] = FX_DBL2FX_LPC(fixp_cos( + fMult(lsp[j][i], FL2FXCONST_SGL((1 << LSPARG_SCALE) * M_PI / 6400.0)), + LSF_SCALE - LSPARG_SCALE)); + } + } +} + +void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, int m) { + FIXP_DBL f; + int i; + + f = FL2FXCONST_DBL(0.92f); + for (i = 0; i < m; i++) { + wA[i] = FX_DBL2FX_LPC(fMult(A[i], f)); + f = fMult(f, FL2FXCONST_DBL(0.92f)); + } +} + +void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code) { + /* gain * 2^(gain_e) = 10^(gain_code/28) */ + *gain = fLdPow( + FL2FXCONST_DBL(3.3219280948873623478703194294894 / 4.0), /* log2(10)*/ + 2, + fMultDiv2((FIXP_DBL)gain_code << (DFRACT_BITS - 1 - 7), + FL2FXCONST_DBL(2.0f / 28.0f)), + 7, gain_e); +} + + /** + * \brief * Find the polynomial F1(z) or F2(z) from the LSPs. + * This is performed by expanding the product polynomials: + * + * F1(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=0,2,4,6,8 + * F2(z) = product ( 1 - 2 LSP_i z^-1 + z^-2 ) + * i=1,3,5,7,9 + * + * where LSP_i are the LSPs in the cosine domain. + * R.A.Salami October 1990 + * \param lsp input, line spectral freq. (cosine domain) + * \param f output, the coefficients of F1 or F2, scaled by 8 bits + * \param n no of coefficients (m/2) + * \param flag 1 : F1(z) ; 2 : F2(z) + */ + +#define SF_F 8 + +static void get_lsppol(FIXP_LPC lsp[], FIXP_DBL f[], int n, int flag) { + FIXP_DBL b; + FIXP_LPC *plsp; + int i, j; + + plsp = lsp + flag - 1; + f[0] = FL2FXCONST_DBL(1.0f / (1 << SF_F)); + b = -FX_LPC2FX_DBL(*plsp); + f[1] = b >> (SF_F - 1); + for (i = 2; i <= n; i++) { + plsp += 2; + b = -FX_LPC2FX_DBL(*plsp); + f[i] = ((fMultDiv2(b, f[i - 1]) << 1) + (f[i - 2])) << 1; + for (j = i - 1; j > 1; j--) { + f[j] = f[j] + (fMultDiv2(b, f[j - 1]) << 2) + f[j - 2]; + } + f[1] = f[1] + (b >> (SF_F - 1)); + } + return; +} + +#define NC M_LP_FILTER_ORDER / 2 + +/** + * \brief lsp input LSP vector + * \brief a output LP filter coefficient vector scaled by SF_A_COEFFS. + */ +void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp) { + FIXP_DBL f1[NC + 1], f2[NC + 1]; + int i, k; + + /*-----------------------------------------------------* + * Find the polynomials F1(z) and F2(z) * + *-----------------------------------------------------*/ + + get_lsppol(lsp, f1, NC, 1); + get_lsppol(lsp, f2, NC, 2); + + /*-----------------------------------------------------* + * Multiply F1(z) by (1+z^-1) and F2(z) by (1-z^-1) * + *-----------------------------------------------------*/ + for (i = NC; i > 0; i--) { + f1[i] += f1[i - 1]; + f2[i] -= f2[i - 1]; + } + + FIXP_DBL aDBL[M_LP_FILTER_ORDER]; + + for (i = 1, k = M_LP_FILTER_ORDER - 1; i <= NC; i++, k--) { + FIXP_DBL tmp1, tmp2; + + tmp1 = f1[i] >> 1; + tmp2 = f2[i] >> 1; + + aDBL[i - 1] = (tmp1 + tmp2); + aDBL[k] = (tmp1 - tmp2); + } + + int headroom_a = getScalefactor(aDBL, M_LP_FILTER_ORDER); + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + a[i] = FX_DBL2FX_LPC(aDBL[i] << headroom_a); + } + + *a_exp = 8 - headroom_a; +} diff --git a/fdk-aac/libAACdec/src/usacdec_lpc.h b/fdk-aac/libAACdec/src/usacdec_lpc.h new file mode 100644 index 0000000..a6713c1 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_lpc.h @@ -0,0 +1,190 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Matthias Hildenbrand, Manuel Jander + + Description: USAC LPC/AVQ decode + +*******************************************************************************/ + +#ifndef USACDEC_LPC_H +#define USACDEC_LPC_H + +#include "channelinfo.h" +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "usacdec_rom.h" + +#define LSPARG_SCALE 10 + +/** + * \brief AVQ (refinement) decode + * \param hBs bitstream handle + * \param lsfq buffer for AVQ decode output. + * \param nk_mode quantization mode. + * \param nqn amount of split/interleaved RE8 vectors. + * \param total amount of individual data values to decode. + * \return 0 on success, -1 on error. + */ +int CLpc_DecodeAVQ(HANDLE_FDK_BITSTREAM hBs, FIXP_DBL *lsfq, int nk_mode, + int nqn, int length); + +/** + * \brief Read and decode LPC coeficient sets. First stage approximation + AVQ + * decode. + * \param[in] hBs bitstream handle to read data from. + * \param[out] lsp buffer into which the decoded LSP coefficients will be stored + * into. + * \param[in,out] lpc4_lsf buffer into which the decoded LCP4 LSF coefficients + * will be stored into (persistent). + * \param[out] lsf_adaptive_mean_cand lsf adaptive mean vector needed for + * concealment. + * \param[out] pStability array with stability values for the ACELP decoder (and + * concealment). + * \param[in] mod array which defines modes (ACELP, TCX20|40|80) are used in + * the current superframe. + * \param[in] first_lpd_flag indicates the presence of LPC0 + * \param[in] last_lpc_lost indicate that LPC4 of previous frame was lost. + * \param[in] last_frame_ok indicate that the last frame was ok. + * \return 0 on success, -1 on error. + */ +int CLpc_Read(HANDLE_FDK_BITSTREAM hBs, FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC lsf_adaptive_mean_cand[M_LP_FILTER_ORDER], + FIXP_SGL pStability[], UCHAR *mod, int first_lpd_flag, + int last_lpc_lost, int last_frame_ok); + +/** + * \brief Generate LPC coefficient sets in case frame loss. + * \param lsp buffer into which the decoded LSP coefficients will be stored + * into. + * \param lpc4_lsf buffer into which the decoded LCP4 LSF coefficients will be + * stored into (persistent). + * \param isf_adaptive_mean + * \param first_lpd_flag indicates the previous LSF4 coefficients lpc4_lsf[] are + * not valid. + */ +void CLpc_Conceal(FIXP_LPC lsp[][M_LP_FILTER_ORDER], + FIXP_LPC lpc4_lsf[M_LP_FILTER_ORDER], + FIXP_LPC isf_adaptive_mean[M_LP_FILTER_ORDER], + const int first_lpd_flag); + +/** + * \brief apply absolute weighting + * \param A weighted LPC coefficient vector output. The first coeffcient is + * implicitly 1.0 + * \param A LPC coefficient vector. The first coeffcient is implicitly 1.0 + * \param m length of vector A + */ +/* static */ +void E_LPC_a_weight(FIXP_LPC *wA, const FIXP_LPC *A, const int m); + +/** + * \brief decode TCX/FAC gain. In case of TCX the lg/sqrt(rms) part + * must still be applied to obtain the gain value. + * \param gain (o) pointer were the gain mantissa is stored into. + * \param gain_e (o) pointer were the gain exponent is stored into. + * \param gain_code (i) the 7 bit binary word from the bitstream + * representing the gain. + */ +void CLpd_DecodeGain(FIXP_DBL *gain, INT *gain_e, int gain_code); + +/** + * \brief convert LSP coefficients into LP domain. + */ +void E_LPC_f_lsp_a_conversion(FIXP_LPC *lsp, FIXP_LPC *a, INT *a_exp); + +#endif /* USACDEC_LPC_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_lpd.cpp b/fdk-aac/libAACdec/src/usacdec_lpd.cpp new file mode 100644 index 0000000..2110172 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_lpd.cpp @@ -0,0 +1,2029 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC Linear Prediction Domain coding + +*******************************************************************************/ + +#include "usacdec_lpd.h" + +#include "usacdec_rom.h" +#include "usacdec_fac.h" +#include "usacdec_lpc.h" +#include "FDK_tools_rom.h" +#include "fft.h" +#include "mdct.h" +#include "usacdec_acelp.h" +#include "overlapadd.h" + +#include "conceal.h" + +#include "block.h" + +#define SF_PITCH_TRACK 6 +#define SF_GAIN 3 +#define MIN_VAL FL2FXCONST_DBL(0.0f) +#define MAX_VAL (FIXP_DBL) MAXVAL_DBL + +#include "ac_arith_coder.h" + +void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, INT stop, int len) { + INT i, j; + FIXP_DBL tmp; + + for (i = 0; i < stop; i++) { + tmp = fMultDiv2(noise[i], filt[0]); // Filt in Q-1.16 + for (j = 1; j <= len; j++) { + tmp += fMultDiv2((noise[i - j] + noise[i + j]), filt[j]); + } + syn_out[i] = (FIXP_PCM)(IMDCT_SCALE(syn[i] - tmp)); + } +} + +void bass_pf_1sf_delay( + FIXP_DBL *syn, /* (i) : 12.8kHz synthesis to postfilter */ + const INT *T_sf, /* (i) : Pitch period for all subframes (T_sf[16]) */ + FIXP_DBL *pit_gain, + const int frame_length, /* (i) : frame length (should be 768|1024) */ + const INT l_frame, + const INT l_next, /* (i) : look ahead for symmetric filtering */ + FIXP_PCM *synth_out, /* (o) : filtered synthesis (with delay of 1 subfr) */ + FIXP_DBL mem_bpf[]) /* i/o : memory state [L_FILT+L_SUBFR] */ +{ + INT i, sf, i_subfr, T, T2, lg; + + FIXP_DBL tmp, ener, corr, gain; + FIXP_DBL *noise, *noise_in; + FIXP_DBL + noise_buf[L_FILT + (2 * L_SUBFR)]; // L_FILT = 12, L_SUBFR = 64 => 140 + const FIXP_DBL *x, *y; + + { + noise = noise_buf + L_FILT; // L_FILT = 12 delay of upsampling filter + noise_in = noise_buf + L_FILT + L_SUBFR; + /* Input scaling of the BPF memory */ + scaleValues(mem_bpf, (L_FILT + L_SUBFR), 1); + } + + int gain_exp = 17; + + sf = 0; + for (i_subfr = 0; i_subfr < l_frame; i_subfr += L_SUBFR, sf++) { + T = T_sf[sf]; + gain = pit_gain[sf]; + + /* Gain is in Q17.14 */ + /* If gain > 1 set to 1 */ + if (gain > (FIXP_DBL)(1 << 14)) gain = (FIXP_DBL)(1 << 14); + + /* If gain < 0 set to 0 */ + if (gain < (FIXP_DBL)0) gain = (FIXP_DBL)0; + + if (gain > (FIXP_DBL)0) { + /* pitch tracker: test pitch/2 to avoid continuous pitch doubling */ + /* Note: pitch is limited to PIT_MIN (34 = 376Hz) at the encoder */ + T2 = T >> 1; + x = &syn[i_subfr - L_EXTRA]; + y = &syn[i_subfr - T2 - L_EXTRA]; + + ener = (FIXP_DBL)0; + corr = (FIXP_DBL)0; + tmp = (FIXP_DBL)0; + + int headroom_x = getScalefactor(x, L_SUBFR + L_EXTRA); + int headroom_y = getScalefactor(y, L_SUBFR + L_EXTRA); + + int width_shift = 7; + + for (i = 0; i < (L_SUBFR + L_EXTRA); i++) { + ener += fPow2Div2((x[i] << headroom_x)) >> width_shift; + corr += fMultDiv2((x[i] << headroom_x), (y[i] << headroom_y)) >> + width_shift; + tmp += fPow2Div2((y[i] << headroom_y)) >> width_shift; + } + + int exp_ener = ((17 - headroom_x) << 1) + width_shift + 1; + int exp_corr = (17 - headroom_x) + (17 - headroom_y) + width_shift + 1; + int exp_tmp = ((17 - headroom_y) << 1) + width_shift + 1; + + /* Add 0.01 to "ener". Adjust exponents */ + FIXP_DBL point_zero_one = (FIXP_DBL)0x51eb851f; /* In Q-6.37 */ + int diff; + ener = fAddNorm(ener, exp_ener, point_zero_one, -6, &exp_ener); + corr = fAddNorm(corr, exp_corr, point_zero_one, -6, &exp_corr); + tmp = fAddNorm(tmp, exp_tmp, point_zero_one, -6, &exp_tmp); + + /* use T2 if normalized correlation > 0.95 */ + INT s1, s2; + s1 = CntLeadingZeros(ener) - 1; + s2 = CntLeadingZeros(tmp) - 1; + + FIXP_DBL ener_by_tmp = fMultDiv2(ener << s1, tmp << s2); + int ener_by_tmp_exp = (exp_ener - s1) + (exp_tmp - s2) + 1; + + if (ener_by_tmp_exp & 1) { + ener_by_tmp <<= 1; + ener_by_tmp_exp -= 1; + } + + int temp_exp = 0; + + FIXP_DBL temp1 = invSqrtNorm2(ener_by_tmp, &temp_exp); + + int temp1_exp = temp_exp - (ener_by_tmp_exp >> 1); + + FIXP_DBL tmp_result = fMult(corr, temp1); + + int tmp_result_exp = exp_corr + temp1_exp; + + diff = tmp_result_exp - 0; + FIXP_DBL point95 = FL2FXCONST_DBL(0.95f); + if (diff >= 0) { + diff = fMin(diff, 31); + point95 = FL2FXCONST_DBL(0.95f) >> diff; + } else { + diff = fMax(diff, -31); + tmp_result >>= (-diff); + } + + if (tmp_result > point95) T = T2; + + /* prevent that noise calculation below reaches into not defined signal + parts at the end of the synth_buf or in other words restrict the below + used index (i+i_subfr+T) < l_frame + l_next + */ + lg = l_frame + l_next - T - i_subfr; + + if (lg > L_SUBFR) + lg = L_SUBFR; + else if (lg < 0) + lg = 0; + + /* limit gain to avoid problem on burst */ + if (lg > 0) { + FIXP_DBL tmp1; + + /* max(lg) = 64 => scale with 6 bits minus 1 (fPow2Div2) */ + + s1 = getScalefactor(&syn[i_subfr], lg); + s2 = getScalefactor(&syn[i_subfr + T], lg); + INT s = fixMin(s1, s2); + + tmp = (FIXP_DBL)0; + ener = (FIXP_DBL)0; + for (i = 0; i < lg; i++) { + tmp += fPow2Div2(syn[i + i_subfr] << s1) >> (SF_PITCH_TRACK); + ener += fPow2Div2(syn[i + i_subfr + T] << s2) >> (SF_PITCH_TRACK); + } + tmp = tmp >> fMin(DFRACT_BITS - 1, (2 * (s1 - s))); + ener = ener >> fMin(DFRACT_BITS - 1, (2 * (s2 - s))); + + /* error robustness: for the specific case syn[...] == -1.0f for all 64 + samples ener or tmp might overflow and become negative. For all sane + cases we have enough headroom. + */ + if (ener <= (FIXP_DBL)0) { + ener = (FIXP_DBL)1; + } + if (tmp <= (FIXP_DBL)0) { + tmp = (FIXP_DBL)1; + } + FDK_ASSERT(ener > (FIXP_DBL)0); + + /* tmp = sqrt(tmp/ener) */ + int result_e = 0; + tmp1 = fDivNorm(tmp, ener, &result_e); + if (result_e & 1) { + tmp1 >>= 1; + result_e += 1; + } + tmp = sqrtFixp(tmp1); + result_e >>= 1; + + gain_exp = 17; + + diff = result_e - gain_exp; + + FIXP_DBL gain1 = gain; + + if (diff >= 0) { + diff = fMin(diff, 31); + gain1 >>= diff; + } else { + result_e += (-diff); + diff = fMax(diff, -31); + tmp >>= (-diff); + } + + if (tmp < gain1) { + gain = tmp; + gain_exp = result_e; + } + } + + /* calculate noise based on voiced pitch */ + /* fMultDiv2() replaces weighting of gain with 0.5 */ + diff = gain_exp - 17; + if (diff >= 0) { + gain <<= diff; + } else { + gain >>= (-diff); + } + + s1 = CntLeadingZeros(gain) - 1; + s1 -= 16; /* Leading bits for SGL */ + + FIXP_SGL gainSGL = FX_DBL2FX_SGL(gain << 16); + + gainSGL = gainSGL << s1; + + { + for (i = 0; i < lg; i++) { + /* scaled with SF_SYNTH + gain_sf + 1 */ + noise_in[i] = + (fMult(gainSGL, syn[i + i_subfr] - (syn[i + i_subfr - T] >> 1) - + (syn[i + i_subfr + T] >> 1))) >> + s1; + } + + for (i = lg; i < L_SUBFR; i++) { + /* scaled with SF_SYNTH + gain_sf + 1 */ + noise_in[i] = + (fMult(gainSGL, syn[i + i_subfr] - syn[i + i_subfr - T])) >> s1; + } + } + } else { + FDKmemset(noise_in, (FIXP_DBL)0, L_SUBFR * sizeof(FIXP_DBL)); + } + + { + FDKmemcpy(noise_buf, mem_bpf, (L_FILT + L_SUBFR) * sizeof(FIXP_DBL)); + + FDKmemcpy(mem_bpf, noise_buf + L_SUBFR, + (L_FILT + L_SUBFR) * sizeof(FIXP_DBL)); + } + + /* substract from voiced speech low-pass filtered noise */ + /* filter coefficients are scaled with factor SF_FILT_LP (1) */ + + { + filtLP(&syn[i_subfr - L_SUBFR], &synth_out[i_subfr], noise, + fdk_dec_filt_lp, L_SUBFR, L_FILT); + } + } + + { + + } + + // To be determined (info from Ben) + { + /* Output scaling of the BPF memory */ + scaleValues(mem_bpf, (L_FILT + L_SUBFR), -1); + /* Copy the rest of the signal (after the fac) */ + scaleValuesSaturate((FIXP_PCM *)&synth_out[l_frame], + (FIXP_DBL *)&syn[l_frame - L_SUBFR], + (frame_length - l_frame), MDCT_OUT_HEADROOM); + } + + return; +} + +/* + * Frequency Domain Noise Shaping + */ + +/** + * \brief Adaptive Low Frequencies Deemphasis of spectral coefficients. + * + * Ensure quantization of low frequencies in case where the + * signal dynamic is higher than the LPC noise shaping. + * This is the inverse operation of adap_low_freq_emph(). + * Output gain of all blocks. + * + * \param x pointer to the spectral coefficients, requires 1 bit headroom. + * \param lg length of x. + * \param bUseNewAlfe if set, apply ALFD for fullband lpd. + * \param gainLpc1 pointer to gain based on old input LPC coefficients. + * \param gainLpc2 pointer to gain based on new input LPC coefficients. + * \param alfd_gains pointer to output gains. + * \param s current scale shift factor of x. + */ +#define ALFDPOW2_SCALE 3 +/*static*/ +void CLpd_AdaptLowFreqDeemph(FIXP_DBL x[], int lg, FIXP_DBL alfd_gains[], + INT s) { + { + int i, j, k, i_max; + FIXP_DBL max, fac; + /* Note: This stack array saves temporary accumulation results to be used in + * a second run */ + /* The size should be limited to (1024/4)/8=32 */ + FIXP_DBL tmp_pow2[32]; + + s = s * 2 + ALFDPOW2_SCALE; + s = fMin(31, s); + + k = 8; + i_max = lg / 4; /* ALFD range = 1600Hz (lg = 6400Hz) */ + + /* find spectral peak */ + max = FL2FX_DBL(0.01f) >> s; + for (i = 0; i < i_max; i += k) { + FIXP_DBL tmp; + + tmp = FIXP_DBL(0); + FIXP_DBL *pX = &x[i]; + + j = 8; + do { + FIXP_DBL x0 = *pX++; + FIXP_DBL x1 = *pX++; + x0 = fPow2Div2(x0); + x1 = fPow2Div2(x1); + tmp = tmp + (x0 >> (ALFDPOW2_SCALE - 1)); + tmp = tmp + (x1 >> (ALFDPOW2_SCALE - 1)); + } while ((j = j - 2) != 0); + tmp = fMax(tmp, (FL2FX_DBL(0.01f) >> s)); + tmp_pow2[i >> 3] = tmp; + if (tmp > max) { + max = tmp; + } + } + + /* deemphasis of all blocks below the peak */ + fac = FL2FX_DBL(0.1f) >> 1; + for (i = 0; i < i_max; i += k) { + FIXP_DBL tmp; + INT shifti; + + tmp = tmp_pow2[i >> 3]; + + /* tmp = (float)sqrt(tmp/max); */ + + /* value of tmp is between 8/2*max^2 and max^2 / 2. */ + /* required shift factor of division can grow up to 27 + (grows exponentially for values toward zero) + thus using normalized division to assure valid result. */ + { + INT sd; + + if (tmp != (FIXP_DBL)0) { + tmp = fDivNorm(max, tmp, &sd); + if (sd & 1) { + sd++; + tmp >>= 1; + } + } else { + tmp = (FIXP_DBL)MAXVAL_DBL; + sd = 0; + } + tmp = invSqrtNorm2(tmp, &shifti); + tmp = scaleValue(tmp, shifti - 1 - (sd / 2)); + } + if (tmp > fac) { + fac = tmp; + } + FIXP_DBL *pX = &x[i]; + + j = 8; + do { + FIXP_DBL x0 = pX[0]; + FIXP_DBL x1 = pX[1]; + x0 = fMultDiv2(x0, fac); + x1 = fMultDiv2(x1, fac); + x0 = x0 << 2; + x1 = x1 << 2; + *pX++ = x0; + *pX++ = x1; + + } while ((j = j - 2) != 0); + /* Store gains for FAC */ + *alfd_gains++ = fac; + } + } +} + +/** + * \brief Interpolated Noise Shaping for mdct coefficients. + * This algorithm shapes temporally the spectral noise between + * the two spectral noise represention (FDNS_NPTS of resolution). + * The noise is shaped monotonically between the two points + * using a curved shape to favor the lower gain in mid-frame. + * ODFT and amplitud calculation are applied to the 2 LPC coefficients first. + * + * \param r pointer to spectrum data. + * \param rms RMS of output spectrum. + * \param lg length of r. + * \param A1 pointer to old input LPC coefficients of length M_LP_FILTER_ORDER + * scaled by SF_A_COEFFS. + * \param A2 pointer to new input LPC coefficients of length M_LP_FILTER_ORDER + * scaled by SF_A_COEFFS. + * \param bLpc2Mdct flags control lpc2mdct conversion and noise shaping. + * \param gainLpc1 pointer to gain based on old input LPC coefficients. + * \param gainLpc2 pointer to gain based on new input LPC coefficients. + * \param gLpc_e pointer to exponent of gainLpc1 and gainLpc2. + */ +/* static */ +#define NSHAPE_SCALE (4) + +#define LPC2MDCT_CALC (1) +#define LPC2MDCT_GAIN_LOAD (2) +#define LPC2MDCT_GAIN_SAVE (4) +#define LPC2MDCT_APPLY_NSHAPE (8) + +void lpc2mdctAndNoiseShaping(FIXP_DBL *r, SHORT *pScale, const INT lg, + const INT fdns_npts, const FIXP_LPC *A1, + const INT A1_exp, const FIXP_LPC *A2, + const INT A2_exp) { + FIXP_DBL *tmp2 = NULL; + FIXP_DBL rr_minus_one; + int i, k, s, step; + + C_AALLOC_SCRATCH_START(tmp1, FIXP_DBL, FDNS_NPTS * 8) + + { + tmp2 = tmp1 + fdns_npts * 4; + + /* lpc2mdct() */ + + /* ODFT. E_LPC_a_weight() for A1 and A2 vectors is included into the loop + * below. */ + FIXP_DBL f = FL2FXCONST_DBL(0.92f); + + const FIXP_STP *SinTab; + int k_step; + /* needed values: sin(phi), cos(phi); phi = i*PI/(2*fdns_npts), i = 0 ... + * M_LP_FILTER_ORDER */ + switch (fdns_npts) { + case 64: + SinTab = SineTable512; + k_step = (512 / 64); + FDK_ASSERT(512 >= 64); + break; + case 48: + SinTab = SineTable384; + k_step = 384 / 48; + FDK_ASSERT(384 >= 48); + break; + default: + FDK_ASSERT(0); + return; + } + + for (i = 0, k = k_step; i < M_LP_FILTER_ORDER; i++, k += k_step) { + FIXP_STP cs = SinTab[k]; + FIXP_DBL wA1, wA2; + + wA1 = fMult(A1[i], f); + wA2 = fMult(A2[i], f); + + /* r[i] = A[i]*cos() */ + tmp1[2 + i * 2] = fMult(wA1, cs.v.re); + tmp2[2 + i * 2] = fMult(wA2, cs.v.re); + /* i[i] = A[i]*sin() */ + tmp1[3 + i * 2] = -fMult(wA1, cs.v.im); + tmp2[3 + i * 2] = -fMult(wA2, cs.v.im); + + f = fMult(f, FL2FXCONST_DBL(0.92f)); + } + + /* Guarantee at least 2 bits of headroom for the FFT */ + /* "3" stands for 1.0 with 2 bits of headroom; (A1_exp + 2) guarantess 2 + * bits of headroom if A1_exp > 1 */ + int A1_exp_fix = fMax(3, A1_exp + 2); + int A2_exp_fix = fMax(3, A2_exp + 2); + + /* Set 1.0 in the proper format */ + tmp1[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A1_exp_fix); + tmp2[0] = (FIXP_DBL)(INT)((ULONG)0x80000000 >> A2_exp_fix); + + tmp1[1] = tmp2[1] = (FIXP_DBL)0; + + /* Clear the resto of the array */ + FDKmemclear( + tmp1 + 2 * (M_LP_FILTER_ORDER + 1), + 2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL)); + FDKmemclear( + tmp2 + 2 * (M_LP_FILTER_ORDER + 1), + 2 * (fdns_npts * 2 - (M_LP_FILTER_ORDER + 1)) * sizeof(FIXP_DBL)); + + /* Guarantee 2 bits of headroom for FFT */ + scaleValues(&tmp1[2], (2 * M_LP_FILTER_ORDER), (A1_exp - A1_exp_fix)); + scaleValues(&tmp2[2], (2 * M_LP_FILTER_ORDER), (A2_exp - A2_exp_fix)); + + INT s2; + s = A1_exp_fix; + s2 = A2_exp_fix; + + fft(2 * fdns_npts, tmp1, &s); + fft(2 * fdns_npts, tmp2, &s2); + + /* Adjust the exponents of both fft outputs if necessary*/ + if (s > s2) { + scaleValues(tmp2, 2 * fdns_npts, s2 - s); + s2 = s; + } else if (s < s2) { + scaleValues(tmp1, 2 * fdns_npts, s - s2); + s = s2; + } + + FDK_ASSERT(s == s2); + } + + /* Get amplitude and apply gains */ + step = lg / fdns_npts; + rr_minus_one = (FIXP_DBL)0; + + for (k = 0; k < fdns_npts; k++) { + FIXP_DBL g1, g2, inv_g1_g2, a, b; + INT inv_g1_g2_e; + int g_e, shift; + + { + FIXP_DBL real, imag; + int si1, si2, sInput; + + real = tmp1[k * 2]; + imag = tmp1[k * 2 + 1]; + sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0); + real <<= sInput; + imag <<= sInput; + /* g1_e = si1 - 2*s/2 */ + g1 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si1); + si1 += sInput; + + real = tmp2[k * 2]; + imag = tmp2[k * 2 + 1]; + sInput = fMax(fMin(fNorm(real), fNorm(imag)) - 1, 0); + real <<= sInput; + imag <<= sInput; + /* g2_e = si2 - 2*s/2 */ + g2 = invSqrtNorm2(fPow2(real) + fPow2(imag), &si2); + si2 += sInput; + + /* Pick a common scale factor for g1 and g2 */ + if (si1 > si2) { + g2 >>= si1 - si2; + g_e = si1 - s; + } else { + g1 >>= si2 - si1; + g_e = si2 - s; + } + } + + /* end of lpc2mdct() */ + + FDK_ASSERT(g1 >= (FIXP_DBL)0); + FDK_ASSERT(g2 >= (FIXP_DBL)0); + + /* mdct_IntNoiseShaping() */ + { + /* inv_g1_g2 * 2^inv_g1_g2_e = 1/(g1+g2) */ + inv_g1_g2 = (g1 >> 1) + (g2 >> 1); + if (inv_g1_g2 != (FIXP_DBL)0) { + inv_g1_g2 = fDivNorm(FL2FXCONST_DBL(0.5f), inv_g1_g2, &inv_g1_g2_e); + inv_g1_g2_e = inv_g1_g2_e - g_e; + } else { + inv_g1_g2 = (FIXP_DBL)MAXVAL_DBL; + inv_g1_g2_e = 0; + } + + if (g_e < 0) { + /* a_e = g_e + inv_g1_g2_e + 1 */ + a = scaleValue(fMult(fMult(g1, g2), inv_g1_g2), g_e); + /* b_e = g_e + inv_g1_g2_e */ + b = fMult(g2 - g1, inv_g1_g2); + shift = g_e + inv_g1_g2_e + 1 - NSHAPE_SCALE; + } else { + /* a_e = (g_e+g_e) + inv_g1_g2_e + 1 */ + a = fMult(fMult(g1, g2), inv_g1_g2); + /* b_e = (g_e+g_e) + inv_g1_g2_e */ + b = scaleValue(fMult(g2 - g1, inv_g1_g2), -g_e); + shift = (g_e + g_e) + inv_g1_g2_e + 1 - NSHAPE_SCALE; + } + + for (i = k * step; i < (k + 1) * step; i++) { + FIXP_DBL tmp; + + /* rr[i] = 2*a*r[i] + b*rr[i-1] */ + tmp = fMult(a, r[i]); + tmp += scaleValue(fMultDiv2(b, rr_minus_one), NSHAPE_SCALE); + tmp = scaleValueSaturate(tmp, shift); + rr_minus_one = tmp; + r[i] = tmp; + } + } + } + + /* end of mdct_IntNoiseShaping() */ + { *pScale += NSHAPE_SCALE; } + + C_AALLOC_SCRATCH_END(tmp1, FIXP_DBL, FDNS_NPTS * 8) +} + +/** + * \brief Calculates the energy. + * \param r pointer to spectrum. + * \param rs scale factor of spectrum r. + * \param lg frame length in audio samples. + * \param rms_e pointer to exponent of energy value. + * \return mantissa of energy value. + */ +static FIXP_DBL calcEnergy(const FIXP_DBL *r, const SHORT rs, const INT lg, + INT *rms_e) { + int headroom = getScalefactor(r, lg); + + FIXP_DBL rms_m = 0; + + /* Calculate number of growth bits due to addition */ + INT shift = (INT)(fNormz((FIXP_DBL)lg)); + shift = 31 - shift; + + /* Generate 1e-2 in Q-6.37 */ + const FIXP_DBL value0_01 = 0x51eb851e; + const INT value0_01_exp = -6; + + /* Find the exponent of the resulting energy value */ + *rms_e = ((rs - headroom) << 1) + shift + 1; + + INT delta = *rms_e - value0_01_exp; + if (delta > 0) { + /* Limit shift_to 31*/ + delta = fMin(31, delta); + rms_m = value0_01 >> delta; + } else { + rms_m = value0_01; + *rms_e = value0_01_exp; + shift = shift - delta; + /* Limit shift_to 31*/ + shift = fMin(31, shift); + } + + for (int i = 0; i < lg; i++) { + rms_m += fPow2Div2(r[i] << headroom) >> shift; + } + + return rms_m; +} + +/** + * \brief TCX gain calculation. + * \param pAacDecoderChannelInfo channel context data. + * \param r output spectrum. + * \param rms_e pointer to mantissa of energy value. + * \param rms_e pointer to exponent of energy value. + * \param frame the frame index of the LPD super frame. + * \param lg the frame length in audio samples. + * \param gain_m pointer to mantissa of TCX gain. + * \param gain_e pointer to exponent of TCX gain. + * \param elFlags element specific parser guidance flags. + * \param lg_fb the fullband frame length in audio samples. + * \param IGF_bgn the IGF start index. + */ +static void calcTCXGain(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + FIXP_DBL *r, FIXP_DBL rms_m, INT rms_e, const INT frame, + const INT lg) { + if ((rms_m != (FIXP_DBL)0)) { + FIXP_DBL tcx_gain_m; + INT tcx_gain_e; + + CLpd_DecodeGain(&tcx_gain_m, &tcx_gain_e, + pAacDecoderChannelInfo->pDynData->specificTo.usac + .tcx_global_gain[frame]); + + /* rms * 2^rms_e = lg/sqrt(sum(spec^2)) */ + if (rms_e & 1) { + rms_m >>= 1; + rms_e++; + } + + { + FIXP_DBL fx_lg; + INT fx_lg_e, s; + INT inv_e; + + /* lg = fx_lg * 2^fx_lg_e */ + s = fNorm((FIXP_DBL)lg); + fx_lg = (FIXP_DBL)lg << s; + fx_lg_e = DFRACT_BITS - 1 - s; + /* 1/sqrt(rms) */ + rms_m = invSqrtNorm2(rms_m, &inv_e); + rms_m = fMult(rms_m, fx_lg); + rms_e = inv_e - (rms_e >> 1) + fx_lg_e; + } + + { + int s = fNorm(tcx_gain_m); + tcx_gain_m = tcx_gain_m << s; + tcx_gain_e -= s; + } + + tcx_gain_m = fMultDiv2(tcx_gain_m, rms_m); + tcx_gain_e = tcx_gain_e + rms_e; + + /* global_gain * 2^(global_gain_e+rms_e) = (10^(global_gain/28)) * rms * + * 2^rms_e */ + { + { tcx_gain_e += 1; } + } + + pAacDecoderChannelInfo->data.usac.tcx_gain[frame] = tcx_gain_m; + pAacDecoderChannelInfo->data.usac.tcx_gain_e[frame] = tcx_gain_e; + + pAacDecoderChannelInfo->specScale[frame] += tcx_gain_e; + } +} + +/** + * \brief FDNS decoding. + * \param pAacDecoderChannelInfo channel context data. + * \param pAacDecoderStaticChannelInfo channel context static data. + * \param r output spectrum. + * \param lg the frame length in audio samples. + * \param frame the frame index of the LPD super frame. + * \param pScale pointer to current scale shift factor of r[]. + * \param A1 old input LPC coefficients of length M_LP_FILTER_ORDER. + * \param A2 new input LPC coefficients of length M_LP_FILTER_ORDER. + * \param pAlfdGains pointer for ALFD gains output scaled by 1. + * \param fdns_npts number of lines (FDNS_NPTS). + * \param inf_mask pointer to noise mask. + * \param IGF_win_mode IGF window mode (LONG, SHORT, TCX10, TCX20). + * \param frameType (IGF_FRAME_DIVISION_AAC_OR_TCX_LONG or + * IGF_FRAME_DIVISION_TCX_SHORT_1). + * \param elFlags element specific parser guidance flags. + * \param lg_fb the fullband frame length in audio samples. + * \param IGF_bgn the IGF start index. + * \param rms_m mantisse of energy. + * \param rms_e exponent of energy. + */ +/* static */ +void CLpd_FdnsDecode(CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + FIXP_DBL r[], const INT lg, const INT frame, SHORT *pScale, + const FIXP_LPC A1[M_LP_FILTER_ORDER], const INT A1_exp, + const FIXP_LPC A2[M_LP_FILTER_ORDER], const INT A2_exp, + FIXP_DBL pAlfdGains[LFAC / 4], const INT fdns_npts) { + /* Weight LPC coefficients using Rm values */ + CLpd_AdaptLowFreqDeemph(r, lg, pAlfdGains, *pScale); + + FIXP_DBL rms_m = (FIXP_DBL)0; + INT rms_e = 0; + { + /* Calculate Energy */ + rms_m = calcEnergy(r, *pScale, lg, &rms_e); + } + + calcTCXGain(pAacDecoderChannelInfo, r, rms_m, rms_e, frame, lg); + + /* Apply ODFT and Noise Shaping. LP coefficient (A1, A2) weighting is done + * inside on the fly. */ + + lpc2mdctAndNoiseShaping(r, pScale, lg, fdns_npts, A1, A1_exp, A2, A2_exp); +} + +/** + * find pitch for TCX20 (time domain) concealment. + */ +static int find_mpitch(FIXP_DBL xri[], int lg) { + FIXP_DBL max, pitch; + INT pitch_e; + int i, n; + + max = (FIXP_DBL)0; + n = 2; + + /* find maximum below 400Hz */ + for (i = 2; i < (lg >> 4); i += 2) { + FIXP_DBL tmp = fPow2Div2(xri[i]) + fPow2Div2(xri[i + 1]); + if (tmp > max) { + max = tmp; + n = i; + } + } + + // pitch = ((float)lg<<1)/(float)n; + pitch = fDivNorm((FIXP_DBL)lg << 1, (FIXP_DBL)n, &pitch_e); + pitch >>= fixMax(0, DFRACT_BITS - 1 - pitch_e - 16); + + /* find pitch multiple under 20ms */ + if (pitch >= (FIXP_DBL)((256 << 16) - 1)) { /*231.0f*/ + n = 256; + } else { + FIXP_DBL mpitch = pitch; + while (mpitch < (FIXP_DBL)(255 << 16)) { + mpitch += pitch; + } + n = (int)(mpitch - pitch) >> 16; + } + + return (n); +} + +/** + * number of spectral coefficients / time domain samples using frame mode as + * index. + */ +static const int lg_table_ccfl[2][4] = { + {256, 256, 512, 1024}, /* coreCoderFrameLength = 1024 */ + {192, 192, 384, 768} /* coreCoderFrameLength = 768 */ +}; + +/** + * \brief Decode and render one MDCT-TCX frame. + * \param pAacDecoderChannelInfo channel context data. + * \param lg the frame length in audio samples. + * \param frame the frame index of the LPD super frame. + */ +static void CLpd_TcxDecode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags, + int mod, int last_mod, int frame, int frameOk) { + FIXP_DBL *pAlfd_gains = pAacDecoderStaticChannelInfo->last_alfd_gains; + ULONG *pSeed = &pAacDecoderStaticChannelInfo->nfRandomSeed; + int lg = (pAacDecoderChannelInfo->granuleLength == 128) + ? lg_table_ccfl[0][mod + 0] + : lg_table_ccfl[1][mod + 0]; + int next_frame = frame + (1 << (mod - 1)); + int isFullBandLpd = 0; + + /* Obtain r[] vector by combining the quant[] and noise[] vectors */ + { + FIXP_DBL noise_level; + FIXP_DBL *coeffs = + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd); + int scale = pAacDecoderChannelInfo->specScale[frame]; + int i, nfBgn, nfEnd; + UCHAR tcx_noise_factor = pAacDecoderChannelInfo->pDynData->specificTo.usac + .tcx_noise_factor[frame]; + + /* find pitch for bfi case */ + pAacDecoderStaticChannelInfo->last_tcx_pitch = find_mpitch(coeffs, lg); + + if (frameOk) { + /* store for concealment */ + pAacDecoderStaticChannelInfo->last_tcx_noise_factor = tcx_noise_factor; + } else { + /* restore last frames value */ + tcx_noise_factor = pAacDecoderStaticChannelInfo->last_tcx_noise_factor; + } + + noise_level = + (FIXP_DBL)((LONG)FL2FXCONST_DBL(0.0625f) * (8 - tcx_noise_factor)); + noise_level = scaleValue(noise_level, -scale); + + const FIXP_DBL neg_noise_level = -noise_level; + + { + nfBgn = lg / 6; + nfEnd = lg; + } + + for (i = nfBgn; i < nfEnd - 7; i += 8) { + LONG tmp; + + /* Fill all 8 consecutive zero coeffs with noise */ + tmp = coeffs[i + 0] | coeffs[i + 1] | coeffs[i + 2] | coeffs[i + 3] | + coeffs[i + 4] | coeffs[i + 5] | coeffs[i + 6] | coeffs[i + 7]; + + if (tmp == 0) { + for (int k = i; k < i + 8; k++) { + UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level) + : (coeffs[k] = noise_level); + } + } + } + if ((nfEnd - i) > + 0) { /* noise filling for last "band" with less than 8 bins */ + LONG tmp = (LONG)coeffs[i]; + int k; + + FDK_ASSERT((nfEnd - i) < 8); + for (k = 1; k < (nfEnd - i); k++) { + tmp |= (LONG)coeffs[i + k]; + } + if (tmp == 0) { + for (k = i; k < nfEnd; k++) { + UsacRandomSign(pSeed) ? (coeffs[k] = neg_noise_level) + : (coeffs[k] = noise_level); + } + } + } + } + + { + /* Convert LPC to LP domain */ + if (last_mod == 0) { + /* Note: The case where last_mod == 255 is handled by other means + * in CLpdChannelStream_Read() */ + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[frame], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame]); + } + + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[next_frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame]); + + /* FDNS decoding */ + CLpd_FdnsDecode( + pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + lg, frame, pAacDecoderChannelInfo->specScale + frame, + pAacDecoderChannelInfo->data.usac.lp_coeff[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[frame], + pAacDecoderChannelInfo->data.usac.lp_coeff[next_frame], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[next_frame], pAlfd_gains, + pAacDecoderChannelInfo->granuleLength / 2 /* == FDNS_NPTS(ccfl) */ + ); + } +} + +/** + * \brief Read the tcx_coding bitstream part + * \param hBs bitstream handle to read from. + * \param pAacDecoderChannelInfo channel context info to store data into. + * \param lg the frame length in audio samples. + * \param first_tcx_flag flag indicating that this is the first TCX frame. + * \param frame the frame index of the LPD super frame. + */ +static AAC_DECODER_ERROR CLpd_TCX_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, int lg, + int first_tcx_flag, int frame, UINT flags) { + AAC_DECODER_ERROR errorAAC = AAC_DEC_OK; + ARITH_CODING_ERROR error = ARITH_CODER_OK; + FIXP_DBL *pSpec; + int arith_reset_flag = 0; + int isFullBandLpd = 0; + + pSpec = SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, frame, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd); + + /* TCX noise level */ + { + pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_noise_factor[frame] = + FDKreadBits(hBs, 3); + } + /* TCX global gain */ + pAacDecoderChannelInfo->pDynData->specificTo.usac.tcx_global_gain[frame] = + FDKreadBits(hBs, 7); + + /* Arithmetic coded residual/spectrum */ + if (first_tcx_flag) { + if (flags & AC_INDEP) { + arith_reset_flag = 1; + } else { + arith_reset_flag = FDKreadBits(hBs, 1); + } + } + + /* CArco_DecodeArithData() output scale of "pSpec" is DFRACT_BITS-1 */ + error = CArco_DecodeArithData(pAacDecoderStaticChannelInfo->hArCo, hBs, pSpec, + lg, lg, arith_reset_flag); + + /* Rescale residual/spectrum */ + { + int scale = getScalefactor(pSpec, lg) - 2; /* Leave 2 bits headroom */ + + /* Exponent of CArco_DecodeArithData() output is DFRACT_BITS; integer + * values. */ + scaleValues(pSpec, lg, scale); + scale = DFRACT_BITS - 1 - scale; + + pAacDecoderChannelInfo->specScale[frame] = scale; + } + + if (error == ARITH_CODER_ERROR) errorAAC = AAC_DEC_UNKNOWN; + + return errorAAC; +} + +/** + * \brief translate lpd_mode into the mod[] array which describes the mode of + * each each LPD frame + * \param mod[] the array that will be filled with the mode indexes of the + * inidividual frames. + * \param lpd_mode the lpd_mode field read from the lpd_channel_stream + */ +static AAC_DECODER_ERROR CLpd_ReadAndMapLpdModeToModArray( + UCHAR mod[4], HANDLE_FDK_BITSTREAM hBs, UINT elFlags) { + int lpd_mode; + + { + lpd_mode = FDKreadBits(hBs, 5); + + if (lpd_mode > 25 || lpd_mode < 0) { + return AAC_DEC_PARSE_ERROR; + } + + switch (lpd_mode) { + case 25: + /* 1 80MS frame */ + mod[0] = mod[1] = mod[2] = mod[3] = 3; + break; + case 24: + /* 2 40MS frames */ + mod[0] = mod[1] = mod[2] = mod[3] = 2; + break; + default: + switch (lpd_mode >> 2) { + case 4: + /* lpd_mode 19 - 16 => 1 40MS and 2 20MS frames */ + mod[0] = mod[1] = 2; + mod[2] = (lpd_mode & 1) ? 1 : 0; + mod[3] = (lpd_mode & 2) ? 1 : 0; + break; + case 5: + /* lpd_mode 23 - 20 => 2 20MS and 1 40MS frames */ + mod[2] = mod[3] = 2; + mod[0] = (lpd_mode & 1) ? 1 : 0; + mod[1] = (lpd_mode & 2) ? 1 : 0; + break; + default: + /* lpd_mode < 16 => 4 20MS frames */ + mod[0] = (lpd_mode & 1) ? 1 : 0; + mod[1] = (lpd_mode & 2) ? 1 : 0; + mod[2] = (lpd_mode & 4) ? 1 : 0; + mod[3] = (lpd_mode & 8) ? 1 : 0; + break; + } + break; + } + } + return AAC_DEC_OK; +} + +static void CLpd_Reset( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + int keep_past_signal) { + int i; + + /* Reset TCX / ACELP common memory */ + if (!keep_past_signal) { + FDKmemclear(pAacDecoderStaticChannelInfo->old_synth, + sizeof(pAacDecoderStaticChannelInfo->old_synth)); + } + + /* Initialize the LSFs */ + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + pAacDecoderStaticChannelInfo->lpc4_lsf[i] = fdk_dec_lsf_init[i]; + } + + /* Reset memory needed by bass post-filter */ + FDKmemclear(pAacDecoderStaticChannelInfo->mem_bpf, + sizeof(pAacDecoderStaticChannelInfo->mem_bpf)); + + pAacDecoderStaticChannelInfo->old_bpf_control_info = 0; + for (i = 0; i < SYN_SFD; i++) { + pAacDecoderStaticChannelInfo->old_T_pf[i] = 64; + pAacDecoderStaticChannelInfo->old_gain_pf[i] = (FIXP_DBL)0; + } + + /* Reset ACELP memory */ + CLpd_AcelpReset(&pAacDecoderStaticChannelInfo->acelp); + + pAacDecoderStaticChannelInfo->last_lpc_lost = 0; /* prev_lpc_lost */ + pAacDecoderStaticChannelInfo->last_tcx_pitch = L_DIV; /* pitch_tcx */ + pAacDecoderStaticChannelInfo->numLostLpdFrames = 0; /* nbLostCmpt */ +} + +/* + * Externally visible functions + */ + +AAC_DECODER_ERROR CLpdChannelStream_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, UINT flags) { + AAC_DECODER_ERROR error = AAC_DEC_OK; + int first_tcx_flag; + int k, nbDiv, fFacDataPresent, first_lpd_flag, acelp_core_mode, + facGetMemState = 0; + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + int lpd_mode_last, prev_frame_was_lpd; + USAC_COREMODE core_mode_last; + const int lg_table_offset = 0; + const int *lg_table = (pAacDecoderChannelInfo->granuleLength == 128) + ? &lg_table_ccfl[0][lg_table_offset] + : &lg_table_ccfl[1][lg_table_offset]; + int last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost; + + int last_frame_ok = CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1); + + INT i_offset; + UINT samplingRate; + + samplingRate = pSamplingRateInfo->samplingRate; + + i_offset = + (INT)(samplingRate * PIT_MIN_12k8 + (FSCALE_DENOM / 2)) / FSCALE_DENOM - + (INT)PIT_MIN_12k8; + + if ((samplingRate < FAC_FSCALE_MIN) || (samplingRate > FAC_FSCALE_MAX)) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + acelp_core_mode = FDKreadBits(hBs, 3); + + /* lpd_mode */ + error = CLpd_ReadAndMapLpdModeToModArray(mod, hBs, 0); + if (error != AAC_DEC_OK) { + goto bail; + } + + /* bpf_control_info */ + pAacDecoderChannelInfo->data.usac.bpf_control_info = FDKreadBit(hBs); + + /* last_core_mode */ + prev_frame_was_lpd = FDKreadBit(hBs); + /* fac_data_present */ + fFacDataPresent = FDKreadBit(hBs); + + /* Set valid values from + * pAacDecoderStaticChannelInfo->{last_core_mode,last_lpd_mode} */ + pAacDecoderChannelInfo->data.usac.core_mode_last = + pAacDecoderStaticChannelInfo->last_core_mode; + lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last = + pAacDecoderStaticChannelInfo->last_lpd_mode; + + if (prev_frame_was_lpd == 0) { + /* Last frame was FD */ + pAacDecoderChannelInfo->data.usac.core_mode_last = FD_LONG; + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255; + } else { + /* Last frame was LPD */ + pAacDecoderChannelInfo->data.usac.core_mode_last = LPD; + if (((mod[0] == 0) && fFacDataPresent) || + ((mod[0] != 0) && !fFacDataPresent)) { + /* Currend mod is ACELP, fac data present -> TCX, current mod TCX, no fac + * data -> TCX */ + if (lpd_mode_last == 0) { + /* Bit stream interruption detected. Assume last TCX mode as TCX20. */ + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 1; + } + /* Else assume that remembered TCX mode is correct. */ + } else { + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 0; + } + } + + first_lpd_flag = (pAacDecoderChannelInfo->data.usac.core_mode_last != + LPD); /* Depends on bitstream configuration */ + first_tcx_flag = 1; + + if (pAacDecoderStaticChannelInfo->last_core_mode != + LPD) { /* ATTENTION: Reset depends on what we rendered before! */ + CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, 0); + + if (!last_frame_ok) { + /* If last rendered frame was not LPD and first lpd flag is not set, this + * must be an error - set last_lpc_lost flag */ + last_lpc_lost |= (first_lpd_flag) ? 0 : 1; + } + } + + core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last; + lpd_mode_last = pAacDecoderChannelInfo->data.usac.lpd_mode_last; + + nbDiv = NB_DIV; + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + + k = 0; + while (k < nbDiv) { + /* Reset FAC data pointers in order to avoid applying old random FAC data. + */ + pAacDecoderChannelInfo->data.usac.fac_data[k] = NULL; + + if ((k == 0 && core_mode_last == LPD && fFacDataPresent) || + (lpd_mode_last == 0 && mod[k] > 0) || + ((lpd_mode_last != 255) && lpd_mode_last > 0 && mod[k] == 0)) { + int err; + + /* Assign FAC memory */ + pAacDecoderChannelInfo->data.usac.fac_data[k] = + CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState); + + /* FAC for (ACELP -> TCX) or (TCX -> ACELP) */ + err = CLpd_FAC_Read( + hBs, pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->data.usac.fac_data_e, + pAacDecoderChannelInfo->granuleLength, /* == fac_length */ + 0, k); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + if (mod[k] == 0) /* acelp-mode */ + { + int err; + err = CLpd_AcelpRead( + hBs, &pAacDecoderChannelInfo->data.usac.acelp[k], acelp_core_mode, + pAacDecoderChannelInfo->granuleLength * 8 /* coreCoderFrameLength */, + i_offset); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + + lpd_mode_last = 0; + k++; + } else /* mode != 0 => TCX */ + { + error = CLpd_TCX_Read(hBs, pAacDecoderChannelInfo, + pAacDecoderStaticChannelInfo, lg_table[mod[k]], + first_tcx_flag, k, flags); + + lpd_mode_last = mod[k]; + first_tcx_flag = 0; + k += 1 << (mod[k] - 1); + } + if (error != AAC_DEC_OK) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + { + int err; + + /* Read LPC coefficients */ + err = CLpc_Read( + hBs, pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand, + pAacDecoderChannelInfo->data.usac.aStability, mod, first_lpd_flag, + /* if last lpc4 is available from concealment do not extrapolate lpc0 + from lpc2 */ + (mod[0] & 0x3) ? 0 + : (last_lpc_lost && + pAacDecoderStaticChannelInfo->last_core_mode != LPD), + last_frame_ok); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + /* adjust old lsp[] following to a bad frame (to avoid overshoot) (ref: + * dec_LPD.c) */ + if (last_lpc_lost && !last_frame_ok) { + int k_next; + k = 0; + while (k < nbDiv) { + int i; + k_next = k + (((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1))); + FIXP_LPC *lsp_old = pAacDecoderChannelInfo->data.usac.lsp_coeff[k]; + FIXP_LPC *lsp_new = pAacDecoderChannelInfo->data.usac.lsp_coeff[k_next]; + + for (i = 0; i < M_LP_FILTER_ORDER; i++) { + if (lsp_new[i] < lsp_old[i]) { + lsp_old[i] = lsp_new[i]; + } + } + k = k_next; + } + } + + if (!CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) { + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[0], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]); + } else if (pAacDecoderStaticChannelInfo->last_lpd_mode != 0) { + if (pAacDecoderStaticChannelInfo->last_lpd_mode == 255) { + /* We need it for TCX decoding or ACELP excitation update */ + E_LPC_f_lsp_a_conversion( + pAacDecoderChannelInfo->data.usac.lsp_coeff[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[0], + &pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]); + } else { /* last_lpd_mode was TCX */ + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } + } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */ + + if (fFacDataPresent && (core_mode_last != LPD)) { + int prev_frame_was_short; + + prev_frame_was_short = FDKreadBit(hBs); + + if (prev_frame_was_short) { + core_mode_last = pAacDecoderChannelInfo->data.usac.core_mode_last = + FD_SHORT; + pAacDecoderChannelInfo->data.usac.lpd_mode_last = 255; + + if ((pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) && + CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 1)) { + /* USAC Conformance document: + short_fac_flag shall be encoded with a value of 1 if the + window_sequence of the previous frame was 2 (EIGHT_SHORT_SEQUENCE). + Otherwise short_fac_flag shall be encoded with a + value of 0. */ + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + + /* Assign memory */ + pAacDecoderChannelInfo->data.usac.fac_data[0] = + CLpd_FAC_GetMemory(pAacDecoderChannelInfo, mod, &facGetMemState); + + { + int err; + + /* FAC for FD -> ACELP */ + err = CLpd_FAC_Read( + hBs, pAacDecoderChannelInfo->data.usac.fac_data[0], + pAacDecoderChannelInfo->data.usac.fac_data_e, + CLpd_FAC_getLength(core_mode_last != FD_SHORT, + pAacDecoderChannelInfo->granuleLength), + 1, 0); + if (err != 0) { + error = AAC_DEC_PARSE_ERROR; + goto bail; + } + } + } + +bail: + if (error == AAC_DEC_OK) { + /* check consitency of last core/lpd mode values */ + if ((pAacDecoderChannelInfo->data.usac.core_mode_last != + pAacDecoderStaticChannelInfo->last_core_mode) && + (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) { + /* Something got wrong! */ + /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */ + } else if ((pAacDecoderChannelInfo->data.usac.core_mode_last == LPD) && + (pAacDecoderChannelInfo->data.usac.lpd_mode_last != + pAacDecoderStaticChannelInfo->last_lpd_mode) && + (pAacDecoderStaticChannelInfo->last_lpc_lost == 0)) { + /* Something got wrong! */ + /* error = AAC_DEC_PARSE_ERROR; */ /* Throwing errors does not help */ + } + } + + return error; +} + +void CLpdChannelStream_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags) { + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + int k; + UCHAR last_lpd_mode; + int nbDiv = NB_DIV; + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + last_lpd_mode = + pAacDecoderChannelInfo->data.usac + .lpd_mode_last; /* could be different to what has been rendered */ + while (k < nbDiv) { + if (mod[k] == 0) { + /* ACELP */ + + /* If FAC (fac_data[k] != NULL), and previous frame was TCX, apply (TCX) + * gains to FAC data */ + if (last_lpd_mode > 0 && last_lpd_mode != 255 && + pAacDecoderChannelInfo->data.usac.fac_data[k]) { + CFac_ApplyGains(pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->granuleLength, + pAacDecoderStaticChannelInfo->last_tcx_gain, + pAacDecoderStaticChannelInfo->last_alfd_gains, + (last_lpd_mode < 4) ? last_lpd_mode : 3); + + pAacDecoderChannelInfo->data.usac.fac_data_e[k] += + pAacDecoderStaticChannelInfo->last_tcx_gain_e; + } + } else { + /* TCX */ + CLpd_TcxDecode(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags, mod[k], last_lpd_mode, k, 1 /* frameOk == 1 */ + ); + + /* Store TCX gain scale for next possible FAC transition. */ + pAacDecoderStaticChannelInfo->last_tcx_gain = + pAacDecoderChannelInfo->data.usac.tcx_gain[k]; + pAacDecoderStaticChannelInfo->last_tcx_gain_e = + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k]; + + /* If FAC (fac_data[k] != NULL), apply gains */ + if (last_lpd_mode == 0 && pAacDecoderChannelInfo->data.usac.fac_data[k]) { + CFac_ApplyGains( + pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->granuleLength /* == fac_length */, + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + pAacDecoderStaticChannelInfo->last_alfd_gains, mod[k]); + + pAacDecoderChannelInfo->data.usac.fac_data_e[k] += + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k]; + } + } + + /* remember previous mode */ + last_lpd_mode = mod[k]; + + /* Increase k to next frame */ + k += (mod[k] == 0) ? 1 : (1 << (mod[k] - 1)); + } +} + +AAC_DECODER_ERROR CLpd_RenderTimeSignal( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, + INT lFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, UINT flags, + UINT strmFlags) { + UCHAR *mod = pAacDecoderChannelInfo->data.usac.mod; + AAC_DECODER_ERROR error = AAC_DEC_OK; + int k, i_offset; + int last_k; + int nrSamples = 0; + int facFB = 1; + int nbDiv = NB_DIV; + int lDiv = lFrame / nbDiv; /* length of division (acelp or tcx20 frame)*/ + int lFac = lDiv / 2; + int nbSubfr = + lFrame / (nbDiv * L_SUBFR); /* number of subframes per division */ + int nbSubfrSuperfr = nbDiv * nbSubfr; + int synSfd = (nbSubfrSuperfr / 2) - BPF_SFD; + int SynDelay = synSfd * L_SUBFR; + int aacDelay = lFrame / 2; + + /* + In respect to the reference software, the synth pointer here is lagging by + aacDelay ( == SYN_DELAY + BPF_DELAY ) samples. The corresponding old + synthesis samples are handled by the IMDCT overlap. + */ + + FIXP_DBL *synth_buf = + pAacDecoderChannelInfo->pComStaticData->pWorkBufferCore1->synth_buf; + FIXP_DBL *synth = synth_buf + PIT_MAX_MAX - BPF_DELAY; + UCHAR last_lpd_mode, last_last_lpd_mode, last_lpc_lost, last_frame_lost; + + INT pitch[NB_SUBFR_SUPERFR + SYN_SFD]; + FIXP_DBL pit_gain[NB_SUBFR_SUPERFR + SYN_SFD]; + + const int *lg_table; + int lg_table_offset = 0; + + UINT samplingRate = pSamplingRateInfo->samplingRate; + + FDKmemclear(pitch, (NB_SUBFR_SUPERFR + SYN_SFD) * sizeof(INT)); + + if (flags & AACDEC_FLUSH) { + CLpd_Reset(pAacDecoderChannelInfo, pAacDecoderStaticChannelInfo, + flags & AACDEC_FLUSH); + frameOk = 0; + } + + switch (lFrame) { + case 1024: + lg_table = &lg_table_ccfl[0][lg_table_offset]; + break; + case 768: + lg_table = &lg_table_ccfl[1][lg_table_offset]; + break; + default: + FDK_ASSERT(0); + return AAC_DEC_UNKNOWN; + } + + last_frame_lost = !CConcealment_GetLastFrameOk( + &pAacDecoderStaticChannelInfo->concealmentInfo, 0); + + /* Maintain LPD mode from previous frame */ + if ((pAacDecoderStaticChannelInfo->last_core_mode == FD_LONG) || + (pAacDecoderStaticChannelInfo->last_core_mode == FD_SHORT)) { + pAacDecoderStaticChannelInfo->last_lpd_mode = 255; + } + + if (!frameOk) { + FIXP_DBL old_tcx_gain; + FIXP_SGL old_stab; + SCHAR old_tcx_gain_e; + int nLostSf; + + last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode; + old_tcx_gain = pAacDecoderStaticChannelInfo->last_tcx_gain; + old_tcx_gain_e = pAacDecoderStaticChannelInfo->last_tcx_gain_e; + old_stab = pAacDecoderStaticChannelInfo->oldStability; + nLostSf = pAacDecoderStaticChannelInfo->numLostLpdFrames; + + /* patch the last LPD mode */ + pAacDecoderChannelInfo->data.usac.lpd_mode_last = last_lpd_mode; + + /* Do mode extrapolation and repeat the previous mode: + if previous mode = ACELP -> ACELP + if previous mode = TCX-20/40 -> TCX-20 + if previous mode = TCX-80 -> TCX-80 + notes: + - ACELP is not allowed after TCX (no pitch information to reuse) + - TCX-40 is not allowed in the mode repetition to keep the logic simple + */ + switch (last_lpd_mode) { + case 0: + mod[0] = mod[1] = mod[2] = mod[3] = 0; /* -> ACELP concealment */ + break; + case 3: + mod[0] = mod[1] = mod[2] = mod[3] = 3; /* -> TCX FD concealment */ + break; + case 2: + mod[0] = mod[1] = mod[2] = mod[3] = 2; /* -> TCX FD concealment */ + break; + case 1: + default: + mod[0] = mod[1] = mod[2] = mod[3] = 4; /* -> TCX TD concealment */ + break; + } + + /* LPC extrapolation */ + CLpc_Conceal(pAacDecoderChannelInfo->data.usac.lsp_coeff, + pAacDecoderStaticChannelInfo->lpc4_lsf, + pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + /*(pAacDecoderStaticChannelInfo->numLostLpdFrames == 0) ||*/ + (last_lpd_mode == 255)); + + if ((last_lpd_mode > 0) && (last_lpd_mode < 255)) { + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } /* case last_lpd_mode was ACELP is handled by CLpd_TcxDecode() */ + /* case last_lpd_mode was Time domain TCX concealment is handled after this + * "if (!frameOk)"-block */ + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + while (k < nbDiv) { + pAacDecoderChannelInfo->data.usac.tcx_gain[k] = old_tcx_gain; + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] = old_tcx_gain_e; + + /* restore stability value from last frame */ + pAacDecoderChannelInfo->data.usac.aStability[k] = old_stab; + + /* Increase k to next frame */ + k += ((mod[k] & 0x3) == 0) ? 1 : (1 << ((mod[k] & 0x3) - 1)); + + nLostSf++; + } + } else { + if ((pAacDecoderStaticChannelInfo->last_lpd_mode == 4) && (mod[0] > 0)) { + /* Copy old LPC4 LP domain coefficients to LPC0 LP domain buffer (to avoid + * converting LSP coefficients again). */ + FDKmemcpy(pAacDecoderChannelInfo->data.usac.lp_coeff[0], + pAacDecoderStaticChannelInfo->lp_coeff_old[0], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0] = + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0]; + } + } + + Acelp_PreProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth, pitch, + pAacDecoderStaticChannelInfo->old_T_pf, pit_gain, + pAacDecoderStaticChannelInfo->old_gain_pf, samplingRate, + &i_offset, lFrame, synSfd, nbSubfrSuperfr); + + /* k is the frame index. If a frame is of size 40MS or 80MS, + this frame index is incremented 2 or 4 instead of 1 respectively. */ + k = 0; + last_k = -1; /* mark invalid */ + last_lpd_mode = pAacDecoderStaticChannelInfo->last_lpd_mode; + last_last_lpd_mode = pAacDecoderStaticChannelInfo->last_last_lpd_mode; + last_lpc_lost = pAacDecoderStaticChannelInfo->last_lpc_lost | last_frame_lost; + + /* This buffer must be avalable for the case of FD->ACELP transition. The + beginning of the buffer is used after the BPF to overwrite the output signal. + Only the FAC area must be affected by the BPF */ + + while (k < nbDiv) { + if (frameOk == 0) { + pAacDecoderStaticChannelInfo->numLostLpdFrames++; + } else { + last_frame_lost |= + (pAacDecoderStaticChannelInfo->numLostLpdFrames > 0) ? 1 : 0; + pAacDecoderStaticChannelInfo->numLostLpdFrames = 0; + } + if (mod[k] == 0 || mod[k] == 4) { + /* ACELP or TCX time domain concealment */ + FIXP_DBL *acelp_out; + + /* FAC management */ + if ((last_lpd_mode != 0) && (last_lpd_mode != 4)) /* TCX TD concealment */ + { + FIXP_DBL *pFacData = NULL; + + if (frameOk && !last_frame_lost) { + pFacData = pAacDecoderChannelInfo->data.usac.fac_data[k]; + } + + nrSamples += CLpd_FAC_Mdct2Acelp( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, pFacData, + pAacDecoderChannelInfo->data.usac.fac_data_e[k], + pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], + lFrame - nrSamples, + CLpd_FAC_getLength( + (pAacDecoderStaticChannelInfo->last_core_mode != FD_SHORT) || + (k > 0), + lFac), + (pAacDecoderStaticChannelInfo->last_core_mode != LPD) && (k == 0), + 0); + + FDKmemcpy( + synth + nrSamples, pAacDecoderStaticChannelInfo->IMdct.overlap.time, + pAacDecoderStaticChannelInfo->IMdct.ov_offset * sizeof(FIXP_DBL)); + { + FIXP_LPC *lp_prev = + pAacDecoderChannelInfo->data.usac + .lp_coeff[0]; /* init value does not real matter */ + INT lp_prev_exp = pAacDecoderChannelInfo->data.usac.lp_coeff_exp[0]; + + if (last_lpd_mode != 255) { /* last mode was tcx */ + last_k = k - (1 << (last_lpd_mode - 1)); + if (last_k < 0) { + lp_prev = pAacDecoderStaticChannelInfo->lp_coeff_old[1]; + lp_prev_exp = pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1]; + } else { + lp_prev = pAacDecoderChannelInfo->data.usac.lp_coeff[last_k]; + lp_prev_exp = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k]; + } + } + + CLpd_AcelpPrepareInternalMem( + synth + aacDelay + k * lDiv, last_lpd_mode, + (last_last_lpd_mode == 4) ? 0 : last_last_lpd_mode, + pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], lp_prev, + lp_prev_exp, &pAacDecoderStaticChannelInfo->acelp, lFrame, + (last_frame_lost && k < 2), mod[k]); + } + } else { + if (k == 0 && pAacDecoderStaticChannelInfo->IMdct.ov_offset != + lFrame / facFB / 2) { + pAacDecoderStaticChannelInfo->IMdct.ov_offset = lFrame / facFB / 2; + } + nrSamples += imdct_drain(&pAacDecoderStaticChannelInfo->IMdct, + synth + nrSamples, lFrame / facFB - nrSamples); + } + + if (nrSamples >= lFrame / facFB) { + /* Write ACELP time domain samples into IMDCT overlap buffer at + * pAacDecoderStaticChannelInfo->IMdct.overlap.time + + * pAacDecoderStaticChannelInfo->IMdct.ov_offset + */ + acelp_out = pAacDecoderStaticChannelInfo->IMdct.overlap.time + + pAacDecoderStaticChannelInfo->IMdct.ov_offset; + + /* Account ACELP time domain output samples to overlap buffer */ + pAacDecoderStaticChannelInfo->IMdct.ov_offset += lDiv; + } else { + /* Write ACELP time domain samples into output buffer at pTimeData + + * nrSamples */ + acelp_out = synth + nrSamples; + + /* Account ACELP time domain output samples to output buffer */ + nrSamples += lDiv; + } + + if (mod[k] == 4) { + pAacDecoderStaticChannelInfo->acelp.wsyn_rms = scaleValue( + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + fixMin(0, + pAacDecoderChannelInfo->data.usac.tcx_gain_e[k] - SF_EXC)); + CLpd_TcxTDConceal(&pAacDecoderStaticChannelInfo->acelp, + &pAacDecoderStaticChannelInfo->last_tcx_pitch, + pAacDecoderChannelInfo->data.usac.lsp_coeff[k], + pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1], + pAacDecoderChannelInfo->data.usac.aStability[k], + pAacDecoderStaticChannelInfo->numLostLpdFrames, + acelp_out, lFrame, + pAacDecoderStaticChannelInfo->last_tcx_noise_factor); + + } else { + FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[k] >= + (FIXP_SGL)0); + CLpd_AcelpDecode(&pAacDecoderStaticChannelInfo->acelp, i_offset, + pAacDecoderChannelInfo->data.usac.lsp_coeff[k], + pAacDecoderChannelInfo->data.usac.lsp_coeff[k + 1], + pAacDecoderChannelInfo->data.usac.aStability[k], + &pAacDecoderChannelInfo->data.usac.acelp[k], + pAacDecoderStaticChannelInfo->numLostLpdFrames, + last_lpc_lost, k, acelp_out, + &pitch[(k * nbSubfr) + synSfd], + &pit_gain[(k * nbSubfr) + synSfd], lFrame); + } + + if (mod[k] != 4) { + if (last_lpd_mode != 0 && + pAacDecoderChannelInfo->data.usac + .bpf_control_info) { /* FD/TCX -> ACELP transition */ + /* bass post-filter past FAC area (past two (one for FD short) + * subframes) */ + int currentSf = synSfd + k * nbSubfr; + + if ((k > 0) || (pAacDecoderStaticChannelInfo->last_core_mode != + FD_SHORT)) { /* TCX or FD long -> ACELP */ + pitch[currentSf - 2] = pitch[currentSf - 1] = pitch[currentSf]; + pit_gain[currentSf - 2] = pit_gain[currentSf - 1] = + pit_gain[currentSf]; + } else { /* FD short -> ACELP */ + pitch[currentSf - 1] = pitch[currentSf]; + pit_gain[currentSf - 1] = pit_gain[currentSf]; + } + } + } + } else { /* TCX */ + int lg = lg_table[mod[k]]; + int isFullBandLpd = 0; + + /* FAC management */ + if ((last_lpd_mode == 0) || (last_lpd_mode == 4)) /* TCX TD concealment */ + { + C_AALLOC_SCRATCH_START(fac_buf, FIXP_DBL, 1024 / 8); + + /* pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL means no FAC + * data available. */ + if (last_frame_lost == 1 || + pAacDecoderChannelInfo->data.usac.fac_data[k] == NULL) { + FDKmemclear(fac_buf, 1024 / 8 * sizeof(FIXP_DBL)); + pAacDecoderChannelInfo->data.usac.fac_data[k] = fac_buf; + pAacDecoderChannelInfo->data.usac.fac_data_e[k] = 0; + } + + nrSamples += CLpd_FAC_Acelp2Mdct( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + pAacDecoderChannelInfo->specScale + k, 1, + pAacDecoderChannelInfo->data.usac.fac_data[k], + pAacDecoderChannelInfo->data.usac.fac_data_e[k], + pAacDecoderChannelInfo->granuleLength /* == fac_length */, + lFrame - nrSamples, lg, + FDKgetWindowSlope(lDiv, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + lDiv, pAacDecoderChannelInfo->data.usac.lp_coeff[k], + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[k], + &pAacDecoderStaticChannelInfo->acelp, + pAacDecoderChannelInfo->data.usac.tcx_gain[k], + (last_frame_lost || !frameOk), 0 /* is not FD FAC */ + , + last_lpd_mode, k, + pAacDecoderChannelInfo + ->currAliasingSymmetry /* Note: The current aliasing + symmetry for a TCX (i.e. LPD) + frame must always be 0 */ + ); + + pitch[(k * nbSubfr) + synSfd + 1] = pitch[(k * nbSubfr) + synSfd] = + pitch[(k * nbSubfr) + synSfd - 1]; + pit_gain[(k * nbSubfr) + synSfd + 1] = + pit_gain[(k * nbSubfr) + synSfd] = + pit_gain[(k * nbSubfr) + synSfd - 1]; + + C_AALLOC_SCRATCH_END(fac_buf, FIXP_DBL, 1024 / 8); + } else { + int tl = lg; + int fl = lDiv; + int fr = lDiv; + + nrSamples += imlt_block( + &pAacDecoderStaticChannelInfo->IMdct, synth + nrSamples, + SPEC_TCX(pAacDecoderChannelInfo->pSpectralCoefficient, k, + pAacDecoderChannelInfo->granuleLength, isFullBandLpd), + pAacDecoderChannelInfo->specScale + k, 1, lFrame - nrSamples, tl, + FDKgetWindowSlope(fl, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fl, + FDKgetWindowSlope(fr, + GetWindowShape(&pAacDecoderChannelInfo->icsInfo)), + fr, pAacDecoderChannelInfo->data.usac.tcx_gain[k], + pAacDecoderChannelInfo->currAliasingSymmetry + ? MLT_FLAG_CURR_ALIAS_SYMMETRY + : 0); + } + } + /* remember previous mode */ + last_last_lpd_mode = last_lpd_mode; + last_lpd_mode = mod[k]; + last_lpc_lost = (frameOk == 0) ? 1 : 0; + + /* Increase k to next frame */ + last_k = k; + k += ((mod[k] & 0x3) == 0) ? 1 : (1 << (mod[k] - 1)); + } + + if (frameOk) { + /* assume data was ok => store for concealment */ + FDK_ASSERT(pAacDecoderChannelInfo->data.usac.aStability[last_k] >= + (FIXP_SGL)0); + pAacDecoderStaticChannelInfo->oldStability = + pAacDecoderChannelInfo->data.usac.aStability[last_k]; + FDKmemcpy(pAacDecoderStaticChannelInfo->lsf_adaptive_mean, + pAacDecoderChannelInfo->data.usac.lsf_adaptive_mean_cand, + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + } + + /* store past lp coeffs for next superframe (they are only valid and needed if + * last_lpd_mode was tcx) */ + if (last_lpd_mode > 0) { + FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[0], + pAacDecoderChannelInfo->data.usac.lp_coeff[nbDiv], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[0] = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[nbDiv]; + FDKmemcpy(pAacDecoderStaticChannelInfo->lp_coeff_old[1], + pAacDecoderChannelInfo->data.usac.lp_coeff[last_k], + M_LP_FILTER_ORDER * sizeof(FIXP_LPC)); + pAacDecoderStaticChannelInfo->lp_coeff_old_exp[1] = + pAacDecoderChannelInfo->data.usac.lp_coeff_exp[last_k]; + } + + FDK_ASSERT(nrSamples == lFrame); + + /* check whether usage of bass postfilter was de-activated in the bitstream; + if yes, set pitch gain to 0 */ + if (!(pAacDecoderChannelInfo->data.usac.bpf_control_info)) { + if (mod[0] != 0 && (pAacDecoderStaticChannelInfo->old_bpf_control_info)) { + for (int i = 2; i < nbSubfrSuperfr; i++) + pit_gain[synSfd + i] = (FIXP_DBL)0; + } else { + for (int i = 0; i < nbSubfrSuperfr; i++) + pit_gain[synSfd + i] = (FIXP_DBL)0; + } + } + + /* for bass postfilter */ + for (int n = 0; n < synSfd; n++) { + pAacDecoderStaticChannelInfo->old_T_pf[n] = pitch[nbSubfrSuperfr + n]; + pAacDecoderStaticChannelInfo->old_gain_pf[n] = pit_gain[nbSubfrSuperfr + n]; + } + + pAacDecoderStaticChannelInfo->old_bpf_control_info = + pAacDecoderChannelInfo->data.usac.bpf_control_info; + + { + INT lookahead = -BPF_DELAY; + int copySamp = (mod[nbDiv - 1] == 0) ? (aacDelay) : (aacDelay - lFac); + + /* Copy enough time domain samples from MDCT to synthesis buffer as needed + * by the bass postfilter */ + + lookahead += imdct_copy_ov_and_nr(&pAacDecoderStaticChannelInfo->IMdct, + synth + nrSamples, copySamp); + + FDK_ASSERT(lookahead == copySamp - BPF_DELAY); + + FIXP_DBL *p2_synth = synth + BPF_DELAY; + + /* recalculate pitch gain to allow postfilering on FAC area */ + for (int i = 0; i < nbSubfrSuperfr; i++) { + int T = pitch[i]; + FIXP_DBL gain = pit_gain[i]; + + if (gain > (FIXP_DBL)0) { + gain = get_gain(&p2_synth[i * L_SUBFR], &p2_synth[(i * L_SUBFR) - T], + L_SUBFR); + pit_gain[i] = gain; + } + } + + { + bass_pf_1sf_delay(p2_synth, pitch, pit_gain, lFrame, lFrame / facFB, + mod[nbDiv - 1] ? (SynDelay - (lDiv / 2)) : SynDelay, + pTimeData, pAacDecoderStaticChannelInfo->mem_bpf); + } + } + + Acelp_PostProcessing(synth_buf, pAacDecoderStaticChannelInfo->old_synth, + pitch, pAacDecoderStaticChannelInfo->old_T_pf, lFrame, + synSfd, nbSubfrSuperfr); + + /* Store last mode for next super frame */ + { pAacDecoderStaticChannelInfo->last_core_mode = LPD; } + pAacDecoderStaticChannelInfo->last_lpd_mode = last_lpd_mode; + pAacDecoderStaticChannelInfo->last_last_lpd_mode = last_last_lpd_mode; + pAacDecoderStaticChannelInfo->last_lpc_lost = last_lpc_lost; + + return error; +} diff --git a/fdk-aac/libAACdec/src/usacdec_lpd.h b/fdk-aac/libAACdec/src/usacdec_lpd.h new file mode 100644 index 0000000..3e7938d --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_lpd.h @@ -0,0 +1,198 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): Manuel Jander + + Description: USAC Linear Prediction Domain coding + +*******************************************************************************/ + +#ifndef USACDEC_LPD_H +#define USACDEC_LPD_H + +#include "channelinfo.h" + +#define OPTIMIZE_AVG_PERFORMANCE + +/** + * \brief read a lpd_channel_stream. + * \param hBs a bit stream handle, where the lpd_channel_stream is located. + * \param pAacDecoderChannelInfo the channel context structure for storing read + * data. + * \param flags bit stream syntax flags. + * \return AAC_DECODER_ERROR error code. + */ +AAC_DECODER_ERROR CLpdChannelStream_Read( + HANDLE_FDK_BITSTREAM hBs, CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + const SamplingRateInfo *pSamplingRateInfo, UINT flags); + +/** + * \brief decode one lpd_channel_stream and render the audio output. + * \param pAacDecoderChannelInfo struct holding the channel information to be + * rendered. + * \param pAacDecoderStaticChannelInfo struct holding the persistent channel + * information to be rendered. + * \param pSamplingRateInfo holds the sampling rate information + * \param elFlags holds the internal decoder flags + */ +void CLpdChannelStream_Decode( + CAacDecoderChannelInfo *pAacDecoderChannelInfo, + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, UINT flags); + +/** + * \brief generate time domain output signal for LPD channel streams + * \param pAacDecoderStaticChannelInfo + * \param pAacDecoderChannelInfo + * \param pTimeData pointer to output buffer + * \param samplesPerFrame amount of output samples + * \param pSamplingRateInfo holds the sampling rate information + * \param pWorkBuffer1 pointer to work buffer for temporal data + */ +AAC_DECODER_ERROR CLpd_RenderTimeSignal( + CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo, + CAacDecoderChannelInfo *pAacDecoderChannelInfo, FIXP_PCM *pTimeData, + INT samplesPerFrame, SamplingRateInfo *pSamplingRateInfo, UINT frameOk, + UINT flags, UINT strmFlags); + +static inline INT CLpd_FAC_getLength(int fNotShortBlock, int fac_length_long) { + if (fNotShortBlock) { + return (fac_length_long); + } else { + return fac_length_long / 2; + } +} + +void filtLP(const FIXP_DBL *syn, FIXP_PCM *syn_out, FIXP_DBL *noise, + const FIXP_SGL *filt, INT stop, int len); + +/** + * \brief perform a low-frequency pitch enhancement on time domain signal + * \param[in] syn pointer to time domain input signal + * \param[in] synFB pointer to time domain input signal + * \param[in] upsampling factor + * \param[in] T_sf array with past decoded pitch period values for each subframe + * \param[in] non_zero_gain_flags indicates whether pitch gains of past + * subframes are zero or not, msb -> [1 BPF_DELAY subfr][7 SYN_DELAY subfr][16 + * new subfr] <- lsb + * \param[in] l_frame length of filtering, must be multiple of L_SUBFR + * \param[in] l_next length of allowed look ahead on syn[i], i < l_frame+l_next + * \param[out] synth_out pointer to time domain output signal + * \param[in,out] mem_bpf pointer to filter memory (L_FILT+L_SUBFR) + */ + +void bass_pf_1sf_delay(FIXP_DBL syn[], const INT T_sf[], FIXP_DBL *pit_gain, + const int frame_length, const INT l_frame, + const INT l_next, FIXP_PCM *synth_out, + FIXP_DBL mem_bpf[]); + +/** + * \brief random sign generator for FD and TCX noise filling + * \param[in,out] seed pointer to random seed + * \return if return value is zero use positive sign + * \Note: This code is also implemented as a copy in block.cpp, grep for + * "UsacRandomSign" + */ +FDK_INLINE +int UsacRandomSign(ULONG *seed) { + *seed = (ULONG)((UINT64)(*seed) * 69069 + 5); + + return (int)((*seed) & 0x10000); +} + +void CFdp_Reset(CAacDecoderStaticChannelInfo *pAacDecoderStaticChannelInfo); + +#endif /* USACDEC_LPD_H */ diff --git a/fdk-aac/libAACdec/src/usacdec_rom.cpp b/fdk-aac/libAACdec/src/usacdec_rom.cpp new file mode 100644 index 0000000..ca3009e --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_rom.cpp @@ -0,0 +1,1504 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): M. Jander + + Description: + +*******************************************************************************/ + +#include "usacdec_rom.h" + +#define NB_SPHERE 32 +#define NB_LEADER 37 +#define NB_LDSIGN 226 +#define NB_LDQ3 9 +#define NB_LDQ4 28 + +/* For bass post filter */ +#define FL2FXCONST_SGL_FILT(a) FL2FXCONST_SGL(a*(1 << SF_FILT_LP)) +#define SF_FILT_LP 1 + +/* table of factorial */ +const UINT fdk_dec_tab_factorial[8] = {5040, 720, 120, 24, 6, 2, 1, 1}; + +/* Da - Absolute leaders */ +const UCHAR fdk_dec_Da[NB_LEADER][8] = { + {1, 1, 1, 1, 1, 1, 1, 1}, {2, 2, 0, 0, 0, 0, 0, 0}, + {2, 2, 2, 2, 0, 0, 0, 0}, {3, 1, 1, 1, 1, 1, 1, 1}, + {4, 0, 0, 0, 0, 0, 0, 0}, {2, 2, 2, 2, 2, 2, 0, 0}, + {3, 3, 1, 1, 1, 1, 1, 1}, {4, 2, 2, 0, 0, 0, 0, 0}, + {2, 2, 2, 2, 2, 2, 2, 2}, {3, 3, 3, 1, 1, 1, 1, 1}, + {4, 2, 2, 2, 2, 0, 0, 0}, {4, 4, 0, 0, 0, 0, 0, 0}, + {5, 1, 1, 1, 1, 1, 1, 1}, {3, 3, 3, 3, 1, 1, 1, 1}, + {4, 2, 2, 2, 2, 2, 2, 0}, {4, 4, 2, 2, 0, 0, 0, 0}, + {5, 3, 1, 1, 1, 1, 1, 1}, {6, 2, 0, 0, 0, 0, 0, 0}, + {4, 4, 4, 0, 0, 0, 0, 0}, {6, 2, 2, 2, 0, 0, 0, 0}, + {6, 4, 2, 0, 0, 0, 0, 0}, {7, 1, 1, 1, 1, 1, 1, 1}, + {8, 0, 0, 0, 0, 0, 0, 0}, {6, 6, 0, 0, 0, 0, 0, 0}, + {8, 2, 2, 0, 0, 0, 0, 0}, {8, 4, 0, 0, 0, 0, 0, 0}, + {9, 1, 1, 1, 1, 1, 1, 1}, {10, 2, 0, 0, 0, 0, 0, 0}, + {8, 8, 0, 0, 0, 0, 0, 0}, {10, 6, 0, 0, 0, 0, 0, 0}, + {12, 0, 0, 0, 0, 0, 0, 0}, {12, 4, 0, 0, 0, 0, 0, 0}, + {10, 10, 0, 0, 0, 0, 0, 0}, {14, 2, 0, 0, 0, 0, 0, 0}, + {12, 8, 0, 0, 0, 0, 0, 0}, {16, 0, 0, 0, 0, 0, 0, 0}, + {20, 0, 0, 0, 0, 0, 0, 0}}; + +/* Ds - Sign codes of all signed leaders */ +const UCHAR fdk_dec_Ds[NB_LDSIGN] = { + 0, 3, 15, 63, 255, 0, 64, 192, 0, 16, 48, 112, 240, 1, 7, + 31, 127, 128, 131, 143, 191, 0, 128, 0, 4, 12, 28, 60, 124, 252, + 0, 3, 15, 63, 65, 71, 95, 192, 195, 207, 255, 0, 32, 96, 128, + 160, 224, 0, 1, 3, 7, 15, 31, 63, 127, 255, 1, 7, 31, 32, + 35, 47, 97, 103, 127, 224, 227, 239, 0, 8, 24, 56, 120, 128, 136, + 152, 184, 248, 0, 64, 192, 0, 3, 15, 63, 129, 135, 159, 255, 0, + 3, 15, 17, 23, 48, 51, 63, 113, 119, 240, 243, 255, 0, 2, 6, + 14, 30, 62, 126, 128, 130, 134, 142, 158, 190, 254, 0, 16, 48, 64, + 80, 112, 192, 208, 240, 1, 7, 31, 64, 67, 79, 127, 128, 131, 143, + 191, 193, 199, 223, 0, 64, 128, 192, 0, 32, 96, 224, 0, 16, 48, + 112, 128, 144, 176, 240, 0, 32, 64, 96, 128, 160, 192, 224, 1, 7, + 31, 127, 128, 131, 143, 191, 0, 128, 0, 64, 192, 0, 32, 96, 128, + 160, 224, 0, 64, 128, 192, 0, 3, 15, 63, 129, 135, 159, 255, 0, + 64, 128, 192, 0, 64, 192, 0, 64, 128, 192, 0, 128, 0, 64, 128, + 192, 0, 64, 192, 0, 64, 128, 192, 0, 64, 128, 192, 0, 128, 0, + 128}; + +/* Ns - Number of signed leader associated to a given absolute leader */ +const UCHAR fdk_dec_Ns[NB_LEADER] = { + 5, 3, 5, 8, 2, 7, 11, 6, 9, 12, 10, 3, 8, 13, 14, 9, 14, 4, 4, + 8, 8, 8, 2, 3, 6, 4, 8, 4, 3, 4, 2, 4, 3, 4, 4, 2, 2}; + +/* Ia - Position of the first signed leader associated to an absolute leader */ +const UCHAR fdk_dec_Ia[NB_LEADER] = { + 0, 5, 8, 13, 21, 23, 30, 41, 47, 56, 68, 78, 81, + 89, 102, 116, 125, 139, 143, 147, 155, 163, 171, 173, 176, 182, + 186, 194, 198, 201, 205, 207, 211, 214, 218, 222, 224}; + +/* Is - Cardinalite offset of signed leaders */ +const USHORT fdk_dec_Is[NB_LDSIGN] = { + 0, 1, 29, 99, 127, 128, 156, 212, 256, 326, 606, + 1026, 1306, 1376, 1432, 1712, 1880, 1888, 1896, 2064, 2344, 240, + 248, 0, 28, 196, 616, 1176, 1596, 1764, 1792, 1820, 2240, + 2660, 2688, 3024, 4144, 4480, 4508, 4928, 5348, 2400, 2568, 2904, + 3072, 3240, 3576, 5376, 5377, 5385, 5413, 5469, 5539, 5595, 5623, + 5631, 5632, 5912, 6472, 6528, 6696, 8376, 9216, 10056, 11736, 11904, + 11960, 12520, 12800, 13080, 14200, 15880, 17000, 17280, 17560, 18680, 20360, + 21480, 3744, 3772, 3828, 21760, 21768, 21936, 22216, 22272, 22328, 22608, + 22776, 22784, 22854, 23274, 23344, 24464, 25584, 26004, 28524, 28944, 30064, + 31184, 31254, 31674, 31744, 31800, 32136, 32976, 34096, 34936, 35272, 35328, + 35384, 35720, 36560, 37680, 38520, 38856, 38912, 39332, 40172, 40592, 41432, + 43112, 43952, 44372, 45212, 45632, 45968, 47088, 47424, 47480, 48320, 49160, + 49216, 49272, 50112, 50952, 51008, 51344, 52464, 3856, 3912, 3968, 4024, + 52800, 52856, 53024, 53192, 53248, 53528, 54368, 55208, 55488, 55768, 56608, + 57448, 57728, 58064, 58400, 58736, 59072, 59408, 59744, 60080, 60416, 60472, + 60752, 60920, 60928, 60936, 61104, 61384, 4080, 4088, 61440, 61468, 61524, + 61552, 61720, 62056, 62224, 62392, 62728, 62896, 62952, 63008, 63064, 63120, + 63128, 63296, 63576, 63632, 63688, 63968, 64136, 64144, 64200, 64256, 64312, + 64368, 64396, 64452, 64480, 64536, 64592, 64648, 64704, 64712, 64720, 64776, + 64832, 64888, 64944, 64972, 65028, 65056, 65112, 65168, 65224, 65280, 65336, + 65392, 65448, 65504, 65512, 65520, 65528}; + +/* A3 - Number of the absolute leaders in codebooks Q2 and Q3 */ +const UCHAR fdk_dec_A3[NB_LDQ3] = {0, 1, 4, 2, 3, 7, 11, 17, 22}; + +/* A4 - Number of the absolute leaders in codebook Q4 */ +const UCHAR fdk_dec_A4[NB_LDQ4] = {5, 6, 8, 9, 10, 12, 13, 14, 15, 16, + 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36}; + +/* I3 - Cardinality offsets for absolute leaders in Q3 */ +const USHORT fdk_dec_I3[NB_LDQ3] = {0, 128, 240, 256, 1376, + 2400, 3744, 3856, 4080}; + +/* I4 - Cardinality offset for absolute leaders in Q4 */ +const USHORT fdk_dec_I4[NB_LDQ4] = { + 0, 1792, 5376, 5632, 12800, 21760, 22784, 31744, 38912, 45632, + 52800, 53248, 57728, 60416, 61440, 61552, 62896, 63120, 64144, 64368, + 64480, 64704, 64720, 64944, 65056, 65280, 65504, 65520}; + +/* Initial ISF memory for concealment case */ +#define LSFI(x) ((x) << (FRACT_BITS - LSF_SCALE - 1)) + +const FIXP_LPC fdk_dec_lsf_init[16] = {1506, 3012, 4518, 6024, 7529, 9035, + 10541, 12047, 13553, 15059, 16565, 18071, + 19576, 21082, 22588, 24094}; + +/* dico_lsf_abs_8b is scaled by 1/(1<<13) */ +#define DICO(x) FX_DBL2FXCONST_LPC(x >> (LSF_SCALE - 13)) + +const FIXP_LPC fdk_dec_dico_lsf_abs_8b[] = { + DICO(0x05e57fe8), DICO(0x0ac00810), DICO(0x11ed8500), DICO(0x16d42ce0), + DICO(0x1beb1e20), DICO(0x217eaf40), DICO(0x2768c740), DICO(0x2d26f600), + DICO(0x32fe68c0), DICO(0x38b1d980), DICO(0x3e95bd80), DICO(0x446dab00), + DICO(0x4abfd280), DICO(0x5094b380), DICO(0x56ccb800), DICO(0x5c9aba00), + DICO(0x09660ca0), DICO(0x10ab4c00), DICO(0x15a16f20), DICO(0x19d3c780), + DICO(0x1ee99060), DICO(0x241d1200), DICO(0x29c83700), DICO(0x2f098f00), + DICO(0x34803fc0), DICO(0x3a37bc00), DICO(0x3ff55580), DICO(0x45da9280), + DICO(0x4bec6700), DICO(0x5169e300), DICO(0x57797c80), DICO(0x5d09ae80), + DICO(0x08a203b0), DICO(0x0d6ed1a0), DICO(0x152ccf20), DICO(0x19639dc0), + DICO(0x1d7e3e60), DICO(0x21f4a7c0), DICO(0x27b2f8c0), DICO(0x2dbb4480), + DICO(0x33ecde80), DICO(0x3982e100), DICO(0x3ea16100), DICO(0x43ab6080), + DICO(0x49534a80), DICO(0x4ea7e100), DICO(0x550d6300), DICO(0x5bcdcc80), + DICO(0x072dd048), DICO(0x0c654690), DICO(0x1436e940), DICO(0x19459680), + DICO(0x1e0041c0), DICO(0x2240dc80), DICO(0x26de4040), DICO(0x2b509b00), + DICO(0x309d8780), DICO(0x36151180), DICO(0x3c6c1200), DICO(0x42df6b80), + DICO(0x4a144400), DICO(0x50541280), DICO(0x56c34b80), DICO(0x5cb6c600), + DICO(0x051fef00), DICO(0x06b9fb48), DICO(0x0b4f9cc0), DICO(0x17e27800), + DICO(0x1b8c7340), DICO(0x1f772ca0), DICO(0x2478dc80), DICO(0x28242240), + DICO(0x2f27c640), DICO(0x33b03e80), DICO(0x381f20c0), DICO(0x3c662c00), + DICO(0x49565080), DICO(0x529b0f00), DICO(0x583ed080), DICO(0x5d8cec00), + DICO(0x071c4d18), DICO(0x097853b0), DICO(0x0f0f0690), DICO(0x157bf980), + DICO(0x1801f580), DICO(0x1deb0c20), DICO(0x2523da40), DICO(0x28534600), + DICO(0x2eb499c0), DICO(0x32eb5ac0), DICO(0x36749580), DICO(0x3a748200), + DICO(0x4325f700), DICO(0x515d8300), DICO(0x58a18700), DICO(0x5d722100), + DICO(0x06cbcd88), DICO(0x08bb6740), DICO(0x0dead310), DICO(0x152f0cc0), + DICO(0x18427640), DICO(0x1d9f2f20), DICO(0x22ba3b40), DICO(0x271a6e80), + DICO(0x2c677ec0), DICO(0x31061b00), DICO(0x349eef40), DICO(0x3c531b80), + DICO(0x4aed0580), DICO(0x4f8bbf80), DICO(0x54b74980), DICO(0x5bc9b700), + DICO(0x046410c8), DICO(0x06522ab0), DICO(0x0b6528c0), DICO(0x0f94bd90), + DICO(0x1a8f8b80), DICO(0x1ea57820), DICO(0x233ee180), DICO(0x27b3acc0), + DICO(0x2bd1d240), DICO(0x2fc4bcc0), DICO(0x3a98ea40), DICO(0x43d3f500), + DICO(0x49b37580), DICO(0x4e2afd00), DICO(0x55953300), DICO(0x5d36f600), + DICO(0x05d0f6c8), DICO(0x07e56d90), DICO(0x0be98080), DICO(0x0f956f30), + DICO(0x1259b3c0), DICO(0x1f08b240), DICO(0x25008c00), DICO(0x2900b180), + DICO(0x31ea6f00), DICO(0x352d1e00), DICO(0x3c970c80), DICO(0x45271200), + DICO(0x4b632280), DICO(0x5098a480), DICO(0x5672fc80), DICO(0x5c163180), + DICO(0x05bd81a0), DICO(0x07d4b8f0), DICO(0x0ce224b0), DICO(0x110abe20), + DICO(0x13dfeac0), DICO(0x17dedae0), DICO(0x2535c0c0), DICO(0x2a19da80), + DICO(0x2e5224c0), DICO(0x38ddeec0), DICO(0x3da99d80), DICO(0x42799100), + DICO(0x48973b00), DICO(0x4ea62880), DICO(0x53f77e80), DICO(0x5bd9c100), + DICO(0x0395cd50), DICO(0x058244b8), DICO(0x0af45520), DICO(0x1329cea0), + DICO(0x1a3970c0), DICO(0x1d9f2e00), DICO(0x21704400), DICO(0x277a34c0), + DICO(0x30215b40), DICO(0x33875040), DICO(0x3c159840), DICO(0x452fea00), + DICO(0x4981d200), DICO(0x4e15a980), DICO(0x54e84780), DICO(0x5c79ea00), + DICO(0x05413b98), DICO(0x08132a80), DICO(0x0dc7f050), DICO(0x13e25460), + DICO(0x1784bf80), DICO(0x1d630200), DICO(0x238bc880), DICO(0x28cc0880), + DICO(0x30da1a40), DICO(0x391e2200), DICO(0x415d8d00), DICO(0x48f13280), + DICO(0x4e300300), DICO(0x52e56580), DICO(0x5849fe80), DICO(0x5cdef400), + DICO(0x04a058c8), DICO(0x07569b88), DICO(0x0ef26610), DICO(0x13208140), + DICO(0x168c0500), DICO(0x1afec080), DICO(0x22a0abc0), DICO(0x2a057880), + DICO(0x2fd1c840), DICO(0x3703c680), DICO(0x3d326b80), DICO(0x43df2e80), + DICO(0x4a6f9000), DICO(0x50900d80), DICO(0x56c73f00), DICO(0x5cc3da80), + DICO(0x065c99e8), DICO(0x09060c50), DICO(0x0d1ef1c0), DICO(0x16bd9020), + DICO(0x1a04dae0), DICO(0x1e3c0580), DICO(0x25783700), DICO(0x29710ac0), + DICO(0x309cbb80), DICO(0x36c66280), DICO(0x3adb0580), DICO(0x41b37e00), + DICO(0x496ca700), DICO(0x4dab7600), DICO(0x52be6280), DICO(0x58fec480), + DICO(0x04640880), DICO(0x05a75ab8), DICO(0x0edba410), DICO(0x16e076a0), + DICO(0x198acec0), DICO(0x1eb5fae0), DICO(0x228c9000), DICO(0x29986c00), + DICO(0x2c780c80), DICO(0x38078dc0), DICO(0x3f42dc00), DICO(0x441ba900), + DICO(0x492f8080), DICO(0x4ed85d00), DICO(0x54605800), DICO(0x5d106a80), + DICO(0x045cb970), DICO(0x0627a828), DICO(0x0db35290), DICO(0x1778f780), + DICO(0x1a243c60), DICO(0x23c2dd40), DICO(0x27c57840), DICO(0x2f53cd80), + DICO(0x36f65600), DICO(0x3bc1b2c0), DICO(0x40c36500), DICO(0x46074180), + DICO(0x4b551b80), DICO(0x50a99700), DICO(0x569b6c80), DICO(0x5ca25780), + DICO(0x05ef2828), DICO(0x07d3adf8), DICO(0x0b5416d0), DICO(0x0f9adb70), + DICO(0x126e7360), DICO(0x1baff460), DICO(0x2b5decc0), DICO(0x31036200), + DICO(0x34ca7500), DICO(0x39681340), DICO(0x3da97100), DICO(0x4161ee00), + DICO(0x46a62e80), DICO(0x4d1b9380), DICO(0x530e0300), DICO(0x59ff0480), + DICO(0x04f5bc50), DICO(0x06e90d18), DICO(0x0c2af480), DICO(0x123f7400), + DICO(0x1530a160), DICO(0x18aa3dc0), DICO(0x1cc0a240), DICO(0x2cdb02c0), + DICO(0x32909a00), DICO(0x36bae640), DICO(0x3c917a80), DICO(0x40121900), + DICO(0x48a90d80), DICO(0x51ccc180), DICO(0x5884ea00), DICO(0x5dbc4280), + DICO(0x05791410), DICO(0x07b0dd80), DICO(0x0bec4190), DICO(0x13c30520), + DICO(0x17ac1900), DICO(0x1b6f1d00), DICO(0x26e54f40), DICO(0x2d4a8040), + DICO(0x311c6840), DICO(0x38ec4180), DICO(0x3f0c4340), DICO(0x427c5b00), + DICO(0x4886e480), DICO(0x504a0b00), DICO(0x56d48700), DICO(0x5c80f600), + DICO(0x04b58880), DICO(0x0743f0d8), DICO(0x0be95e20), DICO(0x0fd0d9b0), + DICO(0x1c2e11a0), DICO(0x2241af80), DICO(0x296e83c0), DICO(0x2f16adc0), + DICO(0x32cd6fc0), DICO(0x374ddec0), DICO(0x3da95f80), DICO(0x45d56c80), + DICO(0x4c6afa80), DICO(0x5141f380), DICO(0x5616b380), DICO(0x5c58f580), + DICO(0x03f4b368), DICO(0x05939890), DICO(0x09d95480), DICO(0x122cac60), + DICO(0x17e27e00), DICO(0x1f9dc680), DICO(0x26e26680), DICO(0x2ae64040), + DICO(0x2dd6cf40), DICO(0x3295c400), DICO(0x3e23b400), DICO(0x44fd0380), + DICO(0x4ad7a700), DICO(0x51295e80), DICO(0x594a9400), DICO(0x5e41aa00), + DICO(0x0424b9d8), DICO(0x05b30508), DICO(0x09380f20), DICO(0x0c9509c0), + DICO(0x18730860), DICO(0x219a9d40), DICO(0x24f699c0), DICO(0x289b2680), + DICO(0x2cb62240), DICO(0x36e88180), DICO(0x3e968800), DICO(0x48053c80), + DICO(0x4d6dca80), DICO(0x51d9a580), DICO(0x563e5a80), DICO(0x5c0b2b80), + DICO(0x03456ae8), DICO(0x04e49948), DICO(0x07dd0e88), DICO(0x0ed5cd30), + DICO(0x1b06e980), DICO(0x1de2b9c0), DICO(0x21160540), DICO(0x270a8240), + DICO(0x3352a280), DICO(0x3b8b6c00), DICO(0x40241400), DICO(0x43f60f80), + DICO(0x4a897900), DICO(0x51692a00), DICO(0x57449d00), DICO(0x5d497480), + DICO(0x04b94290), DICO(0x067e99d0), DICO(0x0ab06840), DICO(0x0e697070), + DICO(0x1745c460), DICO(0x22ee8040), DICO(0x2647e8c0), DICO(0x2bc2c680), + DICO(0x2fd57d00), DICO(0x37186680), DICO(0x3d074500), DICO(0x412b2800), + DICO(0x4579af00), DICO(0x4caff980), DICO(0x557add00), DICO(0x5c6ae780), + DICO(0x0423a090), DICO(0x05b9bca0), DICO(0x091b45d0), DICO(0x0c5b6d60), + DICO(0x194dd1c0), DICO(0x1fc85020), DICO(0x2486b080), DICO(0x2920af80), + DICO(0x2dd4f140), DICO(0x3598be40), DICO(0x3b9c1440), DICO(0x42d19280), + DICO(0x4a314280), DICO(0x50b00a00), DICO(0x56c55400), DICO(0x5d5ba300), + DICO(0x03e68b28), DICO(0x05a7b190), DICO(0x0917f000), DICO(0x0d247050), + DICO(0x19e637a0), DICO(0x2221a540), DICO(0x2777e540), DICO(0x2c103380), + DICO(0x30c2e040), DICO(0x389f1240), DICO(0x3f4a2c80), DICO(0x454a4c00), + DICO(0x4b0ab680), DICO(0x50cf6000), DICO(0x571c0700), DICO(0x5d2ef600), + DICO(0x04886f18), DICO(0x065103e8), DICO(0x0a607d40), DICO(0x0db91960), + DICO(0x13546f20), DICO(0x22f5e200), DICO(0x27064240), DICO(0x2e371d40), + DICO(0x33659240), DICO(0x38aa1c40), DICO(0x417bb280), DICO(0x47ca9480), + DICO(0x4dd6fb80), DICO(0x528e3480), DICO(0x57c49d80), DICO(0x5cc98100), + DICO(0x02db2370), DICO(0x04398848), DICO(0x07a8da38), DICO(0x10b90280), + DICO(0x1a2a4a20), DICO(0x20b1f640), DICO(0x277096c0), DICO(0x2dc568c0), + DICO(0x341b33c0), DICO(0x3a000640), DICO(0x40152880), DICO(0x45eeee00), + DICO(0x4c08c480), DICO(0x51bf0600), DICO(0x5799a180), DICO(0x5d23db80), + DICO(0x047b1498), DICO(0x06089848), DICO(0x0905af20), DICO(0x0bf13c20), + DICO(0x11fcf620), DICO(0x1f79cd00), DICO(0x257f6b40), DICO(0x2cfc2600), + DICO(0x31610040), DICO(0x35ea8280), DICO(0x3c774bc0), DICO(0x44417280), + DICO(0x4b432500), DICO(0x510e9480), DICO(0x56f2e480), DICO(0x5d282780), + DICO(0x02cfd0b0), DICO(0x042845d8), DICO(0x0a1fa610), DICO(0x15911fc0), + DICO(0x1bc07f00), DICO(0x2281d640), DICO(0x287abcc0), DICO(0x2ec6b400), + DICO(0x34a0d040), DICO(0x3aa4dcc0), DICO(0x4074d980), DICO(0x46726b80), + DICO(0x4c3bf900), DICO(0x52055100), DICO(0x57b20500), DICO(0x5d34da80), + DICO(0x04d4f768), DICO(0x06cad828), DICO(0x0b52a540), DICO(0x0ea224e0), + DICO(0x13c3f460), DICO(0x23808900), DICO(0x27d1cec0), DICO(0x2d6051c0), + DICO(0x33c5ff00), DICO(0x37ef2440), DICO(0x3d2a5300), DICO(0x43266000), + DICO(0x4a53a100), DICO(0x50acce80), DICO(0x57612100), DICO(0x5cdee380), + DICO(0x04039a88), DICO(0x0626dcb0), DICO(0x0c059620), DICO(0x12c3db20), + DICO(0x1bb9eb40), DICO(0x240fda00), DICO(0x2baab840), DICO(0x3177c5c0), + DICO(0x36cf2e40), DICO(0x3c025100), DICO(0x40bb8d00), DICO(0x45960800), + DICO(0x4adaca00), DICO(0x505a7300), DICO(0x566a6400), DICO(0x5c8ce000), + DICO(0x062891e8), DICO(0x09680810), DICO(0x0e9a11b0), DICO(0x1523e320), + DICO(0x1c57db00), DICO(0x21f22c80), DICO(0x28aeeb00), DICO(0x2e4fd600), + DICO(0x341cf000), DICO(0x3a5034c0), DICO(0x40600f80), DICO(0x461fde00), + DICO(0x4c368480), DICO(0x51dbbc00), DICO(0x57709780), DICO(0x5cce9880), + DICO(0x05d41f70), DICO(0x0a65bb30), DICO(0x132ddfa0), DICO(0x17d26820), + DICO(0x1e6d8380), DICO(0x24e68dc0), DICO(0x2b68c4c0), DICO(0x30fa2880), + DICO(0x361998c0), DICO(0x3aa1d640), DICO(0x3f942400), DICO(0x44d11680), + DICO(0x4ab8e580), DICO(0x50643b80), DICO(0x5697fe00), DICO(0x5cb3a780), + DICO(0x0707fa10), DICO(0x0cb8beb0), DICO(0x15011d20), DICO(0x1a4ad300), + DICO(0x20997080), DICO(0x26dbe240), DICO(0x2d907880), DICO(0x3307a3c0), + DICO(0x38819740), DICO(0x3d3e89c0), DICO(0x41ea2300), DICO(0x469ce200), + DICO(0x4be61680), DICO(0x51261b80), DICO(0x5716ef80), DICO(0x5cba2900), + DICO(0x084dc830), DICO(0x0f16f610), DICO(0x16ca2420), DICO(0x1bb58380), + DICO(0x22f00f00), DICO(0x296ba4c0), DICO(0x306d2600), DICO(0x362ca080), + DICO(0x3b86d280), DICO(0x3ffa96c0), DICO(0x446a5300), DICO(0x48d0fd00), + DICO(0x4d8a0800), DICO(0x525bf200), DICO(0x57f5aa00), DICO(0x5d569480), + DICO(0x08d664f0), DICO(0x110c8520), DICO(0x1865fa40), DICO(0x1efe3160), + DICO(0x26f38740), DICO(0x2d4608c0), DICO(0x32862500), DICO(0x374f8840), + DICO(0x3bfa9900), DICO(0x3ff5c8c0), DICO(0x4450c500), DICO(0x4918e680), + DICO(0x4e1d0f00), DICO(0x53342600), DICO(0x58a38e00), DICO(0x5dbbff00), + DICO(0x09143fd0), DICO(0x0f401c30), DICO(0x169c1ee0), DICO(0x1bcfb280), + DICO(0x2190dd00), DICO(0x27bf56c0), DICO(0x2e8e0640), DICO(0x34b67080), + DICO(0x3b534dc0), DICO(0x41134c00), DICO(0x467a3280), DICO(0x4bd63600), + DICO(0x50de8700), DICO(0x55657580), DICO(0x5a0cef00), DICO(0x5e8aa200), + DICO(0x06b5d860), DICO(0x0c8a5000), DICO(0x13343620), DICO(0x17a2abe0), + DICO(0x1caf7340), DICO(0x22a3f740), DICO(0x29059980), DICO(0x2ecff880), + DICO(0x34ce0f00), DICO(0x3ad32280), DICO(0x40f08d80), DICO(0x46d1d400), + DICO(0x4ca9df00), DICO(0x523b9580), DICO(0x57ea9b80), DICO(0x5d4a9a00), + DICO(0x03822fec), DICO(0x0522c670), DICO(0x099f89a0), DICO(0x12ddc9c0), + DICO(0x17c3d380), DICO(0x1d27ec20), DICO(0x2219e480), DICO(0x25fdf580), + DICO(0x329d6500), DICO(0x368ba040), DICO(0x3afedb00), DICO(0x430db980), + DICO(0x4a105380), DICO(0x51205080), DICO(0x5673b880), DICO(0x5ca2e500), + DICO(0x04e07408), DICO(0x06a13dc0), DICO(0x0b31c780), DICO(0x0e67fcd0), + DICO(0x13723240), DICO(0x1f87a840), DICO(0x2321ab00), DICO(0x2c604680), + DICO(0x310bc180), DICO(0x351eea40), DICO(0x3a2d6440), DICO(0x3e7ebac0), + DICO(0x4798ef80), DICO(0x50721100), DICO(0x57ff9880), DICO(0x5dc2e080), + DICO(0x05d626b8), DICO(0x07eaf140), DICO(0x0c5675b0), DICO(0x0eba7b00), + DICO(0x1a7f36c0), DICO(0x1f969200), DICO(0x244d8c00), DICO(0x29666440), + DICO(0x2c94b100), DICO(0x31865380), DICO(0x3713c000), DICO(0x3c228f40), + DICO(0x4296ed80), DICO(0x4dcbde00), DICO(0x56059a00), DICO(0x5c932d00), + DICO(0x07dceb20), DICO(0x0b533fe0), DICO(0x0eb18880), DICO(0x13124220), + DICO(0x167f74e0), DICO(0x1afbee40), DICO(0x229e2f80), DICO(0x26b05ec0), + DICO(0x2c7b4040), DICO(0x32806140), DICO(0x38da6540), DICO(0x3e495540), + DICO(0x444d3880), DICO(0x4e784400), DICO(0x5865f580), DICO(0x5e616180), + DICO(0x06395790), DICO(0x084b8f20), DICO(0x0d0e26a0), DICO(0x10897ac0), + DICO(0x14bcd080), DICO(0x1c5babe0), DICO(0x2108f9c0), DICO(0x274f8e80), + DICO(0x2b0ba180), DICO(0x305b8480), DICO(0x383ad300), DICO(0x3e34f440), + DICO(0x47f7aa00), DICO(0x4fdb5880), DICO(0x56b8c280), DICO(0x5d07d700), + DICO(0x051f0880), DICO(0x071b8fa8), DICO(0x0ce79c90), DICO(0x1005bd60), + DICO(0x14a4a080), DICO(0x183def40), DICO(0x1ee8d0a0), DICO(0x2c5b9bc0), + DICO(0x309f9dc0), DICO(0x35659380), DICO(0x3c0439c0), DICO(0x49603800), + DICO(0x5018a800), DICO(0x54862380), DICO(0x593edd80), DICO(0x5d415b80), + DICO(0x051c8108), DICO(0x06bd97d8), DICO(0x0b47d030), DICO(0x0d9c81a0), + DICO(0x178f0be0), DICO(0x1cdf7c80), DICO(0x2183db40), DICO(0x26ec7180), + DICO(0x2a3856c0), DICO(0x366c9b40), DICO(0x3d3611c0), DICO(0x42788100), + DICO(0x4981f200), DICO(0x4dd68380), DICO(0x55286a00), DICO(0x5cc72500), + DICO(0x06ee58c8), DICO(0x098b1310), DICO(0x0ccbd880), DICO(0x0f9d68f0), + DICO(0x1277ac40), DICO(0x1d71faa0), DICO(0x230d9480), DICO(0x276b8c00), + DICO(0x2ec77000), DICO(0x31f2a700), DICO(0x3bee0200), DICO(0x42250700), + DICO(0x466b7100), DICO(0x4de41980), DICO(0x56a08d80), DICO(0x5d700880), + DICO(0x062f1d80), DICO(0x091bcd30), DICO(0x0cd875e0), DICO(0x0fd42e60), + DICO(0x1322b980), DICO(0x1f11b480), DICO(0x2651e5c0), DICO(0x29f9b480), + DICO(0x2e238840), DICO(0x30fc58c0), DICO(0x37aa3040), DICO(0x3e9ac580), + DICO(0x44c6fd00), DICO(0x4eba4300), DICO(0x56fdad00), DICO(0x5d885700), + DICO(0x04213a78), DICO(0x05d028c0), DICO(0x09a1f9e0), DICO(0x0d28ae90), + DICO(0x151819a0), DICO(0x1c78c860), DICO(0x21d78f00), DICO(0x29992cc0), + DICO(0x2fbdc180), DICO(0x36bab700), DICO(0x3d4db1c0), DICO(0x4402a280), + DICO(0x4a920700), DICO(0x50988600), DICO(0x5717c100), DICO(0x5d52c200), + DICO(0x036af4bc), DICO(0x0514cf40), DICO(0x09ec2d30), DICO(0x113de160), + DICO(0x1991b700), DICO(0x20590bc0), DICO(0x23892a00), DICO(0x2654cd00), + DICO(0x2ff5c0c0), DICO(0x387ed380), DICO(0x3e305300), DICO(0x46137700), + DICO(0x4bc29100), DICO(0x4f96dd80), DICO(0x564aca00), DICO(0x5c4d9e80), + DICO(0x041051a0), DICO(0x0734dad8), DICO(0x1064e780), DICO(0x14d8bf00), + DICO(0x19727e40), DICO(0x1f7bede0), DICO(0x25b5ebc0), DICO(0x2c71fd40), + DICO(0x32813740), DICO(0x39340c80), DICO(0x3f974f40), DICO(0x45ca1580), + DICO(0x4be69f00), DICO(0x51c9c900), DICO(0x57a1ce80), DICO(0x5d0b2b00), + DICO(0x04b73008), DICO(0x06598b60), DICO(0x0b0aee00), DICO(0x15ac7ba0), + DICO(0x18b5e340), DICO(0x1f5308c0), DICO(0x23cfc4c0), DICO(0x27d3fdc0), + DICO(0x30138080), DICO(0x343c85c0), DICO(0x389cb540), DICO(0x42def900), + DICO(0x4aa6a000), DICO(0x4f719580), DICO(0x5585d080), DICO(0x5bc03f00), + DICO(0x05601b88), DICO(0x07616b88), DICO(0x0c22ba40), DICO(0x16bc8200), + DICO(0x192ebf80), DICO(0x1f71c120), DICO(0x25c59d00), DICO(0x28f76d00), + DICO(0x33dbdd80), DICO(0x39f40d80), DICO(0x3da0c880), DICO(0x432c1e00), + DICO(0x4aa19d80), DICO(0x51006f80), DICO(0x56a62e80), DICO(0x5c67d000), + DICO(0x053095d0), DICO(0x06c43fc8), DICO(0x0f80a460), DICO(0x139b4960), + DICO(0x1769ed80), DICO(0x1c828b00), DICO(0x21195980), DICO(0x26329800), + DICO(0x29f35900), DICO(0x2dc9df80), DICO(0x3795f0c0), DICO(0x43139b00), + DICO(0x4acae680), DICO(0x5048de00), DICO(0x57c11880), DICO(0x5db35900), + DICO(0x0466e180), DICO(0x05d31550), DICO(0x10cad200), DICO(0x168c2be0), + DICO(0x1a5e9580), DICO(0x1ef2d480), DICO(0x238db240), DICO(0x2920ce80), + DICO(0x2c80b4c0), DICO(0x30bb2700), DICO(0x38b257c0), DICO(0x46abd580), + DICO(0x4c30dd80), DICO(0x50e51880), DICO(0x5782ab80), DICO(0x5d23da80), + DICO(0x06700f78), DICO(0x085ec0a0), DICO(0x0c037280), DICO(0x16d90a60), + DICO(0x1bf46c00), DICO(0x1e6f4740), DICO(0x22c2c180), DICO(0x263fa2c0), + DICO(0x2c4a74c0), DICO(0x3642b040), DICO(0x3a476900), DICO(0x3ea12840), + DICO(0x46b6e880), DICO(0x4b5bad80), DICO(0x5152a500), DICO(0x5c1c6080), + DICO(0x041f8108), DICO(0x05ef1d98), DICO(0x0ce43300), DICO(0x11647cc0), + DICO(0x16e77fe0), DICO(0x1cdafc40), DICO(0x218832c0), DICO(0x26dd1b40), + DICO(0x2c776100), DICO(0x34f1eb80), DICO(0x3caf6100), DICO(0x45630a80), + DICO(0x4c0c5380), DICO(0x517ae980), DICO(0x567f4280), DICO(0x5c4bf900), + DICO(0x06673f18), DICO(0x091ee510), DICO(0x0d6ccb10), DICO(0x12503240), + DICO(0x158696e0), DICO(0x1f035420), DICO(0x24e6eac0), DICO(0x2a03bf40), + DICO(0x329aa000), DICO(0x375aafc0), DICO(0x3da133c0), DICO(0x45645600), + DICO(0x4c447c00), DICO(0x51a26b00), DICO(0x57917c00), DICO(0x5c557680), + DICO(0x04f84c18), DICO(0x06db4c30), DICO(0x0d53a940), DICO(0x1095cd20), + DICO(0x142b0b20), DICO(0x184229c0), DICO(0x20147280), DICO(0x25152740), + DICO(0x2db89fc0), DICO(0x35f3d200), DICO(0x400aa680), DICO(0x47a51c00), + DICO(0x4d9c5c00), DICO(0x525d1680), DICO(0x5832af00), DICO(0x5d27d580), + DICO(0x05c973d0), DICO(0x07c25810), DICO(0x0e928e50), DICO(0x12f5ad00), + DICO(0x16b2a800), DICO(0x1c2c9ce0), DICO(0x20b0f100), DICO(0x28be1940), + DICO(0x2d0f3c00), DICO(0x30a06f40), DICO(0x399e4340), DICO(0x46b48280), + DICO(0x4bbbc300), DICO(0x50283700), DICO(0x54a1a800), DICO(0x5ab20c80), + DICO(0x03df9390), DICO(0x055ff1e0), DICO(0x0bbeb640), DICO(0x17d906c0), + DICO(0x1ac20140), DICO(0x1fd84440), DICO(0x24502600), DICO(0x2a9fe640), + DICO(0x2ef79700), DICO(0x34cbed40), DICO(0x3c48cd00), DICO(0x43ccce80), + DICO(0x49b1d500), DICO(0x50145e00), DICO(0x56f16f80), DICO(0x5d46dd80), + DICO(0x04a69ef0), DICO(0x06470480), DICO(0x0defbd00), DICO(0x1590e900), + DICO(0x18114000), DICO(0x1bda6c60), DICO(0x1f64d160), DICO(0x28d8d640), + DICO(0x2d4e2880), DICO(0x34cfe380), DICO(0x3b7077c0), DICO(0x42f36a80), + DICO(0x49615580), DICO(0x4ff9d200), DICO(0x5657ef80), DICO(0x5cb91300), + DICO(0x038893dc), DICO(0x0535cdf0), DICO(0x0aabff80), DICO(0x146daaa0), + DICO(0x1848c700), DICO(0x1ce578c0), DICO(0x21116000), DICO(0x2b116d40), + DICO(0x32113500), DICO(0x3751a480), DICO(0x3e88c200), DICO(0x44cb1800), + DICO(0x4af1c200), DICO(0x5122b980), DICO(0x5782bc80), DICO(0x5d20be00), + DICO(0x03118434), DICO(0x04afe2e8), DICO(0x08f144f0), DICO(0x12c787c0), + DICO(0x1c32e4e0), DICO(0x1f701180), DICO(0x2362f740), DICO(0x2b995cc0), + DICO(0x3322c540), DICO(0x3951f200), DICO(0x3f7c2c80), DICO(0x4569c480), + DICO(0x4b2a6200), DICO(0x50905e80), DICO(0x56236680), DICO(0x5c32fa00), + DICO(0x0460c3b0), DICO(0x061e1378), DICO(0x0b07f610), DICO(0x166e0680), + DICO(0x18d0f020), DICO(0x21120340), DICO(0x24d4c000), DICO(0x29bafc00), + DICO(0x338c0740), DICO(0x36cfbc00), DICO(0x3f313900), DICO(0x47bf9c00), + DICO(0x4dd5d480), DICO(0x52848200), DICO(0x585add00), DICO(0x5cf7b480), + DICO(0x041a4bc8), DICO(0x05ca0920), DICO(0x0a3ae5b0), DICO(0x13fbb840), + DICO(0x1cdd3d00), DICO(0x209d5b80), DICO(0x27e78e80), DICO(0x2d1f4ec0), + DICO(0x32d84c80), DICO(0x3b8aa680), DICO(0x4289c180), DICO(0x46c33580), + DICO(0x4c23e580), DICO(0x51583180), DICO(0x56f52680), DICO(0x5c7a3d00), + DICO(0x03067404), DICO(0x05914038), DICO(0x10d33e60), DICO(0x17377180), + DICO(0x1d7f32a0), DICO(0x23848880), DICO(0x29d32200), DICO(0x2fb167c0), + DICO(0x356c8480), DICO(0x3b420280), DICO(0x4106d080), DICO(0x46d29280), + DICO(0x4c8a1200), DICO(0x52383300), DICO(0x57db8f80), DICO(0x5d61f200), + DICO(0x04baf368), DICO(0x06670a08), DICO(0x0e0cbd90), DICO(0x126299c0), + DICO(0x17ed7220), DICO(0x1e369900), DICO(0x22d7d300), DICO(0x2c0f9300), + DICO(0x2f5e7fc0), DICO(0x3b7c0d40), DICO(0x405aff80), DICO(0x44f2ef80), + DICO(0x4982b400), DICO(0x4e501380), DICO(0x539daa00), DICO(0x5c114b00), + DICO(0x0694c170), DICO(0x092d6890), DICO(0x0d0faee0), DICO(0x13800d00), + DICO(0x170f8d80), DICO(0x1bcd8240), DICO(0x246a8480), DICO(0x28bab640), + DICO(0x2f482ac0), DICO(0x36e736c0), DICO(0x3aaa68c0), DICO(0x3fc43500), + DICO(0x46e16000), DICO(0x4b3fbc00), DICO(0x4ff68e80), DICO(0x5aabf600), + DICO(0x05e849a0), DICO(0x0b485a80), DICO(0x14be52c0), DICO(0x1a079380), + DICO(0x1e8b1ce0), DICO(0x22fbca00), DICO(0x28c36a40), DICO(0x2e3b2a00), + DICO(0x34360b80), DICO(0x3a24cf00), DICO(0x3fff6200), DICO(0x45a6bf00), + DICO(0x4baf7800), DICO(0x51720e80), DICO(0x57560c80), DICO(0x5ce57e00), + DICO(0x0751da38), DICO(0x0f0949f0), DICO(0x18141860), DICO(0x1dfcb2c0), + DICO(0x24adbf00), DICO(0x296af240), DICO(0x2dbe60c0), DICO(0x3179ae40), + DICO(0x35ec4400), DICO(0x3ab76400), DICO(0x4034f400), DICO(0x45cfc700), + DICO(0x4bea6b00), DICO(0x516f5f00), DICO(0x57655300), DICO(0x5cfc0e00), + DICO(0x069900d0), DICO(0x0d379520), DICO(0x175d0560), DICO(0x1c4d92c0), + DICO(0x21407680), DICO(0x250d0340), DICO(0x29804940), DICO(0x2dfb9ac0), + DICO(0x337a1f80), DICO(0x39105fc0), DICO(0x3efd0380), DICO(0x44bce380), + DICO(0x4b07cc80), DICO(0x50ad7d00), DICO(0x56ddce80), DICO(0x5cb9a000), + DICO(0x069c6948), DICO(0x0a56ea10), DICO(0x0f7cca20), DICO(0x12d18680), + DICO(0x17036d00), DICO(0x1f4c1e80), DICO(0x262e5540), DICO(0x2b951e40), + DICO(0x3468ad40), DICO(0x3a2b2100), DICO(0x3f02f0c0), DICO(0x4383e400), + DICO(0x48374180), DICO(0x4d8eec80), DICO(0x54d74800), DICO(0x5c309600), + DICO(0x05a50158), DICO(0x0797e350), DICO(0x0cf1f230), DICO(0x14f3fb20), + DICO(0x17676400), DICO(0x20636780), DICO(0x2617ef80), DICO(0x29cbf700), + DICO(0x32ed57c0), DICO(0x374c3080), DICO(0x3b348e40), DICO(0x3fde0180), + DICO(0x44d38c00), DICO(0x4a8c6100), DICO(0x55f0e400), DICO(0x5dfed100), + DICO(0x04b74228), DICO(0x0623d3e0), DICO(0x0ab4c670), DICO(0x1bde7fa0), + DICO(0x1fcb6ac0), DICO(0x2344a540), DICO(0x275f7c40), DICO(0x2b7a8300), + DICO(0x31407440), DICO(0x35237700), DICO(0x38798540), DICO(0x3d0af340), + DICO(0x4224c980), DICO(0x49a17900), DICO(0x57702880), DICO(0x5dba4c00), + DICO(0x03c83c84), DICO(0x05cc52d8), DICO(0x0b644c10), DICO(0x129ab9a0), + DICO(0x1cee46c0), DICO(0x2152b080), DICO(0x247b1c00), DICO(0x27697180), + DICO(0x304f7500), DICO(0x3895d880), DICO(0x3c3a1740), DICO(0x413ace80), + DICO(0x462b0100), DICO(0x4ab07e00), DICO(0x50967580), DICO(0x5ba5e700), + DICO(0x06bcfda8), DICO(0x08c8b920), DICO(0x0de21530), DICO(0x1028d320), + DICO(0x168cfe00), DICO(0x20f78a40), DICO(0x248493c0), DICO(0x2c34bf80), + DICO(0x2ff88540), DICO(0x32d28c40), DICO(0x36d99640), DICO(0x4438e500), + DICO(0x4bacdb00), DICO(0x50343700), DICO(0x56b79080), DICO(0x5b694d00), + DICO(0x069109a0), DICO(0x0a73bc50), DICO(0x0e3c8330), DICO(0x13082620), + DICO(0x1c3a3760), DICO(0x200b5e80), DICO(0x256a4880), DICO(0x2b256ac0), + DICO(0x2f34afc0), DICO(0x35580200), DICO(0x3e0bd9c0), DICO(0x43d92900), + DICO(0x494e6e00), DICO(0x4f1a2780), DICO(0x5532a980), DICO(0x5a835a80), + DICO(0x04053450), DICO(0x05cb8fe0), DICO(0x097387b0), DICO(0x1121af00), + DICO(0x1abf62c0), DICO(0x1e39bbe0), DICO(0x243de300), DICO(0x2b440ec0), + DICO(0x2f2c1480), DICO(0x34697d80), DICO(0x405f8600), DICO(0x440b6f80), + DICO(0x47373100), DICO(0x4c764f80), DICO(0x55293780), DICO(0x5c59a780), + DICO(0x03c5b4a4), DICO(0x056fb380), DICO(0x09b8f910), DICO(0x13833fa0), + DICO(0x185eed60), DICO(0x1ce33d40), DICO(0x242e4100), DICO(0x282e5b80), + DICO(0x2cfe4d40), DICO(0x38a06d80), DICO(0x3e002240), DICO(0x423be400), + DICO(0x49a5e600), DICO(0x5092b780), DICO(0x57023d00), DICO(0x5d5f7c80), + DICO(0x077ada38), DICO(0x09d5ac70), DICO(0x0e58be30), DICO(0x14fb2040), + DICO(0x17fc9dc0), DICO(0x1c2c31e0), DICO(0x26cf1b00), DICO(0x2a91ba80), + DICO(0x2ed880c0), DICO(0x38cbf900), DICO(0x3d2fc700), DICO(0x405d2280), + DICO(0x439c1d00), DICO(0x4dd16800), DICO(0x5672c080), DICO(0x5d313880), + DICO(0x04272090), DICO(0x05d76e18), DICO(0x0b4d8080), DICO(0x12883f60), + DICO(0x17952180), DICO(0x2040d480), DICO(0x23e8cc00), DICO(0x2819c200), + DICO(0x2b871040), DICO(0x357c8f00), DICO(0x3caf9ac0), DICO(0x40a39380), + DICO(0x45bc2780), DICO(0x4e4aa300), DICO(0x568c2280), DICO(0x5cadc400), + DICO(0x0375b03c), DICO(0x056f0b40), DICO(0x0b0dc930), DICO(0x128c51e0), + DICO(0x189fa360), DICO(0x1c8197e0), DICO(0x1eed52a0), DICO(0x23ed4500), + DICO(0x2e5eb840), DICO(0x36415a40), DICO(0x3dcf6340), DICO(0x43126e80), + DICO(0x4aeb7f80), DICO(0x501e1280), DICO(0x5852b100), DICO(0x5d040d80), + DICO(0x06351b88), DICO(0x07f90ac0), DICO(0x0bab4ea0), DICO(0x18d04b40), + DICO(0x1f1e1480), DICO(0x219abcc0), DICO(0x261c31c0), DICO(0x2a611a00), + DICO(0x2e725480), DICO(0x36b511c0), DICO(0x3d362f00), DICO(0x40be6d80), + DICO(0x456dc400), DICO(0x4b74c580), DICO(0x55c82680), DICO(0x5e318480), + DICO(0x046212d8), DICO(0x05ca95e8), DICO(0x0a02d910), DICO(0x1ae58f40), + DICO(0x1e73ec20), DICO(0x2197d640), DICO(0x2581df00), DICO(0x29c83780), + DICO(0x31294300), DICO(0x356f8a40), DICO(0x3b97d240), DICO(0x4505cc80), + DICO(0x4b497600), DICO(0x504e8780), DICO(0x55644480), DICO(0x5bdedf80), + DICO(0x0514f798), DICO(0x06bd0d00), DICO(0x0fc31550), DICO(0x13dfb1a0), + DICO(0x17dda900), DICO(0x204a8c40), DICO(0x23095300), DICO(0x2d0da040), + DICO(0x31b2a540), DICO(0x34620180), DICO(0x3ab3e000), DICO(0x448ac300), + DICO(0x4be6a600), DICO(0x5114e280), DICO(0x562b0780), DICO(0x5b833c00), + DICO(0x070f5ef0), DICO(0x0919c2b0), DICO(0x0e778740), DICO(0x154db320), + DICO(0x177cfbe0), DICO(0x1ea66040), DICO(0x23666680), DICO(0x2839c400), + DICO(0x30cc4ec0), DICO(0x3444a280), DICO(0x38c93580), DICO(0x42a80e00), + DICO(0x4c433880), DICO(0x519e4f80), DICO(0x56ff8f80), DICO(0x5be18200), + DICO(0x066c5968), DICO(0x08a589f0), DICO(0x0ca4d7a0), DICO(0x0ffdefb0), + DICO(0x12943f40), DICO(0x1be84ee0), DICO(0x21276540), DICO(0x265a9540), + DICO(0x2e0de140), DICO(0x325148c0), DICO(0x3bd05d40), DICO(0x41e81780), + DICO(0x4b7cf400), DICO(0x53289400), DICO(0x597d9000), DICO(0x5e458e00), + DICO(0x04da3e40), DICO(0x06e8e1b0), DICO(0x0b9b1a20), DICO(0x11264bc0), + DICO(0x14f3d7e0), DICO(0x1cf9c100), DICO(0x23568f40), DICO(0x292b5380), + DICO(0x33878d40), DICO(0x38dac840), DICO(0x3d578200), DICO(0x4223a880), + DICO(0x473fb700), DICO(0x4c765500), DICO(0x546c6480), DICO(0x5c76d280), + DICO(0x05e63bb0), DICO(0x07a1a428), DICO(0x0ec4ff10), DICO(0x1348a100), + DICO(0x16204f40), DICO(0x1a0a6440), DICO(0x1e33f6c0), DICO(0x2ae8ccc0), + DICO(0x2ed5e6c0), DICO(0x32427600), DICO(0x379d9980), DICO(0x3c0f4080), + DICO(0x441ea680), DICO(0x4e592b00), DICO(0x56e27700), DICO(0x5da2e280), + DICO(0x0474de80), DICO(0x06167248), DICO(0x0ce650e0), DICO(0x135b4aa0), + DICO(0x16cea2a0), DICO(0x1d138ac0), DICO(0x220a84c0), DICO(0x275ca380), + DICO(0x2c300340), DICO(0x333b3d80), DICO(0x37a35080), DICO(0x40b83880), + DICO(0x494c4780), DICO(0x4ff71c80), DICO(0x56db2d80), DICO(0x5d0aac00), + DICO(0x0746cd00), DICO(0x09deff10), DICO(0x0e4a3560), DICO(0x14f005e0), + DICO(0x186a4de0), DICO(0x1cd0b240), DICO(0x22287bc0), DICO(0x26ced500), + DICO(0x2d57c440), DICO(0x31d943c0), DICO(0x364b0f80), DICO(0x3c85a040), + DICO(0x4240ca00), DICO(0x4a648080), DICO(0x54d12200), DICO(0x5d1a1c00), + DICO(0x05522eb0), DICO(0x0704efb8), DICO(0x0c66cd50), DICO(0x15aefca0), + DICO(0x184f7b00), DICO(0x1e4b26a0), DICO(0x22667640), DICO(0x284e4e00), + DICO(0x2d8be3c0), DICO(0x31376f00), DICO(0x39cd9800), DICO(0x3e46b740), + DICO(0x43af0380), DICO(0x4e1dec00), DICO(0x562ac500), DICO(0x5d45f580), + DICO(0x062f5708), DICO(0x08d079a0), DICO(0x0c1b4920), DICO(0x13f147c0), + DICO(0x1ae77c80), DICO(0x1d200ea0), DICO(0x236e4740), DICO(0x2b98d000), + DICO(0x2eefc600), DICO(0x34c674c0), DICO(0x3d36f540), DICO(0x411d8c00), + DICO(0x45c50300), DICO(0x4d207480), DICO(0x55603100), DICO(0x5c442d80), + DICO(0x0510bcd0), DICO(0x06ec00a0), DICO(0x0b639550), DICO(0x15daa2c0), + DICO(0x18c0ba60), DICO(0x1e0f7d60), DICO(0x24b05c80), DICO(0x280638c0), + DICO(0x314a6580), DICO(0x35e4b2c0), DICO(0x3aef2bc0), DICO(0x4158c280), + DICO(0x4d245100), DICO(0x53c69a80), DICO(0x597f1000), DICO(0x5dcb0080), + DICO(0x042cb748), DICO(0x05d710b0), DICO(0x0afe6130), DICO(0x1256cdc0), + DICO(0x15b8cd00), DICO(0x1dc72d20), DICO(0x2205fc00), DICO(0x2a3d0d00), + DICO(0x2f3ba600), DICO(0x33b3d840), DICO(0x3b5a5440), DICO(0x416c9d00), + DICO(0x497cdd80), DICO(0x50405e00), DICO(0x570ca980), DICO(0x5d3aa180), + DICO(0x0443b7b8), DICO(0x063d8588), DICO(0x0c76ef20), DICO(0x12709b40), + DICO(0x1649f0a0), DICO(0x20c522c0), DICO(0x24cde400), DICO(0x2ba78280), + DICO(0x3104c340), DICO(0x360b1740), DICO(0x3cd6a6c0), DICO(0x42573800), + DICO(0x48b18480), DICO(0x4fca1e00), DICO(0x5700c100), DICO(0x5cf14480), + DICO(0x05123628), DICO(0x06bf10b0), DICO(0x0bde7570), DICO(0x175b7ee0), + DICO(0x1a134460), DICO(0x20fa4100), DICO(0x25eda440), DICO(0x29c3b540), + DICO(0x318a1b40), DICO(0x35e0d500), DICO(0x3a147f00), DICO(0x3f08e980), + DICO(0x445d7580), DICO(0x4ec48c80), DICO(0x588bce80), DICO(0x5dfae300), + DICO(0x04c9e750), DICO(0x065224f8), DICO(0x0c6f1e30), DICO(0x1a2ffca0), + DICO(0x1cac6140), DICO(0x21c2a640), DICO(0x25fb8ac0), DICO(0x2ab90f00), + DICO(0x33189200), DICO(0x38088ac0), DICO(0x3bb7de40), DICO(0x40180800), + DICO(0x4453c300), DICO(0x4cdba880), DICO(0x54902680), DICO(0x5bb21700), + DICO(0x06958570), DICO(0x097f32b0), DICO(0x0cb418b0), DICO(0x141b6900), + DICO(0x1c8cfb00), DICO(0x1fab7920), DICO(0x2477c800), DICO(0x2aabed40), + DICO(0x2eb1a080), DICO(0x339f67c0), DICO(0x3abcc240), DICO(0x3f661b00), + DICO(0x45663280), DICO(0x4c680800), DICO(0x51703000), DICO(0x58a0e000), + DICO(0x069f6c88), DICO(0x095e1490), DICO(0x0cf442b0), DICO(0x10ea8d60), + DICO(0x1377b580), DICO(0x195ed480), DICO(0x26542b00), DICO(0x2c9ea700), + DICO(0x318d8ac0), DICO(0x364e5a40), DICO(0x3a0db000), DICO(0x3e1087c0), + DICO(0x450ca380), DICO(0x4c781d00), DICO(0x53cf7a00), DICO(0x5c7d1280), + DICO(0x06e51d98), DICO(0x09eb8d30), DICO(0x0e6683d0), DICO(0x129418a0), + DICO(0x1562fc80), DICO(0x1f708660), DICO(0x253f1000), DICO(0x293a16c0), + DICO(0x2e7c1d80), DICO(0x316e75c0), DICO(0x35a7fbc0), DICO(0x3bfbf780), + DICO(0x416a9200), DICO(0x4be36400), DICO(0x56dc7a80), DICO(0x5d64ea80), + DICO(0x0574d0c8), DICO(0x0748efd0), DICO(0x0b510860), DICO(0x0e219e00), + DICO(0x1299cc00), DICO(0x1ef706a0), DICO(0x22ca38c0), DICO(0x28820a00), + DICO(0x2cc635c0), DICO(0x31ef4740), DICO(0x3a5e89c0), DICO(0x42acaa00), + DICO(0x4b2bf500), DICO(0x515e0980), DICO(0x57949400), DICO(0x5d002500), + DICO(0x07c715d0), DICO(0x0b3fa110), DICO(0x0e745370), DICO(0x11e93560), + DICO(0x14bad680), DICO(0x189a0400), DICO(0x240b1240), DICO(0x2a6b3580), + DICO(0x2e5e1380), DICO(0x352072c0), DICO(0x3a5037c0), DICO(0x3e3726c0), + DICO(0x4725ed80), DICO(0x4f885900), DICO(0x54c8d580), DICO(0x5b261680), + DICO(0x075f02a8), DICO(0x0a214900), DICO(0x0e189de0), DICO(0x1376d5a0), + DICO(0x163d5c80), DICO(0x1a94b3e0), DICO(0x21376980), DICO(0x259c3140), + DICO(0x2e663bc0), DICO(0x337884c0), DICO(0x3a035c00), DICO(0x40b32c00), + DICO(0x4b21de00), DICO(0x53298f00), DICO(0x58788080), DICO(0x5cfa7c00), + DICO(0x05658988), DICO(0x0797f470), DICO(0x0d250810), DICO(0x102fc2a0), + DICO(0x13738fe0), DICO(0x1740bbc0), DICO(0x2491b380), DICO(0x28bc5800), + DICO(0x2c75a940), DICO(0x325cb500), DICO(0x37944740), DICO(0x405f2d80), + DICO(0x48eb8f00), DICO(0x50676f80), DICO(0x56f70380), DICO(0x5d62c000), + DICO(0x0531b540), DICO(0x06ae64c0), DICO(0x0cf7ad30), DICO(0x11c83000), + DICO(0x14edc980), DICO(0x18d436c0), DICO(0x1e184080), DICO(0x2603bb80), + DICO(0x2a2f2f80), DICO(0x33bdbe00), DICO(0x3a1066c0), DICO(0x42b9ff00), + DICO(0x4a617580), DICO(0x51619480), DICO(0x57ccd500), DICO(0x5d4d1600), + DICO(0x03e40bac), DICO(0x05f53158), DICO(0x0e76d3b0), DICO(0x17c157a0), + DICO(0x1ccb5bc0), DICO(0x250129c0), DICO(0x2b7d9d00), DICO(0x33224d80), + DICO(0x3966f600), DICO(0x3f399480), DICO(0x4449fc80), DICO(0x49401b80), + DICO(0x4e2ab580), DICO(0x53117000), DICO(0x5848e080), DICO(0x5d66a280), + DICO(0x041d4f60), DICO(0x070e8080), DICO(0x1390ec40), DICO(0x177c42c0), + DICO(0x1beb1400), DICO(0x208b0580), DICO(0x264cbb40), DICO(0x2bd30940), + DICO(0x30b30880), DICO(0x36978e80), DICO(0x3cb2a140), DICO(0x43f6b080), + DICO(0x4a881000), DICO(0x505ca780), DICO(0x569a5d80), DICO(0x5cae3580), + DICO(0x03f3c760), DICO(0x05564e08), DICO(0x09e310d0), DICO(0x1b9b3d00), + DICO(0x20909ac0), DICO(0x2382eec0), DICO(0x278c6700), DICO(0x2b34d500), + DICO(0x30fa2ac0), DICO(0x34d27d40), DICO(0x38e334c0), DICO(0x3d732440), + DICO(0x46d07800), DICO(0x51f4d400), DICO(0x57744f80), DICO(0x5d56bb80), + DICO(0x03abfdd8), DICO(0x0512b140), DICO(0x135f7500), DICO(0x19fcc4c0), + DICO(0x1d0b1b80), DICO(0x21eca540), DICO(0x258f8700), DICO(0x29e292c0), + DICO(0x2c51fe80), DICO(0x31e2a180), DICO(0x3c638640), DICO(0x44873a00), + DICO(0x4bb7e800), DICO(0x5078f700), DICO(0x57fc9b80), DICO(0x5def1c00), + DICO(0x04721ef0), DICO(0x06688158), DICO(0x0f65a5d0), DICO(0x14499840), + DICO(0x1bf5b8c0), DICO(0x1f33b700), DICO(0x264b6900), DICO(0x2c3e6780), + DICO(0x2ec8d440), DICO(0x323885c0), DICO(0x37143300), DICO(0x3bafa800), + DICO(0x49030480), DICO(0x54c16b00), DICO(0x58ec4b00), DICO(0x5d713d00), + DICO(0x03d114e4), DICO(0x067e5b40), DICO(0x10393420), DICO(0x14961300), + DICO(0x1a59cfa0), DICO(0x20854240), DICO(0x26b3f300), DICO(0x2e3e2840), + DICO(0x323bd300), DICO(0x37c49280), DICO(0x3d79e500), DICO(0x4352d880), + DICO(0x49e17980), DICO(0x4fc72f80), DICO(0x55c0c680), DICO(0x5c53c700), + DICO(0x053f5de8), DICO(0x075162b8), DICO(0x0fae8050), DICO(0x13ec0ee0), + DICO(0x17f92440), DICO(0x1f054440), DICO(0x24b15d40), DICO(0x2add4480), + DICO(0x2e306300), DICO(0x35420680), DICO(0x3c6b6e00), DICO(0x42fc0380), + DICO(0x4732e380), DICO(0x4ceb2200), DICO(0x522efe00), DICO(0x5aa12680), + DICO(0x06111728), DICO(0x08183c80), DICO(0x0d026650), DICO(0x14b41940), + DICO(0x17e37320), DICO(0x1c40b160), DICO(0x219c5400), DICO(0x26d88840), + DICO(0x2bfdfe00), DICO(0x315a2800), DICO(0x38cd7140), DICO(0x3de22740), + DICO(0x48ff1300), DICO(0x53ef4180), DICO(0x5a479380), DICO(0x5ea1e380), + DICO(0x07ea0fa8), DICO(0x0a844ef0), DICO(0x0e1023c0), DICO(0x1208d980), + DICO(0x15891360), DICO(0x1bebc380), DICO(0x2087da40), DICO(0x257ac940), + DICO(0x2caefa00), DICO(0x300defc0), DICO(0x376aa000), DICO(0x438aad80), + DICO(0x49f00500), DICO(0x4e023780), DICO(0x524e5800), DICO(0x5abcb980), + DICO(0x079cfc88), DICO(0x0a367240), DICO(0x0f224330), DICO(0x15b51540), + DICO(0x19065420), DICO(0x1ddbe0a0), DICO(0x23a99d80), DICO(0x28c2d340), + DICO(0x2f627e40), DICO(0x3487e080), DICO(0x38b76bc0), DICO(0x3d135580), + DICO(0x43799a80), DICO(0x489a5000), DICO(0x4ece6280), DICO(0x5a82f500), + DICO(0x06c37e40), DICO(0x093f0540), DICO(0x0e0d0c30), DICO(0x17487860), + DICO(0x1bf78020), DICO(0x20318000), DICO(0x260b8300), DICO(0x2c615980), + DICO(0x30c88440), DICO(0x36433b40), DICO(0x3bdb8c40), DICO(0x40050c80), + DICO(0x44062f80), DICO(0x48a8d480), DICO(0x4dd64d00), DICO(0x55abd380), + DICO(0x05e9e828), DICO(0x07f24330), DICO(0x0c8b4fe0), DICO(0x0ecd2820), + DICO(0x17f05c00), DICO(0x1fdb4560), DICO(0x24b4c940), DICO(0x2968d0c0), + DICO(0x2cbf3500), DICO(0x381eadc0), DICO(0x3d3baf40), DICO(0x42828080), + DICO(0x47f36300), DICO(0x4c8c6600), DICO(0x51d66f00), DICO(0x5a7e0300), + DICO(0x065c5cf8), DICO(0x08882540), DICO(0x0d887c70), DICO(0x112ac560), + DICO(0x150ccdc0), DICO(0x19e49c20), DICO(0x1eb65680), DICO(0x2a76e040), + DICO(0x2f65fc00), DICO(0x36d79cc0), DICO(0x3c85a900), DICO(0x408dc680), + DICO(0x44964700), DICO(0x4a98eb00), DICO(0x5528b500), DICO(0x5d660f80), + DICO(0x06b56230), DICO(0x08e340f0), DICO(0x0e1e4380), DICO(0x112d2d40), + DICO(0x158dfde0), DICO(0x227e6040), DICO(0x26bff7c0), DICO(0x2b73a100), + DICO(0x32199580), DICO(0x3585a240), DICO(0x398a5d40), DICO(0x3db8c6c0), + DICO(0x43905600), DICO(0x4945f800), DICO(0x4f310380), DICO(0x5a6d2400), + DICO(0x05cfc6f8), DICO(0x0832e650), DICO(0x0de82f80), DICO(0x1a1afe80), + DICO(0x1e9a1f80), DICO(0x221acd80), DICO(0x27fa00c0), DICO(0x2c4df980), + DICO(0x31e04bc0), DICO(0x38c9ed40), DICO(0x3db86080), DICO(0x428ec800), + DICO(0x48500500), DICO(0x4e1ca580), DICO(0x53d3f500), DICO(0x5aa6be00), + DICO(0x050cc4d0), DICO(0x070c2180), DICO(0x0c4ca980), DICO(0x0fce9f40), + DICO(0x14af4160), DICO(0x2206a780), DICO(0x25848e80), DICO(0x2c2b84c0), + DICO(0x35a39980), DICO(0x3914bd80), DICO(0x3caff580), DICO(0x3fcb0600), + DICO(0x4426b380), DICO(0x486c9700), DICO(0x4f730480), DICO(0x5afd3980), + DICO(0x05e40640), DICO(0x0830df50), DICO(0x0b9e83e0), DICO(0x158bacc0), + DICO(0x1d0692e0), DICO(0x2021e0c0), DICO(0x26572e00), DICO(0x2d58cc40), + DICO(0x30dd0f80), DICO(0x361d68c0), DICO(0x3e3086c0), DICO(0x42450800), + DICO(0x46c25800), DICO(0x4c45cf00), DICO(0x51dd4200), DICO(0x57326500), + DICO(0x04d32fa0), DICO(0x064ed2c0), DICO(0x0b07cd70), DICO(0x1c7f6da0), + DICO(0x213bc140), DICO(0x25051fc0), DICO(0x295cd1c0), DICO(0x2c9f4f80), + DICO(0x32271540), DICO(0x36a8ec80), DICO(0x3a8e6b40), DICO(0x3e137580), + DICO(0x42795480), DICO(0x4779b780), DICO(0x4f7d9600), DICO(0x5c09b000), + DICO(0x044b0748), DICO(0x05fee680), DICO(0x08f66960), DICO(0x11db5940), + DICO(0x219ede80), DICO(0x27fb96c0), DICO(0x2affc980), DICO(0x2eadc3c0), + DICO(0x32895700), DICO(0x37180d00), DICO(0x3d4bf880), DICO(0x41741980), + DICO(0x460d8280), DICO(0x4c34be80), DICO(0x54531e80), DICO(0x5c874000), + DICO(0x03e25dcc), DICO(0x069e8170), DICO(0x13b3d9c0), DICO(0x1a803260), + DICO(0x1ed3a4a0), DICO(0x23ea6380), DICO(0x2883b900), DICO(0x2e0ceac0), + DICO(0x3308e400), DICO(0x38796dc0), DICO(0x3e318e80), DICO(0x441da080), + DICO(0x4a892300), DICO(0x509b9f80), DICO(0x56caa380), DICO(0x5cc39e00), + DICO(0x05023038), DICO(0x06b6b4d8), DICO(0x0a449370), DICO(0x15b86ea0), + DICO(0x224a9200), DICO(0x272e6f40), DICO(0x2a617700), DICO(0x2e915d00), + DICO(0x3240ac40), DICO(0x37636300), DICO(0x3dd3ea80), DICO(0x420e1f80), + DICO(0x45bf0680), DICO(0x4a26d980), DICO(0x4f82a900), DICO(0x56576800), + DICO(0x03d630f4), DICO(0x082140a0), DICO(0x12644700), DICO(0x16b80cc0), + DICO(0x1ba90c40), DICO(0x21c38300), DICO(0x27dd1480), DICO(0x2e18ee00), + DICO(0x33fb72c0), DICO(0x39f9d980), DICO(0x40219300), DICO(0x4607fd00), + DICO(0x4c07e500), DICO(0x51ba8f00), DICO(0x57a24280), DICO(0x5d367700), + DICO(0x080a5880), DICO(0x0ef3f570), DICO(0x141fd6c0), DICO(0x17c163a0), + DICO(0x1c2840a0), DICO(0x2111fe00), DICO(0x27376bc0), DICO(0x2cc7edc0), + DICO(0x329b0100), DICO(0x386d3e40), DICO(0x3ec1bdc0), DICO(0x453f6200), + DICO(0x4bf16080), DICO(0x51bded00), DICO(0x57ba6800), DICO(0x5d2ffd80), + DICO(0x08643590), DICO(0x0e911f00), DICO(0x15911380), DICO(0x1ab5e180), + DICO(0x207ff600), DICO(0x26399b00), DICO(0x2cadae80), DICO(0x3276ca40), + DICO(0x389d9cc0), DICO(0x3eb22180), DICO(0x44570700), DICO(0x49d15800), + DICO(0x4f591300), DICO(0x54566a80), DICO(0x5967db00), DICO(0x5e307780), + DICO(0x07120fa8), DICO(0x0c791c60), DICO(0x112d3b60), DICO(0x149452a0), + DICO(0x19d2c100), DICO(0x202f1540), DICO(0x269c10c0), DICO(0x2be22880), + DICO(0x312a07c0), DICO(0x36984fc0), DICO(0x3c7ac3c0), DICO(0x435b5000), + DICO(0x4aa60280), DICO(0x50f50c00), DICO(0x5719f700), DICO(0x5cb98680), + DICO(0x05517c88), DICO(0x06ba0a70), DICO(0x0da167c0), DICO(0x19918440), + DICO(0x1bb37220), DICO(0x20681080), DICO(0x23dc6740), DICO(0x2a1403c0), + DICO(0x31a71580), DICO(0x34ff0600), DICO(0x395b7cc0), DICO(0x42019200), + DICO(0x4c818d00), DICO(0x513ff400), DICO(0x5731ce00), DICO(0x5c5f1180), + DICO(0x04f74ec0), DICO(0x067b4628), DICO(0x0dc4c9c0), DICO(0x19e9fa40), + DICO(0x1cf00a00), DICO(0x21602a80), DICO(0x25334a80), DICO(0x29b3a800), + DICO(0x2f9b3600), DICO(0x338c0540), DICO(0x370c3cc0), DICO(0x3abbc3c0), + DICO(0x4053a000), DICO(0x4f14d980), DICO(0x57e0b600), DICO(0x5d95e780), + DICO(0x05d844b8), DICO(0x07a05608), DICO(0x0b7837f0), DICO(0x161fb460), + DICO(0x19c31d00), DICO(0x1cf36280), DICO(0x20ccc200), DICO(0x24ae3980), + DICO(0x2e2b5800), DICO(0x3316af80), DICO(0x37432b00), DICO(0x4050b280), + DICO(0x4605be00), DICO(0x4cc78900), DICO(0x556d2080), DICO(0x5c578300), + DICO(0x0551b768), DICO(0x07024f60), DICO(0x1045fde0), DICO(0x16480120), + DICO(0x19974420), DICO(0x1ec2b280), DICO(0x228b30c0), DICO(0x295e0ec0), + DICO(0x2d8775c0), DICO(0x30ef1440), DICO(0x35978080), DICO(0x3a2ab480), + DICO(0x40229780), DICO(0x4da40980), DICO(0x5718e480), DICO(0x5d68d400), + DICO(0x03f903e4), DICO(0x06731580), DICO(0x0ecf4850), DICO(0x12e57920), + DICO(0x1a69ece0), DICO(0x1fe32700), DICO(0x2585b9c0), DICO(0x2aa006c0), + DICO(0x2f20ea80), DICO(0x37298bc0), DICO(0x3df2a000), DICO(0x44a6c600), + DICO(0x4b10de00), DICO(0x510fb880), DICO(0x5749c280), DICO(0x5d0b9480), + DICO(0x03c418fc), DICO(0x056c4cd0), DICO(0x0d0cf070), DICO(0x1907a2c0), + DICO(0x1be9bc00), DICO(0x21599480), DICO(0x25700e40), DICO(0x2c83e280), + DICO(0x329fa7c0), DICO(0x389f4cc0), DICO(0x3ef60900), DICO(0x44c19300), + DICO(0x4af56d00), DICO(0x512eec80), DICO(0x5772ad00), DICO(0x5d37f380), + DICO(0x04d57920), DICO(0x0716b5e0), DICO(0x0cb3bcc0), DICO(0x1197f740), + DICO(0x163e5fc0), DICO(0x2194e400), DICO(0x274bb600), DICO(0x2f5d7080), + DICO(0x361ee340), DICO(0x3b3b22c0), DICO(0x3f800400), DICO(0x4327ef80), + DICO(0x48b5d200), DICO(0x5116d300), DICO(0x59652e80), DICO(0x5e444d00), + DICO(0x0755b6b0), DICO(0x0b68c2c0), DICO(0x0f3441d0), DICO(0x124a01a0), + DICO(0x18910600), DICO(0x20911b80), DICO(0x281f7100), DICO(0x2e4dd640), + DICO(0x335bd8c0), DICO(0x37f14a80), DICO(0x3cab7b80), DICO(0x43be3180), + DICO(0x4beee100), DICO(0x52292180), DICO(0x57efea00), DICO(0x5d177300), + DICO(0x071a7748), DICO(0x0c6cf1b0), DICO(0x10db1500), DICO(0x143bca00), + DICO(0x1b86a900), DICO(0x22ed1d80), DICO(0x2a1f61c0), DICO(0x305f1400), + DICO(0x3645f580), DICO(0x3be45b00), DICO(0x4166ea80), DICO(0x46c3f200), + DICO(0x4c740400), DICO(0x51e30d00), DICO(0x57a37000), DICO(0x5cfc4980), + DICO(0x08cdd5b0), DICO(0x0daf9840), DICO(0x11cc02a0), DICO(0x1588ed40), + DICO(0x1cfef5e0), DICO(0x239f12c0), DICO(0x296d3b40), DICO(0x2e61c240), + DICO(0x333dc800), DICO(0x385d0000), DICO(0x3e1e5180), DICO(0x44196e00), + DICO(0x4a833000), DICO(0x503d7b80), DICO(0x56556680), DICO(0x5c410c00), + DICO(0x07372408), DICO(0x0d5c41f0), DICO(0x155dc140), DICO(0x1a9a3cc0), + DICO(0x21740980), DICO(0x27139f40), DICO(0x2c977040), DICO(0x30cfe5c0), + DICO(0x35381240), DICO(0x39b83140), DICO(0x3ef3fe80), DICO(0x44547200), + DICO(0x4a812800), DICO(0x5046c200), DICO(0x56957d00), DICO(0x5c85cd80), + DICO(0x06da6990), DICO(0x0bc41250), DICO(0x13d54800), DICO(0x1979c220), + DICO(0x1fad2f00), DICO(0x24bbe0c0), DICO(0x29c08f00), DICO(0x2e34b940), + DICO(0x32c89e40), DICO(0x376a2040), DICO(0x3cd81080), DICO(0x4267bd00), + DICO(0x48e8e800), DICO(0x4f150280), DICO(0x55cb1980), DICO(0x5c428b80), + DICO(0x087d45d0), DICO(0x0cf1ef20), DICO(0x135cba20), DICO(0x16fc7420), + DICO(0x1b2772e0), DICO(0x1fd4fe60), DICO(0x260a0b80), DICO(0x2bc54c00), + DICO(0x31694cc0), DICO(0x36d08080), DICO(0x3c245c80), DICO(0x41170900), + DICO(0x47b18600), DICO(0x4e706180), DICO(0x558d2000), DICO(0x5c428d00), + DICO(0x081e6490), DICO(0x0d16a7d0), DICO(0x124ccd20), DICO(0x154c20c0), + DICO(0x1945d8c0), DICO(0x1ee0b700), DICO(0x26a01f00), DICO(0x2d554e40), + DICO(0x3432eb80), DICO(0x3a605500), DICO(0x401d8980), DICO(0x45737680), + DICO(0x4b03cb00), DICO(0x50666780), DICO(0x56a0cd00), DICO(0x5cb46480), + DICO(0x06c58278), DICO(0x091b10b0), DICO(0x0e0e74f0), DICO(0x11faf980), + DICO(0x14a48600), DICO(0x1e6f7500), DICO(0x27f77100), DICO(0x2ab49940), + DICO(0x32a1f680), DICO(0x38cb2a80), DICO(0x3c3ff140), DICO(0x3f681cc0), + DICO(0x44310700), DICO(0x4fa21700), DICO(0x586c6180), DICO(0x5df74200), + DICO(0x06a3e478), DICO(0x09714400), DICO(0x0d90b7a0), DICO(0x12df2720), + DICO(0x1618f320), DICO(0x1ac52840), DICO(0x27612900), DICO(0x2e438e00), + DICO(0x322b6ac0), DICO(0x38022940), DICO(0x3d2a5180), DICO(0x40d76b80), + DICO(0x46671500), DICO(0x4c5bd480), DICO(0x517a2500), DICO(0x57775b00), + DICO(0x056c2230), DICO(0x07b8f9d8), DICO(0x0bc6e060), DICO(0x16ac2c80), + DICO(0x1a92fc00), DICO(0x1e15f000), DICO(0x28b73200), DICO(0x2cd9e5c0), + DICO(0x3196ecc0), DICO(0x3abae340), DICO(0x4040c580), DICO(0x44c18d80), + DICO(0x4c086800), DICO(0x50b78500), DICO(0x54e42600), DICO(0x5a549a80), + DICO(0x04f9fa10), DICO(0x07419358), DICO(0x0c3e15f0), DICO(0x174c1800), + DICO(0x1ab1fe60), DICO(0x23a12680), DICO(0x27955780), DICO(0x2d14b1c0), + DICO(0x35cefb00), DICO(0x39576700), DICO(0x3e82b780), DICO(0x42b6a680), + DICO(0x476d1880), DICO(0x4b6cdd00), DICO(0x52758680), DICO(0x5b69e500), + DICO(0x060b7ab0), DICO(0x081c05c0), DICO(0x0b540300), DICO(0x0f564270), + DICO(0x1210aa80), DICO(0x1771e060), DICO(0x25d73280), DICO(0x2e49e380), + DICO(0x319c1100), DICO(0x3771e700), DICO(0x3c532f40), DICO(0x40c9a900), + DICO(0x48cbf580), DICO(0x4f819980), DICO(0x566f9400), DICO(0x5cfdd980), + DICO(0x04efb7b8), DICO(0x0b8a3710), DICO(0x124fd520), DICO(0x1846dde0), + DICO(0x1e77a9e0), DICO(0x243ea800), DICO(0x2a4e3280), DICO(0x2ff532c0), + DICO(0x35d27680), DICO(0x3b8cdb00), DICO(0x41463000), DICO(0x4706c700), + DICO(0x4ca42d80), DICO(0x525d9200), DICO(0x57dabb80), DICO(0x5d59a800), + DICO(0x03620dec), DICO(0x095872e0), DICO(0x108d4920), DICO(0x16e9ea00), + DICO(0x1d60b2e0), DICO(0x235e9d00), DICO(0x29893b80), DICO(0x2f59a3c0), + DICO(0x3556b880), DICO(0x3b10bdc0), DICO(0x40f49500), DICO(0x469cc480), + DICO(0x4c762d00), DICO(0x51f16980), DICO(0x578c6d00), DICO(0x5c9b5a00), + DICO(0x05dd9bc0), DICO(0x079c5b20), DICO(0x0d319af0), DICO(0x18997040), + DICO(0x1c0a1980), DICO(0x20e926c0), DICO(0x25ca1640), DICO(0x29879340), + DICO(0x30b27040), DICO(0x36077340), DICO(0x39ac3d00), DICO(0x3d686cc0), + DICO(0x428e5f00), DICO(0x47c1bf80), DICO(0x4e720800), DICO(0x5b419880), + DICO(0x07694258), DICO(0x0b50db90), DICO(0x0f384950), DICO(0x140dac40), + DICO(0x17c50d80), DICO(0x1b49b300), DICO(0x24746200), DICO(0x2ce92fc0), + DICO(0x309fdac0), DICO(0x35c02a00), DICO(0x3aa3df00), DICO(0x3e1edb00), + DICO(0x431ad280), DICO(0x4b57f500), DICO(0x51463980), DICO(0x586b5200), + DICO(0x06401dd0), DICO(0x08d3d9b0), DICO(0x0ca0f510), DICO(0x10ed1920), + DICO(0x1451c2e0), DICO(0x2082f640), DICO(0x2872c0c0), DICO(0x2ca9da00), + DICO(0x3219cd00), DICO(0x35977300), DICO(0x3a8ba1c0), DICO(0x43d5f280), + DICO(0x49a51f00), DICO(0x4de9b400), DICO(0x5362ef80), DICO(0x59387300), + DICO(0x0589c430), DICO(0x07809918), DICO(0x0d086f80), DICO(0x10371c20), + DICO(0x151842c0), DICO(0x1bfcb1c0), DICO(0x22441040), DICO(0x2722b5c0), + DICO(0x2b603fc0), DICO(0x314465c0), DICO(0x40308b00), DICO(0x47d5a200), + DICO(0x4bf7e000), DICO(0x4f937200), DICO(0x5584eb00), DICO(0x5cb02200), + DICO(0x03b592f0), DICO(0x056ba738), DICO(0x0a8e2250), DICO(0x172436c0), + DICO(0x1ad35da0), DICO(0x1d72dc80), DICO(0x20cd3900), DICO(0x2a962940), + DICO(0x2f3b6700), DICO(0x33312b40), DICO(0x38dc6680), DICO(0x41659200), + DICO(0x4d36a380), DICO(0x52b00980), DICO(0x58c82800), DICO(0x5d741600), + DICO(0x05bdfe10), DICO(0x0756da20), DICO(0x0cd31fe0), DICO(0x130f1820), + DICO(0x1561caa0), DICO(0x1962ab20), DICO(0x1c310840), DICO(0x28bf6f80), + DICO(0x2d2d4500), DICO(0x3230f900), DICO(0x3ac2ea80), DICO(0x3ebe71c0), + DICO(0x48280700), DICO(0x50254900), DICO(0x5850a200), DICO(0x5e687200), + DICO(0x04e2b7e8), DICO(0x067f5430), DICO(0x0a8899a0), DICO(0x0d571560), + DICO(0x1c42f440), DICO(0x22e21fc0), DICO(0x27074340), DICO(0x2c493240), + DICO(0x2f7ece00), DICO(0x33959ec0), DICO(0x392d3000), DICO(0x459fc800), + DICO(0x4ba5f700), DICO(0x4fde7780), DICO(0x55f90380), DICO(0x5c928b00), + DICO(0x0557b940), DICO(0x075f0158), DICO(0x0bd8c540), DICO(0x0f4ee370), + DICO(0x141dc900), DICO(0x1b241f00), DICO(0x21c32a80), DICO(0x29a23980), + DICO(0x2e475380), DICO(0x3616f9c0), DICO(0x3a52a500), DICO(0x40345f00), + DICO(0x4763a500), DICO(0x4eb5bb80), DICO(0x561d4480), DICO(0x5d388580), + DICO(0x057d7d08), DICO(0x0738c240), DICO(0x0bf46e10), DICO(0x0ec93da0), + DICO(0x14ab3cc0), DICO(0x23d0f5c0), DICO(0x271e9900), DICO(0x2c0ee4c0), + DICO(0x301d1f00), DICO(0x33868040), DICO(0x37cdde00), DICO(0x3c805440), + DICO(0x43c69200), DICO(0x4f5c9a00), DICO(0x56eb3e80), DICO(0x5cdadc80), + DICO(0x06cdbab0), DICO(0x0999e600), DICO(0x0df39790), DICO(0x12ffc9a0), + DICO(0x15cfe7a0), DICO(0x1c599300), DICO(0x21afd600), DICO(0x26842bc0), + DICO(0x32067c00), DICO(0x368bb080), DICO(0x3c350c40), DICO(0x44e8be00), + DICO(0x4ac84000), DICO(0x4f9c1280), DICO(0x5449ec00), DICO(0x594d5880), + DICO(0x049a6bd0), DICO(0x06849f08), DICO(0x10592b40), DICO(0x168c1940), + DICO(0x1992df40), DICO(0x1e91b300), DICO(0x2237e100), DICO(0x2cd73a80), + DICO(0x30e7c100), DICO(0x361a45c0), DICO(0x3cdd1f40), DICO(0x41d5d100), + DICO(0x46f79480), DICO(0x4e44c880), DICO(0x55830e80), DICO(0x5d7c0680), + DICO(0x05087958), DICO(0x06fb7e40), DICO(0x0ac5ace0), DICO(0x14e91d80), + DICO(0x19ac68c0), DICO(0x1dbf7600), DICO(0x26f916c0), DICO(0x2bd2c980), + DICO(0x307f7900), DICO(0x38e07e40), DICO(0x3df7f1c0), DICO(0x41323d00), + DICO(0x44d2f480), DICO(0x48fb0480), DICO(0x51e17900), DICO(0x5c15d700), + DICO(0x0346cf40), DICO(0x05423408), DICO(0x0b640ce0), DICO(0x13055060), + DICO(0x1a8c0b60), DICO(0x1d8d2280), DICO(0x218b6500), DICO(0x2c385700), + DICO(0x30927b40), DICO(0x35d82880), DICO(0x3aa87e00), DICO(0x3da46a40), + DICO(0x45ea5280), DICO(0x511ecb80), DICO(0x57b53b00), DICO(0x5d491400), + DICO(0x056aa1c8), DICO(0x075a09a0), DICO(0x0a5d61d0), DICO(0x13cb9fe0), + DICO(0x1f924dc0), DICO(0x237a11c0), DICO(0x277d6b80), DICO(0x2c2ba440), + DICO(0x30195c80), DICO(0x35250cc0), DICO(0x3b718200), DICO(0x40113c80), + DICO(0x44df2680), DICO(0x49f0ed80), DICO(0x50791980), DICO(0x5ac10600), + DICO(0x046f1e50), DICO(0x061dd758), DICO(0x1236bec0), DICO(0x16c07340), + DICO(0x1a7399c0), DICO(0x1f61ee20), DICO(0x244b2280), DICO(0x2b803e40), + DICO(0x2eda5300), DICO(0x331210c0), DICO(0x3773bfc0), DICO(0x411c8400), + DICO(0x488ff380), DICO(0x4fad2700), DICO(0x55845000), DICO(0x5ca74c00), + DICO(0x04b456f0), DICO(0x05fca198), DICO(0x0ad056d0), DICO(0x19c3bfe0), + DICO(0x1d446100), DICO(0x20f67200), DICO(0x24a40b40), DICO(0x28d472c0), + DICO(0x2da813c0), DICO(0x31880200), DICO(0x35344f40), DICO(0x3ca7f340), + DICO(0x4aa94300), DICO(0x4f921500), DICO(0x5516d700), DICO(0x5c832880), + DICO(0x07f468c0), DICO(0x0bbb6e90), DICO(0x0f0f8730), DICO(0x143d6180), + DICO(0x198b84c0), DICO(0x1c6b30a0), DICO(0x219c8000), DICO(0x28795780), + DICO(0x2cce3d00), DICO(0x329b1100), DICO(0x3a8d2240), DICO(0x3f579080), + DICO(0x45a74400), DICO(0x4d000f80), DICO(0x52bd6880), DICO(0x5a743a80), + DICO(0x06979498), DICO(0x088fecf0), DICO(0x0f1dac90), DICO(0x12077160), + DICO(0x16d5b120), DICO(0x1c5465c0), DICO(0x21ad14c0), DICO(0x282be280), + DICO(0x2b66a380), DICO(0x2fa3f200), DICO(0x35a06500), DICO(0x3a458d00), + DICO(0x44aefc00), DICO(0x4e92f600), DICO(0x55b9fa80), DICO(0x5cfe0280), + DICO(0x0552b408), DICO(0x06f6ce38), DICO(0x0e8f8d80), DICO(0x1395e900), + DICO(0x17c7b440), DICO(0x1ec64dc0), DICO(0x236e2200), DICO(0x2abc0b80), + DICO(0x2e131240), DICO(0x32921100), DICO(0x372633c0), DICO(0x3ca97840), + DICO(0x496e5000), DICO(0x4f86a800), DICO(0x54072300), DICO(0x5be31c80), + DICO(0x0470c0b8), DICO(0x0662c468), DICO(0x0c493fd0), DICO(0x1a1949c0), + DICO(0x1febcc20), DICO(0x2364e900), DICO(0x2a0cce00), DICO(0x2f6f8140), + DICO(0x3418b000), DICO(0x3c5c7a40), DICO(0x42d39100), DICO(0x476c2b00), + DICO(0x4e11c300), DICO(0x53621500), DICO(0x583fd280), DICO(0x5ce26600), + DICO(0x04b006c0), DICO(0x09a1ed40), DICO(0x135aee00), DICO(0x193b5180), + DICO(0x1f3679a0), DICO(0x24fdbcc0), DICO(0x2b823e00), DICO(0x31835780), + DICO(0x37c74cc0), DICO(0x3df66780), DICO(0x43c18580), DICO(0x49465980), + DICO(0x4ed0ce00), DICO(0x53d6fb80), DICO(0x59064300), DICO(0x5deaa100), + DICO(0x03cbc49c), DICO(0x07735930), DICO(0x138aaa20), DICO(0x1a1e69a0), + DICO(0x21be93c0), DICO(0x2936f780), DICO(0x2fa76f80), DICO(0x34ae6b00), + DICO(0x396b7b80), DICO(0x3dbc6700), DICO(0x421a9100), DICO(0x46fd2180), + DICO(0x4c5dca80), DICO(0x51923b80), DICO(0x576d1300), DICO(0x5d288680), + DICO(0x03cab7d0), DICO(0x052c88b8), DICO(0x09ed24f0), DICO(0x1c261820), + DICO(0x209096c0), DICO(0x2361e080), DICO(0x27292800), DICO(0x2bbdc6c0), + DICO(0x3292da80), DICO(0x36866a40), DICO(0x3c4d5100), DICO(0x45233400), + DICO(0x4d928a00), DICO(0x52ca9d00), DICO(0x5820d000), DICO(0x5d903880), + DICO(0x03f83718), DICO(0x0540fa90), DICO(0x13028120), DICO(0x1ad6e160), + DICO(0x1d784880), DICO(0x22028900), DICO(0x25976b40), DICO(0x2b293700), + DICO(0x2ddb86c0), DICO(0x317c4340), DICO(0x34e62ec0), DICO(0x3b71bd00), + DICO(0x4bc34780), DICO(0x52982400), DICO(0x57fa2800), DICO(0x5f19cc00), + DICO(0x049ceb50), DICO(0x06a8d4e0), DICO(0x09db2470), DICO(0x120e3e60), + DICO(0x1c8ebb80), DICO(0x21221d00), DICO(0x2679bfc0), DICO(0x2b1e7600), + DICO(0x2ebbcf80), DICO(0x32d5afc0), DICO(0x3d1bef00), DICO(0x41b11a00), + DICO(0x45bb2d80), DICO(0x4cb70300), DICO(0x572fdc80), DICO(0x5d876e80), + DICO(0x04abda68), DICO(0x06698cd0), DICO(0x0ca87230), DICO(0x15086a80), + DICO(0x176cf4e0), DICO(0x22899440), DICO(0x268fc500), DICO(0x2ba2d940), + DICO(0x33505980), DICO(0x36944bc0), DICO(0x3b20c280), DICO(0x437e8f00), + DICO(0x4bf29e80), DICO(0x51776a80), DICO(0x57a77800), DICO(0x5cf6c180), + DICO(0x06d7f5c0), DICO(0x08fd3cc0), DICO(0x0d8807e0), DICO(0x1140d500), + DICO(0x146dfc80), DICO(0x1e9fbaa0), DICO(0x23d7bf00), DICO(0x28b2ae80), + DICO(0x2e5a9b00), DICO(0x327005c0), DICO(0x37736640), DICO(0x4001c500), + DICO(0x4a862b00), DICO(0x4f7a2e00), DICO(0x54a22080), DICO(0x5b76c380), + DICO(0x0671fb68), DICO(0x08e4bf30), DICO(0x0d801250), DICO(0x1176b820), + DICO(0x15128860), DICO(0x1ee21180), DICO(0x24799580), DICO(0x29415a40), + DICO(0x2efa2380), DICO(0x33fe5040), DICO(0x39bf6d00), DICO(0x3f28b380), + DICO(0x442b2280), DICO(0x493de680), DICO(0x54377700), DICO(0x5d3a5480), + DICO(0x065b7970), DICO(0x087820b0), DICO(0x0d8d6aa0), DICO(0x16718620), + DICO(0x1a3a8f40), DICO(0x1f4099c0), DICO(0x24d87b40), DICO(0x296d85c0), + DICO(0x2f887c80), DICO(0x342d1b40), DICO(0x3887fc40), DICO(0x3d758b40), + DICO(0x42641c80), DICO(0x47bf6980), DICO(0x55f82900), DICO(0x5e132a00), + DICO(0x05ddbc00), DICO(0x081f17a0), DICO(0x0bf23ac0), DICO(0x12fc8d60), + DICO(0x172bc440), DICO(0x1a833540), DICO(0x1e942200), DICO(0x21e477c0), + DICO(0x2e75da80), DICO(0x399efac0), DICO(0x3dfb6900), DICO(0x428b3780), + DICO(0x4922a080), DICO(0x4d4c1700), DICO(0x51bbee00), DICO(0x5b4cfc80), + DICO(0x06ecf380), DICO(0x08f83990), DICO(0x0cb55680), DICO(0x140b2860), + DICO(0x18084d00), DICO(0x1aff9940), DICO(0x1f5f6f00), DICO(0x224a3d80), + DICO(0x2b0f49c0), DICO(0x3613b280), DICO(0x39188f40), DICO(0x3efa3640), + DICO(0x4771e400), DICO(0x4ca32380), DICO(0x54627580), DICO(0x5cb91000), + DICO(0x069e7f98), DICO(0x0870c760), DICO(0x0d7b73a0), DICO(0x15ab1040), + DICO(0x18a4d220), DICO(0x1c4c1f20), DICO(0x1ffaf200), DICO(0x24142580), + DICO(0x30e47540), DICO(0x37340200), DICO(0x3a69af40), DICO(0x3ed471c0), + DICO(0x44157880), DICO(0x486b7f00), DICO(0x52ed2b00), DICO(0x5ce3a980), + DICO(0x047f1080), DICO(0x06463230), DICO(0x0b566e80), DICO(0x0edb9080), + DICO(0x128a2fa0), DICO(0x1748b340), DICO(0x210b2b00), DICO(0x28099b80), + DICO(0x2f519740), DICO(0x36fe82c0), DICO(0x3d924b80), DICO(0x43cd3c00), + DICO(0x4a774680), DICO(0x50d15f00), DICO(0x573b3580), DICO(0x5d4c1c00), + DICO(0x05fa6a68), DICO(0x0866e4c0), DICO(0x0d133cc0), DICO(0x156d6b20), + DICO(0x18abebe0), DICO(0x1d374900), DICO(0x23d23d00), DICO(0x27b370c0), + DICO(0x2f63ef00), DICO(0x352a0600), DICO(0x3a643a40), DICO(0x3f57f980), + DICO(0x457a7f00), DICO(0x520f6200), DICO(0x593b2c80), DICO(0x5e192b80), + DICO(0x04e4e0c8), DICO(0x067c3450), DICO(0x0acabe70), DICO(0x1865eec0), + DICO(0x1c5e9bc0), DICO(0x202facc0), DICO(0x24a609c0), DICO(0x28db7b00), + DICO(0x2efbd780), DICO(0x336fe5c0), DICO(0x3819a5c0), DICO(0x3e709b40), + DICO(0x4435ff80), DICO(0x4bd5fb80), DICO(0x5564a100), DICO(0x5d0a4980), + DICO(0x05a72f00), DICO(0x070199b0), DICO(0x0e654780), DICO(0x14fc7780), + DICO(0x174283c0), DICO(0x1b231480), DICO(0x1e7b9000), DICO(0x27a013c0), + DICO(0x2b42f500), DICO(0x2fd9ca00), DICO(0x3672a0c0), DICO(0x3cc23f40), + DICO(0x48299d80), DICO(0x4f92a800), DICO(0x564d7680), DICO(0x5d3ab580), + DICO(0x03e63764), DICO(0x05baa3f0), DICO(0x0ab2a300), DICO(0x12cc5f60), + DICO(0x19a8d5e0), DICO(0x1ea788e0), DICO(0x22cd50c0), DICO(0x25d48a00), + DICO(0x29924540), DICO(0x32762a00), DICO(0x3bba55c0), DICO(0x4222e800), + DICO(0x4aba1280), DICO(0x501d0b80), DICO(0x57091200), DICO(0x5d6bf180), + DICO(0x047daeb0), DICO(0x069548b8), DICO(0x0b002410), DICO(0x13ff7060), + DICO(0x186aec40), DICO(0x210db240), DICO(0x26f1ce80), DICO(0x2b73c9c0), + DICO(0x33d57240), DICO(0x385898c0), DICO(0x3eea8cc0), DICO(0x43c79b00), + DICO(0x496ec200), DICO(0x4e150780), DICO(0x54dcb700), DICO(0x5c3f7380), + DICO(0x079fd258), DICO(0x0b93bd50), DICO(0x0ff7d8b0), DICO(0x14bd4e00), + DICO(0x19536ae0), DICO(0x1d8b1640), DICO(0x23747cc0), DICO(0x2861f280), + DICO(0x2d7d2880), DICO(0x3583b040), DICO(0x3c3cab00), DICO(0x41b7b580), + DICO(0x498cfc80), DICO(0x506cbd00), DICO(0x57847600), DICO(0x5d05de80), + DICO(0x06434ec0), DICO(0x0805ccd0), DICO(0x0c4b4c00), DICO(0x13d551c0), + DICO(0x1685abe0), DICO(0x1a83ea60), DICO(0x1ddc3700), DICO(0x22bc4600), + DICO(0x2c7ca5c0), DICO(0x30a589c0), DICO(0x395a8700), DICO(0x40c92900), + DICO(0x472fae80), DICO(0x4f6f6e80), DICO(0x571b3f80), DICO(0x5d8e6980), + DICO(0x05ec21b0), DICO(0x079ee388), DICO(0x0e4b4580), DICO(0x11abf100), + DICO(0x16588ec0), DICO(0x1c984ec0), DICO(0x20a384c0), DICO(0x28d6be00), + DICO(0x2bcca740), DICO(0x3604b600), DICO(0x3f027280), DICO(0x434af000), + DICO(0x48dac280), DICO(0x4d7e8a00), DICO(0x51f61800), DICO(0x5a6d9380), + DICO(0x0552c6c0), DICO(0x070c22a0), DICO(0x0a411b50), DICO(0x0e3e5270), + DICO(0x1193bb60), DICO(0x1b177e00), DICO(0x275b2500), DICO(0x2b42bd80), + DICO(0x322d7e40), DICO(0x3a170880), DICO(0x3d66b580), DICO(0x41413280), + DICO(0x46a9ce80), DICO(0x4e4e3800), DICO(0x571f8380), DICO(0x5ddae380), + DICO(0x055602c0), DICO(0x06e69118), DICO(0x0c9d13f0), DICO(0x1090d500), + DICO(0x138d2280), DICO(0x171bf540), DICO(0x1b585180), DICO(0x288b9740), + DICO(0x2db202c0), DICO(0x3525e680), DICO(0x3c303900), DICO(0x4311df80), + DICO(0x49b92c00), DICO(0x509de900), DICO(0x56e9a080), DICO(0x5d523a80), + DICO(0x04e79810), DICO(0x069626e8), DICO(0x0a6cf680), DICO(0x0da668c0), + DICO(0x115872a0), DICO(0x2032eec0), DICO(0x25345dc0), DICO(0x2ae8ea40), + DICO(0x30224280), DICO(0x351ff640), DICO(0x3ce65a80), DICO(0x454bff00), + DICO(0x4ee08980), DICO(0x543b4280), DICO(0x59c19280), DICO(0x5ddfbb00), + DICO(0x03f0bb98), DICO(0x0588f4f0), DICO(0x0a862bc0), DICO(0x14ec76e0), + DICO(0x184b8a80), DICO(0x1f7bbd80), DICO(0x23f1a7c0), DICO(0x2c367900), + DICO(0x3234af80), DICO(0x35460ac0), DICO(0x38514c00), DICO(0x3d5f3540), + DICO(0x48394980), DICO(0x4fbdd380), DICO(0x56de0280), DICO(0x5d4e6500), + DICO(0x06050f28), DICO(0x08070af0), DICO(0x0be31240), DICO(0x0f5e53e0), + DICO(0x125f1740), DICO(0x215b1fc0), DICO(0x2883d880), DICO(0x2c181080), + DICO(0x32810280), DICO(0x35d56800), DICO(0x3a9b0880), DICO(0x3ffaaf80), + DICO(0x44c65500), DICO(0x4a45ae80), DICO(0x56b4ed80), DICO(0x5e4adc00), + DICO(0x0372bbb4), DICO(0x04ea4848), DICO(0x09b8de70), DICO(0x151b4a40), + DICO(0x1be65a00), DICO(0x207655c0), DICO(0x2720dd00), DICO(0x2fc6cc00), + DICO(0x35b063c0), DICO(0x39bd30c0), DICO(0x3dc5b580), DICO(0x42af7b00), + DICO(0x48d2bf00), DICO(0x4f46bb80), DICO(0x55f7ca80), DICO(0x5ca7e980), + DICO(0x033f868c), DICO(0x04d9a0e0), DICO(0x0a18d6d0), DICO(0x13da5580), + DICO(0x181ae880), DICO(0x207d8580), DICO(0x262022c0), DICO(0x2c6de040), + DICO(0x3321f100), DICO(0x3927f0c0), DICO(0x3f74ce40), DICO(0x4573e980), + DICO(0x4ba66c80), DICO(0x51a26100), DICO(0x57d3a800), DICO(0x5d52e780), + DICO(0x05189860), DICO(0x07231848), DICO(0x0b915710), DICO(0x0f05d6c0), + DICO(0x13bb0820), DICO(0x223adf00), DICO(0x26ce1ec0), DICO(0x2ce1ac00), + DICO(0x3401f6c0), DICO(0x3b8c2240), DICO(0x40e4a400), DICO(0x45674f00), + DICO(0x4b04b880), DICO(0x4f253200), DICO(0x54168600), DICO(0x58f52780), + DICO(0x0338d184), DICO(0x05205790), DICO(0x09abcd80), DICO(0x0f53ff60), + DICO(0x1a7fe900), DICO(0x1ef93860), DICO(0x238e2d80), DICO(0x2bd81bc0), + DICO(0x33161240), DICO(0x368cfb80), DICO(0x3a28b5c0), DICO(0x40c7a600), + DICO(0x4bac7780), DICO(0x524b7880), DICO(0x58638480), DICO(0x5da07b00), + DICO(0x04d06f38), DICO(0x065f1518), DICO(0x0c9b31b0), DICO(0x10570d40), + DICO(0x15e790a0), DICO(0x20f16380), DICO(0x246f23c0), DICO(0x2e222800), + DICO(0x3198bf00), DICO(0x34b84640), DICO(0x38f5b440), DICO(0x4312df80), + DICO(0x4d2d3000), DICO(0x5209ee80), DICO(0x579cf180), DICO(0x5cb37680), + DICO(0x042e6560), DICO(0x05eaff30), DICO(0x0a090d30), DICO(0x0d9f2ab0), + DICO(0x1a6f0260), DICO(0x209e0c00), DICO(0x25dc95c0), DICO(0x29f89840), + DICO(0x2f372840), DICO(0x3a301940), DICO(0x3f0e2e80), DICO(0x44465c80), + DICO(0x49207780), DICO(0x4dfdab80), DICO(0x532ec000), DICO(0x5acefd00), + DICO(0x04e18ad8), DICO(0x06d5b660), DICO(0x0b2a22d0), DICO(0x0e0e4ef0), + DICO(0x198304a0), DICO(0x1e4a25c0), DICO(0x23de37c0), DICO(0x290679c0), + DICO(0x2d523b00), DICO(0x337df940), DICO(0x37948100), DICO(0x3de07300), + DICO(0x49ee6e80), DICO(0x50576100), DICO(0x55fb1e00), DICO(0x5d080500), + DICO(0x05312308), DICO(0x070463f0), DICO(0x0daffba0), DICO(0x12d8c3c0), + DICO(0x163ab7a0), DICO(0x20c64c40), DICO(0x24c8fe40), DICO(0x2a6f65c0), + DICO(0x3055e100), DICO(0x34420d80), DICO(0x389ded00), DICO(0x3cc57640), + DICO(0x4280cd00), DICO(0x4e0a4c00), DICO(0x57675f00), DICO(0x5d87d480), + DICO(0x047bd598), DICO(0x06cb1498), DICO(0x0c359930), DICO(0x138165e0), + DICO(0x1cae3640), DICO(0x21647640), DICO(0x2836fac0), DICO(0x2cd7b840), + DICO(0x30d839c0), DICO(0x360c9440), DICO(0x3ae5ca40), DICO(0x40a93b00), + DICO(0x49401e80), DICO(0x4f739c80), DICO(0x54f33c00), DICO(0x5c190200), + DICO(0x051c0000), DICO(0x06b45258), DICO(0x0a5eee50), DICO(0x0d46fc30), + DICO(0x125bbc60), DICO(0x253d8cc0), DICO(0x2a1fd6c0), DICO(0x2df4cf80), + DICO(0x3239e3c0), DICO(0x35a683c0), DICO(0x3b0bb980), DICO(0x409b3d00), + DICO(0x46633580), DICO(0x4f2b0600), DICO(0x577cea80), DICO(0x5d86ef00), + DICO(0x03d19eec), DICO(0x07cce6d0), DICO(0x143b4b00), DICO(0x1a657880), + DICO(0x212e0280), DICO(0x2831fbc0), DICO(0x2f8ba080), DICO(0x35db8040), + DICO(0x3bf17f00), DICO(0x413eb100), DICO(0x46154900), DICO(0x4ae18080), + DICO(0x4f9ba180), DICO(0x5428ba00), DICO(0x590e9080), DICO(0x5de0d880), + DICO(0x08c7e720), DICO(0x0ff14810), DICO(0x1758cc40), DICO(0x1cc744c0), + DICO(0x23e45cc0), DICO(0x2b527940), DICO(0x32138580), DICO(0x37b77380), + DICO(0x3d7da480), DICO(0x4275a800), DICO(0x473ecf00), DICO(0x4bc7dc80), + DICO(0x50512400), DICO(0x54d2c600), DICO(0x598ce680), DICO(0x5e1e0800), + DICO(0x09167910), DICO(0x107644a0), DICO(0x171a59e0), DICO(0x1be1ea60), + DICO(0x21347680), DICO(0x265a5b00), DICO(0x2be41a40), DICO(0x3116e700), + DICO(0x368b0300), DICO(0x3c225e80), DICO(0x41a6e880), DICO(0x47631680), + DICO(0x4d47d900), DICO(0x52a28400), DICO(0x583f0e80), DICO(0x5d77bc80), + DICO(0x040bdf88), DICO(0x05b062a0), DICO(0x0b4a2f70), DICO(0x1b8cd880), + DICO(0x1ec58c40), DICO(0x23661880), DICO(0x2790ba80), DICO(0x2d0d6c40), + DICO(0x34f0bc40), DICO(0x3a353f80), DICO(0x3fc3bc40), DICO(0x44998700), + DICO(0x49b17080), DICO(0x4f31fa00), DICO(0x55311c80), DICO(0x5b5c8f80), + DICO(0x043e2bd0), DICO(0x0645b0f0), DICO(0x0ade5b90), DICO(0x0d653a90), + DICO(0x1bc224a0), DICO(0x1f623dc0), DICO(0x27e9a840), DICO(0x2c719bc0), + DICO(0x2f2ac040), DICO(0x32688300), DICO(0x36695c00), DICO(0x3b8abe40), + DICO(0x47153a80), DICO(0x52491b00), DICO(0x57ba7680), DICO(0x5ce6c300), + DICO(0x052940b8), DICO(0x06f28228), DICO(0x0a741c90), DICO(0x0daa3110), + DICO(0x113bb2e0), DICO(0x2010b640), DICO(0x2610f380), DICO(0x2a5c7740), + DICO(0x2f7703c0), DICO(0x3388d080), DICO(0x3ceabe40), DICO(0x42462a80), + DICO(0x47fb0e00), DICO(0x4f7ac480), DICO(0x5706f580), DICO(0x5d92b800), + DICO(0x03a134a4), DICO(0x05623470), DICO(0x090a0fe0), DICO(0x12f7d3e0), + DICO(0x1d63e440), DICO(0x20e6ac80), DICO(0x247da8c0), DICO(0x27d99600), + DICO(0x312e99c0), DICO(0x368fb380), DICO(0x3b3e3ec0), DICO(0x40fead80), + DICO(0x4888fa00), DICO(0x4fbd5600), DICO(0x5795a480), DICO(0x5d973000), + DICO(0x05697990), DICO(0x06f33800), DICO(0x0b298290), DICO(0x0de47a60), + DICO(0x12ef62a0), DICO(0x21e30a00), DICO(0x25f8ff00), DICO(0x2b2287c0), + DICO(0x2f11fc00), DICO(0x33138000), DICO(0x37b49f80), DICO(0x41325100), + DICO(0x4ab62800), DICO(0x501eae80), DICO(0x56228780), DICO(0x5c5d8300), + DICO(0x063830d8), DICO(0x08a76a30), DICO(0x0d376890), DICO(0x117d3a00), + DICO(0x1476e5c0), DICO(0x1e215720), DICO(0x24bcd680), DICO(0x29674ac0), + DICO(0x2faab340), DICO(0x33843a00), DICO(0x3822e900), DICO(0x3d30b6c0), + DICO(0x49cd5480), DICO(0x53187d00), DICO(0x591fe100), DICO(0x5db30f80), + DICO(0x05cdc378), DICO(0x075c50c8), DICO(0x0e01f830), DICO(0x12b70480), + DICO(0x15e333e0), DICO(0x192c9f40), DICO(0x1d2d6b80), DICO(0x2c09ca40), + DICO(0x2eea5cc0), DICO(0x32c89380), DICO(0x376a5b40), DICO(0x42a42600), + DICO(0x4c695900), DICO(0x5269e380), DICO(0x586d6c80), DICO(0x5cebdb80), + DICO(0x052bbb80), DICO(0x0702e268), DICO(0x0ca196d0), DICO(0x0f48cef0), + DICO(0x19d28b60), DICO(0x1ec44a40), DICO(0x24d40f00), DICO(0x29e1eac0), + DICO(0x2cafaa80), DICO(0x301bd4c0), DICO(0x357ec200), DICO(0x42254480), + DICO(0x4be32000), DICO(0x4f7a4a00), DICO(0x5447fc00), DICO(0x5cca6a00), + DICO(0x050fdd18), DICO(0x06c77e10), DICO(0x10561140), DICO(0x1564c340), + DICO(0x1867abe0), DICO(0x1f00fba0), DICO(0x22c06240), DICO(0x2aed7680), + DICO(0x2ecc24c0), DICO(0x32abb300), DICO(0x36b42340), DICO(0x3ed8f480), + DICO(0x4bbdfe80), DICO(0x516bf800), DICO(0x58688b00), DICO(0x5dd44980), + DICO(0x058aa130), DICO(0x07d69ba8), DICO(0x0d521f40), DICO(0x0ff37ba0), + DICO(0x18125ec0), DICO(0x1f3a4520), DICO(0x23349840), DICO(0x2c759580), + DICO(0x2fc21c00), DICO(0x33a42fc0), DICO(0x3dc92900), DICO(0x47befd00), + DICO(0x4ccd2480), DICO(0x5197a200), DICO(0x56a2ea00), DICO(0x5bdfa900), + DICO(0x05ac8640), DICO(0x076aec88), DICO(0x0e2e3230), DICO(0x114b6f40), + DICO(0x155d10a0), DICO(0x19bac600), DICO(0x1fbd75c0), DICO(0x2459c0c0), + DICO(0x28229b80), DICO(0x2f586fc0), DICO(0x3d0697c0), DICO(0x42a7a500), + DICO(0x49b0bb80), DICO(0x4e642e80), DICO(0x55774280), DICO(0x5d1a7900), + DICO(0x05efb470), DICO(0x0831c8a0), DICO(0x0d35ece0), DICO(0x13edc400), + DICO(0x16c8fec0), DICO(0x1bb25860), DICO(0x204f3140), DICO(0x277b8a40), + DICO(0x2fe9a000), DICO(0x33af7c40), DICO(0x3b7d2900), DICO(0x419c9a80), + DICO(0x4591dc80), DICO(0x4bdafd00), DICO(0x55638880), DICO(0x5cef2300), + DICO(0x05cf4988), DICO(0x078fa8c0), DICO(0x0c291950), DICO(0x12e05320), + DICO(0x155997e0), DICO(0x195df540), DICO(0x1c1b82c0), DICO(0x22c29400), + DICO(0x307edec0), DICO(0x34e829c0), DICO(0x3b1b5040), DICO(0x434de400), + DICO(0x496b9900), DICO(0x4ff88080), DICO(0x5604c480), DICO(0x5c84b080), + DICO(0x03679fa4), DICO(0x050d4a20), DICO(0x09feec10), DICO(0x100a21e0), + DICO(0x1483b260), DICO(0x1d76c780), DICO(0x24e75c80), DICO(0x2bd62880), + DICO(0x32350a40), DICO(0x38be01c0), DICO(0x3f05a280), DICO(0x45295e80), + DICO(0x4b554800), DICO(0x51618880), DICO(0x575a1500), DICO(0x5d109d80), + DICO(0x034ffd08), DICO(0x04dccea8), DICO(0x07e289b8), DICO(0x0d6950d0), + DICO(0x189acec0), DICO(0x1e3bf240), DICO(0x2535aa40), DICO(0x2b88d140), + DICO(0x329bbb00), DICO(0x386c3500), DICO(0x3e950800), DICO(0x44c43f00), + DICO(0x4b089780), DICO(0x51223280), DICO(0x574c9780), DICO(0x5d366400), + DICO(0x036d8db8), DICO(0x04fd88b8), DICO(0x09700a70), DICO(0x116b73c0), + DICO(0x17258c40), DICO(0x1fd03000), DICO(0x23fdf400), DICO(0x28e08dc0), + DICO(0x32d688c0), DICO(0x37920b00), DICO(0x3daaa080), DICO(0x46a16c00), + DICO(0x4f8c3100), DICO(0x54a13700), DICO(0x59d24b80), DICO(0x5cea4d80), + DICO(0x05797c88), DICO(0x080dc8f0), DICO(0x0bd21520), DICO(0x1095b540), + DICO(0x138fd400), DICO(0x1aed19c0), DICO(0x29fead00), DICO(0x2f70cec0), + DICO(0x3327df00), DICO(0x3a812d00), DICO(0x400a8380), DICO(0x449daa00), + DICO(0x4cd6b600), DICO(0x51f12400), DICO(0x56bdfd80), DICO(0x5be0a100), + DICO(0x04de6d78), DICO(0x072aed40), DICO(0x0c6fc460), DICO(0x0f260220), + DICO(0x179d00c0), DICO(0x1e8244e0), DICO(0x23867240), DICO(0x2baf7680), + DICO(0x2fa6d240), DICO(0x37e83d40), DICO(0x3d1cbfc0), DICO(0x439d0a00), + DICO(0x49fd3e00), DICO(0x50095e80), DICO(0x559f2080), DICO(0x5b889a00), + DICO(0x042f5c10), DICO(0x061ab3e8), DICO(0x0dd8f160), DICO(0x126e0b40), + DICO(0x16ea9040), DICO(0x20a31700), DICO(0x24608140), DICO(0x2ec65080), + DICO(0x334e1a40), DICO(0x38252100), DICO(0x3fff0900), DICO(0x46519a80), + DICO(0x4c5e0d80), DICO(0x518c5800), DICO(0x56c5b080), DICO(0x5c6ebb80), + DICO(0x045ce230), DICO(0x067547b0), DICO(0x0a21c670), DICO(0x1408b820), + DICO(0x1c0505c0), DICO(0x1e806c80), DICO(0x26d3c640), DICO(0x2ca573c0), + DICO(0x3014d880), DICO(0x377108c0), DICO(0x3f35cf80), DICO(0x43566100), + DICO(0x4a612900), DICO(0x5160c780), DICO(0x57d3e300), DICO(0x5d414b80), + DICO(0x04c8eda8), DICO(0x06a32320), DICO(0x09ab2590), DICO(0x14230760), + DICO(0x20fb23c0), DICO(0x24aa2880), DICO(0x285a2580), DICO(0x2c464ac0), + DICO(0x30098280), DICO(0x36232780), DICO(0x3e428d40), DICO(0x42982280), + DICO(0x47e60d80), DICO(0x4e1ecc00), DICO(0x55eb9200), DICO(0x5c81ed00), + DICO(0x040d0b90), DICO(0x0586c5c0), DICO(0x0bea2190), DICO(0x1dc8dd60), + DICO(0x20a07c40), DICO(0x2437e580), DICO(0x27ca5fc0), DICO(0x2d017980), + DICO(0x34100040), DICO(0x38d3afc0), DICO(0x3da9b700), DICO(0x42082480), + DICO(0x46586f00), DICO(0x4e3c3d80), DICO(0x55e1ee00), DICO(0x5c938d00), + DICO(0x03d18c64), DICO(0x05941d60), DICO(0x116b2560), DICO(0x19cc8820), + DICO(0x1ce930c0), DICO(0x22626080), DICO(0x26d2cf80), DICO(0x2ce2c980), + DICO(0x305361c0), DICO(0x34b65900), DICO(0x39ee5b40), DICO(0x41508400), + DICO(0x47ee1e80), DICO(0x50311180), DICO(0x56cb0c00), DICO(0x5d561680), + DICO(0x0af22cf0), DICO(0x154e1c60), DICO(0x1b44ff60), DICO(0x2087d0c0), + DICO(0x252f7380), DICO(0x28fe66c0), DICO(0x2d0e9800), DICO(0x30f7ee00), + DICO(0x3606d640), DICO(0x3bac0a40), DICO(0x417c3700), DICO(0x470c2900), + DICO(0x4cc20d00), DICO(0x51e55e80), DICO(0x576bc200), DICO(0x5caa7080), + DICO(0x043314e0), DICO(0x05cb47b0), DICO(0x0985df20), DICO(0x185a22c0), + DICO(0x1ea68300), DICO(0x21af9100), DICO(0x25cdcb40), DICO(0x297e0a80), + DICO(0x3142ac80), DICO(0x358bb040), DICO(0x3a1345c0), DICO(0x402ca580), + DICO(0x4d964780), DICO(0x5420cf80), DICO(0x592adf80), DICO(0x5dfe7a80), + DICO(0x04c70e20), DICO(0x062fd6f0), DICO(0x113c60a0), DICO(0x159e9900), + DICO(0x1933e5a0), DICO(0x1decffa0), DICO(0x22373400), DICO(0x27ed7180), + DICO(0x2a8349c0), DICO(0x2f78f940), DICO(0x3d5c8540), DICO(0x429c3500), + DICO(0x4936e300), DICO(0x4de08d00), DICO(0x52627700), DICO(0x5d822680), + DICO(0x04982770), DICO(0x06ab1ad8), DICO(0x0cba1090), DICO(0x10839d60), + DICO(0x1acd6a60), DICO(0x1f554560), DICO(0x2431c1c0), DICO(0x295db800), + DICO(0x2d374c00), DICO(0x31f2fd80), DICO(0x3a200480), DICO(0x416bea80), + DICO(0x4ba1ce00), DICO(0x52a88000), DICO(0x58d0db00), DICO(0x5d3e5800), + DICO(0x059e0e70), DICO(0x08166ba0), DICO(0x0c9df590), DICO(0x11de5f40), + DICO(0x14c08ea0), DICO(0x1c5ad6e0), DICO(0x24178ec0), DICO(0x28eb7640), + DICO(0x31626280), DICO(0x35d43100), DICO(0x3cad10c0), DICO(0x422e1480), + DICO(0x49baee00), DICO(0x53dd7180), DICO(0x5a17bb80), DICO(0x5e4bb180), + DICO(0x03c64d00), DICO(0x05de0b28), DICO(0x0ccb82b0), DICO(0x144b1c00), + DICO(0x19e39ec0), DICO(0x21e795c0), DICO(0x28149380), DICO(0x2f1ff7c0), + DICO(0x35b7c900), DICO(0x3c5f4800), DICO(0x42799c00), DICO(0x48746180), + DICO(0x4e8f4d00), DICO(0x53b98380), DICO(0x58d60000), DICO(0x5d71a000), + DICO(0x050a2990), DICO(0x071bdb88), DICO(0x0f0d76b0), DICO(0x17a78de0), + DICO(0x1aa20720), DICO(0x22eea3c0), DICO(0x276e9640), DICO(0x2ecc4d80), + DICO(0x335f7900), DICO(0x37838640), DICO(0x3c81be80), DICO(0x41a4e400), + DICO(0x476fa280), DICO(0x4f2ab780), DICO(0x56e87b80), DICO(0x5cbf2900), + DICO(0x06724c98), DICO(0x099f5e20), DICO(0x119bcec0), DICO(0x16be11a0), + DICO(0x19d53b00), DICO(0x1eb51360), DICO(0x2302c300), DICO(0x29c20d40), + DICO(0x30dd5200), DICO(0x36576a80), DICO(0x3e3e7540), DICO(0x45aa9f80), + DICO(0x4c833300), DICO(0x51d7ed00), DICO(0x57a4a380), DICO(0x5cce9100), + DICO(0x05588b60), DICO(0x075a70a0), DICO(0x0ef96e30), DICO(0x12ac1100), + DICO(0x1649dde0), DICO(0x1a50cdc0), DICO(0x22486140), DICO(0x27c7c800), + DICO(0x2e08bd80), DICO(0x355d20c0), DICO(0x3925a9c0), DICO(0x44e2b480), + DICO(0x4fa4e680), DICO(0x5470e180), DICO(0x595fee80), DICO(0x5d672f00), + DICO(0x04a781c0), DICO(0x060a89f0), DICO(0x111f56a0), DICO(0x16b93be0), + DICO(0x19ce9120), DICO(0x1e1fda60), DICO(0x2259f880), DICO(0x285cad80), + DICO(0x2b140ec0), DICO(0x2f069940), DICO(0x33bbce40), DICO(0x3dd3e6c0), + DICO(0x49154880), DICO(0x5008e380), DICO(0x568c4680), DICO(0x5da43780), + DICO(0x053ade38), DICO(0x0708a200), DICO(0x0bad43d0), DICO(0x1860cf40), + DICO(0x1c40dbe0), DICO(0x1f5a0120), DICO(0x25bcf7c0), DICO(0x29e0c840), + DICO(0x2f223840), DICO(0x390c8940), DICO(0x3e1d7340), DICO(0x41c6a000), + DICO(0x46cc2880), DICO(0x5006e280), DICO(0x5744e180), DICO(0x5d297780), + DICO(0x0401a3f0), DICO(0x07be4a08), DICO(0x14f5f1a0), DICO(0x1c348080), + DICO(0x226753c0), DICO(0x274b1b80), DICO(0x2c11a300), DICO(0x30798c00), + DICO(0x35598c80), DICO(0x3aab18c0), DICO(0x4030f380), DICO(0x45c7b400), + DICO(0x4be5be00), DICO(0x5180db80), DICO(0x57613b00), DICO(0x5cffff80), + DICO(0x084b3090), DICO(0x0fe5b3b0), DICO(0x16dfd480), DICO(0x1d0aa700), + DICO(0x24e08180), DICO(0x2b498640), DICO(0x30885b80), DICO(0x34ccc480), + DICO(0x38fedec0), DICO(0x3cdf9c40), DICO(0x41737600), DICO(0x46ab9800), + DICO(0x4c772e80), DICO(0x51e5b980), DICO(0x57df9900), DICO(0x5d5d7180), + DICO(0x09549f00), DICO(0x12b84da0), DICO(0x1aeaf1c0), DICO(0x2142a9c0), + DICO(0x275c9a00), DICO(0x2c260c80), DICO(0x3038c700), DICO(0x34081d00), + DICO(0x38612f40), DICO(0x3d0bf8c0), DICO(0x42473e00), DICO(0x47ecad80), + DICO(0x4db34380), DICO(0x52f0ab00), DICO(0x584cc980), DICO(0x5d62ae80), + DICO(0x0aeca1e0), DICO(0x14354700), DICO(0x19955ba0), DICO(0x1de331e0), + DICO(0x21cd60c0), DICO(0x25e72d80), DICO(0x2a402880), DICO(0x2efa64c0), + DICO(0x3478d9c0), DICO(0x3a889e80), DICO(0x40744e00), DICO(0x4626fe80), + DICO(0x4bd80900), DICO(0x51120f00), DICO(0x56d8d280), DICO(0x5c654400), + DICO(0x07a40af8), DICO(0x0e65ec20), DICO(0x14c76780), DICO(0x19b35a60), + DICO(0x1f76b7c0), DICO(0x24f512c0), DICO(0x2ae89f00), DICO(0x3036c3c0), + DICO(0x36041800), DICO(0x3bc4df80), DICO(0x41adb080), DICO(0x477fbb80), + DICO(0x4d5aa480), DICO(0x52cb0600), DICO(0x586f7280), DICO(0x5db40180), + DICO(0x03997610), DICO(0x06175db0), DICO(0x0ea8c9c0), DICO(0x14397000), + DICO(0x1ba34f60), DICO(0x22346680), DICO(0x28958080), DICO(0x2ea76840), + DICO(0x33ee68c0), DICO(0x39e769c0), DICO(0x3f862500), DICO(0x4579b080), + DICO(0x4b49cd00), DICO(0x5107da80), DICO(0x573cde00), DICO(0x5d090780), + DICO(0x046fc2f8), DICO(0x0640dbc0), DICO(0x09da7ab0), DICO(0x174e4220), + DICO(0x23dc8cc0), DICO(0x27016200), DICO(0x2a9a5240), DICO(0x2e6cc7c0), + DICO(0x321ced40), DICO(0x38ca2d00), DICO(0x41482680), DICO(0x451e3700), + DICO(0x4b90d800), DICO(0x50d0ba80), DICO(0x55602e80), DICO(0x5a465200), + DICO(0x03ca7e28), DICO(0x057c9dd0), DICO(0x0c9ff0e0), DICO(0x1957fae0), + DICO(0x1fef7860), DICO(0x27920c80), DICO(0x2cb233c0), DICO(0x32015c80), + DICO(0x36af4f40), DICO(0x3ac18240), DICO(0x3f93d8c0), DICO(0x44eaef80), + DICO(0x4aab5d80), DICO(0x50840e80), DICO(0x56c4cc80), DICO(0x5cb26600), + DICO(0x038d53f8), DICO(0x050d1118), DICO(0x0bc14690), DICO(0x18918000), + DICO(0x1e2a6ee0), DICO(0x24cc0c00), DICO(0x2a767d40), DICO(0x2e614940), + DICO(0x32859c40), DICO(0x377fd940), DICO(0x3d3a3e40), DICO(0x43e81380), + DICO(0x4aaac080), DICO(0x509e7800), DICO(0x57023a00), DICO(0x5d733c00), + DICO(0x04cfa5e0), DICO(0x06deeb38), DICO(0x0a501c40), DICO(0x136d8aa0), + DICO(0x17f16e40), DICO(0x1c119300), DICO(0x26154b00), DICO(0x2a0da100), + DICO(0x2f5935c0), DICO(0x37108d40), DICO(0x3aef07c0), DICO(0x3fccf340), + DICO(0x47e4a080), DICO(0x4d8de100), DICO(0x54eb6980), DICO(0x5cdb5380)}; + +/* ACELP: table for decoding + adaptive codebook gain g_p (left column). Scaled by 2.0f. + innovative codebook gain g_c (right column). Scaled by 16.0f. +*/ +const FIXP_SGL fdk_t_qua_gain7b[128 * 2] = { + 204, 441, 464, 1977, 869, 1077, 1072, 3062, 1281, 4759, 1647, + 1539, 1845, 7020, 1853, 634, 1995, 2336, 2351, 15400, 2661, 1165, + 2702, 3900, 2710, 10133, 3195, 1752, 3498, 2624, 3663, 849, 3984, + 5697, 4214, 3399, 4415, 1304, 4695, 2056, 5376, 4558, 5386, 676, + 5518, 23554, 5567, 7794, 5644, 3061, 5672, 1513, 5957, 2338, 6533, + 1060, 6804, 5998, 6820, 1767, 6937, 3837, 7277, 414, 7305, 2665, + 7466, 11304, 7942, 794, 8007, 1982, 8007, 1366, 8326, 3105, 8336, + 4810, 8708, 7954, 8989, 2279, 9031, 1055, 9247, 3568, 9283, 1631, + 9654, 6311, 9811, 2605, 10120, 683, 10143, 4179, 10245, 1946, 10335, + 1218, 10468, 9960, 10651, 3000, 10951, 1530, 10969, 5290, 11203, 2305, + 11325, 3562, 11771, 6754, 11839, 1849, 11941, 4495, 11954, 1298, 11975, + 15223, 11977, 883, 11986, 2842, 12438, 2141, 12593, 3665, 12636, 8367, + 12658, 1594, 12886, 2628, 12984, 4942, 13146, 1115, 13224, 524, 13341, + 3163, 13399, 1923, 13549, 5961, 13606, 1401, 13655, 2399, 13782, 3909, + 13868, 10923, 14226, 1723, 14232, 2939, 14278, 7528, 14439, 4598, 14451, + 984, 14458, 2265, 14792, 1403, 14818, 3445, 14899, 5709, 15017, 15362, + 15048, 1946, 15069, 2655, 15405, 9591, 15405, 4079, 15570, 7183, 15687, + 2286, 15691, 1624, 15699, 3068, 15772, 5149, 15868, 1205, 15970, 696, + 16249, 3584, 16338, 1917, 16424, 2560, 16483, 4438, 16529, 6410, 16620, + 11966, 16839, 8780, 17030, 3050, 17033, 18325, 17092, 1568, 17123, 5197, + 17351, 2113, 17374, 980, 17566, 26214, 17609, 3912, 17639, 32767, 18151, + 7871, 18197, 2516, 18202, 5649, 18679, 3283, 18930, 1370, 19271, 13757, + 19317, 4120, 19460, 1973, 19654, 10018, 19764, 6792, 19912, 5135, 20040, + 2841, 21234, 19833}; + +/* ACELP: factor table for interpolation of LPC coeffs in LSP domain */ +const FIXP_SGL lsp_interpol_factor[2][NB_SUBFR] = { + {FL2FXCONST_SGL(0.125f), FL2FXCONST_SGL(0.375f), FL2FXCONST_SGL(0.625f), + FL2FXCONST_SGL(0.875f)}, /* for coreCoderFrameLength = 1024 */ + {FL2FXCONST_SGL(0.166667f), FL2FXCONST_SGL(0.5f), FL2FXCONST_SGL(0.833333f), + 0x0} /* for coreCoderFrameLength = 768 */ +}; + +/* For bass post filter */ +#ifndef TABLE_filt_lp +const FIXP_SGL fdk_dec_filt_lp[1 + L_FILT] = { + FL2FXCONST_SGL_FILT(0.088250f), FL2FXCONST_SGL_FILT(0.086410f), + FL2FXCONST_SGL_FILT(0.081074f), FL2FXCONST_SGL_FILT(0.072768f), + FL2FXCONST_SGL_FILT(0.062294f), FL2FXCONST_SGL_FILT(0.050623f), + FL2FXCONST_SGL_FILT(0.038774f), FL2FXCONST_SGL_FILT(0.027692f), + FL2FXCONST_SGL_FILT(0.018130f), FL2FXCONST_SGL_FILT(0.010578f), + FL2FXCONST_SGL_FILT(0.005221f), FL2FXCONST_SGL_FILT(0.001946f), + FL2FXCONST_SGL_FILT(0.000385f)}; +#endif + +/* FAC window tables for coreCoderFrameLength = 1024 */ +const FIXP_WTB FacWindowSynth128[] = { + WTC(0x7fff6216), WTC(0x7ffa72d1), WTC(0x7ff09478), WTC(0x7fe1c76b), + WTC(0x7fce0c3e), WTC(0x7fb563b3), WTC(0x7f97cebd), WTC(0x7f754e80), + WTC(0x7f4de451), WTC(0x7f2191b4), WTC(0x7ef05860), WTC(0x7eba3a39), + WTC(0x7e7f3957), WTC(0x7e3f57ff), WTC(0x7dfa98a8), WTC(0x7db0fdf8), + WTC(0x7d628ac6), WTC(0x7d0f4218), WTC(0x7cb72724), WTC(0x7c5a3d50), + WTC(0x7bf88830), WTC(0x7b920b89), WTC(0x7b26cb4f), WTC(0x7ab6cba4), + WTC(0x7a4210d8), WTC(0x79c89f6e), WTC(0x794a7c12), WTC(0x78c7aba2), + WTC(0x78403329), WTC(0x77b417df), WTC(0x77235f2d), WTC(0x768e0ea6), + WTC(0x75f42c0b), WTC(0x7555bd4c), WTC(0x74b2c884), WTC(0x740b53fb), + WTC(0x735f6626), WTC(0x72af05a7), WTC(0x71fa3949), WTC(0x71410805), + WTC(0x708378ff), WTC(0x6fc19385), WTC(0x6efb5f12), WTC(0x6e30e34a), + WTC(0x6d6227fa), WTC(0x6c8f351c), WTC(0x6bb812d1), WTC(0x6adcc964), + WTC(0x69fd614a), WTC(0x6919e320), WTC(0x683257ab), WTC(0x6746c7d8), + WTC(0x66573cbb), WTC(0x6563bf92), WTC(0x646c59bf), WTC(0x637114cc), + WTC(0x6271fa69), WTC(0x616f146c), WTC(0x60686ccf), WTC(0x5f5e0db3), + WTC(0x5e50015d), WTC(0x5d3e5237), WTC(0x5c290acc), WTC(0x5b1035cf), + WTC(0x59f3de12), WTC(0x58d40e8c), WTC(0x57b0d256), WTC(0x568a34a9), + WTC(0x556040e2), WTC(0x5433027d), WTC(0x53028518), WTC(0x51ced46e), + WTC(0x5097fc5e), WTC(0x4f5e08e3), WTC(0x4e210617), WTC(0x4ce10034), + WTC(0x4b9e0390), WTC(0x4a581c9e), WTC(0x490f57ee), WTC(0x47c3c22f), + WTC(0x46756828), WTC(0x452456bd), WTC(0x43d09aed), WTC(0x427a41d0), + WTC(0x4121589b), WTC(0x3fc5ec98), WTC(0x3e680b2c), WTC(0x3d07c1d6), + WTC(0x3ba51e29), WTC(0x3a402dd2), WTC(0x38d8fe93), WTC(0x376f9e46), + WTC(0x36041ad9), WTC(0x34968250), WTC(0x3326e2c3), WTC(0x31b54a5e), + WTC(0x3041c761), WTC(0x2ecc681e), WTC(0x2d553afc), WTC(0x2bdc4e6f), + WTC(0x2a61b101), WTC(0x28e5714b), WTC(0x27679df4), WTC(0x25e845b6), + WTC(0x24677758), WTC(0x22e541af), WTC(0x2161b3a0), WTC(0x1fdcdc1b), + WTC(0x1e56ca1e), WTC(0x1ccf8cb3), WTC(0x1b4732ef), WTC(0x19bdcbf3), + WTC(0x183366e9), WTC(0x16a81305), WTC(0x151bdf86), WTC(0x138edbb1), + WTC(0x120116d5), WTC(0x1072a048), WTC(0x0ee38766), WTC(0x0d53db92), + WTC(0x0bc3ac35), WTC(0x0a3308bd), WTC(0x08a2009a), WTC(0x0710a345), + WTC(0x057f0035), WTC(0x03ed26e6), WTC(0x025b26d7), WTC(0x00c90f88), +}; +const FIXP_WTB FacWindowZir128[] = { + WTC(0x7f36f078), WTC(0x7da4d929), WTC(0x7c12d91a), WTC(0x7a80ffcb), + WTC(0x78ef5cbb), WTC(0x775dff66), WTC(0x75ccf743), WTC(0x743c53cb), + WTC(0x72ac246e), WTC(0x711c789a), WTC(0x6f8d5fb8), WTC(0x6dfee92b), + WTC(0x6c71244f), WTC(0x6ae4207a), WTC(0x6957ecfb), WTC(0x67cc9917), + WTC(0x6642340d), WTC(0x64b8cd11), WTC(0x6330734d), WTC(0x61a935e2), + WTC(0x602323e5), WTC(0x5e9e4c60), WTC(0x5d1abe51), WTC(0x5b9888a8), + WTC(0x5a17ba4a), WTC(0x5898620c), WTC(0x571a8eb5), WTC(0x559e4eff), + WTC(0x5423b191), WTC(0x52aac504), WTC(0x513397e2), WTC(0x4fbe389f), + WTC(0x4e4ab5a2), WTC(0x4cd91d3d), WTC(0x4b697db0), WTC(0x49fbe527), + WTC(0x489061ba), WTC(0x4727016d), WTC(0x45bfd22e), WTC(0x445ae1d7), + WTC(0x42f83e2a), WTC(0x4197f4d4), WTC(0x403a1368), WTC(0x3edea765), + WTC(0x3d85be30), WTC(0x3c2f6513), WTC(0x3adba943), WTC(0x398a97d8), + WTC(0x383c3dd1), WTC(0x36f0a812), WTC(0x35a7e362), WTC(0x3461fc70), + WTC(0x331effcc), WTC(0x31def9e9), WTC(0x30a1f71d), WTC(0x2f6803a2), + WTC(0x2e312b92), WTC(0x2cfd7ae8), WTC(0x2bccfd83), WTC(0x2a9fbf1e), + WTC(0x2975cb57), WTC(0x284f2daa), WTC(0x272bf174), WTC(0x260c21ee), + WTC(0x24efca31), WTC(0x23d6f534), WTC(0x22c1adc9), WTC(0x21affea3), + WTC(0x20a1f24d), WTC(0x1f979331), WTC(0x1e90eb94), WTC(0x1d8e0597), + WTC(0x1c8eeb34), WTC(0x1b93a641), WTC(0x1a9c406e), WTC(0x19a8c345), + WTC(0x18b93828), WTC(0x17cda855), WTC(0x16e61ce0), WTC(0x16029eb6), + WTC(0x1523369c), WTC(0x1447ed2f), WTC(0x1370cae4), WTC(0x129dd806), + WTC(0x11cf1cb6), WTC(0x1104a0ee), WTC(0x103e6c7b), WTC(0x0f7c8701), + WTC(0x0ebef7fb), WTC(0x0e05c6b7), WTC(0x0d50fa59), WTC(0x0ca099da), + WTC(0x0bf4ac05), WTC(0x0b4d377c), WTC(0x0aaa42b4), WTC(0x0a0bd3f5), + WTC(0x0971f15a), WTC(0x08dca0d3), WTC(0x084be821), WTC(0x07bfccd7), + WTC(0x0738545e), WTC(0x06b583ee), WTC(0x06376092), WTC(0x05bdef28), + WTC(0x0549345c), WTC(0x04d934b1), WTC(0x046df477), WTC(0x040777d0), + WTC(0x03a5c2b0), WTC(0x0348d8dc), WTC(0x02f0bde8), WTC(0x029d753a), + WTC(0x024f0208), WTC(0x02056758), WTC(0x01c0a801), WTC(0x0180c6a9), + WTC(0x0145c5c7), WTC(0x010fa7a0), WTC(0x00de6e4c), WTC(0x00b21baf), + WTC(0x008ab180), WTC(0x00683143), WTC(0x004a9c4d), WTC(0x0031f3c2), + WTC(0x001e3895), WTC(0x000f6b88), WTC(0x00058d2f), WTC(0x00009dea), +}; +const FIXP_WTB FacWindowSynth64[] = { + WTC(0x7ffd885a), WTC(0x7fe9cbc0), WTC(0x7fc25596), WTC(0x7f872bf3), + WTC(0x7f3857f6), WTC(0x7ed5e5c6), WTC(0x7e5fe493), WTC(0x7dd6668f), + WTC(0x7d3980ec), WTC(0x7c894bde), WTC(0x7bc5e290), WTC(0x7aef6323), + WTC(0x7a05eead), WTC(0x7909a92d), WTC(0x77fab989), WTC(0x76d94989), + WTC(0x75a585cf), WTC(0x745f9dd1), WTC(0x7307c3d0), WTC(0x719e2cd2), + WTC(0x7023109a), WTC(0x6e96a99d), WTC(0x6cf934fc), WTC(0x6b4af279), + WTC(0x698c246c), WTC(0x67bd0fbd), WTC(0x65ddfbd3), WTC(0x63ef3290), + WTC(0x61f1003f), WTC(0x5fe3b38d), WTC(0x5dc79d7c), WTC(0x5b9d1154), + WTC(0x59646498), WTC(0x571deefa), WTC(0x54ca0a4b), WTC(0x5269126e), + WTC(0x4ffb654d), WTC(0x4d8162c4), WTC(0x4afb6c98), WTC(0x4869e665), + WTC(0x45cd358f), WTC(0x4325c135), WTC(0x4073f21d), WTC(0x3db832a6), + WTC(0x3af2eeb7), WTC(0x382493b0), WTC(0x354d9057), WTC(0x326e54c7), + WTC(0x2f875262), WTC(0x2c98fbba), WTC(0x29a3c485), WTC(0x26a82186), + WTC(0x23a6887f), WTC(0x209f701c), WTC(0x1d934fe5), WTC(0x1a82a026), + WTC(0x176dd9de), WTC(0x145576b1), WTC(0x1139f0cf), WTC(0x0e1bc2e4), + WTC(0x0afb6805), WTC(0x07d95b9e), WTC(0x04b6195d), WTC(0x01921d20), +}; +const FIXP_WTB FacWindowZir64[] = { + WTC(0x7e6de2e0), WTC(0x7b49e6a3), WTC(0x7826a462), WTC(0x750497fb), + WTC(0x71e43d1c), WTC(0x6ec60f31), WTC(0x6baa894f), WTC(0x68922622), + WTC(0x657d5fda), WTC(0x626cb01b), WTC(0x5f608fe4), WTC(0x5c597781), + WTC(0x5957de7a), WTC(0x565c3b7b), WTC(0x53670446), WTC(0x5078ad9e), + WTC(0x4d91ab39), WTC(0x4ab26fa9), WTC(0x47db6c50), WTC(0x450d1149), + WTC(0x4247cd5a), WTC(0x3f8c0de3), WTC(0x3cda3ecb), WTC(0x3a32ca71), + WTC(0x3796199b), WTC(0x35049368), WTC(0x327e9d3c), WTC(0x30049ab3), + WTC(0x2d96ed92), WTC(0x2b35f5b5), WTC(0x28e21106), WTC(0x269b9b68), + WTC(0x2462eeac), WTC(0x22386284), WTC(0x201c4c73), WTC(0x1e0effc1), + WTC(0x1c10cd70), WTC(0x1a22042d), WTC(0x1842f043), WTC(0x1673db94), + WTC(0x14b50d87), WTC(0x1306cb04), WTC(0x11695663), WTC(0x0fdcef66), + WTC(0x0e61d32e), WTC(0x0cf83c30), WTC(0x0ba0622f), WTC(0x0a5a7a31), + WTC(0x0926b677), WTC(0x08054677), WTC(0x06f656d3), WTC(0x05fa1153), + WTC(0x05109cdd), WTC(0x043a1d70), WTC(0x0376b422), WTC(0x02c67f14), + WTC(0x02299971), WTC(0x01a01b6d), WTC(0x012a1a3a), WTC(0x00c7a80a), + WTC(0x0078d40d), WTC(0x003daa6a), WTC(0x00163440), WTC(0x000277a6), +}; +const FIXP_WTB FacWindowSynth32[] = { + WTC(0x7ff62182), WTC(0x7fa736b4), WTC(0x7f0991c4), WTC(0x7e1d93ea), + WTC(0x7ce3ceb2), WTC(0x7b5d039e), WTC(0x798a23b1), WTC(0x776c4edb), + WTC(0x7504d345), WTC(0x72552c85), WTC(0x6f5f02b2), WTC(0x6c242960), + WTC(0x68a69e81), WTC(0x64e88926), WTC(0x60ec3830), WTC(0x5cb420e0), + WTC(0x5842dd54), WTC(0x539b2af0), WTC(0x4ebfe8a5), WTC(0x49b41533), + WTC(0x447acd50), WTC(0x3f1749b8), WTC(0x398cdd32), WTC(0x33def287), + WTC(0x2e110a62), WTC(0x2826b928), WTC(0x2223a4c5), WTC(0x1c0b826a), + WTC(0x15e21445), WTC(0x0fab272b), WTC(0x096a9049), WTC(0x03242abf), +}; +const FIXP_WTB FacWindowZir32[] = { + WTC(0x7cdbd541), WTC(0x76956fb7), WTC(0x7054d8d5), WTC(0x6a1debbb), + WTC(0x63f47d96), WTC(0x5ddc5b3b), WTC(0x57d946d8), WTC(0x51eef59e), + WTC(0x4c210d79), WTC(0x467322ce), WTC(0x40e8b648), WTC(0x3b8532b0), + WTC(0x364beacd), WTC(0x3140175b), WTC(0x2c64d510), WTC(0x27bd22ac), + WTC(0x234bdf20), WTC(0x1f13c7d0), WTC(0x1b1776da), WTC(0x1759617f), + WTC(0x13dbd6a0), WTC(0x10a0fd4e), WTC(0x0daad37b), WTC(0x0afb2cbb), + WTC(0x0893b125), WTC(0x0675dc4f), WTC(0x04a2fc62), WTC(0x031c314e), + WTC(0x01e26c16), WTC(0x00f66e3c), WTC(0x0058c94c), WTC(0x0009de7e), +}; + +/* FAC window tables for coreCoderFrameLength = 768 */ +const FIXP_WTB FacWindowSynth96[] = { + WTC(0x7ffee744), WTC(0x7ff62182), WTC(0x7fe49698), WTC(0x7fca47b9), + WTC(0x7fa736b4), WTC(0x7f7b65ef), WTC(0x7f46d86c), WTC(0x7f0991c4), + WTC(0x7ec3962a), WTC(0x7e74ea6a), WTC(0x7e1d93ea), WTC(0x7dbd98a4), + WTC(0x7d54ff2e), WTC(0x7ce3ceb2), WTC(0x7c6a0ef2), WTC(0x7be7c847), + WTC(0x7b5d039e), WTC(0x7ac9ca7a), WTC(0x7a2e26f2), WTC(0x798a23b1), + WTC(0x78ddcbf5), WTC(0x78292b8d), WTC(0x776c4edb), WTC(0x76a742d1), + WTC(0x75da14ef), WTC(0x7504d345), WTC(0x74278c72), WTC(0x73424fa0), + WTC(0x72552c85), WTC(0x71603361), WTC(0x706374ff), WTC(0x6f5f02b2), + WTC(0x6e52ee52), WTC(0x6d3f4a40), WTC(0x6c242960), WTC(0x6b019f1a), + WTC(0x69d7bf57), WTC(0x68a69e81), WTC(0x676e5183), WTC(0x662eedc3), + WTC(0x64e88926), WTC(0x639b3a0b), WTC(0x62471749), WTC(0x60ec3830), + WTC(0x5f8ab487), WTC(0x5e22a487), WTC(0x5cb420e0), WTC(0x5b3f42ae), + WTC(0x59c42381), WTC(0x5842dd54), WTC(0x56bb8a90), WTC(0x552e4605), + WTC(0x539b2af0), WTC(0x520254ef), WTC(0x5063e008), WTC(0x4ebfe8a5), + WTC(0x4d168b8b), WTC(0x4b67e5e4), WTC(0x49b41533), WTC(0x47fb3757), + WTC(0x463d6a87), WTC(0x447acd50), WTC(0x42b37e96), WTC(0x40e79d8c), + WTC(0x3f1749b8), WTC(0x3d42a2ec), WTC(0x3b69c947), WTC(0x398cdd32), + WTC(0x37abff5d), WTC(0x35c750bc), WTC(0x33def287), WTC(0x31f30638), + WTC(0x3003ad85), WTC(0x2e110a62), WTC(0x2c1b3efb), WTC(0x2a226db5), + WTC(0x2826b928), WTC(0x26284422), WTC(0x2427319d), WTC(0x2223a4c5), + WTC(0x201dc0ef), WTC(0x1e15a99a), WTC(0x1c0b826a), WTC(0x19ff6f2a), + WTC(0x17f193c5), WTC(0x15e21445), WTC(0x13d114d0), WTC(0x11beb9aa), + WTC(0x0fab272b), WTC(0x0d9681c2), WTC(0x0b80edf1), WTC(0x096a9049), + WTC(0x07538d6b), WTC(0x053c0a01), WTC(0x03242abf), WTC(0x010c1460), +}; +const FIXP_WTB FacWindowZir96[] = { + WTC(0x7ef3eba0), WTC(0x7cdbd541), WTC(0x7ac3f5ff), WTC(0x78ac7295), + WTC(0x76956fb7), WTC(0x747f120f), WTC(0x72697e3e), WTC(0x7054d8d5), + WTC(0x6e414656), WTC(0x6c2eeb30), WTC(0x6a1debbb), WTC(0x680e6c3b), + WTC(0x660090d6), WTC(0x63f47d96), WTC(0x61ea5666), WTC(0x5fe23f11), + WTC(0x5ddc5b3b), WTC(0x5bd8ce63), WTC(0x59d7bbde), WTC(0x57d946d8), + WTC(0x55dd924b), WTC(0x53e4c105), WTC(0x51eef59e), WTC(0x4ffc527b), + WTC(0x4e0cf9c8), WTC(0x4c210d79), WTC(0x4a38af44), WTC(0x485400a3), + WTC(0x467322ce), WTC(0x449636b9), WTC(0x42bd5d14), WTC(0x40e8b648), + WTC(0x3f186274), WTC(0x3d4c816a), WTC(0x3b8532b0), WTC(0x39c29579), + WTC(0x3804c8a9), WTC(0x364beacd), WTC(0x34981a1c), WTC(0x32e97475), + WTC(0x3140175b), WTC(0x2f9c1ff8), WTC(0x2dfdab11), WTC(0x2c64d510), + WTC(0x2ad1b9fb), WTC(0x29447570), WTC(0x27bd22ac), WTC(0x263bdc7f), + WTC(0x24c0bd52), WTC(0x234bdf20), WTC(0x21dd5b79), WTC(0x20754b79), + WTC(0x1f13c7d0), WTC(0x1db8e8b7), WTC(0x1c64c5f5), WTC(0x1b1776da), + WTC(0x19d1123d), WTC(0x1891ae7d), WTC(0x1759617f), WTC(0x162840a9), + WTC(0x14fe60e6), WTC(0x13dbd6a0), WTC(0x12c0b5c0), WTC(0x11ad11ae), + WTC(0x10a0fd4e), WTC(0x0f9c8b01), WTC(0x0e9fcc9f), WTC(0x0daad37b), + WTC(0x0cbdb060), WTC(0x0bd8738e), WTC(0x0afb2cbb), WTC(0x0a25eb11), + WTC(0x0958bd2f), WTC(0x0893b125), WTC(0x07d6d473), WTC(0x0722340b), + WTC(0x0675dc4f), WTC(0x05d1d90e), WTC(0x05363586), WTC(0x04a2fc62), + WTC(0x041837b9), WTC(0x0395f10e), WTC(0x031c314e), WTC(0x02ab00d2), + WTC(0x0242675c), WTC(0x01e26c16), WTC(0x018b1596), WTC(0x013c69d6), + WTC(0x00f66e3c), WTC(0x00b92794), WTC(0x00849a11), WTC(0x0058c94c), + WTC(0x0035b847), WTC(0x001b6968), WTC(0x0009de7e), WTC(0x000118bc), +}; +const FIXP_WTB FacWindowSynth48[] = { + WTC(0x7ffb9d15), WTC(0x7fd8878e), WTC(0x7f92661d), WTC(0x7f294bfd), + WTC(0x7e9d55fc), WTC(0x7deeaa7a), WTC(0x7d1d7958), WTC(0x7c29fbee), + WTC(0x7b1474fd), WTC(0x79dd3098), WTC(0x78848414), WTC(0x770acdec), + WTC(0x757075ac), WTC(0x73b5ebd1), WTC(0x71dba9ab), WTC(0x6fe2313c), + WTC(0x6dca0d14), WTC(0x6b93d02e), WTC(0x694015c3), WTC(0x66cf8120), + WTC(0x6442bd7e), WTC(0x619a7dce), WTC(0x5ed77c8a), WTC(0x5bfa7b82), + WTC(0x590443a7), WTC(0x55f5a4d2), WTC(0x52cf758f), WTC(0x4f9292dc), + WTC(0x4c3fdff4), WTC(0x48d84609), WTC(0x455cb40c), WTC(0x41ce1e65), + WTC(0x3e2d7eb1), WTC(0x3a7bd382), WTC(0x36ba2014), WTC(0x32e96c09), + WTC(0x2f0ac320), WTC(0x2b1f34eb), WTC(0x2727d486), WTC(0x2325b847), + WTC(0x1f19f97b), WTC(0x1b05b40f), WTC(0x16ea0646), WTC(0x12c8106f), + WTC(0x0ea0f48c), WTC(0x0a75d60e), WTC(0x0647d97c), WTC(0x02182427), +}; +const FIXP_WTB FacWindowZir48[] = { + WTC(0x7de7dbd9), WTC(0x79b82684), WTC(0x758a29f2), WTC(0x715f0b74), + WTC(0x6d37ef91), WTC(0x6915f9ba), WTC(0x64fa4bf1), WTC(0x60e60685), + WTC(0x5cda47b9), WTC(0x58d82b7a), WTC(0x54e0cb15), WTC(0x50f53ce0), + WTC(0x4d1693f7), WTC(0x4945dfec), WTC(0x45842c7e), WTC(0x41d2814f), + WTC(0x3e31e19b), WTC(0x3aa34bf4), WTC(0x3727b9f7), WTC(0x33c0200c), + WTC(0x306d6d24), WTC(0x2d308a71), WTC(0x2a0a5b2e), WTC(0x26fbbc59), + WTC(0x2405847e), WTC(0x21288376), WTC(0x1e658232), WTC(0x1bbd4282), + WTC(0x19307ee0), WTC(0x16bfea3d), WTC(0x146c2fd2), WTC(0x1235f2ec), + WTC(0x101dcec4), WTC(0x0e245655), WTC(0x0c4a142f), WTC(0x0a8f8a54), + WTC(0x08f53214), WTC(0x077b7bec), WTC(0x0622cf68), WTC(0x04eb8b03), + WTC(0x03d60412), WTC(0x02e286a8), WTC(0x02115586), WTC(0x0162aa04), + WTC(0x00d6b403), WTC(0x006d99e3), WTC(0x00277872), WTC(0x000462eb), +}; diff --git a/fdk-aac/libAACdec/src/usacdec_rom.h b/fdk-aac/libAACdec/src/usacdec_rom.h new file mode 100644 index 0000000..f969e90 --- /dev/null +++ b/fdk-aac/libAACdec/src/usacdec_rom.h @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC decoder library ****************************** + + Author(s): M. Jander + + Description: re8.h + +*******************************************************************************/ + +#ifndef USACDEC_ROM_H +#define USACDEC_ROM_H + +#include "common_fix.h" +#include "FDK_lpc.h" + +#include "usacdec_const.h" + +/* RE8 lattice quantiser constants */ +#define NB_SPHERE 32 +#define NB_LEADER 37 +#define NB_LDSIGN 226 +#define NB_LDQ3 9 +#define NB_LDQ4 28 + +#define LSF_SCALE 13 + +/* RE8 lattice quantiser tables */ +extern const UINT fdk_dec_tab_factorial[8]; +extern const UCHAR fdk_dec_Ia[NB_LEADER]; +extern const UCHAR fdk_dec_Ds[NB_LDSIGN]; +extern const USHORT fdk_dec_Is[NB_LDSIGN]; +extern const UCHAR fdk_dec_Ns[], fdk_dec_A3[], fdk_dec_A4[]; +extern const UCHAR fdk_dec_Da[][8]; +extern const USHORT fdk_dec_I3[], fdk_dec_I4[]; + +/* temp float tables for LPC decoding */ +extern const FIXP_LPC fdk_dec_lsf_init[16]; +extern const FIXP_LPC fdk_dec_dico_lsf_abs_8b[16 * 256]; + +/* ACELP tables */ +#define SF_QUA_GAIN7B 4 +extern const FIXP_SGL fdk_t_qua_gain7b[128 * 2]; +extern const FIXP_SGL lsp_interpol_factor[2][NB_SUBFR]; + +/* For bass post filter */ +#define L_FILT 12 /* Delay of up-sampling filter */ + +extern const FIXP_SGL fdk_dec_filt_lp[1 + L_FILT]; + +extern const FIXP_WTB FacWindowSynth128[128]; +extern const FIXP_WTB FacWindowZir128[128]; +extern const FIXP_WTB FacWindowSynth64[64]; +extern const FIXP_WTB FacWindowZir64[64]; +extern const FIXP_WTB FacWindowSynth32[32]; +extern const FIXP_WTB FacWindowZir32[32]; +extern const FIXP_WTB FacWindowSynth96[96]; +extern const FIXP_WTB FacWindowZir96[96]; +extern const FIXP_WTB FacWindowSynth48[48]; +extern const FIXP_WTB FacWindowZir48[48]; + +#endif /* USACDEC_ROM_H */ diff --git a/fdk-aac/libAACenc/include/aacenc_lib.h b/fdk-aac/libAACenc/include/aacenc_lib.h new file mode 100644 index 0000000..231bbb4 --- /dev/null +++ b/fdk-aac/libAACenc/include/aacenc_lib.h @@ -0,0 +1,1733 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: + +*******************************************************************************/ + +/** + * \file aacenc_lib.h + * \brief FDK AAC Encoder library interface header file. + * +\mainpage Introduction + +\section Scope + +This document describes the high-level interface and usage of the ISO/MPEG-2/4 +AAC Encoder library developed by the Fraunhofer Institute for Integrated +Circuits (IIS). + +The library implements encoding on the basis of the MPEG-2 and MPEG-4 AAC +Low-Complexity standard, and depending on the library's configuration, MPEG-4 +High-Efficiency AAC v2 and/or AAC-ELD standard. + +All references to SBR (Spectral Band Replication) are only applicable to HE-AAC +or AAC-ELD versions of the library. All references to PS (Parametric Stereo) are +only applicable to HE-AAC v2 versions of the library. + +\section encBasics Encoder Basics + +This document can only give a rough overview about the ISO/MPEG-2 and ISO/MPEG-4 +AAC audio coding standard. To understand all the terms in this document, you are +encouraged to read the following documents. + +- ISO/IEC 13818-7 (MPEG-2 AAC), which defines the syntax of MPEG-2 AAC audio +bitstreams. +- ISO/IEC 14496-3 (MPEG-4 AAC, subparts 1 and 4), which defines the syntax of +MPEG-4 AAC audio bitstreams. +- Lutzky, Schuller, Gayer, Krämer, Wabnik, "A guideline to audio codec +delay", 116th AES Convention, May 8, 2004 + +MPEG Advanced Audio Coding is based on a time-to-frequency mapping of the +signal. The signal is partitioned into overlapping portions and transformed into +frequency domain. The spectral components are then quantized and coded. \n An +MPEG-2 or MPEG-4 AAC audio bitstream is composed of frames. Contrary to MPEG-1/2 +Layer-3 (mp3), the length of individual frames is not restricted to a fixed +number of bytes, but can take on any length between 1 and 768 bytes. + + +\page LIBUSE Library Usage + +\section InterfaceDescription API Files + +All API header files are located in the folder /include of the release package. +All header files are provided for usage in C/C++ programs. The AAC encoder +library API functions are located in aacenc_lib.h. + +In binary releases the encoder core resides in statically linkable libraries +called for example libAACenc.a/libFDK.a (LINUX) or FDK_fastaaclib.lib (MS Visual +C++) for the plain AAC-LC core encoder and libSBRenc.a (LINUX) or +FDK_sbrEncLib.lib (MS Visual C++) for the SBR (Spectral Band Replication) and PS +(Parametric Stereo) modules. + +\section CallingSequence Calling Sequence + +For encoding of ISO/MPEG-2/4 AAC bitstreams the following sequence is mandatory. +Input read and output write functions as well as the corresponding open and +close functions are left out, since they may be implemented differently +according to the user's specific requirements. The example implementation uses +file-based input/output. + +-# Call aacEncOpen() to allocate encoder instance with required \ref encOpen +"configuration". \code HANDLE_AACENCODER hAacEncoder = NULL; if ( (ErrorStatus = +aacEncOpen(&hAacEncoder,0,0)) != AACENC_OK ) { \endcode +-# Call aacEncoder_SetParam() for each parameter to be set. AOT, samplingrate, +channelMode, bitrate and transport type are \ref encParams "mandatory". \code +ErrorStatus = aacEncoder_SetParam(hAacEncoder, parameter, value); +\endcode +-# Call aacEncEncode() with NULL parameters to \ref encReconf "initialize" +encoder instance with present parameter set. \code ErrorStatus = +aacEncEncode(hAacEncoder, NULL, NULL, NULL, NULL); \endcode +-# Call aacEncInfo() to retrieve a configuration data block to be transmitted +out of band. This is required when using RFC3640 or RFC3016 like transport. +\code +AACENC_InfoStruct encInfo; +aacEncInfo(hAacEncoder, &encInfo); +\endcode +-# Encode input audio data in loop. +\code +do +{ +\endcode +Feed \ref feedInBuf "input buffer" with new audio data and provide input/output +\ref bufDes "arguments" to aacEncEncode(). \code ErrorStatus = +aacEncEncode(hAacEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs); \endcode +Write \ref writeOutData "output data" to file or audio device. +\code +} while (ErrorStatus==AACENC_OK); +\endcode +-# Call aacEncClose() and destroy encoder instance. +\code +aacEncClose(&hAacEncoder); +\endcode + + +\section encOpen Encoder Instance Allocation + +The assignment of the aacEncOpen() function is very flexible and can be used in +the following way. +- If the amount of memory consumption is not an issue, the encoder instance can +be allocated for the maximum number of possible audio channels (for example 6 or +8) with the full functional range supported by the library. This is the default +open procedure for the AAC encoder if memory consumption does not need to be +minimized. \code aacEncOpen(&hAacEncoder,0,0) \endcode +- If the required MPEG-4 AOTs do not call for the full functional range of the +library, encoder modules can be allocated selectively. \verbatim +------------------------------------------------------ + AAC | SBR | PS | MD | FLAGS | value +-----+-----+-----+----+-----------------------+------- + X | - | - | - | (0x01) | 0x01 + X | X | - | - | (0x01|0x02) | 0x03 + X | X | X | - | (0x01|0x02|0x04) | 0x07 + X | - | - | X | (0x01 |0x10) | 0x11 + X | X | - | X | (0x01|0x02 |0x10) | 0x13 + X | X | X | X | (0x01|0x02|0x04|0x10) | 0x17 +------------------------------------------------------ + - AAC: Allocate AAC Core Encoder module. + - SBR: Allocate Spectral Band Replication module. + - PS: Allocate Parametric Stereo module. + - MD: Allocate Meta Data module within AAC encoder. +\endverbatim +\code aacEncOpen(&hAacEncoder,value,0) \endcode +- Specifying the maximum number of channels to be supported in the encoder +instance can be done as follows. + - For example allocate an encoder instance which supports 2 channels for all +supported AOTs. The library itself may be capable of encoding up to 6 or 8 +channels but in this example only 2 channel encoding is required and thus only +buffers for 2 channels are allocated to save data memory. \code +aacEncOpen(&hAacEncoder,0,2) \endcode + - Additionally the maximum number of supported channels in the SBR module can +be denoted separately.\n In this example the encoder instance provides a maximum +of 6 channels out of which up to 2 channels support SBR. This encoder instance +can produce for example 5.1 channel AAC-LC streams or stereo HE-AAC (v2) +streams. HE-AAC 5.1 multi channel is not possible since only 2 out of 6 channels +support SBR, which saves data memory. \code aacEncOpen(&hAacEncoder,0,6|(2<<8)) +\endcode \n + +\section bufDes Input/Output Arguments + +\subsection allocIOBufs Provide Buffer Descriptors +In the present encoder API, the input and output buffers are described with \ref +AACENC_BufDesc "buffer descriptors". This mechanism allows a flexible handling +of input and output buffers without impact to the actual encoding call. Optional +buffers are necessary e.g. for ancillary data, meta data input or additional +output buffers describing superframing data in DAB+ or DRM+.\n At least one +input buffer for audio input data and one output buffer for bitstream data must +be allocated. The input buffer size can be a user defined multiple of the number +of input channels. PCM input data will be copied from the user defined PCM +buffer to an internal input buffer and so input data can be less than one AAC +audio frame. The output buffer size should be 6144 bits per channel excluding +the LFE channel. If the output data does not fit into the provided buffer, an +AACENC_ERROR will be returned by aacEncEncode(). \code static INT_PCM +inputBuffer[8*2048]; static UCHAR ancillaryBuffer[50]; static +AACENC_MetaData metaDataSetup; static UCHAR outputBuffer[8192]; +\endcode + +All input and output buffer must be clustered in input and output buffer arrays. +\code +static void* inBuffer[] = { inputBuffer, ancillaryBuffer, &metaDataSetup +}; static INT inBufferIds[] = { IN_AUDIO_DATA, IN_ANCILLRY_DATA, +IN_METADATA_SETUP }; static INT inBufferSize[] = { sizeof(inputBuffer), +sizeof(ancillaryBuffer), sizeof(metaDataSetup) }; static INT inBufferElSize[] += { sizeof(INT_PCM), sizeof(UCHAR), sizeof(AACENC_MetaData) }; + +static void* outBuffer[] = { outputBuffer }; +static INT outBufferIds[] = { OUT_BITSTREAM_DATA }; +static INT outBufferSize[] = { sizeof(outputBuffer) }; +static INT outBufferElSize[] = { sizeof(UCHAR) }; +\endcode + +Allocate buffer descriptors +\code +AACENC_BufDesc inBufDesc; +AACENC_BufDesc outBufDesc; +\endcode + +Initialize input buffer descriptor +\code +inBufDesc.numBufs = sizeof(inBuffer)/sizeof(void*); +inBufDesc.bufs = (void**)&inBuffer; +inBufDesc.bufferIdentifiers = inBufferIds; +inBufDesc.bufSizes = inBufferSize; +inBufDesc.bufElSizes = inBufferElSize; +\endcode + +Initialize output buffer descriptor +\code +outBufDesc.numBufs = sizeof(outBuffer)/sizeof(void*); +outBufDesc.bufs = (void**)&outBuffer; +outBufDesc.bufferIdentifiers = outBufferIds; +outBufDesc.bufSizes = outBufferSize; +outBufDesc.bufElSizes = outBufferElSize; +\endcode + +\subsection argLists Provide Input/Output Argument Lists +The input and output arguments of an aacEncEncode() call are described in +argument structures. \code AACENC_InArgs inargs; AACENC_OutArgs outargs; +\endcode + +\section feedInBuf Feed Input Buffer +The input buffer should be handled as a modulo buffer. New audio data in the +form of pulse-code- modulated samples (PCM) must be read from external and be +fed to the input buffer depending on its fill level. The required sample bitrate +(represented by the data type INT_PCM which is 16, 24 or 32 bits wide) is fixed +and depends on library configuration (usually 16 bit). \code inargs.numInSamples ++= WAV_InputRead ( wavIn, &inputBuffer[inargs.numInSamples], + FDKmin(encInfo.inputChannels*encInfo.frameLength, + sizeof(inputBuffer) / + sizeof(INT_PCM)-inargs.numInSamples), + SAMPLE_BITS + ); +\endcode + +After the encoder's internal buffer is fed with incoming audio samples, and +aacEncEncode() processed the new input data, update/move remaining samples in +input buffer, simulating a modulo buffer: \code if (outargs.numInSamples>0) { + FDKmemmove( inputBuffer, + &inputBuffer[outargs.numInSamples], + sizeof(INT_PCM)*(inargs.numInSamples-outargs.numInSamples) ); + inargs.numInSamples -= outargs.numInSamples; +} +\endcode + +\section writeOutData Output Bitstream Data +If any AAC bitstream data is available, write it to output file or device. This +can be done once the following condition is true: \code if +(outargs.numOutBytes>0) { + +} +\endcode + +If you use file I/O then for example call mpegFileWrite_Write() from the library +libMpegFileWrite \code mpegFileWrite_Write(hMpegFile, outputBuffer, +outargs.numOutBytes, aacEncoder_GetParam(hAacEncoder, AACENC_GRANULE_LENGTH)); +\endcode + +\section cfgMetaData Meta Data Configuration + +If the present library is configured with Metadata support, it is possible to +insert meta data side info into the generated audio bitstream while encoding. + +To work with meta data the encoder instance has to be \ref encOpen "allocated" +with meta data support. The meta data mode must be be configured with the +::AACENC_METADATA_MODE parameter and aacEncoder_SetParam() function. \code +aacEncoder_SetParam(hAacEncoder, AACENC_METADATA_MODE, 0-3); \endcode + +This configuration indicates how to embed meta data into bitstrem. Either no +insertion, MPEG or ETSI style. The meta data itself must be specified within the +meta data setup structure AACENC_MetaData. + +Changing one of the AACENC_MetaData setup parameters can be achieved from +outside the library within ::IN_METADATA_SETUP input buffer. There is no need to +supply meta data setup structure every frame. If there is no new meta setup data +available, the encoder uses the previous setup or the default configuration in +initial state. + +In general the audio compressor and limiter within the encoder library can be +configured with the ::AACENC_METADATA_DRC_PROFILE parameter +AACENC_MetaData::drc_profile and and AACENC_MetaData::comp_profile. +\n + +\section encReconf Encoder Reconfiguration + +The encoder library allows reconfiguration of the encoder instance with new +settings continuously between encoding frames. Each parameter to be changed must +be set with a single aacEncoder_SetParam() call. The internal status of each +parameter can be retrieved with an aacEncoder_GetParam() call.\n There is no +stand-alone reconfiguration function available. When parameters were modified +from outside the library, an internal control mechanism triggers the necessary +reconfiguration process which will be applied at the beginning of the following +aacEncEncode() call. This state can be observed from external via the +AACENC_INIT_STATUS and aacEncoder_GetParam() function. The reconfiguration +process can also be applied immediately when all parameters of an aacEncEncode() +call are NULL with a valid encoder handle.\n\n The internal reconfiguration +process can be controlled from extern with the following access. \code +aacEncoder_SetParam(hAacEncoder, AACENC_CONTROL_STATE, AACENC_CTRLFLAGS); +\endcode + + +\section encParams Encoder Parametrization + +All parameteres listed in ::AACENC_PARAM can be modified within an encoder +instance. + +\subsection encMandatory Mandatory Encoder Parameters +The following parameters must be specified when the encoder instance is +initialized. \code aacEncoder_SetParam(hAacEncoder, AACENC_AOT, value); +aacEncoder_SetParam(hAacEncoder, AACENC_BITRATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_SAMPLERATE, value); +aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); +\endcode +Beyond that is an internal auto mode which preinitizializes the ::AACENC_BITRATE +parameter if the parameter was not set from extern. The bitrate depends on the +number of effective channels and sampling rate and is determined as follows. +\code +AAC-LC (AOT_AAC_LC): 1.5 bits per sample +HE-AAC (AOT_SBR): 0.625 bits per sample (dualrate sbr) +HE-AAC (AOT_SBR): 1.125 bits per sample (downsampled sbr) +HE-AAC v2 (AOT_PS): 0.5 bits per sample +\endcode + +\subsection channelMode Channel Mode Configuration +The input audio data is described with the ::AACENC_CHANNELMODE parameter in the +aacEncoder_SetParam() call. It is not possible to use the encoder instance with +a 'number of input channels' argument. Instead, the channelMode must be set as +follows. \code aacEncoder_SetParam(hAacEncoder, AACENC_CHANNELMODE, value); +\endcode The parameter is specified in ::CHANNEL_MODE and can be mapped from the +number of input channels in the following way. \code CHANNEL_MODE chMode = +MODE_INVALID; + +switch (nChannels) { + case 1: chMode = MODE_1; break; + case 2: chMode = MODE_2; break; + case 3: chMode = MODE_1_2; break; + case 4: chMode = MODE_1_2_1; break; + case 5: chMode = MODE_1_2_2; break; + case 6: chMode = MODE_1_2_2_1; break; + case 7: chMode = MODE_6_1; break; + case 8: chMode = MODE_7_1_BACK; break; + default: + chMode = MODE_INVALID; +} +return chMode; +\endcode + +\subsection bitreservoir Bitreservoir Configuration +In AAC, the default bitreservoir configuration depends on the chosen bitrate per +frame and the number of effective channels. The size can be determined as below. +\f[ +bitreservoir = nEffChannels*6144 - (bitrate*framelength/samplerate) +\f] +Due to audio quality concerns it is not recommended to change the bitreservoir +size to a lower value than the default setting! However, for minimizing the +delay for streaming applications or for achieving a constant size of the +bitstream packages in each frame, it may be necessaray to change the +bitreservoir size. This can be done with the ::AACENC_PEAK_BITRATE parameter. +\code +aacEncoder_SetParam(hAacEncoder, AACENC_PEAK_BITRATE, value); +\endcode +By setting ::AACENC_BITRATEMODE to fixed framing, the bitreservoir is disabled. +A disabled bitreservoir results in a constant size for each bitstream package. +Please note that especially at lower bitrates a disabled bitreservoir can +downgrade the audio quality considerably! The default bitreservoir configuration +can be achieved as follows. \code aacEncoder_SetParam(hAacEncoder, +AACENC_BITRESERVOIR, -1); \endcode + +To achieve acceptable audio quality with a reduced bitreservoir size setting at +least 1000 bits per audio channel is recommended. For a multichannel audio file +with 5.1 channels the bitreservoir reduced to 5000 bits results in acceptable +audio quality. + + +\subsection vbrmode Variable Bitrate Mode +The encoder provides various Variable Bitrate Modes that differ in audio quality +and average overall bitrate. The given values are averages over time, different +encoder settings and strongly depend on the type of audio signal. The VBR +configurations can be adjusted via ::AACENC_BITRATEMODE encoder parameter. +\verbatim +-------------------------------------------- + VBR_MODE | Approx. Bitrate in kbps/channel + | AAC-LC | AAC-LD/AC_ELD +----------+---------------+----------------- + VBR_1 | 32 - 48 | 32 - 56 + VBR_2 | 40 - 56 | 40 - 64 + VBR_3 | 48 - 64 | 48 - 72 + VBR_4 | 64 - 80 | 64 - 88 + VBR_5 | 96 - 120 | 112 - 144 +-------------------------------------------- +\endverbatim +The bitrate ranges apply for individual audio channels. In case of multichannel +configurations the average bitrate might be estimated by multiplying with the +number of effective channels. This corresponds to all audio input channels +exclusively the low frequency channel. At configurations which are making use of +downmix modules the AAC core channels respectively downmix channels shall be +considered. For ::AACENC_AOT which are using SBR, the average bitrate can be +estimated by using the ratio of 0.5 for dualrate SBR and 0.75 for downsampled +SBR configurations. + + +\subsection encQual Audio Quality Considerations +The default encoder configuration is suggested to be used. Encoder tools such as +TNS and PNS are activated by default and are internally controlled (see \ref +BEHAVIOUR_TOOLS). + +There is an additional quality parameter called ::AACENC_AFTERBURNER. In the +default configuration this quality switch is deactivated because it would cause +a workload increase which might be significant. If workload is not an issue in +the application we recommended to activate this feature. \code +aacEncoder_SetParam(hAacEncoder, AACENC_AFTERBURNER, 0/1); \endcode + +\subsection encELD ELD Auto Configuration Mode +For ELD configuration a so called auto configurator is available which +configures SBR and the SBR ratio by itself. The configurator is used when the +encoder parameter ::AACENC_SBR_MODE and ::AACENC_SBR_RATIO are not set +explicitly. + +Based on sampling rate and chosen bitrate a reasonable SBR configuration will be +used. \verbatim +------------------------------------------------------------------ + Sampling Rate | Total Bitrate | No. of | SBR | SBR Ratio + [kHz] | [bit/s] | Chan | | + | | | | +---------------+-----------------+--------+-----+----------------- + ]min, 16[ | min - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + [16] | min - 27999 | 1 | on | downsampled SBR + | 28000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]16 - 24] | min - 39999 | 1 | on | downsampled SBR + | 40000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]24 - 32] | min - 27999 | 1 | on | dualrate SBR + | 28000 - 55999 | 1 | on | downsampled SBR + | 56000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]32 - 44.1] | min - 63999 | 1 | on | dualrate SBR + | 64000 - max | 1 | off | --- +---------------+-----------------+--------------+----------------- + ]44.1 - 48] | min - 63999 | 1 | on | dualrate SBR + | 64000 - max | 1 | off | --- + | | | | +---------------+-----------------+--------+-----+----------------- + ]min, 16[ | min - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + [16] | min - 31999 | 2 | on | downsampled SBR + | 32000 - 63999 | 2 | on | downsampled SBR + | 64000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]16 - 24] | min - 47999 | 2 | on | downsampled SBR + | 48000 - 79999 | 2 | on | downsampled SBR + | 80000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]24 - 32] | min - 31999 | 2 | on | dualrate SBR + | 32000 - 67999 | 2 | on | dualrate SBR + | 68000 - 95999 | 2 | on | downsampled SBR + | 96000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]32 - 44.1] | min - 43999 | 2 | on | dualrate SBR + | 44000 - 127999 | 2 | on | dualrate SBR + | 128000 - max | 2 | off | --- +---------------+-----------------+--------------+----------------- + ]44.1 - 48] | min - 43999 | 2 | on | dualrate SBR + | 44000 - 127999 | 2 | on | dualrate SBR + | 128000 - max | 2 | off | --- + | | | +------------------------------------------------------------------ +\endverbatim + +\subsection encDsELD Reduced Delay (Downscaled) Mode +The downscaled mode of AAC-ELD reduces the algorithmic delay of AAC-ELD by +virtually increasing the sampling rate. When using the downscaled mode, the +bitrate should be increased for keeping the same audio quality level. For common +signals, the bitrate should be increased by 25% for a downscale factor of 2. + +Currently, downscaling factors 2 and 4 are supported. +To enable the downscaled mode in the encoder, the framelength parameter +AACENC_GRANULE_LENGTH must be set accordingly to 256 or 240 for a downscale +factor of 2 or 128 or 120 for a downscale factor of 4. The default values of 512 +or 480 mean that no downscaling is applied. \code +aacEncoder_SetParam(hAacEncoder, AACENC_GRANULE_LENGTH, 256); +aacEncoder_SetParam(hAacEncoder, AACENC_GRANULE_LENGTH, 128); +\endcode + +Downscaled bitstreams are fully backwards compatible. However, the legacy +decoder needs to support high sample rate, e.g. 96kHz. The signaled sampling +rate is multiplied by the downscale factor. Although not required, downscaling +should be applied when decoding downscaled bitstreams. It reduces CPU workload +and the output will have the same sampling rate as the input. In an ideal +configuration both encoder and decoder should run with the same downscale +factor. + +The following table shows approximate filter bank delays in ms for common +sampling rates(sr) at framesize(fs), and downscale factor(dsf), based on this +formula: \f[ 1000 * fs / (dsf * sr) \f] + +\verbatim +-------------------------------------- + | 512/2 | 512/4 | 480/2 | 480/4 +------+-------+-------+-------+------- +22050 | 17.41 | 8.71 | 16.33 | 8.16 +32000 | 12.00 | 6.00 | 11.25 | 5.62 +44100 | 8.71 | 4.35 | 8.16 | 4.08 +48000 | 8.00 | 4.00 | 7.50 | 3.75 +-------------------------------------- +\endverbatim + +\section audiochCfg Audio Channel Configuration +The MPEG standard refers often to the so-called Channel Configuration. This +Channel Configuration is used for a fixed Channel Mapping. The configurations +1-7 and 11,12,14 are predefined in MPEG standard and used for implicit +signalling within the encoded bitstream. For user defined Configurations the +Channel Configuration is set to 0 and the Channel Mapping must be explecitly +described with an appropriate Program Config Element. The present Encoder +implementation does not allow the user to configure this Channel Configuration +from extern. The Encoder implementation supports fixed Channel Modes which are +mapped to Channel Configuration as follow. \verbatim +---------------------------------------------------------------------------------------- + ChannelMode | ChCfg | Height | front_El | side_El | back_El | +lfe_El +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_1 | 1 | NORM | SCE | | | +MODE_2 | 2 | NORM | CPE | | | +MODE_1_2 | 3 | NORM | SCE, CPE | | | +MODE_1_2_1 | 4 | NORM | SCE, CPE | | SCE | +MODE_1_2_2 | 5 | NORM | SCE, CPE | | CPE | +MODE_1_2_2_1 | 6 | NORM | SCE, CPE | | CPE | +LFE MODE_1_2_2_2_1 | 7 | NORM | SCE, CPE, CPE | | CPE +| LFE MODE_6_1 | 11 | NORM | SCE, CPE | | CPE, +SCE | LFE MODE_7_1_BACK | 12 | NORM | SCE, CPE | | +CPE, CPE | LFE +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_7_1_TOP_FRONT | 14 | NORM | SCE, CPE | | CPE | +LFE | | TOP | CPE | | | +-----------------------+-------+--------+---------------+----------+----------+--------- +MODE_7_1_REAR_SURROUND | 0 | NORM | SCE, CPE | | CPE, CPE | +LFE MODE_7_1_FRONT_CENTER | 0 | NORM | SCE, CPE, CPE | | CPE +| LFE +---------------------------------------------------------------------------------------- +- NORM: Normal Height Layer. - TOP: Top Height Layer. - BTM: Bottom Height +Layer. +- SCE: Single Channel Element. - CPE: Channel Pair. - LFE: Low Frequency +Element. \endverbatim + +The Table describes all fixed Channel Elements for each Channel Mode which are +assigned to a speaker arrangement. The arrangement includes front, side, back +and lfe Audio Channel Elements in the normal height layer, possibly followed by +front, side, and back elements in the top and bottom layer (Channel +Configuration 14). \n This mapping of Audio Channel Elements is defined in MPEG +standard for Channel Config 1-7 and 11,12,14.\n In case of Channel Config 0 or +writing matrix mixdown coefficients, the encoder enables the writing of Program +Config Element itself as described in \ref encPCE. The configuration used in +Program Config Element refers to the denoted Table.\n Beside the Channel Element +assignment the Channel Modes are resposible for audio input data channel +mapping. The Channel Mapping of the audio data depends on the selected +::AACENC_CHANNELORDER which can be MPEG or WAV like order.\n Following table +describes the complete channel mapping for both Channel Order configurations. +\verbatim +--------------------------------------------------------------------------------------- +ChannelMode | MPEG-Channelorder | WAV-Channelorder +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_1 | 0 | | | | | | | | 0 | | | | | | +| MODE_2 | 0 | 1 | | | | | | | 0 | 1 | | | | +| | MODE_1_2 | 0 | 1 | 2 | | | | | | 2 | 0 | 1 | | +| | | MODE_1_2_1 | 0 | 1 | 2 | 3 | | | | | 2 | 0 | 1 | 3 +| | | | MODE_1_2_2 | 0 | 1 | 2 | 3 | 4 | | | | 2 | 0 | 1 +| 3 | 4 | | | MODE_1_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | | | 2 | 0 +| 1 | 4 | 5 | 3 | | MODE_1_2_2_2_1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 +| 6 | 7 | 0 | 1 | 4 | 5 | 3 MODE_6_1 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | +| 2 | 0 | 1 | 4 | 5 | 6 | 3 | MODE_7_1_BACK | 0 | 1 | 2 | 3 | 4 | 5 | 6 +| 7 | 2 | 0 | 1 | 6 | 7 | 4 | 5 | 3 MODE_7_1_TOP_FRONT | 0 | 1 | 2 | 3 | 4 | +5 | 6 | 7 | 2 | 0 | 1 | 4 | 5 | 3 | 6 | 7 +-----------------------+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+--- +MODE_7_1_REAR_SURROUND | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 0 | 1 | 6 | 7 | 4 | +5 | 3 MODE_7_1_FRONT_CENTER | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 2 | 6 | 7 | 0 | 1 +| 4 | 5 | 3 +--------------------------------------------------------------------------------------- +\endverbatim + +The denoted mapping is important for correct audio channel assignment when using +MPEG or WAV ordering. The incoming audio channels are distributed MPEG like +starting at the front channels and ending at the back channels. The distribution +is used as described in Table concering Channel Config and fix channel elements. +Please see the following example for clarification. + +\verbatim +Example: MODE_1_2_2_1 - WAV-Channelorder 5.1 +------------------------------------------ + Input Channel | Coder Channel +--------------------+--------------------- + 2 (front center) | 0 (SCE channel) + 0 (left center) | 1 (1st of 1st CPE) + 1 (right center) | 2 (2nd of 1st CPE) + 4 (left surround) | 3 (1st of 2nd CPE) + 5 (right surround) | 4 (2nd of 2nd CPE) + 3 (LFE) | 5 (LFE) +------------------------------------------ +\endverbatim + + +\section suppBitrates Supported Bitrates + +The FDK AAC Encoder provides a wide range of supported bitrates. +The minimum and maximum allowed bitrate depends on the Audio Object Type. For +AAC-LC the minimum bitrate is the bitrate that is required to write the most +basic and minimal valid bitstream. It consists of the bitstream format header +information and other static/mandatory information within the AAC payload. The +maximum AAC framesize allowed by the MPEG-4 standard determines the maximum +allowed bitrate for AAC-LC. For HE-AAC and HE-AAC v2 a library internal look-up +table is used. + +A good working point in terms of audio quality, sampling rate and bitrate, is at +1 to 1.5 bits/audio sample for AAC-LC, 0.625 bits/audio sample for dualrate +HE-AAC, 1.125 bits/audio sample for downsampled HE-AAC and 0.5 bits/audio sample +for HE-AAC v2. For example for one channel with a sampling frequency of 48 kHz, +the range from 48 kbit/s to 72 kbit/s achieves reasonable audio quality for +AAC-LC. + +For HE-AAC and HE-AAC v2 the lowest possible audio input sampling frequency is +16 kHz because then the AAC-LC core encoder operates in dual rate mode at its +lowest possible sampling frequency, which is 8 kHz. HE-AAC v2 requires stereo +input audio data. + +Please note that in HE-AAC or HE-AAC v2 mode the encoder supports much higher +bitrates than are appropriate for HE-AAC or HE-AAC v2. For example, at a bitrate +of more than 64 kbit/s for a stereo audio signal at 44.1 kHz it usually makes +sense to use AAC-LC, which will produce better audio quality at that bitrate +than HE-AAC or HE-AAC v2. + +\section reommendedConfig Recommended Sampling Rate and Bitrate Combinations + +The following table provides an overview of recommended encoder configuration +parameters which we determined by virtue of numerous listening tests. + +\subsection reommendedConfigLC AAC-LC, HE-AAC, HE-AACv2 in Dualrate SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR + PS | 8000 - 11999 | 22.05, 24.00 | 24.00 | 2 +AAC LC + SBR + PS | 12000 - 17999 | 32.00 | 32.00 | 2 +AAC LC + SBR + PS | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR + PS | 40000 - 64000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 8000 - 11999 | 22.05, 24.00 | 24.00 | 1 +AAC LC + SBR | 12000 - 17999 | 32.00 | 32.00 | 1 +AAC LC + SBR | 18000 - 39999 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC + SBR | 40000 - 64000 | 32.00, 44.10, 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 16000 - 27999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC + SBR | 28000 - 63999 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC + SBR | 64000 - 128000 | 32.00, 44.10, 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC + SBR | 64000 - 69999 | 32.00, 44.10, 48.00 | 32.00 | +5, 5.1 AAC LC + SBR | 70000 - 239999 | 32.00, 44.10, 48.00 | 44.10 +| 5, 5.1 AAC LC + SBR | 240000 - 319999 | 32.00, 44.10, 48.00 | +48.00 | 5, 5.1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 8000 - 15999 | 11.025, 12.00, 16.00 | 12.00 | 1 +AAC LC | 16000 - 23999 | 16.00 | 16.00 | 1 +AAC LC | 24000 - 31999 | 16.00, 22.05, 24.00 | 24.00 | 1 +AAC LC | 32000 - 55999 | 32.00 | 32.00 | 1 +AAC LC | 56000 - 160000 | 32.00, 44.10, 48.00 | 44.10 | 1 +AAC LC | 160001 - 288000 | 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 16000 - 23999 | 11.025, 12.00, 16.00 | 12.00 | 2 +AAC LC | 24000 - 31999 | 16.00 | 16.00 | 2 +AAC LC | 32000 - 39999 | 16.00, 22.05, 24.00 | 22.05 | 2 +AAC LC | 40000 - 95999 | 32.00 | 32.00 | 2 +AAC LC | 96000 - 111999 | 32.00, 44.10, 48.00 | 32.00 | 2 +AAC LC | 112000 - 320001 | 32.00, 44.10, 48.00 | 44.10 | 2 +AAC LC | 320002 - 576000 | 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +AAC LC | 160000 - 239999 | 32.00 | 32.00 | +5, 5.1 AAC LC | 240000 - 279999 | 32.00, 44.10, 48.00 | 32.00 +| 5, 5.1 AAC LC | 280000 - 800000 | 32.00, 44.10, 48.00 | +44.10 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigLD AAC-LD, AAC-ELD, AAC-ELD with SBR in Dualrate SBR +mode. Unlike to HE-AAC configuration the SBR is not covered by ELD audio object +type and needs to be enabled explicitly. Use ::AACENC_SBR_MODE to configure SBR +and its samplingrate ratio with ::AACENC_SBR_RATIO parameter. \verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 32.00 - 44.10 | 32.00 | 1 +ELD + SBR | 25000 - 31999 | 32.00 - 48.00 | 32.00 | 1 +ELD + SBR | 32000 - 64000 | 32.00 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 32000 - 51999 | 32.00 - 48.00 | 44.10 | 2 +ELD + SBR | 52000 - 128000 | 32.00 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 78000 - 160000 | 32.00 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 104000 - 212000 | 32.00 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 130000 - 246000 | 32.00 - 48.00 | 48.00 | +5, 5.1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 16000 - 19999 | 16.00 - 24.00 | 16.00 | 1 +LD, ELD | 20000 - 39999 | 16.00 - 32.00 | 24.00 | 1 +LD, ELD | 40000 - 49999 | 22.05 - 32.00 | 32.00 | 1 +LD, ELD | 50000 - 61999 | 24.00 - 44.10 | 32.00 | 1 +LD, ELD | 62000 - 84999 | 32.00 - 48.00 | 44.10 | 1 +LD, ELD | 85000 - 192000 | 44.10 - 48.00 | 48.00 | 1 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 64000 - 75999 | 24.00 - 32.00 | 32.00 | 2 +LD, ELD | 76000 - 97999 | 24.00 - 44.10 | 32.00 | 2 +LD, ELD | 98000 - 135999 | 32.00 - 48.00 | 44.10 | 2 +LD, ELD | 136000 - 384000 | 44.10 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 96000 - 113999 | 24.00 - 32.00 | 32.00 | 3 +LD, ELD | 114000 - 146999 | 24.00 - 44.10 | 32.00 | 3 +LD, ELD | 147000 - 203999 | 32.00 - 48.00 | 44.10 | 3 +LD, ELD | 204000 - 576000 | 44.10 - 48.00 | 48.00 | 3 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 128000 - 151999 | 24.00 - 32.00 | 32.00 | 4 +LD, ELD | 152000 - 195999 | 24.00 - 44.10 | 32.00 | 4 +LD, ELD | 196000 - 271999 | 32.00 - 48.00 | 44.10 | 4 +LD, ELD | 272000 - 768000 | 44.10 - 48.00 | 48.00 | 4 +-------------------+------------------+-----------------------+------------+------- +LD, ELD | 160000 - 189999 | 24.00 - 32.00 | 32.00 | +5, 5.1 LD, ELD | 190000 - 244999 | 24.00 - 44.10 | 32.00 +| 5, 5.1 LD, ELD | 245000 - 339999 | 32.00 - 48.00 | +44.10 | 5, 5.1 LD, ELD | 340000 - 960000 | 44.10 - 48.00 | +48.00 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigELD AAC-ELD with SBR in Downsampled SBR mode. +\verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 18000 - 24999 | 16.00 - 22.05 | 22.05 | 1 +(downsampled SBR) | 25000 - 31999 | 16.00 - 24.00 | 24.00 | 1 + | 32000 - 47999 | 22.05 - 32.00 | 32.00 | 1 + | 48000 - 64000 | 22.05 - 48.00 | 32.00 | 1 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 32000 - 51999 | 16.00 - 24.00 | 24.00 | 2 +(downsampled SBR) | 52000 - 59999 | 22.05 - 24.00 | 24.00 | 2 + | 60000 - 95999 | 22.05 - 32.00 | 32.00 | 2 + | 96000 - 128000 | 22.05 - 48.00 | 32.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 78000 - 99999 | 22.05 - 24.00 | 24.00 | 3 +(downsampled SBR) | 100000 - 143999 | 22.05 - 32.00 | 32.00 | 3 + | 144000 - 159999 | 22.05 - 48.00 | 32.00 | 3 + | 160000 - 192000 | 32.00 - 48.00 | 32.00 | 3 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 104000 - 149999 | 22.05 - 24.00 | 24.00 | 4 +(downsampled SBR) | 150000 - 191999 | 22.05 - 32.00 | 32.00 | 4 + | 192000 - 211999 | 22.05 - 48.00 | 32.00 | 4 + | 212000 - 256000 | 32.00 - 48.00 | 32.00 | 4 +-------------------+------------------+-----------------------+------------+------- +ELD + SBR | 130000 - 171999 | 22.05 - 24.00 | 24.00 | +5, 5.1 (downsampled SBR) | 172000 - 239999 | 22.05 - 32.00 | 32.00 +| 5, 5.1 | 240000 - 320000 | 32.00 - 48.00 | 32.00 | 5, 5.1 +----------------------------------------------------------------------------------- +\endverbatim \n + +\subsection reommendedConfigELDv2 AAC-ELD v2, AAC-ELD v2 with SBR. +The ELD v2 212 configuration must be configured explicitly with +::AACENC_CHANNELMODE parameter according MODE_212 value. SBR can be configured +separately through ::AACENC_SBR_MODE and ::AACENC_SBR_RATIO parameter. Following +configurations shall apply to both framelengths 480 and 512. For ELD v2 +configuration without SBR and framelength 480 the supported sampling rate is +restricted to the range from 16 kHz up to 24 kHz. \verbatim +----------------------------------------------------------------------------------- +Audio Object Type | Bit Rate Range | Supported | Preferred | No. +of | [bit/s] | Sampling Rates | Sampl. | Chan. | +| [kHz] | Rate | | | +| [kHz] | +-------------------+------------------+-----------------------+------------+------- +ELD-212 | 16000 - 19999 | 16.00 - 24.00 | 16.00 | 2 +(without SBR) | 20000 - 39999 | 16.00 - 32.00 | 24.00 | 2 + | 40000 - 49999 | 22.05 - 32.00 | 32.00 | 2 + | 50000 - 61999 | 24.00 - 44.10 | 32.00 | 2 + | 62000 - 84999 | 32.00 - 48.00 | 44.10 | 2 + | 85000 - 192000 | 44.10 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD-212 + SBR | 18000 - 20999 | 32.00 | 32.00 | 2 +(dualrate SBR) | 21000 - 25999 | 32.00 - 44.10 | 32.00 | 2 + | 26000 - 31999 | 32.00 - 48.00 | 44.10 | 2 + | 32000 - 64000 | 32.00 - 48.00 | 48.00 | 2 +-------------------+------------------+-----------------------+------------+------- +ELD-212 + SBR | 18000 - 19999 | 16.00 - 22.05 | 22.05 | 2 +(downsampled SBR) | 20000 - 24999 | 16.00 - 24.00 | 22.05 | 2 + | 25000 - 31999 | 16.00 - 24.00 | 24.00 | 2 + | 32000 - 64000 | 24.00 - 24.00 | 24.00 | 2 +-------------------+------------------+-----------------------+------------+------- +\endverbatim \n + +\page ENCODERBEHAVIOUR Encoder Behaviour + +\section BEHAVIOUR_BANDWIDTH Bandwidth + +The FDK AAC encoder usually does not use the full frequency range of the input +signal, but restricts the bandwidth according to certain library-internal +settings. They can be changed in the table "bandWidthTable" in the file +bandwidth.cpp (if available). + +The encoder API provides the ::AACENC_BANDWIDTH parameter to adjust the +bandwidth explicitly. \code aacEncoder_SetParam(hAacEncoder, AACENC_BANDWIDTH, +value); \endcode + +However it is not recommended to change these settings, because they are based +on numerous listening tests and careful tweaks to ensure the best overall +encoding quality. Also, the maximum bandwidth that can be set manually by the +user is 20kHz or fs/2, whichever value is smaller. + +Theoretically a signal of for example 48 kHz can contain frequencies up to 24 +kHz, but to use this full range in an audio encoder usually does not make sense. +Usually the encoder has a very limited amount of bits to spend (typically 128 +kbit/s for stereo 48 kHz content) and to allow full range bandwidth would waste +a lot of these bits for frequencies the human ear is hardly able to perceive +anyway, if at all. Hence it is wise to use the available bits for the really +important frequency range and just skip the rest. At lower bitrates (e. g. <= 80 +kbit/s for stereo 48 kHz content) the encoder will choose an even smaller +bandwidth, because an encoded signal with smaller bandwidth and hence less +artifacts sounds better than a signal with higher bandwidth but then more coding +artefacts across all frequencies. These artefacts would occur if small bitrates +and high bandwidths are chosen because the available bits are just not enough to +encode all frequencies well. + +Unfortunately some people evaluate encoding quality based on possible bandwidth +as well, but it is a double-edged sword considering the trade-off described +above. + +Another aspect is workload consumption. The higher the allowed bandwidth, the +more frequency lines have to be processed, which in turn increases the workload. + +\section FRAMESIZES_AND_BIT_RESERVOIR Frame Sizes & Bit Reservoir + +For AAC there is a difference between constant bit rate and constant frame +length due to the so-called bit reservoir technique, which allows the encoder to +use less bits in an AAC frame for those audio signal sections which are easy to +encode, and then spend them at a later point in time for more complex audio +sections. The extent to which this "bit exchange" is done is limited to allow +for reliable and relatively low delay real time streaming. Therefore, for +AAC-ELD, the bitreservoir is limited. It varies between 500 and 4000 bits/frame, +depending on the bitrate/channel. +- For a bitrate of 12kbps/channel and below, the AAC-ELD bitreservoir is 500 +bits/frame. +- For a bitrate of 70kbps/channel and above, the AAC-ELD bitreservoir is 4000 +bits/frame. +- Between 12kbps/channel and 70kbps/channel, the AAC-ELD bitrervoir is increased +linearly. +- For AAC-LC, the bitrate is only limited by the maximum AAC frame length. It +is, regardless of the available bit reservoir, defined as 6144 bits per channel. + +Over a longer period in time the bitrate will be constant in the AAC constant +bitrate mode, e.g. for ISDN transmission. This means that in AAC each bitstream +frame will in general have a different length in bytes but over time it +will reach the target bitrate. + + +One could also make an MPEG compliant +AAC encoder which always produces constant length packages for each AAC frame, +but the audio quality would be considerably worse since the bit reservoir +technique would have to be switched off completely. A higher bit rate would have +to be used to get the same audio quality as with an enabled bit reservoir. + +For mp3 by the way, the same bit reservoir technique exists, but there each bit +stream frame has a constant length for a given bit rate (ignoring the +padding byte). In mp3 there is a so-called "back pointer" which tells +the decoder which bits belong to the current mp3 frame - and in general some or +many bits have been transmitted in an earlier mp3 frame. Basically this leads to +the same "bit exchange between mp3 frames" as in AAC but with virtually constant +length frames. + +This variable frame length at "constant bit rate" is not something special +in this Fraunhofer IIS AAC encoder. AAC has been designed in that way. + +\subsection BEHAVIOUR_ESTIM_AVG_FRAMESIZES Estimating Average Frame Sizes + +A HE-AAC v1 or v2 audio frame contains 2048 PCM samples per channel (there is +also one mode with 1920 samples per channel but this is only for special +purposes such as DAB+ digital radio). + +The number of HE-AAC frames \f$N\_FRAMES\f$ per second at 44.1 kHz is: + +\f[ +N\_FRAMES = 44100 / 2048 = 21.5332 +\f] + +At a bit rate of 8 kbps the average number of bits per frame +\f$N\_BITS\_PER\_FRAME\f$ is: + +\f[ +N\_BITS\_PER\_FRAME = 8000 / 21.5332 = 371.52 +\f] + +which is about 46.44 bytes per encoded frame. + +At a bit rate of 32 kbps, which is quite high for single channel HE-AAC v1, it +is: + +\f[ +N\_BITS\_PER\_FRAME = 32000 / 21.5332 = 1486 +\f] + +which is about 185.76 bytes per encoded frame. + +These bits/frame figures are average figures where each AAC frame generally has +a different size in bytes. To calculate the same for AAC-LC just use 1024 +instead of 2048 PCM samples per frame and channel. For AAC-LD/ELD it is either +480 or 512 PCM samples per frame and channel. + + +\section BEHAVIOUR_TOOLS Encoder Tools + +The AAC encoder supports TNS, PNS, MS, Intensity and activates these tools +depending on the audio signal and the encoder configuration (i.e. bitrate or +AOT). It is not required to configure these tools manually. + +PNS improves encoding quality only for certain bitrates. Therefore it makes +sense to activate PNS only for these bitrates and save the processing power +required for PNS (about 10 % of the encoder) when using other bitrates. This is +done automatically inside the encoder library. PNS is disabled inside the +encoder library if an MPEG-2 AOT is choosen since PNS is an MPEG-4 AAC feature. + +If SBR is activated, the encoder automatically deactivates PNS internally. If +TNS is disabled but PNS is allowed, the encoder deactivates PNS calculation +internally. + +*/ + +#ifndef AACENC_LIB_H +#define AACENC_LIB_H + +#include "machine_type.h" +#include "FDK_audio.h" + +#define AACENCODER_LIB_VL0 4 +#define AACENCODER_LIB_VL1 0 +#define AACENCODER_LIB_VL2 0 + +/** + * AAC encoder error codes. + */ +typedef enum { + AACENC_OK = 0x0000, /*!< No error happened. All fine. */ + + AACENC_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + AACENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + AACENC_UNSUPPORTED_PARAMETER = 0x0022, /*!< Parameter not available. */ + AACENC_INVALID_CONFIG = 0x0023, /*!< Configuration not provided. */ + + AACENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + AACENC_INIT_AAC_ERROR = 0x0041, /*!< AAC library initialization error. */ + AACENC_INIT_SBR_ERROR = 0x0042, /*!< SBR library initialization error. */ + AACENC_INIT_TP_ERROR = 0x0043, /*!< Transport library initialization error. */ + AACENC_INIT_META_ERROR = + 0x0044, /*!< Meta data library initialization error. */ + AACENC_INIT_MPS_ERROR = 0x0045, /*!< MPS library initialization error. */ + + AACENC_ENCODE_ERROR = 0x0060, /*!< The encoding process was interrupted by an + unexpected error. */ + + AACENC_ENCODE_EOF = 0x0080 /*!< End of file reached. */ + +} AACENC_ERROR; + +/** + * AAC encoder buffer descriptors identifier. + * This identifier are used within buffer descriptors + * AACENC_BufDesc::bufferIdentifiers. + */ +typedef enum { + /* Input buffer identifier. */ + IN_AUDIO_DATA = 0, /*!< Audio input buffer, interleaved INT_PCM samples. */ + IN_ANCILLRY_DATA = 1, /*!< Ancillary data to be embedded into bitstream. */ + IN_METADATA_SETUP = 2, /*!< Setup structure for embedding meta data. */ + + /* Output buffer identifier. */ + OUT_BITSTREAM_DATA = 3, /*!< Buffer holds bitstream output data. */ + OUT_AU_SIZES = + 4 /*!< Buffer contains sizes of each access unit. This information + is necessary for superframing. */ + +} AACENC_BufferIdentifier; + +/** + * AAC encoder handle. + */ +typedef struct AACENCODER *HANDLE_AACENCODER; + +/** + * Provides some info about the encoder configuration. + */ +typedef struct { + UINT maxOutBufBytes; /*!< Maximum number of encoder bitstream bytes within one + frame. Size depends on maximum number of supported + channels in encoder instance. For superframing (as + used for example in DAB+), size has to be a multiple + accordingly. */ + + UINT maxAncBytes; /*!< Maximum number of ancillary data bytes which can be + inserted into bitstream within one frame. */ + + UINT inBufFillLevel; /*!< Internal input buffer fill level in samples per + channel. This parameter will automatically be cleared + if samplingrate or channel(Mode/Order) changes. */ + + UINT inputChannels; /*!< Number of input channels expected in encoding + process. */ + + UINT frameLength; /*!< Amount of input audio samples consumed each frame per + channel, depending on audio object type configuration. */ + + UINT nDelay; /*!< Codec delay in PCM samples/channel. Depends on framelength + and AOT. Does not include framing delay for filling up encoder + PCM input buffer. */ + + UINT nDelayCore; /*!< Codec delay in PCM samples/channel, w/o delay caused by + the decoder SBR module. This delay is needed to correctly + write edit lists for gapless playback. The decoder may not + know how much delay is introdcued by SBR, since it may not + know if SBR is active at all (implicit signaling), + therefore the deocder must take into account any delay + caused by the SBR module. */ + + UCHAR confBuf[64]; /*!< Configuration buffer in binary format as an + AudioSpecificConfig or StreamMuxConfig according to the + selected transport type. */ + + UINT confSize; /*!< Number of valid bytes in confBuf. */ + +} AACENC_InfoStruct; + +/** + * Describes the input and output buffers for an aacEncEncode() call. + */ +typedef struct { + INT numBufs; /*!< Number of buffers. */ + void **bufs; /*!< Pointer to vector containing buffer addresses. */ + INT *bufferIdentifiers; /*!< Identifier of each buffer element. See + ::AACENC_BufferIdentifier. */ + INT *bufSizes; /*!< Size of each buffer in 8-bit bytes. */ + INT *bufElSizes; /*!< Size of each buffer element in bytes. */ + +} AACENC_BufDesc; + +/** + * Defines the input arguments for an aacEncEncode() call. + */ +typedef struct { + INT numInSamples; /*!< Number of valid input audio samples (multiple of input + channels). */ + INT numAncBytes; /*!< Number of ancillary data bytes to be encoded. */ + +} AACENC_InArgs; + +/** + * Defines the output arguments for an aacEncEncode() call. + */ +typedef struct { + INT numOutBytes; /*!< Number of valid bitstream bytes generated during + aacEncEncode(). */ + INT numInSamples; /*!< Number of input audio samples consumed by the encoder. + */ + INT numAncBytes; /*!< Number of ancillary data bytes consumed by the encoder. + */ + INT bitResState; /*!< State of the bit reservoir in bits. */ + +} AACENC_OutArgs; + +/** + * Meta Data Compression Profiles. + */ +typedef enum { + AACENC_METADATA_DRC_NONE = 0, /*!< None. */ + AACENC_METADATA_DRC_FILMSTANDARD = 1, /*!< Film standard. */ + AACENC_METADATA_DRC_FILMLIGHT = 2, /*!< Film light. */ + AACENC_METADATA_DRC_MUSICSTANDARD = 3, /*!< Music standard. */ + AACENC_METADATA_DRC_MUSICLIGHT = 4, /*!< Music light. */ + AACENC_METADATA_DRC_SPEECH = 5, /*!< Speech. */ + AACENC_METADATA_DRC_NOT_PRESENT = + 256 /*!< Disable writing gain factor (used for comp_profile only). */ + +} AACENC_METADATA_DRC_PROFILE; + +/** + * Meta Data setup structure. + */ +typedef struct { + AACENC_METADATA_DRC_PROFILE + drc_profile; /*!< MPEG DRC compression profile. See + ::AACENC_METADATA_DRC_PROFILE. */ + AACENC_METADATA_DRC_PROFILE + comp_profile; /*!< ETSI heavy compression profile. See + ::AACENC_METADATA_DRC_PROFILE. */ + + INT drc_TargetRefLevel; /*!< Used to define expected level to: + Scaled with 16 bit. x*2^16. */ + INT comp_TargetRefLevel; /*!< Adjust limiter to avoid overload. + Scaled with 16 bit. x*2^16. */ + + INT prog_ref_level_present; /*!< Flag, if prog_ref_level is present */ + INT prog_ref_level; /*!< Programme Reference Level = Dialogue Level: + -31.75dB .. 0 dB ; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + + UCHAR PCE_mixdown_idx_present; /*!< Flag, if dmx-idx should be written in + programme config element */ + UCHAR ETSI_DmxLvl_present; /*!< Flag, if dmx-lvl should be written in + ETSI-ancData */ + + SCHAR centerMixLevel; /*!< Center downmix level (0...7, according to table) */ + SCHAR surroundMixLevel; /*!< Surround downmix level (0...7, according to + table) */ + + UCHAR + dolbySurroundMode; /*!< Indication for Dolby Surround Encoding Mode. + - 0: Dolby Surround mode not indicated + - 1: 2-ch audio part is not Dolby surround encoded + - 2: 2-ch audio part is Dolby surround encoded */ + + UCHAR drcPresentationMode; /*!< Indicatin for DRC Presentation Mode. + - 0: Presentation mode not inticated + - 1: Presentation mode 1 + - 2: Presentation mode 2 */ + + struct { + /* extended ancillary data */ + UCHAR extAncDataEnable; /*< Indicates if MPEG4_ext_ancillary_data() exists. + - 0: No MPEG4_ext_ancillary_data(). + - 1: Insert MPEG4_ext_ancillary_data(). */ + + UCHAR + extDownmixLevelEnable; /*< Indicates if ext_downmixing_levels() exists. + - 0: No ext_downmixing_levels(). + - 1: Insert ext_downmixing_levels(). */ + UCHAR extDownmixLevel_A; /*< Downmix level index A (0...7, according to + table) */ + UCHAR extDownmixLevel_B; /*< Downmix level index B (0...7, according to + table) */ + + UCHAR dmxGainEnable; /*< Indicates if ext_downmixing_global_gains() exists. + - 0: No ext_downmixing_global_gains(). + - 1: Insert ext_downmixing_global_gains(). */ + INT dmxGain5; /*< Gain factor for downmix to 5 channels. + -15.75dB .. -15.75dB; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + INT dmxGain2; /*< Gain factor for downmix to 2 channels. + -15.75dB .. -15.75dB; stepsize: 0.25dB + Scaled with 16 bit. x*2^16.*/ + + UCHAR lfeDmxEnable; /*< Indicates if ext_downmixing_lfe_level() exists. + - 0: No ext_downmixing_lfe_level(). + - 1: Insert ext_downmixing_lfe_level(). */ + UCHAR lfeDmxLevel; /*< Downmix level index for LFE (0..15, according to + table) */ + + } ExtMetaData; + +} AACENC_MetaData; + +/** + * AAC encoder control flags. + * + * In interaction with the ::AACENC_CONTROL_STATE parameter it is possible to + * get information about the internal initialization process. It is also + * possible to overwrite the internal state from extern when necessary. + */ +typedef enum { + AACENC_INIT_NONE = 0x0000, /*!< Do not trigger initialization. */ + AACENC_INIT_CONFIG = + 0x0001, /*!< Initialize all encoder modules configuration. */ + AACENC_INIT_STATES = 0x0002, /*!< Reset all encoder modules history buffer. */ + AACENC_INIT_TRANSPORT = + 0x1000, /*!< Initialize transport lib with new parameters. */ + AACENC_RESET_INBUFFER = + 0x2000, /*!< Reset fill level of internal input buffer. */ + AACENC_INIT_ALL = 0xFFFF /*!< Initialize all. */ +} AACENC_CTRLFLAGS; + +/** + * \brief AAC encoder setting parameters. + * + * Use aacEncoder_SetParam() function to configure, or use aacEncoder_GetParam() + * function to read the internal status of the following parameters. + */ +typedef enum { + AACENC_AOT = + 0x0100, /*!< Audio object type. See ::AUDIO_OBJECT_TYPE in FDK_audio.h. + - 2: MPEG-4 AAC Low Complexity. + - 5: MPEG-4 AAC Low Complexity with Spectral Band Replication + (HE-AAC). + - 29: MPEG-4 AAC Low Complexity with Spectral Band + Replication and Parametric Stereo (HE-AAC v2). This + configuration can be used only with stereo input audio data. + - 23: MPEG-4 AAC Low-Delay. + - 39: MPEG-4 AAC Enhanced Low-Delay. Since there is no + ::AUDIO_OBJECT_TYPE for ELD in combination with SBR defined, + enable SBR explicitely by ::AACENC_SBR_MODE parameter. The ELD + v2 212 configuration can be configured by ::AACENC_CHANNELMODE + parameter. + - 129: MPEG-2 AAC Low Complexity. + - 132: MPEG-2 AAC Low Complexity with Spectral Band + Replication (HE-AAC). + + Please note that the virtual MPEG-2 AOT's basically disables + non-existing Perceptual Noise Substitution tool in AAC encoder + and controls the MPEG_ID flag in adts header. The virtual + MPEG-2 AOT doesn't prohibit specific transport formats. */ + + AACENC_BITRATE = 0x0101, /*!< Total encoder bitrate. This parameter is + mandatory and interacts with ::AACENC_BITRATEMODE. + - CBR: Bitrate in bits/second. + - VBR: Variable bitrate. Bitrate argument will + be ignored. See \ref suppBitrates for details. */ + + AACENC_BITRATEMODE = 0x0102, /*!< Bitrate mode. Configuration can be different + kind of bitrate configurations: + - 0: Constant bitrate, use bitrate according + to ::AACENC_BITRATE. (default) Within none + LD/ELD ::AUDIO_OBJECT_TYPE, the CBR mode makes + use of full allowed bitreservoir. In contrast, + at Low-Delay ::AUDIO_OBJECT_TYPE the + bitreservoir is kept very small. + - 1: Variable bitrate mode, \ref vbrmode + "very low bitrate". + - 2: Variable bitrate mode, \ref vbrmode + "low bitrate". + - 3: Variable bitrate mode, \ref vbrmode + "medium bitrate". + - 4: Variable bitrate mode, \ref vbrmode + "high bitrate". + - 5: Variable bitrate mode, \ref vbrmode + "very high bitrate". */ + + AACENC_SAMPLERATE = 0x0103, /*!< Audio input data sampling rate. Encoder + supports following sampling rates: 8000, 11025, + 12000, 16000, 22050, 24000, 32000, 44100, + 48000, 64000, 88200, 96000 */ + + AACENC_SBR_MODE = 0x0104, /*!< Configure SBR independently of the chosen Audio + Object Type ::AUDIO_OBJECT_TYPE. This parameter + is for ELD audio object type only. + - -1: Use ELD SBR auto configurator (default). + - 0: Disable Spectral Band Replication. + - 1: Enable Spectral Band Replication. */ + + AACENC_GRANULE_LENGTH = + 0x0105, /*!< Core encoder (AAC) audio frame length in samples: + - 1024: Default configuration. + - 960: DRM/DAB+. + - 512: Default length in LD/ELD configuration. + - 480: Length in LD/ELD configuration. + - 256: Length for ELD reduced delay mode (x2). + - 240: Length for ELD reduced delay mode (x2). + - 128: Length for ELD reduced delay mode (x4). + - 120: Length for ELD reduced delay mode (x4). */ + + AACENC_CHANNELMODE = 0x0106, /*!< Set explicit channel mode. Channel mode must + match with number of input channels. + - 1-7, 11,12,14 and 33,34: MPEG channel + modes supported, see ::CHANNEL_MODE in + FDK_audio.h. */ + + AACENC_CHANNELORDER = + 0x0107, /*!< Input audio data channel ordering scheme: + - 0: MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE). + (default) + - 1: WAVE file format channel ordering (e. g. 5.1: L, R, C, + LFE, SL, SR). */ + + AACENC_SBR_RATIO = + 0x0108, /*!< Controls activation of downsampled SBR. With downsampled + SBR, the delay will be shorter. On the other hand, for + achieving the same quality level, downsampled SBR needs more + bits than dual-rate SBR. With downsampled SBR, the AAC encoder + will work at the same sampling rate as the SBR encoder (single + rate). Downsampled SBR is supported for AAC-ELD and HE-AACv1. + - 1: Downsampled SBR (default for ELD). + - 2: Dual-rate SBR (default for HE-AAC). */ + + AACENC_AFTERBURNER = + 0x0200, /*!< This parameter controls the use of the afterburner feature. + The afterburner is a type of analysis by synthesis algorithm + which increases the audio quality but also the required + processing power. It is recommended to always activate this if + additional memory consumption and processing power consumption + is not a problem. If increased MHz and memory consumption are + an issue then the MHz and memory cost of this optional module + need to be evaluated against the improvement in audio quality + on a case by case basis. + - 0: Disable afterburner (default). + - 1: Enable afterburner. */ + + AACENC_BANDWIDTH = 0x0203, /*!< Core encoder audio bandwidth: + - 0: Determine audio bandwidth internally + (default, see chapter \ref BEHAVIOUR_BANDWIDTH). + - 1 to fs/2: Audio bandwidth in Hertz. Limited + to 20kHz max. Not usable if SBR is active. This + setting is for experts only, better do not touch + this value to avoid degraded audio quality. */ + + AACENC_PEAK_BITRATE = + 0x0207, /*!< Peak bitrate configuration parameter to adjust maximum bits + per audio frame. Bitrate is in bits/second. The peak bitrate + will internally be limited to the chosen bitrate + ::AACENC_BITRATE as lower limit and the + number_of_effective_channels*6144 bit as upper limit. + + Setting the peak bitrate equal to ::AACENC_BITRATE does not + necessarily mean that the audio frames will be of constant + size. Since the peak bitate is in bits/second, the frame sizes + can vary by one byte in one or the other direction over various + frames. However, it is not recommended to reduce the peak + pitrate to ::AACENC_BITRATE - it would disable the + bitreservoir, which would affect the audio quality by a large + amount. */ + + AACENC_TRANSMUX = 0x0300, /*!< Transport type to be used. See ::TRANSPORT_TYPE + in FDK_audio.h. Following types can be configured + in encoder library: + - 0: raw access units + - 1: ADIF bitstream format + - 2: ADTS bitstream format + - 6: Audio Mux Elements (LATM) with + muxConfigPresent = 1 + - 7: Audio Mux Elements (LATM) with + muxConfigPresent = 0, out of band StreamMuxConfig + - 10: Audio Sync Stream (LOAS) */ + + AACENC_HEADER_PERIOD = + 0x0301, /*!< Frame count period for sending in-band configuration buffers + within LATM/LOAS transport layer. Additionally this parameter + configures the PCE repetition period in raw_data_block(). See + \ref encPCE. + - 0xFF: auto-mode default 10 for TT_MP4_ADTS, TT_MP4_LOAS and + TT_MP4_LATM_MCP1, otherwise 0. + - n: Frame count period. */ + + AACENC_SIGNALING_MODE = + 0x0302, /*!< Signaling mode of the extension AOT: + - 0: Implicit backward compatible signaling (default for + non-MPEG-4 based AOT's and for the transport formats ADIF and + ADTS) + - A stream that uses implicit signaling can be decoded + by every AAC decoder, even AAC-LC-only decoders + - An AAC-LC-only decoder will only decode the + low-frequency part of the stream, resulting in a band-limited + output + - This method works with all transport formats + - This method does not work with downsampled SBR + - 1: Explicit backward compatible signaling + - A stream that uses explicit backward compatible + signaling can be decoded by every AAC decoder, even AAC-LC-only + decoders + - An AAC-LC-only decoder will only decode the + low-frequency part of the stream, resulting in a band-limited + output + - A decoder not capable of decoding PS will only decode + the AAC-LC+SBR part. If the stream contained PS, the result + will be a a decoded mono downmix + - This method does not work with ADIF or ADTS. For + LOAS/LATM, it only works with AudioMuxVersion==1 + - This method does work with downsampled SBR + - 2: Explicit hierarchical signaling (default for MPEG-4 + based AOT's and for all transport formats excluding ADIF and + ADTS) + - A stream that uses explicit hierarchical signaling can + be decoded only by HE-AAC decoders + - An AAC-LC-only decoder will not decode a stream that + uses explicit hierarchical signaling + - A decoder not capable of decoding PS will not decode + the stream at all if it contained PS + - This method does not work with ADIF or ADTS. It works + with LOAS/LATM and the MPEG-4 File format + - This method does work with downsampled SBR + + For making sure that the listener always experiences the + best audio quality, explicit hierarchical signaling should be + used. This makes sure that only a full HE-AAC-capable decoder + will decode those streams. The audio is played at full + bandwidth. For best backwards compatibility, it is recommended + to encode with implicit SBR signaling. A decoder capable of + AAC-LC only will then only decode the AAC part, which means the + decoded audio will sound band-limited. + + For MPEG-2 transport types (ADTS,ADIF), only implicit + signaling is possible. + + For LOAS and LATM, explicit backwards compatible signaling + only works together with AudioMuxVersion==1. The reason is + that, for explicit backwards compatible signaling, additional + information will be appended to the ASC. A decoder that is only + capable of decoding AAC-LC will skip this part. Nevertheless, + for jumping to the end of the ASC, it needs to know the ASC + length. Transmitting the length of the ASC is a feature of + AudioMuxVersion==1, it is not possible to transmit the length + of the ASC with AudioMuxVersion==0, therefore an AAC-LC-only + decoder will not be able to parse a LOAS/LATM stream that was + being encoded with AudioMuxVersion==0. + + For downsampled SBR, explicit signaling is mandatory. The + reason for this is that the extension sampling frequency (which + is in case of SBR the sampling frequqncy of the SBR part) can + only be signaled in explicit mode. + + For AAC-ELD, the SBR information is transmitted in the + ELDSpecific Config, which is part of the AudioSpecificConfig. + Therefore, the settings here will have no effect on AAC-ELD.*/ + + AACENC_TPSUBFRAMES = + 0x0303, /*!< Number of sub frames in a transport frame for LOAS/LATM or + ADTS (default 1). + - ADTS: Maximum number of sub frames restricted to 4. + - DAB+: Maximum number of sub frames restricted to 6. + - LOAS/LATM: Maximum number of sub frames restricted to 2.*/ + + AACENC_AUDIOMUXVER = + 0x0304, /*!< AudioMuxVersion to be used for LATM. (AudioMuxVersionA, + currently not implemented): + - 0: Default, no transmission of tara Buffer fullness, no ASC + length and including actual latm Buffer fullnes. + - 1: Transmission of tara Buffer fullness, ASC length and + actual latm Buffer fullness. + - 2: Transmission of tara Buffer fullness, ASC length and + maximum level of latm Buffer fullness. */ + + AACENC_PROTECTION = 0x0306, /*!< Configure protection in transport layer: + - 0: No protection. (default) + - 1: CRC active for ADTS transport format. */ + + AACENC_ANCILLARY_BITRATE = + 0x0500, /*!< Constant ancillary data bitrate in bits/second. + - 0: Either no ancillary data or insert exact number of + bytes, denoted via input parameter, numAncBytes in + AACENC_InArgs. + - else: Insert ancillary data with specified bitrate. */ + + AACENC_METADATA_MODE = 0x0600, /*!< Configure Meta Data. See ::AACENC_MetaData + for further details: + - 0: Do not embed any metadata. + - 1: Embed dynamic_range_info metadata. + - 2: Embed dynamic_range_info and + ancillary_data metadata. + - 3: Embed ancillary_data metadata. */ + + AACENC_CONTROL_STATE = + 0xFF00, /*!< There is an automatic process which internally reconfigures + the encoder instance when a configuration parameter changed or + an error occured. This paramerter allows overwriting or getting + the control status of this process. See ::AACENC_CTRLFLAGS. */ + + AACENC_NONE = 0xFFFF /*!< ------ */ + +} AACENC_PARAM; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Open an instance of the encoder. + * + * Allocate memory for an encoder instance with a functional range denoted by + * the function parameters. Preinitialize encoder instance with default + * configuration. + * + * \param phAacEncoder A pointer to an encoder handle. Initialized on return. + * \param encModules Specify encoder modules to be supported in this encoder + * instance: + * - 0x0: Allocate memory for all available encoder + * modules. + * - else: Select memory allocation regarding encoder + * modules. Following flags are possible and can be combined. + * - 0x01: AAC module. + * - 0x02: SBR module. + * - 0x04: PS module. + * - 0x08: MPS module. + * - 0x10: Metadata module. + * - example: (0x01|0x02|0x04|0x08|0x10) allocates + * all modules and is equivalent to default configuration denotet by 0x0. + * \param maxChannels Number of channels to be allocated. This parameter can + * be used in different ways: + * - 0: Allocate maximum number of AAC and SBR channels as + * supported by the library. + * - nChannels: Use same maximum number of channels for + * allocating memory in AAC and SBR module. + * - nChannels | (nSbrCh<<8): Number of SBR channels can be + * different to AAC channels to save data memory. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INVALID_HANDLE, AACENC_MEMORY_ERROR, AACENC_INVALID_CONFIG, + * on failure. + */ +AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules, + const UINT maxChannels); + +/** + * \brief Close the encoder instance. + * + * Deallocate encoder instance and free whole memory. + * + * \param phAacEncoder Pointer to the encoder handle to be deallocated. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, on failure. + */ +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder); + +/** + * \brief Encode audio data. + * + * This function is mainly for encoding audio data. In addition the function can + * be used for an encoder (re)configuration process. + * - PCM input data will be retrieved from external input buffer until the fill + * level allows encoding a single frame. This functionality allows an external + * buffer with reduced size in comparison to the AAC or HE-AAC audio frame + * length. + * - If the value of the input samples argument is zero, just internal + * reinitialization will be applied if it is requested. + * - At the end of a file the flushing process can be triggerd via setting the + * value of the input samples argument to -1. The encoder delay lines are fully + * flushed when the encoder returns no valid bitstream data + * AACENC_OutArgs::numOutBytes. Furthermore the end of file is signaled by the + * return value AACENC_ENCODE_EOF. + * - If an error occured in the previous frame or any of the encoder parameters + * changed, an internal reinitialization process will be applied before encoding + * the incoming audio samples. + * - The function can also be used for an independent reconfiguration process + * without encoding. The first parameter has to be a valid encoder handle and + * all other parameters can be set to NULL. + * - If the size of the external bitbuffer in outBufDesc is not sufficient for + * writing the whole bitstream, an internal error will be the return value and a + * reconfiguration will be triggered. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param inBufDesc Input buffer descriptor, see AACENC_BufDesc: + * - At least one input buffer with audio data is + * expected. + * - Optionally a second input buffer with + * ancillary data can be fed. + * \param outBufDesc Output buffer descriptor, see AACENC_BufDesc: + * - Provide one output buffer for the encoded + * bitstream. + * \param inargs Input arguments, see AACENC_InArgs. + * \param outargs Output arguments, AACENC_OutArgs. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_ENCODE_ERROR, on failure in encoding + * process. + * - AACENC_INVALID_CONFIG, AACENC_INIT_ERROR, AACENC_INIT_AAC_ERROR, + * AACENC_INIT_SBR_ERROR, AACENC_INIT_TP_ERROR, AACENC_INIT_META_ERROR, + * AACENC_INIT_MPS_ERROR, on failure in encoder initialization. + * - AACENC_UNSUPPORTED_PARAMETER, on incorrect input or output buffer + * descriptor initialization. + * - AACENC_ENCODE_EOF, when flushing fully concluded. + */ +AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, AACENC_OutArgs *outargs); + +/** + * \brief Acquire info about present encoder instance. + * + * This function retrieves information of the encoder configuration. In addition + * to informative internal states, a configuration data block of the current + * encoder settings will be returned. The format is either Audio Specific Config + * in case of Raw Packets transport format or StreamMuxConfig in case of + * LOAS/LATM transport format. The configuration data block is binary coded as + * specified in ISO/IEC 14496-3 (MPEG-4 audio), to be used directly for MPEG-4 + * File Format or RFC3016 or RFC3640 applications. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param pInfo Pointer to AACENC_InfoStruct. Filled on return. + * + * \return + * - AACENC_OK, on succes. + * - AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo); + +/** + * \brief Set one single AAC encoder parameter. + * + * This function allows configuration of all encoder parameters specified in + * ::AACENC_PARAM. Each parameter must be set with a separate function call. An + * internal validation of the configuration value range will be done and an + * internal reconfiguration will be signaled. The actual configuration adoption + * is part of the subsequent aacEncEncode() call. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be set. See ::AACENC_PARAM. + * \param value Parameter value. See parameter description in + * ::AACENC_PARAM. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_UNSUPPORTED_PARAMETER, + * AACENC_INVALID_CONFIG, on failure. + */ +AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, const UINT value); + +/** + * \brief Get one single AAC encoder parameter. + * + * This function is the complement to aacEncoder_SetParam(). After encoder + * reinitialization with user defined settings, the internal status can be + * obtained of each parameter, specified with ::AACENC_PARAM. + * + * \param hAacEncoder A valid AAC encoder handle. + * \param param Parameter to be returned. See ::AACENC_PARAM. + * + * \return Internal configuration value of specifed parameter ::AACENC_PARAM. + */ +UINT aacEncoder_GetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param); + +/** + * \brief Get information about encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - AACENC_OK, on success. + * - AACENC_INVALID_HANDLE, AACENC_INIT_ERROR, on failure. + */ +AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* AACENC_LIB_H */ diff --git a/fdk-aac/libAACenc/src/aacEnc_ram.cpp b/fdk-aac/libAACenc/src/aacEnc_ram.cpp new file mode 100644 index 0000000..77b1131 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacEnc_ram.cpp @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#include "aacEnc_ram.h" + +C_AALLOC_MEM(AACdynamic_RAM, FIXP_DBL, AAC_ENC_DYN_RAM_SIZE / sizeof(FIXP_DBL)) + +/* + Static memory areas, must not be overwritten in other sections of the decoder + ! +*/ + +/* + The structure AacEncoder contains all Encoder structures. +*/ + +C_ALLOC_MEM(Ram_aacEnc_AacEncoder, struct AAC_ENC, 1) + +/* + The structure PSY_INTERNAl contains all psych configuration and data pointer. + * PsyStatic holds last and current Psych data. + * PsyInputBuffer contains time input. Signal is needed at the beginning of + Psych. Memory can be reused after signal is in time domain. + * PsyData contains spectral, nrg and threshold information. Necessary data + are copied into PsyOut, so memory is available after leaving psych. + * TnsData, ChaosMeasure, PnsData are temporarily necessary, e.g. use memory + from PsyInputBuffer. +*/ + +C_ALLOC_MEM2(Ram_aacEnc_PsyElement, PSY_ELEMENT, 1, ((8))) + +C_ALLOC_MEM(Ram_aacEnc_PsyInternal, PSY_INTERNAL, 1) +C_ALLOC_MEM2(Ram_aacEnc_PsyStatic, PSY_STATIC, 1, (8)) + +C_ALLOC_MEM2(Ram_aacEnc_PsyInputBuffer, INT_PCM, MAX_INPUT_BUFFER_SIZE, (8)) + +PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1 + n*sizeof(PSY_DYNAMIC)) is sufficiently aligned, so + * the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_1 + n * sizeof(PSY_DYNAMIC))); +} + +/* + The structure PSY_OUT holds all psychoaccoustic data needed + in quantization module +*/ +C_ALLOC_MEM2(Ram_aacEnc_PsyOut, PSY_OUT, 1, (1)) + +C_ALLOC_MEM2(Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT, 1, (1) * ((8))) +C_ALLOC_MEM2(Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL, 1, (1) * (8)) + +/* + The structure QC_STATE contains preinitialized settings and quantizer + structures. + * AdjustThreshold structure contains element-wise settings. + * ElementBits contains elemnt-wise bit consumption settings. + * When CRC is active, lookup table is necessary for fast crc calculation. + * Bitcounter contains buffer to find optimal codebooks and minimal bit + consumption. Values are temporarily, so dynamic memory can be used. +*/ + +C_ALLOC_MEM(Ram_aacEnc_QCstate, QC_STATE, 1) +C_ALLOC_MEM(Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE, 1) + +C_ALLOC_MEM2(Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT, 1, ((8))) +C_ALLOC_MEM2(Ram_aacEnc_ElementBits, ELEMENT_BITS, 1, ((8))) +C_ALLOC_MEM(Ram_aacEnc_BitCntrState, struct BITCNTR_STATE, 1) + +INT *GetRam_aacEnc_BitLookUp(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1) is sufficiently aligned, so the cast is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + P_BUF_1)); +} +INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_1 + sizeof(INT)*(MAX_SFB_LONG*(CODE_BOOK_ESC_NDX+1))) + * is sufficiently aligned, so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_1 + + sizeof(INT) * (MAX_SFB_LONG * (CODE_BOOK_ESC_NDX + 1)))); +} + +/* + The structure QC_OUT contains settings and structures holding all necessary + information needed in bitstreamwriter. +*/ + +C_ALLOC_MEM2(Ram_aacEnc_QCout, QC_OUT, 1, (1)) +C_ALLOC_MEM2(Ram_aacEnc_QCelement, QC_OUT_ELEMENT, 1, (1) * ((8))) +QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel(int n, UCHAR *dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + P_BUF_0 + n*sizeof(QC_OUT_CHANNEL)) is sufficiently aligned, + * so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + P_BUF_0 + n * sizeof(QC_OUT_CHANNEL))); +} diff --git a/fdk-aac/libAACenc/src/aacEnc_ram.h b/fdk-aac/libAACenc/src/aacEnc_ram.h new file mode 100644 index 0000000..0775aae --- /dev/null +++ b/fdk-aac/libAACenc/src/aacEnc_ram.h @@ -0,0 +1,249 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AACENC_RAM_H +#define AACENC_RAM_H + +#include "common_fix.h" + +#include "aacenc.h" +#include "psy_data.h" +#include "interface.h" +#include "psy_main.h" +#include "bitenc.h" +#include "bit_cnt.h" +#include "psy_const.h" + +#define OUTPUTBUFFER_SIZE \ + (8192) /*!< Output buffer size has to be at least 6144 bits per channel \ + (768 bytes). FDK bitbuffer implementation expects buffer of \ + size 2^n. */ + +/* + Moved AAC_ENC struct definition from aac_enc.cpp into aacEnc_ram.h to get size + and respective static memory in aacEnc_ram.cpp. aac_enc.h is the outward + visible header file and putting the struct into would cause necessity of + additional visible header files outside library. +*/ + +/* define hBitstream size: max AAC framelength is 6144 bits/channel */ +/*#define BUFFER_BITSTR_SIZE ((6400*(8)/bbWordSize) +((bbWordSize - 1) / + * bbWordSize))*/ + +struct AAC_ENC { + AACENC_CONFIG *config; + + INT ancillaryBitsPerFrame; /* ancillary bits per frame calculated from + ancillary rate */ + + CHANNEL_MAPPING channelMapping; + + QC_STATE *qcKernel; + QC_OUT *qcOut[(1)]; + + PSY_OUT *psyOut[(1)]; + PSY_INTERNAL *psyKernel; + + /* lifetime vars */ + + CHANNEL_MODE encoderMode; + INT bandwidth90dB; + AACENC_BITRATE_MODE bitrateMode; + + INT dontWriteAdif; /* use: write ADIF header only before 1st frame */ + + FIXP_DBL *dynamic_RAM; + + INT maxChannels; /* used while allocation */ + INT maxElements; + INT maxFrames; + + AUDIO_OBJECT_TYPE aot; /* AOT to be used while encoding. */ +}; + +#define maxSize(a, b) (((a) > (b)) ? (a) : (b)) + +#define BIT_LOOK_UP_SIZE \ + (sizeof(INT) * (MAX_SFB_LONG * (CODE_BOOK_ESC_NDX + 1))) +#define MERGE_GAIN_LOOK_UP_SIZE (sizeof(INT) * MAX_SFB_LONG) + +/* Size of AhFlag buffer in function FDKaacEnc_adaptThresholdsToPe() */ +#define ADJ_THR_AH_FLAG_SIZE (sizeof(UCHAR) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Size of ThrExp buffer in function FDKaacEnc_adaptThresholdsToPe() */ +#define ADJ_THR_THR_EXP_SIZE (sizeof(FIXP_DBL) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Size of sfbNActiveLinesLdData buffer in function FDKaacEnc_correctThresh() */ +#define ADJ_THR_ACT_LIN_LD_DATA_SIZE \ + (sizeof(FIXP_DBL) * ((8)) * (2) * MAX_GROUPED_SFB) +/* Total amount of dynamic buffer needed in adjust thresholds functionality */ +#define ADJ_THR_SIZE \ + (ADJ_THR_AH_FLAG_SIZE + ADJ_THR_THR_EXP_SIZE + ADJ_THR_ACT_LIN_LD_DATA_SIZE) + +/* Dynamic RAM - Allocation */ +/* + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | P_BUF_0 | P_BUF_1 | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | QC_OUT_CH | PSY_DYN | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | BitLookUp+MergeGainLookUp | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | AH_FLAG | THR_EXP | ACT_LIN_LD_DATA | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ + | | Bitstream output buffer | + +++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + +#define BUF_SIZE_0 (ALIGN_SIZE(sizeof(QC_OUT_CHANNEL) * (8))) +#define BUF_SIZE_1 \ + (ALIGN_SIZE(maxSize(maxSize(sizeof(PSY_DYNAMIC), \ + (BIT_LOOK_UP_SIZE + MERGE_GAIN_LOOK_UP_SIZE)), \ + ADJ_THR_SIZE))) + +#define P_BUF_0 (0) +#define P_BUF_1 (P_BUF_0 + BUF_SIZE_0) + +#define AAC_ENC_DYN_RAM_SIZE (BUF_SIZE_0 + BUF_SIZE_1) + +H_ALLOC_MEM(AACdynamic_RAM, FIXP_DBL) +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +END - Dynamic RAM - Allocation */ + +/* + See further Memory Allocation details in aacEnc_ram.cpp +*/ +H_ALLOC_MEM(Ram_aacEnc_AacEncoder, AAC_ENC) + +H_ALLOC_MEM(Ram_aacEnc_PsyElement, PSY_ELEMENT) + +H_ALLOC_MEM(Ram_aacEnc_PsyInternal, PSY_INTERNAL) +H_ALLOC_MEM(Ram_aacEnc_PsyStatic, PSY_STATIC) +H_ALLOC_MEM(Ram_aacEnc_PsyInputBuffer, INT_PCM) + +PSY_DYNAMIC *GetRam_aacEnc_PsyDynamic(int n, UCHAR *dynamic_RAM); + +H_ALLOC_MEM(Ram_aacEnc_PsyOutChannel, PSY_OUT_CHANNEL) + +H_ALLOC_MEM(Ram_aacEnc_PsyOut, PSY_OUT) +H_ALLOC_MEM(Ram_aacEnc_PsyOutElements, PSY_OUT_ELEMENT) + +H_ALLOC_MEM(Ram_aacEnc_QCstate, QC_STATE) +H_ALLOC_MEM(Ram_aacEnc_AdjustThreshold, ADJ_THR_STATE) + +H_ALLOC_MEM(Ram_aacEnc_AdjThrStateElement, ATS_ELEMENT) +H_ALLOC_MEM(Ram_aacEnc_ElementBits, ELEMENT_BITS) +H_ALLOC_MEM(Ram_aacEnc_BitCntrState, BITCNTR_STATE) + +INT *GetRam_aacEnc_BitLookUp(int n, UCHAR *dynamic_RAM); +INT *GetRam_aacEnc_MergeGainLookUp(int n, UCHAR *dynamic_RAM); +QC_OUT_CHANNEL *GetRam_aacEnc_QCchannel(int n, UCHAR *dynamic_RAM); + +H_ALLOC_MEM(Ram_aacEnc_QCout, QC_OUT) +H_ALLOC_MEM(Ram_aacEnc_QCelement, QC_OUT_ELEMENT) + +#endif /* #ifndef AACENC_RAM_H */ diff --git a/fdk-aac/libAACenc/src/aacEnc_rom.cpp b/fdk-aac/libAACenc/src/aacEnc_rom.cpp new file mode 100644 index 0000000..ac0fa9d --- /dev/null +++ b/fdk-aac/libAACenc/src/aacEnc_rom.cpp @@ -0,0 +1,2486 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#include "aacEnc_rom.h" + +/* + Huffman Tables +*/ +const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3] = { + {{{0x000b0009, 0x00090007, 0x000b0009}, + {0x000a0008, 0x00070006, 0x000a0008}, + {0x000b0009, 0x00090008, 0x000b0009}}, + {{0x000a0008, 0x00070006, 0x000a0007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090007, 0x00070006, 0x000a0008}}, + {{0x000b0009, 0x00090007, 0x000b0008}, + {0x00090008, 0x00070006, 0x00090008}, + {0x000b0009, 0x00090007, 0x000b0009}}}, + {{{0x00090008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090007, 0x00070006, 0x00090008}}, + {{0x00070006, 0x00050005, 0x00070006}, + {0x00050005, 0x00010003, 0x00050005}, + {0x00070006, 0x00050005, 0x00070006}}, + {{0x00090008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050005, 0x00070006}, + {0x00090008, 0x00070006, 0x00090008}}}, + {{{0x000b0009, 0x00090007, 0x000b0009}, + {0x00090008, 0x00070006, 0x00090008}, + {0x000b0008, 0x00090007, 0x000b0009}}, + {{0x000a0008, 0x00070006, 0x00090007}, + {0x00070006, 0x00050004, 0x00070006}, + {0x00090008, 0x00070006, 0x000a0007}}, + {{0x000b0009, 0x00090007, 0x000b0009}, + {0x000a0007, 0x00070006, 0x00090008}, + {0x000b0009, 0x00090007, 0x000b0009}}}}; + +const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3] = { + {{{0x00010004, 0x00040005, 0x00080008}, + {0x00040005, 0x00050004, 0x00080008}, + {0x00090009, 0x00090008, 0x000a000b}}, + {{0x00040005, 0x00060005, 0x00090008}, + {0x00060005, 0x00060004, 0x00090008}, + {0x00090008, 0x00090007, 0x000a000a}}, + {{0x00090009, 0x000a0008, 0x000d000b}, + {0x00090008, 0x00090008, 0x000b000a}, + {0x000b000b, 0x000a000a, 0x000c000b}}}, + {{{0x00040004, 0x00060005, 0x000a0008}, + {0x00060004, 0x00070004, 0x000a0008}, + {0x000a0008, 0x000a0008, 0x000c000a}}, + {{0x00050004, 0x00070004, 0x000b0008}, + {0x00060004, 0x00070004, 0x000a0007}, + {0x00090008, 0x00090007, 0x000b0009}}, + {{0x00090008, 0x000a0008, 0x000d000a}, + {0x00080007, 0x00090007, 0x000c0009}, + {0x000a000a, 0x000b0009, 0x000c000a}}}, + {{{0x00080008, 0x000a0008, 0x000f000b}, + {0x00090008, 0x000b0007, 0x000f000a}, + {0x000d000b, 0x000e000a, 0x0010000c}}, + {{0x00080008, 0x000a0007, 0x000e000a}, + {0x00090007, 0x000a0007, 0x000e0009}, + {0x000c000a, 0x000c0009, 0x000f000b}}, + {{0x000b000b, 0x000c000a, 0x0010000c}, + {0x000a000a, 0x000b0009, 0x000f000b}, + {0x000c000b, 0x000c000a, 0x000f000b}}}}; + +const ULONG FDKaacEnc_huff_ltab5_6[9][9] = { + {0x000d000b, 0x000c000a, 0x000b0009, 0x000b0009, 0x000a0009, 0x000b0009, + 0x000b0009, 0x000c000a, 0x000d000b}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, + 0x000a0008, 0x000b0009, 0x000c000a}, + {0x000c0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, + 0x00090006, 0x000a0008, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, + 0x00080006, 0x00090007, 0x000b0009}, + {0x000a0009, 0x00080007, 0x00070006, 0x00040004, 0x00010004, 0x00040004, + 0x00070006, 0x00080007, 0x000b0009}, + {0x000b0009, 0x00090007, 0x00080006, 0x00050004, 0x00040004, 0x00050004, + 0x00080006, 0x00090007, 0x000b0009}, + {0x000b0009, 0x000a0008, 0x00090006, 0x00080006, 0x00070006, 0x00080006, + 0x00090006, 0x000a0008, 0x000b0009}, + {0x000c000a, 0x000b0009, 0x000a0008, 0x00090007, 0x00080007, 0x00090007, + 0x000a0007, 0x000b0008, 0x000c000a}, + {0x000d000b, 0x000c000a, 0x000c0009, 0x000b0009, 0x000a0009, 0x000a0009, + 0x000b0009, 0x000c000a, 0x000d000b}}; + +const ULONG FDKaacEnc_huff_ltab7_8[8][8] = { + {0x00010005, 0x00030004, 0x00060005, 0x00070006, 0x00080007, 0x00090008, + 0x000a0009, 0x000b000a}, + {0x00030004, 0x00040003, 0x00060004, 0x00070005, 0x00080006, 0x00080007, + 0x00090007, 0x00090008}, + {0x00060005, 0x00060004, 0x00070004, 0x00080005, 0x00080006, 0x00090007, + 0x00090007, 0x000a0008}, + {0x00070006, 0x00070005, 0x00080005, 0x00080006, 0x00090006, 0x00090007, + 0x000a0008, 0x000a0008}, + {0x00080007, 0x00080006, 0x00090006, 0x00090006, 0x000a0007, 0x000a0007, + 0x000a0008, 0x000b0009}, + {0x00090008, 0x00080007, 0x00090006, 0x00090007, 0x000a0007, 0x000a0008, + 0x000b0008, 0x000b000a}, + {0x000a0009, 0x00090007, 0x00090007, 0x000a0008, 0x000a0008, 0x000b0008, + 0x000c0009, 0x000c0009}, + {0x000b000a, 0x000a0008, 0x000a0008, 0x000a0008, 0x000b0009, 0x000b0009, + 0x000c0009, 0x000c000a}}; + +const ULONG FDKaacEnc_huff_ltab9_10[13][13] = { + {0x00010006, 0x00030005, 0x00060006, 0x00080006, 0x00090007, 0x000a0008, + 0x000a0009, 0x000b000a, 0x000b000a, 0x000c000a, 0x000c000b, 0x000d000b, + 0x000d000c}, + {0x00030005, 0x00040004, 0x00060004, 0x00070005, 0x00080006, 0x00080007, + 0x00090007, 0x000a0008, 0x000a0008, 0x000a0009, 0x000b000a, 0x000c000a, + 0x000c000b}, + {0x00060006, 0x00060004, 0x00070005, 0x00080005, 0x00080006, 0x00090006, + 0x000a0007, 0x000a0008, 0x000a0008, 0x000b0009, 0x000c0009, 0x000c000a, + 0x000c000a}, + {0x00080006, 0x00070005, 0x00080005, 0x00090005, 0x00090006, 0x000a0007, + 0x000a0007, 0x000b0008, 0x000b0008, 0x000b0009, 0x000c0009, 0x000c000a, + 0x000d000a}, + {0x00090007, 0x00080006, 0x00090006, 0x00090006, 0x000a0006, 0x000a0007, + 0x000b0007, 0x000b0008, 0x000b0008, 0x000c0009, 0x000c0009, 0x000c000a, + 0x000d000a}, + {0x000a0008, 0x00090007, 0x00090006, 0x000a0007, 0x000b0007, 0x000b0007, + 0x000b0008, 0x000c0008, 0x000b0008, 0x000c0009, 0x000c000a, 0x000d000a, + 0x000d000b}, + {0x000b0009, 0x00090007, 0x000a0007, 0x000b0007, 0x000b0007, 0x000b0008, + 0x000c0008, 0x000c0009, 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, + 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000c0008, + 0x000c0009, 0x000d0009, 0x000d0009, 0x000d000a, 0x000d000a, 0x000d000b, + 0x000d000b}, + {0x000b0009, 0x000a0008, 0x000a0008, 0x000b0008, 0x000b0008, 0x000b0008, + 0x000c0009, 0x000c0009, 0x000d000a, 0x000d000a, 0x000e000a, 0x000d000b, + 0x000e000b}, + {0x000b000a, 0x000a0009, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, + 0x000c0009, 0x000c000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, + 0x000e000c}, + {0x000c000a, 0x000b0009, 0x000b0009, 0x000c0009, 0x000c0009, 0x000c000a, + 0x000d000a, 0x000d000a, 0x000d000a, 0x000e000b, 0x000e000b, 0x000e000b, + 0x000f000c}, + {0x000c000b, 0x000b000a, 0x000c0009, 0x000c000a, 0x000c000a, 0x000d000a, + 0x000d000a, 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000b, 0x000f000b, + 0x000f000c}, + {0x000d000b, 0x000c000a, 0x000c000a, 0x000c000a, 0x000d000a, 0x000d000a, + 0x000d000a, 0x000d000b, 0x000e000b, 0x000e000c, 0x000e000c, 0x000e000c, + 0x000f000c}}; + +const UCHAR FDKaacEnc_huff_ltab11[17][17] = { + {0x04, 0x05, 0x06, 0x07, 0x08, 0x08, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0c, 0x0b, 0x0c, 0x0c, 0x0a}, + {0x05, 0x04, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x06, 0x05, 0x05, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x07, 0x06, 0x06, 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x08, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0a, 0x08}, + {0x0a, 0x09, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0a, 0x0b, 0x08}, + {0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0a, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, + 0x0b, 0x0a, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x08}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x09}, + {0x0c, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0c, 0x0c, 0x09}, + {0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x09, 0x05}}; + +const UCHAR FDKaacEnc_huff_ltabscf[121] = { + 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x12, 0x13, 0x12, + 0x11, 0x11, 0x10, 0x11, 0x10, 0x10, 0x10, 0x10, 0x0f, 0x0f, 0x0e, + 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0b, + 0x0c, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x07, + 0x06, 0x06, 0x05, 0x04, 0x03, 0x01, 0x04, 0x04, 0x05, 0x06, 0x06, + 0x07, 0x07, 0x08, 0x08, 0x09, 0x09, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d, 0x0e, 0x0e, 0x10, 0x0f, + 0x10, 0x0f, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +const USHORT FDKaacEnc_huff_ctab1[3][3][3][3] = {{{{0x07f8, 0x01f1, 0x07fd}, + {0x03f5, 0x0068, 0x03f0}, + {0x07f7, 0x01ec, 0x07f5}}, + {{0x03f1, 0x0072, 0x03f4}, + {0x0074, 0x0011, 0x0076}, + {0x01eb, 0x006c, 0x03f6}}, + {{0x07fc, 0x01e1, 0x07f1}, + {0x01f0, 0x0061, 0x01f6}, + {0x07f2, 0x01ea, 0x07fb}}}, + {{{0x01f2, 0x0069, 0x01ed}, + {0x0077, 0x0017, 0x006f}, + {0x01e6, 0x0064, 0x01e5}}, + {{0x0067, 0x0015, 0x0062}, + {0x0012, 0x0000, 0x0014}, + {0x0065, 0x0016, 0x006d}}, + {{0x01e9, 0x0063, 0x01e4}, + {0x006b, 0x0013, 0x0071}, + {0x01e3, 0x0070, 0x01f3}}}, + {{{0x07fe, 0x01e7, 0x07f3}, + {0x01ef, 0x0060, 0x01ee}, + {0x07f0, 0x01e2, 0x07fa}}, + {{0x03f3, 0x006a, 0x01e8}, + {0x0075, 0x0010, 0x0073}, + {0x01f4, 0x006e, 0x03f7}}, + {{0x07f6, 0x01e0, 0x07f9}, + {0x03f2, 0x0066, 0x01f5}, + {0x07ff, 0x01f7, 0x07f4}}}}; + +const USHORT FDKaacEnc_huff_ctab2[3][3][3][3] = {{{{0x01f3, 0x006f, 0x01fd}, + {0x00eb, 0x0023, 0x00ea}, + {0x01f7, 0x00e8, 0x01fa}}, + {{0x00f2, 0x002d, 0x0070}, + {0x0020, 0x0006, 0x002b}, + {0x006e, 0x0028, 0x00e9}}, + {{0x01f9, 0x0066, 0x00f8}, + {0x00e7, 0x001b, 0x00f1}, + {0x01f4, 0x006b, 0x01f5}}}, + {{{0x00ec, 0x002a, 0x006c}, + {0x002c, 0x000a, 0x0027}, + {0x0067, 0x001a, 0x00f5}}, + {{0x0024, 0x0008, 0x001f}, + {0x0009, 0x0000, 0x0007}, + {0x001d, 0x000b, 0x0030}}, + {{0x00ef, 0x001c, 0x0064}, + {0x001e, 0x000c, 0x0029}, + {0x00f3, 0x002f, 0x00f0}}}, + {{{0x01fc, 0x0071, 0x01f2}, + {0x00f4, 0x0021, 0x00e6}, + {0x00f7, 0x0068, 0x01f8}}, + {{0x00ee, 0x0022, 0x0065}, + {0x0031, 0x0002, 0x0026}, + {0x00ed, 0x0025, 0x006a}}, + {{0x01fb, 0x0072, 0x01fe}, + {0x0069, 0x002e, 0x00f6}, + {0x01ff, 0x006d, 0x01f6}}}}; + +const USHORT FDKaacEnc_huff_ctab3[3][3][3][3] = {{{{0x0000, 0x0009, 0x00ef}, + {0x000b, 0x0019, 0x00f0}, + {0x01eb, 0x01e6, 0x03f2}}, + {{0x000a, 0x0035, 0x01ef}, + {0x0034, 0x0037, 0x01e9}, + {0x01ed, 0x01e7, 0x03f3}}, + {{0x01ee, 0x03ed, 0x1ffa}, + {0x01ec, 0x01f2, 0x07f9}, + {0x07f8, 0x03f8, 0x0ff8}}}, + {{{0x0008, 0x0038, 0x03f6}, + {0x0036, 0x0075, 0x03f1}, + {0x03eb, 0x03ec, 0x0ff4}}, + {{0x0018, 0x0076, 0x07f4}, + {0x0039, 0x0074, 0x03ef}, + {0x01f3, 0x01f4, 0x07f6}}, + {{0x01e8, 0x03ea, 0x1ffc}, + {0x00f2, 0x01f1, 0x0ffb}, + {0x03f5, 0x07f3, 0x0ffc}}}, + {{{0x00ee, 0x03f7, 0x7ffe}, + {0x01f0, 0x07f5, 0x7ffd}, + {0x1ffb, 0x3ffa, 0xffff}}, + {{0x00f1, 0x03f0, 0x3ffc}, + {0x01ea, 0x03ee, 0x3ffb}, + {0x0ff6, 0x0ffa, 0x7ffc}}, + {{0x07f2, 0x0ff5, 0xfffe}, + {0x03f4, 0x07f7, 0x7ffb}, + {0x0ff7, 0x0ff9, 0x7ffa}}}}; + +const USHORT FDKaacEnc_huff_ctab4[3][3][3][3] = {{{{0x0007, 0x0016, 0x00f6}, + {0x0018, 0x0008, 0x00ef}, + {0x01ef, 0x00f3, 0x07f8}}, + {{0x0019, 0x0017, 0x00ed}, + {0x0015, 0x0001, 0x00e2}, + {0x00f0, 0x0070, 0x03f0}}, + {{0x01ee, 0x00f1, 0x07fa}, + {0x00ee, 0x00e4, 0x03f2}, + {0x07f6, 0x03ef, 0x07fd}}}, + {{{0x0005, 0x0014, 0x00f2}, + {0x0009, 0x0004, 0x00e5}, + {0x00f4, 0x00e8, 0x03f4}}, + {{0x0006, 0x0002, 0x00e7}, + {0x0003, 0x0000, 0x006b}, + {0x00e3, 0x0069, 0x01f3}}, + {{0x00eb, 0x00e6, 0x03f6}, + {0x006e, 0x006a, 0x01f4}, + {0x03ec, 0x01f0, 0x03f9}}}, + {{{0x00f5, 0x00ec, 0x07fb}, + {0x00ea, 0x006f, 0x03f7}, + {0x07f9, 0x03f3, 0x0fff}}, + {{0x00e9, 0x006d, 0x03f8}, + {0x006c, 0x0068, 0x01f5}, + {0x03ee, 0x01f2, 0x07f4}}, + {{0x07f7, 0x03f1, 0x0ffe}, + {0x03ed, 0x01f1, 0x07f5}, + {0x07fe, 0x03f5, 0x07fc}}}}; + +const USHORT FDKaacEnc_huff_ctab5[9][9] = { + {0x1fff, 0x0ff7, 0x07f4, 0x07e8, 0x03f1, 0x07ee, 0x07f9, 0x0ff8, 0x1ffd}, + {0x0ffd, 0x07f1, 0x03e8, 0x01e8, 0x00f0, 0x01ec, 0x03ee, 0x07f2, 0x0ffa}, + {0x0ff4, 0x03ef, 0x01f2, 0x00e8, 0x0070, 0x00ec, 0x01f0, 0x03ea, 0x07f3}, + {0x07eb, 0x01eb, 0x00ea, 0x001a, 0x0008, 0x0019, 0x00ee, 0x01ef, 0x07ed}, + {0x03f0, 0x00f2, 0x0073, 0x000b, 0x0000, 0x000a, 0x0071, 0x00f3, 0x07e9}, + {0x07ef, 0x01ee, 0x00ef, 0x0018, 0x0009, 0x001b, 0x00eb, 0x01e9, 0x07ec}, + {0x07f6, 0x03eb, 0x01f3, 0x00ed, 0x0072, 0x00e9, 0x01f1, 0x03ed, 0x07f7}, + {0x0ff6, 0x07f0, 0x03e9, 0x01ed, 0x00f1, 0x01ea, 0x03ec, 0x07f8, 0x0ff9}, + {0x1ffc, 0x0ffc, 0x0ff5, 0x07ea, 0x03f3, 0x03f2, 0x07f5, 0x0ffb, 0x1ffe}}; + +const USHORT FDKaacEnc_huff_ctab6[9][9] = { + {0x07fe, 0x03fd, 0x01f1, 0x01eb, 0x01f4, 0x01ea, 0x01f0, 0x03fc, 0x07fd}, + {0x03f6, 0x01e5, 0x00ea, 0x006c, 0x0071, 0x0068, 0x00f0, 0x01e6, 0x03f7}, + {0x01f3, 0x00ef, 0x0032, 0x0027, 0x0028, 0x0026, 0x0031, 0x00eb, 0x01f7}, + {0x01e8, 0x006f, 0x002e, 0x0008, 0x0004, 0x0006, 0x0029, 0x006b, 0x01ee}, + {0x01ef, 0x0072, 0x002d, 0x0002, 0x0000, 0x0003, 0x002f, 0x0073, 0x01fa}, + {0x01e7, 0x006e, 0x002b, 0x0007, 0x0001, 0x0005, 0x002c, 0x006d, 0x01ec}, + {0x01f9, 0x00ee, 0x0030, 0x0024, 0x002a, 0x0025, 0x0033, 0x00ec, 0x01f2}, + {0x03f8, 0x01e4, 0x00ed, 0x006a, 0x0070, 0x0069, 0x0074, 0x00f1, 0x03fa}, + {0x07ff, 0x03f9, 0x01f6, 0x01ed, 0x01f8, 0x01e9, 0x01f5, 0x03fb, 0x07fc}}; + +const USHORT FDKaacEnc_huff_ctab7[8][8] = { + {0x0000, 0x0005, 0x0037, 0x0074, 0x00f2, 0x01eb, 0x03ed, 0x07f7}, + {0x0004, 0x000c, 0x0035, 0x0071, 0x00ec, 0x00ee, 0x01ee, 0x01f5}, + {0x0036, 0x0034, 0x0072, 0x00ea, 0x00f1, 0x01e9, 0x01f3, 0x03f5}, + {0x0073, 0x0070, 0x00eb, 0x00f0, 0x01f1, 0x01f0, 0x03ec, 0x03fa}, + {0x00f3, 0x00ed, 0x01e8, 0x01ef, 0x03ef, 0x03f1, 0x03f9, 0x07fb}, + {0x01ed, 0x00ef, 0x01ea, 0x01f2, 0x03f3, 0x03f8, 0x07f9, 0x07fc}, + {0x03ee, 0x01ec, 0x01f4, 0x03f4, 0x03f7, 0x07f8, 0x0ffd, 0x0ffe}, + {0x07f6, 0x03f0, 0x03f2, 0x03f6, 0x07fa, 0x07fd, 0x0ffc, 0x0fff}}; + +const USHORT FDKaacEnc_huff_ctab8[8][8] = { + {0x000e, 0x0005, 0x0010, 0x0030, 0x006f, 0x00f1, 0x01fa, 0x03fe}, + {0x0003, 0x0000, 0x0004, 0x0012, 0x002c, 0x006a, 0x0075, 0x00f8}, + {0x000f, 0x0002, 0x0006, 0x0014, 0x002e, 0x0069, 0x0072, 0x00f5}, + {0x002f, 0x0011, 0x0013, 0x002a, 0x0032, 0x006c, 0x00ec, 0x00fa}, + {0x0071, 0x002b, 0x002d, 0x0031, 0x006d, 0x0070, 0x00f2, 0x01f9}, + {0x00ef, 0x0068, 0x0033, 0x006b, 0x006e, 0x00ee, 0x00f9, 0x03fc}, + {0x01f8, 0x0074, 0x0073, 0x00ed, 0x00f0, 0x00f6, 0x01f6, 0x01fd}, + {0x03fd, 0x00f3, 0x00f4, 0x00f7, 0x01f7, 0x01fb, 0x01fc, 0x03ff}}; + +const USHORT FDKaacEnc_huff_ctab9[13][13] = { + {0x0000, 0x0005, 0x0037, 0x00e7, 0x01de, 0x03ce, 0x03d9, 0x07c8, 0x07cd, + 0x0fc8, 0x0fdd, 0x1fe4, 0x1fec}, + {0x0004, 0x000c, 0x0035, 0x0072, 0x00ea, 0x00ed, 0x01e2, 0x03d1, 0x03d3, + 0x03e0, 0x07d8, 0x0fcf, 0x0fd5}, + {0x0036, 0x0034, 0x0071, 0x00e8, 0x00ec, 0x01e1, 0x03cf, 0x03dd, 0x03db, + 0x07d0, 0x0fc7, 0x0fd4, 0x0fe4}, + {0x00e6, 0x0070, 0x00e9, 0x01dd, 0x01e3, 0x03d2, 0x03dc, 0x07cc, 0x07ca, + 0x07de, 0x0fd8, 0x0fea, 0x1fdb}, + {0x01df, 0x00eb, 0x01dc, 0x01e6, 0x03d5, 0x03de, 0x07cb, 0x07dd, 0x07dc, + 0x0fcd, 0x0fe2, 0x0fe7, 0x1fe1}, + {0x03d0, 0x01e0, 0x01e4, 0x03d6, 0x07c5, 0x07d1, 0x07db, 0x0fd2, 0x07e0, + 0x0fd9, 0x0feb, 0x1fe3, 0x1fe9}, + {0x07c4, 0x01e5, 0x03d7, 0x07c6, 0x07cf, 0x07da, 0x0fcb, 0x0fda, 0x0fe3, + 0x0fe9, 0x1fe6, 0x1ff3, 0x1ff7}, + {0x07d3, 0x03d8, 0x03e1, 0x07d4, 0x07d9, 0x0fd3, 0x0fde, 0x1fdd, 0x1fd9, + 0x1fe2, 0x1fea, 0x1ff1, 0x1ff6}, + {0x07d2, 0x03d4, 0x03da, 0x07c7, 0x07d7, 0x07e2, 0x0fce, 0x0fdb, 0x1fd8, + 0x1fee, 0x3ff0, 0x1ff4, 0x3ff2}, + {0x07e1, 0x03df, 0x07c9, 0x07d6, 0x0fca, 0x0fd0, 0x0fe5, 0x0fe6, 0x1feb, + 0x1fef, 0x3ff3, 0x3ff4, 0x3ff5}, + {0x0fe0, 0x07ce, 0x07d5, 0x0fc6, 0x0fd1, 0x0fe1, 0x1fe0, 0x1fe8, 0x1ff0, + 0x3ff1, 0x3ff8, 0x3ff6, 0x7ffc}, + {0x0fe8, 0x07df, 0x0fc9, 0x0fd7, 0x0fdc, 0x1fdc, 0x1fdf, 0x1fed, 0x1ff5, + 0x3ff9, 0x3ffb, 0x7ffd, 0x7ffe}, + {0x1fe7, 0x0fcc, 0x0fd6, 0x0fdf, 0x1fde, 0x1fda, 0x1fe5, 0x1ff2, 0x3ffa, + 0x3ff7, 0x3ffc, 0x3ffd, 0x7fff}}; + +const USHORT FDKaacEnc_huff_ctab10[13][13] = { + {0x0022, 0x0008, 0x001d, 0x0026, 0x005f, 0x00d3, 0x01cf, 0x03d0, 0x03d7, + 0x03ed, 0x07f0, 0x07f6, 0x0ffd}, + {0x0007, 0x0000, 0x0001, 0x0009, 0x0020, 0x0054, 0x0060, 0x00d5, 0x00dc, + 0x01d4, 0x03cd, 0x03de, 0x07e7}, + {0x001c, 0x0002, 0x0006, 0x000c, 0x001e, 0x0028, 0x005b, 0x00cd, 0x00d9, + 0x01ce, 0x01dc, 0x03d9, 0x03f1}, + {0x0025, 0x000b, 0x000a, 0x000d, 0x0024, 0x0057, 0x0061, 0x00cc, 0x00dd, + 0x01cc, 0x01de, 0x03d3, 0x03e7}, + {0x005d, 0x0021, 0x001f, 0x0023, 0x0027, 0x0059, 0x0064, 0x00d8, 0x00df, + 0x01d2, 0x01e2, 0x03dd, 0x03ee}, + {0x00d1, 0x0055, 0x0029, 0x0056, 0x0058, 0x0062, 0x00ce, 0x00e0, 0x00e2, + 0x01da, 0x03d4, 0x03e3, 0x07eb}, + {0x01c9, 0x005e, 0x005a, 0x005c, 0x0063, 0x00ca, 0x00da, 0x01c7, 0x01ca, + 0x01e0, 0x03db, 0x03e8, 0x07ec}, + {0x01e3, 0x00d2, 0x00cb, 0x00d0, 0x00d7, 0x00db, 0x01c6, 0x01d5, 0x01d8, + 0x03ca, 0x03da, 0x07ea, 0x07f1}, + {0x01e1, 0x00d4, 0x00cf, 0x00d6, 0x00de, 0x00e1, 0x01d0, 0x01d6, 0x03d1, + 0x03d5, 0x03f2, 0x07ee, 0x07fb}, + {0x03e9, 0x01cd, 0x01c8, 0x01cb, 0x01d1, 0x01d7, 0x01df, 0x03cf, 0x03e0, + 0x03ef, 0x07e6, 0x07f8, 0x0ffa}, + {0x03eb, 0x01dd, 0x01d3, 0x01d9, 0x01db, 0x03d2, 0x03cc, 0x03dc, 0x03ea, + 0x07ed, 0x07f3, 0x07f9, 0x0ff9}, + {0x07f2, 0x03ce, 0x01e4, 0x03cb, 0x03d8, 0x03d6, 0x03e2, 0x03e5, 0x07e8, + 0x07f4, 0x07f5, 0x07f7, 0x0ffb}, + {0x07fa, 0x03ec, 0x03df, 0x03e1, 0x03e4, 0x03e6, 0x03f0, 0x07e9, 0x07ef, + 0x0ff8, 0x0ffe, 0x0ffc, 0x0fff}}; + +const USHORT FDKaacEnc_huff_ctab11[21][17] = { + {0x0000, 0x0006, 0x0019, 0x003d, 0x009c, 0x00c6, 0x01a7, 0x0390, 0x03c2, + 0x03df, 0x07e6, 0x07f3, 0x0ffb, 0x07ec, 0x0ffa, 0x0ffe, 0x038e}, + {0x0005, 0x0001, 0x0008, 0x0014, 0x0037, 0x0042, 0x0092, 0x00af, 0x0191, + 0x01a5, 0x01b5, 0x039e, 0x03c0, 0x03a2, 0x03cd, 0x07d6, 0x00ae}, + {0x0017, 0x0007, 0x0009, 0x0018, 0x0039, 0x0040, 0x008e, 0x00a3, 0x00b8, + 0x0199, 0x01ac, 0x01c1, 0x03b1, 0x0396, 0x03be, 0x03ca, 0x009d}, + {0x003c, 0x0015, 0x0016, 0x001a, 0x003b, 0x0044, 0x0091, 0x00a5, 0x00be, + 0x0196, 0x01ae, 0x01b9, 0x03a1, 0x0391, 0x03a5, 0x03d5, 0x0094}, + {0x009a, 0x0036, 0x0038, 0x003a, 0x0041, 0x008c, 0x009b, 0x00b0, 0x00c3, + 0x019e, 0x01ab, 0x01bc, 0x039f, 0x038f, 0x03a9, 0x03cf, 0x0093}, + {0x00bf, 0x003e, 0x003f, 0x0043, 0x0045, 0x009e, 0x00a7, 0x00b9, 0x0194, + 0x01a2, 0x01ba, 0x01c3, 0x03a6, 0x03a7, 0x03bb, 0x03d4, 0x009f}, + {0x01a0, 0x008f, 0x008d, 0x0090, 0x0098, 0x00a6, 0x00b6, 0x00c4, 0x019f, + 0x01af, 0x01bf, 0x0399, 0x03bf, 0x03b4, 0x03c9, 0x03e7, 0x00a8}, + {0x01b6, 0x00ab, 0x00a4, 0x00aa, 0x00b2, 0x00c2, 0x00c5, 0x0198, 0x01a4, + 0x01b8, 0x038c, 0x03a4, 0x03c4, 0x03c6, 0x03dd, 0x03e8, 0x00ad}, + {0x03af, 0x0192, 0x00bd, 0x00bc, 0x018e, 0x0197, 0x019a, 0x01a3, 0x01b1, + 0x038d, 0x0398, 0x03b7, 0x03d3, 0x03d1, 0x03db, 0x07dd, 0x00b4}, + {0x03de, 0x01a9, 0x019b, 0x019c, 0x01a1, 0x01aa, 0x01ad, 0x01b3, 0x038b, + 0x03b2, 0x03b8, 0x03ce, 0x03e1, 0x03e0, 0x07d2, 0x07e5, 0x00b7}, + {0x07e3, 0x01bb, 0x01a8, 0x01a6, 0x01b0, 0x01b2, 0x01b7, 0x039b, 0x039a, + 0x03ba, 0x03b5, 0x03d6, 0x07d7, 0x03e4, 0x07d8, 0x07ea, 0x00ba}, + {0x07e8, 0x03a0, 0x01bd, 0x01b4, 0x038a, 0x01c4, 0x0392, 0x03aa, 0x03b0, + 0x03bc, 0x03d7, 0x07d4, 0x07dc, 0x07db, 0x07d5, 0x07f0, 0x00c1}, + {0x07fb, 0x03c8, 0x03a3, 0x0395, 0x039d, 0x03ac, 0x03ae, 0x03c5, 0x03d8, + 0x03e2, 0x03e6, 0x07e4, 0x07e7, 0x07e0, 0x07e9, 0x07f7, 0x0190}, + {0x07f2, 0x0393, 0x01be, 0x01c0, 0x0394, 0x0397, 0x03ad, 0x03c3, 0x03c1, + 0x03d2, 0x07da, 0x07d9, 0x07df, 0x07eb, 0x07f4, 0x07fa, 0x0195}, + {0x07f8, 0x03bd, 0x039c, 0x03ab, 0x03a8, 0x03b3, 0x03b9, 0x03d0, 0x03e3, + 0x03e5, 0x07e2, 0x07de, 0x07ed, 0x07f1, 0x07f9, 0x07fc, 0x0193}, + {0x0ffd, 0x03dc, 0x03b6, 0x03c7, 0x03cc, 0x03cb, 0x03d9, 0x03da, 0x07d3, + 0x07e1, 0x07ee, 0x07ef, 0x07f5, 0x07f6, 0x0ffc, 0x0fff, 0x019d}, + {0x01c2, 0x00b5, 0x00a1, 0x0096, 0x0097, 0x0095, 0x0099, 0x00a0, 0x00a2, + 0x00ac, 0x00a9, 0x00b1, 0x00b3, 0x00bb, 0x00c0, 0x018f, 0x0004}, + {0x0018, 0x002e, 0x0000, 0x005a, 0x00a5, 0x00f8, 0x00b7, 0x0094, 0x00f9, + 0x004d, 0x0021, 0x002b, 0x004f, 0x007b, 0x00bc, 0x0046, 0x0015}, + {0x0042, 0x0037, 0x0078, 0x000d, 0x0068, 0x005f, 0x000d, 0x005e, 0x005a, + 0x00be, 0x0063, 0x007e, 0x001f, 0x0092, 0x001a, 0x00ab, 0x0032}, + {0x00e6, 0x0037, 0x0000, 0x0058, 0x000b, 0x005a, 0x00e1, 0x005d, 0x0029, + 0x0017, 0x007e, 0x0069, 0x00aa, 0x0054, 0x0029, 0x0032, 0x0041}, + {0x0046, 0x00ea, 0x0034, 0x00ea, 0x0011, 0x001b, 0x00a9, 0x0094, 0x00e2, + 0x0031, 0x00d0, 0x00e5, 0x0007, 0x0070, 0x0069, 0x003e, 0x0021}}; + +const ULONG FDKaacEnc_huff_ctabscf[121] = { + 0x0003ffe8, 0x0003ffe6, 0x0003ffe7, 0x0003ffe5, 0x0007fff5, 0x0007fff1, + 0x0007ffed, 0x0007fff6, 0x0007ffee, 0x0007ffef, 0x0007fff0, 0x0007fffc, + 0x0007fffd, 0x0007ffff, 0x0007fffe, 0x0007fff7, 0x0007fff8, 0x0007fffb, + 0x0007fff9, 0x0003ffe4, 0x0007fffa, 0x0003ffe3, 0x0001ffef, 0x0001fff0, + 0x0000fff5, 0x0001ffee, 0x0000fff2, 0x0000fff3, 0x0000fff4, 0x0000fff1, + 0x00007ff6, 0x00007ff7, 0x00003ff9, 0x00003ff5, 0x00003ff7, 0x00003ff3, + 0x00003ff6, 0x00003ff2, 0x00001ff7, 0x00001ff5, 0x00000ff9, 0x00000ff7, + 0x00000ff6, 0x000007f9, 0x00000ff4, 0x000007f8, 0x000003f9, 0x000003f7, + 0x000003f5, 0x000001f8, 0x000001f7, 0x000000fa, 0x000000f8, 0x000000f6, + 0x00000079, 0x0000003a, 0x00000038, 0x0000001a, 0x0000000b, 0x00000004, + 0x00000000, 0x0000000a, 0x0000000c, 0x0000001b, 0x00000039, 0x0000003b, + 0x00000078, 0x0000007a, 0x000000f7, 0x000000f9, 0x000001f6, 0x000001f9, + 0x000003f4, 0x000003f6, 0x000003f8, 0x000007f5, 0x000007f4, 0x000007f6, + 0x000007f7, 0x00000ff5, 0x00000ff8, 0x00001ff4, 0x00001ff6, 0x00001ff8, + 0x00003ff8, 0x00003ff4, 0x0000fff0, 0x00007ff4, 0x0000fff6, 0x00007ff5, + 0x0003ffe2, 0x0007ffd9, 0x0007ffda, 0x0007ffdb, 0x0007ffdc, 0x0007ffdd, + 0x0007ffde, 0x0007ffd8, 0x0007ffd2, 0x0007ffd3, 0x0007ffd4, 0x0007ffd5, + 0x0007ffd6, 0x0007fff2, 0x0007ffdf, 0x0007ffe7, 0x0007ffe8, 0x0007ffe9, + 0x0007ffea, 0x0007ffeb, 0x0007ffe6, 0x0007ffe0, 0x0007ffe1, 0x0007ffe2, + 0x0007ffe3, 0x0007ffe4, 0x0007ffe5, 0x0007ffd7, 0x0007ffec, 0x0007fff4, + 0x0007fff3}; + +/* + table of (0.50000...1.00000) ^0.75 +*/ +const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE] = { + QTC(0x4c1bf829), QTC(0x4c3880de), QTC(0x4c550603), QTC(0x4c71879c), + QTC(0x4c8e05aa), QTC(0x4caa8030), QTC(0x4cc6f72f), QTC(0x4ce36aab), + QTC(0x4cffdaa4), QTC(0x4d1c471d), QTC(0x4d38b019), QTC(0x4d55159a), + QTC(0x4d7177a1), QTC(0x4d8dd631), QTC(0x4daa314b), QTC(0x4dc688f3), + QTC(0x4de2dd2a), QTC(0x4dff2df2), QTC(0x4e1b7b4d), QTC(0x4e37c53d), + QTC(0x4e540bc5), QTC(0x4e704ee6), QTC(0x4e8c8ea3), QTC(0x4ea8cafd), + QTC(0x4ec503f7), QTC(0x4ee13992), QTC(0x4efd6bd0), QTC(0x4f199ab4), + QTC(0x4f35c640), QTC(0x4f51ee75), QTC(0x4f6e1356), QTC(0x4f8a34e4), + QTC(0x4fa65321), QTC(0x4fc26e10), QTC(0x4fde85b2), QTC(0x4ffa9a0a), + QTC(0x5016ab18), QTC(0x5032b8e0), QTC(0x504ec362), QTC(0x506acaa1), + QTC(0x5086cea0), QTC(0x50a2cf5e), QTC(0x50becce0), QTC(0x50dac725), + QTC(0x50f6be31), QTC(0x5112b205), QTC(0x512ea2a3), QTC(0x514a900d), + QTC(0x51667a45), QTC(0x5182614c), QTC(0x519e4524), QTC(0x51ba25cf), + QTC(0x51d60350), QTC(0x51f1dda7), QTC(0x520db4d6), QTC(0x522988e0), + QTC(0x524559c6), QTC(0x52612789), QTC(0x527cf22d), QTC(0x5298b9b1), + QTC(0x52b47e19), QTC(0x52d03f65), QTC(0x52ebfd98), QTC(0x5307b8b4), + QTC(0x532370b9), QTC(0x533f25aa), QTC(0x535ad789), QTC(0x53768656), + QTC(0x53923215), QTC(0x53addac6), QTC(0x53c9806b), QTC(0x53e52306), + QTC(0x5400c298), QTC(0x541c5f24), QTC(0x5437f8ab), QTC(0x54538f2e), + QTC(0x546f22af), QTC(0x548ab330), QTC(0x54a640b3), QTC(0x54c1cb38), + QTC(0x54dd52c2), QTC(0x54f8d753), QTC(0x551458eb), QTC(0x552fd78d), + QTC(0x554b5339), QTC(0x5566cbf3), QTC(0x558241bb), QTC(0x559db492), + QTC(0x55b9247b), QTC(0x55d49177), QTC(0x55effb87), QTC(0x560b62ad), + QTC(0x5626c6eb), QTC(0x56422842), QTC(0x565d86b4), QTC(0x5678e242), + QTC(0x56943aee), QTC(0x56af90b9), QTC(0x56cae3a4), QTC(0x56e633b2), + QTC(0x570180e4), QTC(0x571ccb3b), QTC(0x573812b8), QTC(0x5753575e), + QTC(0x576e992e), QTC(0x5789d829), QTC(0x57a51450), QTC(0x57c04da6), + QTC(0x57db842b), QTC(0x57f6b7e1), QTC(0x5811e8c9), QTC(0x582d16e6), + QTC(0x58484238), QTC(0x58636ac0), QTC(0x587e9081), QTC(0x5899b37c), + QTC(0x58b4d3b1), QTC(0x58cff123), QTC(0x58eb0bd3), QTC(0x590623c2), + QTC(0x592138f2), QTC(0x593c4b63), QTC(0x59575b19), QTC(0x59726812), + QTC(0x598d7253), QTC(0x59a879da), QTC(0x59c37eab), QTC(0x59de80c6), + QTC(0x59f9802d), QTC(0x5a147ce0), QTC(0x5a2f76e2), QTC(0x5a4a6e34), + QTC(0x5a6562d6), QTC(0x5a8054cb), QTC(0x5a9b4414), QTC(0x5ab630b2), + QTC(0x5ad11aa6), QTC(0x5aec01f1), QTC(0x5b06e696), QTC(0x5b21c895), + QTC(0x5b3ca7ef), QTC(0x5b5784a6), QTC(0x5b725ebc), QTC(0x5b8d3631), + QTC(0x5ba80b06), QTC(0x5bc2dd3e), QTC(0x5bddacd9), QTC(0x5bf879d8), + QTC(0x5c13443d), QTC(0x5c2e0c09), QTC(0x5c48d13e), QTC(0x5c6393dc), + QTC(0x5c7e53e5), QTC(0x5c99115a), QTC(0x5cb3cc3c), QTC(0x5cce848d), + QTC(0x5ce93a4e), QTC(0x5d03ed80), QTC(0x5d1e9e24), QTC(0x5d394c3b), + QTC(0x5d53f7c7), QTC(0x5d6ea0c9), QTC(0x5d894742), QTC(0x5da3eb33), + QTC(0x5dbe8c9e), QTC(0x5dd92b84), QTC(0x5df3c7e5), QTC(0x5e0e61c3), + QTC(0x5e28f920), QTC(0x5e438dfc), QTC(0x5e5e2059), QTC(0x5e78b037), + QTC(0x5e933d99), QTC(0x5eadc87e), QTC(0x5ec850e9), QTC(0x5ee2d6da), + QTC(0x5efd5a53), QTC(0x5f17db54), QTC(0x5f3259e0), QTC(0x5f4cd5f6), + QTC(0x5f674f99), QTC(0x5f81c6c8), QTC(0x5f9c3b87), QTC(0x5fb6add4), + QTC(0x5fd11db3), QTC(0x5feb8b23), QTC(0x6005f626), QTC(0x60205ebd), + QTC(0x603ac4e9), QTC(0x605528ac), QTC(0x606f8a05), QTC(0x6089e8f7), + QTC(0x60a44583), QTC(0x60be9fa9), QTC(0x60d8f76b), QTC(0x60f34cca), + QTC(0x610d9fc7), QTC(0x6127f062), QTC(0x61423e9e), QTC(0x615c8a7a), + QTC(0x6176d3f9), QTC(0x61911b1b), QTC(0x61ab5fe1), QTC(0x61c5a24d), + QTC(0x61dfe25f), QTC(0x61fa2018), QTC(0x62145b7a), QTC(0x622e9485), + QTC(0x6248cb3b), QTC(0x6262ff9d), QTC(0x627d31ab), QTC(0x62976167), + QTC(0x62b18ed1), QTC(0x62cbb9eb), QTC(0x62e5e2b6), QTC(0x63000933), + QTC(0x631a2d62), QTC(0x63344f45), QTC(0x634e6edd), QTC(0x63688c2b), + QTC(0x6382a730), QTC(0x639cbfec), QTC(0x63b6d661), QTC(0x63d0ea90), + QTC(0x63eafc7a), QTC(0x64050c1f), QTC(0x641f1982), QTC(0x643924a2), + QTC(0x64532d80), QTC(0x646d341f), QTC(0x6487387e), QTC(0x64a13a9e), + QTC(0x64bb3a81), QTC(0x64d53828), QTC(0x64ef3393), QTC(0x65092cc4), + QTC(0x652323bb), QTC(0x653d1879), QTC(0x65570b00), QTC(0x6570fb50), + QTC(0x658ae96b), QTC(0x65a4d550), QTC(0x65bebf01), QTC(0x65d8a680), + QTC(0x65f28bcc), QTC(0x660c6ee8), QTC(0x66264fd3), QTC(0x66402e8f), + QTC(0x665a0b1c), QTC(0x6673e57d), QTC(0x668dbdb0), QTC(0x66a793b8), + QTC(0x66c16795), QTC(0x66db3949), QTC(0x66f508d4), QTC(0x670ed636), + QTC(0x6728a172), QTC(0x67426a87), QTC(0x675c3177), QTC(0x6775f643), + QTC(0x678fb8eb), QTC(0x67a97971), QTC(0x67c337d5), QTC(0x67dcf418), + QTC(0x67f6ae3b), QTC(0x6810663f), QTC(0x682a1c25), QTC(0x6843cfed), + QTC(0x685d8199), QTC(0x68773129), QTC(0x6890de9f), QTC(0x68aa89fa), + QTC(0x68c4333d), QTC(0x68ddda67), QTC(0x68f77f7a), QTC(0x69112277), + QTC(0x692ac35e), QTC(0x69446230), QTC(0x695dfeee), QTC(0x6977999a), + QTC(0x69913232), QTC(0x69aac8ba), QTC(0x69c45d31), QTC(0x69ddef98), + QTC(0x69f77ff0), QTC(0x6a110e3a), QTC(0x6a2a9a77), QTC(0x6a4424a8), + QTC(0x6a5daccc), QTC(0x6a7732e6), QTC(0x6a90b6f6), QTC(0x6aaa38fd), + QTC(0x6ac3b8fb), QTC(0x6add36f2), QTC(0x6af6b2e2), QTC(0x6b102ccd), + QTC(0x6b29a4b2), QTC(0x6b431a92), QTC(0x6b5c8e6f), QTC(0x6b76004a), + QTC(0x6b8f7022), QTC(0x6ba8ddf9), QTC(0x6bc249d0), QTC(0x6bdbb3a7), + QTC(0x6bf51b80), QTC(0x6c0e815a), QTC(0x6c27e537), QTC(0x6c414718), + QTC(0x6c5aa6fd), QTC(0x6c7404e7), QTC(0x6c8d60d7), QTC(0x6ca6bace), + QTC(0x6cc012cc), QTC(0x6cd968d2), QTC(0x6cf2bce1), QTC(0x6d0c0ef9), + QTC(0x6d255f1d), QTC(0x6d3ead4b), QTC(0x6d57f985), QTC(0x6d7143cc), + QTC(0x6d8a8c21), QTC(0x6da3d283), QTC(0x6dbd16f5), QTC(0x6dd65976), + QTC(0x6def9a08), QTC(0x6e08d8ab), QTC(0x6e221560), QTC(0x6e3b5027), + QTC(0x6e548902), QTC(0x6e6dbff1), QTC(0x6e86f4f5), QTC(0x6ea0280e), + QTC(0x6eb9593e), QTC(0x6ed28885), QTC(0x6eebb5e3), QTC(0x6f04e15a), + QTC(0x6f1e0aea), QTC(0x6f373294), QTC(0x6f505859), QTC(0x6f697c39), + QTC(0x6f829e35), QTC(0x6f9bbe4e), QTC(0x6fb4dc85), QTC(0x6fcdf8d9), + QTC(0x6fe7134d), QTC(0x70002be0), QTC(0x70194293), QTC(0x70325767), + QTC(0x704b6a5d), QTC(0x70647b76), QTC(0x707d8ab1), QTC(0x70969811), + QTC(0x70afa394), QTC(0x70c8ad3d), QTC(0x70e1b50c), QTC(0x70fabb01), + QTC(0x7113bf1d), QTC(0x712cc161), QTC(0x7145c1ce), QTC(0x715ec064), + QTC(0x7177bd24), QTC(0x7190b80f), QTC(0x71a9b124), QTC(0x71c2a866), + QTC(0x71db9dd4), QTC(0x71f49170), QTC(0x720d8339), QTC(0x72267331), + QTC(0x723f6159), QTC(0x72584db0), QTC(0x72713838), QTC(0x728a20f1), + QTC(0x72a307db), QTC(0x72bbecf9), QTC(0x72d4d049), QTC(0x72edb1ce), + QTC(0x73069187), QTC(0x731f6f75), QTC(0x73384b98), QTC(0x735125f3), + QTC(0x7369fe84), QTC(0x7382d54d), QTC(0x739baa4e), QTC(0x73b47d89), + QTC(0x73cd4efd), QTC(0x73e61eab), QTC(0x73feec94), QTC(0x7417b8b8), + QTC(0x74308319), QTC(0x74494bb6), QTC(0x74621291), QTC(0x747ad7aa), + QTC(0x74939b02), QTC(0x74ac5c98), QTC(0x74c51c6f), QTC(0x74ddda86), + QTC(0x74f696de), QTC(0x750f5178), QTC(0x75280a54), QTC(0x7540c174), + QTC(0x755976d7), QTC(0x75722a7e), QTC(0x758adc69), QTC(0x75a38c9b), + QTC(0x75bc3b12), QTC(0x75d4e7cf), QTC(0x75ed92d4), QTC(0x76063c21), + QTC(0x761ee3b6), QTC(0x76378994), QTC(0x76502dbc), QTC(0x7668d02e), + QTC(0x768170eb), QTC(0x769a0ff3), QTC(0x76b2ad47), QTC(0x76cb48e7), + QTC(0x76e3e2d5), QTC(0x76fc7b10), QTC(0x7715119a), QTC(0x772da673), + QTC(0x7746399b), QTC(0x775ecb13), QTC(0x77775adc), QTC(0x778fe8f6), + QTC(0x77a87561), QTC(0x77c1001f), QTC(0x77d98930), QTC(0x77f21095), + QTC(0x780a964d), QTC(0x78231a5b), QTC(0x783b9cbd), QTC(0x78541d75), + QTC(0x786c9c84), QTC(0x788519e9), QTC(0x789d95a6), QTC(0x78b60fbb), + QTC(0x78ce8828), QTC(0x78e6feef), QTC(0x78ff740f), QTC(0x7917e78a), + QTC(0x7930595f), QTC(0x7948c990), QTC(0x7961381d), QTC(0x7979a506), + QTC(0x7992104c), QTC(0x79aa79f0), QTC(0x79c2e1f1), QTC(0x79db4852), + QTC(0x79f3ad11), QTC(0x7a0c1031), QTC(0x7a2471b0), QTC(0x7a3cd191), + QTC(0x7a552fd3), QTC(0x7a6d8c76), QTC(0x7a85e77d), QTC(0x7a9e40e6), + QTC(0x7ab698b2), QTC(0x7aceeee3), QTC(0x7ae74378), QTC(0x7aff9673), + QTC(0x7b17e7d2), QTC(0x7b303799), QTC(0x7b4885c5), QTC(0x7b60d259), + QTC(0x7b791d55), QTC(0x7b9166b9), QTC(0x7ba9ae86), QTC(0x7bc1f4bc), + QTC(0x7bda395c), QTC(0x7bf27c66), QTC(0x7c0abddb), QTC(0x7c22fdbb), + QTC(0x7c3b3c07), QTC(0x7c5378c0), QTC(0x7c6bb3e5), QTC(0x7c83ed78), + QTC(0x7c9c2579), QTC(0x7cb45be9), QTC(0x7ccc90c7), QTC(0x7ce4c414), + QTC(0x7cfcf5d2), QTC(0x7d152600), QTC(0x7d2d549f), QTC(0x7d4581b0), + QTC(0x7d5dad32), QTC(0x7d75d727), QTC(0x7d8dff8f), QTC(0x7da6266a), + QTC(0x7dbe4bba), QTC(0x7dd66f7d), QTC(0x7dee91b6), QTC(0x7e06b264), + QTC(0x7e1ed188), QTC(0x7e36ef22), QTC(0x7e4f0b34), QTC(0x7e6725bd), + QTC(0x7e7f3ebd), QTC(0x7e975636), QTC(0x7eaf6c28), QTC(0x7ec78093), + QTC(0x7edf9378), QTC(0x7ef7a4d7), QTC(0x7f0fb4b1), QTC(0x7f27c307), + QTC(0x7f3fcfd8), QTC(0x7f57db25), QTC(0x7f6fe4ef), QTC(0x7f87ed36), + QTC(0x7f9ff3fb), QTC(0x7fb7f93e), QTC(0x7fcffcff), QTC(0x7fe7ff40)}; + +/* + table of pow(2.0,0.25*q)/2.0, q[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableQ[4] = {QTC(0x40000000), QTC(0x4c1bf7ff), + QTC(0x5a82797f), QTC(0x6ba27e7f)}; + +/* + table of pow(2.0,0.75*e)/8.0, e[0..4) +*/ +const FIXP_QTD FDKaacEnc_quantTableE[4] = {QTC(0x10000000), QTC(0x1ae89f99), + QTC(0x2d413ccd), QTC(0x4c1bf828)}; + +/* + table to count used number of bits +*/ +const SHORT FDKaacEnc_sideInfoTabLong[] = { + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x0009, 0x0009, 0x0009, 0x0009, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, + 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e, 0x000e}; + +const SHORT FDKaacEnc_sideInfoTabShort[] = { + 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x000a, + 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x000d, 0x000d}; + +/* + Psy Configuration constants +*/ + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024 = { + 40, {12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 80}}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024 = { + 43, {8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, 24, 28, + 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, + 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, 20, 20, 24, 24, + 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128 = { + 15, {4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 20}}; +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024 = { + 51, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024 = { + 49, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96}}; +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024 = { + 49, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 96}}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128 = { + 14, {4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 16}}; +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024 = { + 47, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, + 8, 8, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40}}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024 = { + 41, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024 = { + 41, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 8, 8, 8, 8, 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, + 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64}}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128 = { + 12, {4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 36}}; + +/* + TNS filter coefficients +*/ + +/* + 3 bit resolution +*/ +const FIXP_LPC FDKaacEnc_tnsEncCoeff3[8] = { + FX_DBL2FXCONST_LPC(0x81f1d201), FX_DBL2FXCONST_LPC(0x91261481), + FX_DBL2FXCONST_LPC(0xadb92301), FX_DBL2FXCONST_LPC(0xd438af00), + FX_DBL2FXCONST_LPC(0x00000000), FX_DBL2FXCONST_LPC(0x37898080), + FX_DBL2FXCONST_LPC(0x64130dff), FX_DBL2FXCONST_LPC(0x7cca6fff)}; +const FIXP_LPC FDKaacEnc_tnsCoeff3Borders[8] = { + FX_DBL2FXCONST_LPC(0x80000001) /*-4*/, + FX_DBL2FXCONST_LPC(0x87b826df) /*-3*/, + FX_DBL2FXCONST_LPC(0x9df24154) /*-2*/, + FX_DBL2FXCONST_LPC(0xbfffffe5) /*-1*/, + FX_DBL2FXCONST_LPC(0xe9c5e578) /* 0*/, + FX_DBL2FXCONST_LPC(0x1c7b90f0) /* 1*/, + FX_DBL2FXCONST_LPC(0x4fce83a9) /* 2*/, + FX_DBL2FXCONST_LPC(0x7352f2c3) /* 3*/ +}; + +/* + 4 bit resolution +*/ +const FIXP_LPC FDKaacEnc_tnsEncCoeff4[16] = { + FX_DBL2FXCONST_LPC(0x808bc881), FX_DBL2FXCONST_LPC(0x84e2e581), + FX_DBL2FXCONST_LPC(0x8d6b4a01), FX_DBL2FXCONST_LPC(0x99da9201), + FX_DBL2FXCONST_LPC(0xa9c45701), FX_DBL2FXCONST_LPC(0xbc9dde81), + FX_DBL2FXCONST_LPC(0xd1c2d500), FX_DBL2FXCONST_LPC(0xe87ae540), + FX_DBL2FXCONST_LPC(0x00000000), FX_DBL2FXCONST_LPC(0x1a9cd9c0), + FX_DBL2FXCONST_LPC(0x340ff240), FX_DBL2FXCONST_LPC(0x4b3c8bff), + FX_DBL2FXCONST_LPC(0x5f1f5e7f), FX_DBL2FXCONST_LPC(0x6ed9eb7f), + FX_DBL2FXCONST_LPC(0x79bc387f), FX_DBL2FXCONST_LPC(0x7f4c7e7f)}; +const FIXP_LPC FDKaacEnc_tnsCoeff4Borders[16] = { + FX_DBL2FXCONST_LPC(0x80000001) /*-8*/, + FX_DBL2FXCONST_LPC(0x822deff0) /*-7*/, + FX_DBL2FXCONST_LPC(0x88a4bfe6) /*-6*/, + FX_DBL2FXCONST_LPC(0x932c159d) /*-5*/, + FX_DBL2FXCONST_LPC(0xa16827c2) /*-4*/, + FX_DBL2FXCONST_LPC(0xb2dcde27) /*-3*/, + FX_DBL2FXCONST_LPC(0xc6f20b91) /*-2*/, + FX_DBL2FXCONST_LPC(0xdcf89c64) /*-1*/, + FX_DBL2FXCONST_LPC(0xf4308ce1) /* 0*/, + FX_DBL2FXCONST_LPC(0x0d613054) /* 1*/, + FX_DBL2FXCONST_LPC(0x278dde80) /* 2*/, + FX_DBL2FXCONST_LPC(0x4000001b) /* 3*/, + FX_DBL2FXCONST_LPC(0x55a6127b) /* 4*/, + FX_DBL2FXCONST_LPC(0x678dde8f) /* 5*/, + FX_DBL2FXCONST_LPC(0x74ef0ed7) /* 6*/, + FX_DBL2FXCONST_LPC(0x7d33f0da) /* 7*/ +}; +const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512] = { + FL2FXCONST_DBL(0.3968502629920499), FL2FXCONST_DBL(0.3978840634868335), + FL2FXCONST_DBL(0.3989185359354711), FL2FXCONST_DBL(0.3999536794661432), + FL2FXCONST_DBL(0.4009894932098531), FL2FXCONST_DBL(0.4020259763004115), + FL2FXCONST_DBL(0.4030631278744227), FL2FXCONST_DBL(0.4041009470712695), + FL2FXCONST_DBL(0.4051394330330996), FL2FXCONST_DBL(0.4061785849048110), + FL2FXCONST_DBL(0.4072184018340380), FL2FXCONST_DBL(0.4082588829711372), + FL2FXCONST_DBL(0.4093000274691739), FL2FXCONST_DBL(0.4103418344839078), + FL2FXCONST_DBL(0.4113843031737798), FL2FXCONST_DBL(0.4124274326998980), + FL2FXCONST_DBL(0.4134712222260245), FL2FXCONST_DBL(0.4145156709185620), + FL2FXCONST_DBL(0.4155607779465400), FL2FXCONST_DBL(0.4166065424816022), + FL2FXCONST_DBL(0.4176529636979932), FL2FXCONST_DBL(0.4187000407725452), + FL2FXCONST_DBL(0.4197477728846652), FL2FXCONST_DBL(0.4207961592163222), + FL2FXCONST_DBL(0.4218451989520345), FL2FXCONST_DBL(0.4228948912788567), + FL2FXCONST_DBL(0.4239452353863673), FL2FXCONST_DBL(0.4249962304666564), + FL2FXCONST_DBL(0.4260478757143130), FL2FXCONST_DBL(0.4271001703264124), + FL2FXCONST_DBL(0.4281531135025046), FL2FXCONST_DBL(0.4292067044446017), + FL2FXCONST_DBL(0.4302609423571658), FL2FXCONST_DBL(0.4313158264470970), + FL2FXCONST_DBL(0.4323713559237216), FL2FXCONST_DBL(0.4334275299987803), + FL2FXCONST_DBL(0.4344843478864161), FL2FXCONST_DBL(0.4355418088031630), + FL2FXCONST_DBL(0.4365999119679339), FL2FXCONST_DBL(0.4376586566020096), + FL2FXCONST_DBL(0.4387180419290272), FL2FXCONST_DBL(0.4397780671749683), + FL2FXCONST_DBL(0.4408387315681480), FL2FXCONST_DBL(0.4419000343392039), + FL2FXCONST_DBL(0.4429619747210847), FL2FXCONST_DBL(0.4440245519490388), + FL2FXCONST_DBL(0.4450877652606038), FL2FXCONST_DBL(0.4461516138955953), + FL2FXCONST_DBL(0.4472160970960963), FL2FXCONST_DBL(0.4482812141064458), + FL2FXCONST_DBL(0.4493469641732286), FL2FXCONST_DBL(0.4504133465452648), + FL2FXCONST_DBL(0.4514803604735984), FL2FXCONST_DBL(0.4525480052114875), + FL2FXCONST_DBL(0.4536162800143939), FL2FXCONST_DBL(0.4546851841399719), + FL2FXCONST_DBL(0.4557547168480591), FL2FXCONST_DBL(0.4568248774006652), + FL2FXCONST_DBL(0.4578956650619623), FL2FXCONST_DBL(0.4589670790982746), + FL2FXCONST_DBL(0.4600391187780688), FL2FXCONST_DBL(0.4611117833719430), + FL2FXCONST_DBL(0.4621850721526184), FL2FXCONST_DBL(0.4632589843949278), + FL2FXCONST_DBL(0.4643335193758069), FL2FXCONST_DBL(0.4654086763742842), + FL2FXCONST_DBL(0.4664844546714713), FL2FXCONST_DBL(0.4675608535505532), + FL2FXCONST_DBL(0.4686378722967790), FL2FXCONST_DBL(0.4697155101974522), + FL2FXCONST_DBL(0.4707937665419216), FL2FXCONST_DBL(0.4718726406215713), + FL2FXCONST_DBL(0.4729521317298118), FL2FXCONST_DBL(0.4740322391620711), + FL2FXCONST_DBL(0.4751129622157845), FL2FXCONST_DBL(0.4761943001903867), + FL2FXCONST_DBL(0.4772762523873015), FL2FXCONST_DBL(0.4783588181099338), + FL2FXCONST_DBL(0.4794419966636599), FL2FXCONST_DBL(0.4805257873558190), + FL2FXCONST_DBL(0.4816101894957042), FL2FXCONST_DBL(0.4826952023945537), + FL2FXCONST_DBL(0.4837808253655421), FL2FXCONST_DBL(0.4848670577237714), + FL2FXCONST_DBL(0.4859538987862632), FL2FXCONST_DBL(0.4870413478719488), + FL2FXCONST_DBL(0.4881294043016621), FL2FXCONST_DBL(0.4892180673981298), + FL2FXCONST_DBL(0.4903073364859640), FL2FXCONST_DBL(0.4913972108916533), + FL2FXCONST_DBL(0.4924876899435545), FL2FXCONST_DBL(0.4935787729718844), + FL2FXCONST_DBL(0.4946704593087116), FL2FXCONST_DBL(0.4957627482879484), + FL2FXCONST_DBL(0.4968556392453423), FL2FXCONST_DBL(0.4979491315184684), + FL2FXCONST_DBL(0.4990432244467211), FL2FXCONST_DBL(0.5001379173713062), + FL2FXCONST_DBL(0.5012332096352328), FL2FXCONST_DBL(0.5023291005833056), + FL2FXCONST_DBL(0.5034255895621171), FL2FXCONST_DBL(0.5045226759200399), + FL2FXCONST_DBL(0.5056203590072181), FL2FXCONST_DBL(0.5067186381755611), + FL2FXCONST_DBL(0.5078175127787346), FL2FXCONST_DBL(0.5089169821721536), + FL2FXCONST_DBL(0.5100170457129749), FL2FXCONST_DBL(0.5111177027600893), + FL2FXCONST_DBL(0.5122189526741143), FL2FXCONST_DBL(0.5133207948173868), + FL2FXCONST_DBL(0.5144232285539552), FL2FXCONST_DBL(0.5155262532495726), + FL2FXCONST_DBL(0.5166298682716894), FL2FXCONST_DBL(0.5177340729894460), + FL2FXCONST_DBL(0.5188388667736652), FL2FXCONST_DBL(0.5199442489968457), + FL2FXCONST_DBL(0.5210502190331544), FL2FXCONST_DBL(0.5221567762584198), + FL2FXCONST_DBL(0.5232639200501247), FL2FXCONST_DBL(0.5243716497873989), + FL2FXCONST_DBL(0.5254799648510130), FL2FXCONST_DBL(0.5265888646233705), + FL2FXCONST_DBL(0.5276983484885021), FL2FXCONST_DBL(0.5288084158320574), + FL2FXCONST_DBL(0.5299190660412995), FL2FXCONST_DBL(0.5310302985050975), + FL2FXCONST_DBL(0.5321421126139198), FL2FXCONST_DBL(0.5332545077598274), + FL2FXCONST_DBL(0.5343674833364678), FL2FXCONST_DBL(0.5354810387390675), + FL2FXCONST_DBL(0.5365951733644262), FL2FXCONST_DBL(0.5377098866109097), + FL2FXCONST_DBL(0.5388251778784438), FL2FXCONST_DBL(0.5399410465685075), + FL2FXCONST_DBL(0.5410574920841272), FL2FXCONST_DBL(0.5421745138298695), + FL2FXCONST_DBL(0.5432921112118353), FL2FXCONST_DBL(0.5444102836376534), + FL2FXCONST_DBL(0.5455290305164744), FL2FXCONST_DBL(0.5466483512589642), + FL2FXCONST_DBL(0.5477682452772976), FL2FXCONST_DBL(0.5488887119851529), + FL2FXCONST_DBL(0.5500097507977050), FL2FXCONST_DBL(0.5511313611316194), + FL2FXCONST_DBL(0.5522535424050467), FL2FXCONST_DBL(0.5533762940376158), + FL2FXCONST_DBL(0.5544996154504284), FL2FXCONST_DBL(0.5556235060660528), + FL2FXCONST_DBL(0.5567479653085183), FL2FXCONST_DBL(0.5578729926033087), + FL2FXCONST_DBL(0.5589985873773569), FL2FXCONST_DBL(0.5601247490590389), + FL2FXCONST_DBL(0.5612514770781683), FL2FXCONST_DBL(0.5623787708659898), + FL2FXCONST_DBL(0.5635066298551742), FL2FXCONST_DBL(0.5646350534798125), + FL2FXCONST_DBL(0.5657640411754097), FL2FXCONST_DBL(0.5668935923788799), + FL2FXCONST_DBL(0.5680237065285404), FL2FXCONST_DBL(0.5691543830641059), + FL2FXCONST_DBL(0.5702856214266832), FL2FXCONST_DBL(0.5714174210587655), + FL2FXCONST_DBL(0.5725497814042271), FL2FXCONST_DBL(0.5736827019083177), + FL2FXCONST_DBL(0.5748161820176573), FL2FXCONST_DBL(0.5759502211802304), + FL2FXCONST_DBL(0.5770848188453810), FL2FXCONST_DBL(0.5782199744638067), + FL2FXCONST_DBL(0.5793556874875542), FL2FXCONST_DBL(0.5804919573700131), + FL2FXCONST_DBL(0.5816287835659116), FL2FXCONST_DBL(0.5827661655313104), + FL2FXCONST_DBL(0.5839041027235979), FL2FXCONST_DBL(0.5850425946014850), + FL2FXCONST_DBL(0.5861816406250000), FL2FXCONST_DBL(0.5873212402554834), + FL2FXCONST_DBL(0.5884613929555826), FL2FXCONST_DBL(0.5896020981892474), + FL2FXCONST_DBL(0.5907433554217242), FL2FXCONST_DBL(0.5918851641195517), + FL2FXCONST_DBL(0.5930275237505556), FL2FXCONST_DBL(0.5941704337838434), + FL2FXCONST_DBL(0.5953138936897999), FL2FXCONST_DBL(0.5964579029400819), + FL2FXCONST_DBL(0.5976024610076139), FL2FXCONST_DBL(0.5987475673665825), + FL2FXCONST_DBL(0.5998932214924321), FL2FXCONST_DBL(0.6010394228618597), + FL2FXCONST_DBL(0.6021861709528106), FL2FXCONST_DBL(0.6033334652444733), + FL2FXCONST_DBL(0.6044813052172748), FL2FXCONST_DBL(0.6056296903528761), + FL2FXCONST_DBL(0.6067786201341671), FL2FXCONST_DBL(0.6079280940452625), + FL2FXCONST_DBL(0.6090781115714966), FL2FXCONST_DBL(0.6102286721994192), + FL2FXCONST_DBL(0.6113797754167908), FL2FXCONST_DBL(0.6125314207125777), + FL2FXCONST_DBL(0.6136836075769482), FL2FXCONST_DBL(0.6148363355012674), + FL2FXCONST_DBL(0.6159896039780929), FL2FXCONST_DBL(0.6171434125011708), + FL2FXCONST_DBL(0.6182977605654305), FL2FXCONST_DBL(0.6194526476669808), + FL2FXCONST_DBL(0.6206080733031054), FL2FXCONST_DBL(0.6217640369722584), + FL2FXCONST_DBL(0.6229205381740598), FL2FXCONST_DBL(0.6240775764092919), + FL2FXCONST_DBL(0.6252351511798939), FL2FXCONST_DBL(0.6263932619889586), + FL2FXCONST_DBL(0.6275519083407275), FL2FXCONST_DBL(0.6287110897405869), + FL2FXCONST_DBL(0.6298708056950635), FL2FXCONST_DBL(0.6310310557118203), + FL2FXCONST_DBL(0.6321918392996523), FL2FXCONST_DBL(0.6333531559684823), + FL2FXCONST_DBL(0.6345150052293571), FL2FXCONST_DBL(0.6356773865944432), + FL2FXCONST_DBL(0.6368402995770224), FL2FXCONST_DBL(0.6380037436914881), + FL2FXCONST_DBL(0.6391677184533411), FL2FXCONST_DBL(0.6403322233791856), + FL2FXCONST_DBL(0.6414972579867254), FL2FXCONST_DBL(0.6426628217947594), + FL2FXCONST_DBL(0.6438289143231779), FL2FXCONST_DBL(0.6449955350929588), + FL2FXCONST_DBL(0.6461626836261636), FL2FXCONST_DBL(0.6473303594459330), + FL2FXCONST_DBL(0.6484985620764839), FL2FXCONST_DBL(0.6496672910431047), + FL2FXCONST_DBL(0.6508365458721518), FL2FXCONST_DBL(0.6520063260910459), + FL2FXCONST_DBL(0.6531766312282679), FL2FXCONST_DBL(0.6543474608133552), + FL2FXCONST_DBL(0.6555188143768979), FL2FXCONST_DBL(0.6566906914505349), + FL2FXCONST_DBL(0.6578630915669509), FL2FXCONST_DBL(0.6590360142598715), + FL2FXCONST_DBL(0.6602094590640603), FL2FXCONST_DBL(0.6613834255153149), + FL2FXCONST_DBL(0.6625579131504635), FL2FXCONST_DBL(0.6637329215073610), + FL2FXCONST_DBL(0.6649084501248851), FL2FXCONST_DBL(0.6660844985429335), + FL2FXCONST_DBL(0.6672610663024197), FL2FXCONST_DBL(0.6684381529452691), + FL2FXCONST_DBL(0.6696157580144163), FL2FXCONST_DBL(0.6707938810538011), + FL2FXCONST_DBL(0.6719725216083646), FL2FXCONST_DBL(0.6731516792240465), + FL2FXCONST_DBL(0.6743313534477807), FL2FXCONST_DBL(0.6755115438274927), + FL2FXCONST_DBL(0.6766922499120955), FL2FXCONST_DBL(0.6778734712514865), + FL2FXCONST_DBL(0.6790552073965435), FL2FXCONST_DBL(0.6802374578991223), + FL2FXCONST_DBL(0.6814202223120524), FL2FXCONST_DBL(0.6826035001891340), + FL2FXCONST_DBL(0.6837872910851345), FL2FXCONST_DBL(0.6849715945557853), + FL2FXCONST_DBL(0.6861564101577784), FL2FXCONST_DBL(0.6873417374487629), + FL2FXCONST_DBL(0.6885275759873420), FL2FXCONST_DBL(0.6897139253330697), + FL2FXCONST_DBL(0.6909007850464473), FL2FXCONST_DBL(0.6920881546889198), + FL2FXCONST_DBL(0.6932760338228737), FL2FXCONST_DBL(0.6944644220116332), + FL2FXCONST_DBL(0.6956533188194565), FL2FXCONST_DBL(0.6968427238115332), + FL2FXCONST_DBL(0.6980326365539813), FL2FXCONST_DBL(0.6992230566138435), + FL2FXCONST_DBL(0.7004139835590845), FL2FXCONST_DBL(0.7016054169585869), + FL2FXCONST_DBL(0.7027973563821499), FL2FXCONST_DBL(0.7039898014004843), + FL2FXCONST_DBL(0.7051827515852106), FL2FXCONST_DBL(0.7063762065088554), + FL2FXCONST_DBL(0.7075701657448483), FL2FXCONST_DBL(0.7087646288675196), + FL2FXCONST_DBL(0.7099595954520960), FL2FXCONST_DBL(0.7111550650746988), + FL2FXCONST_DBL(0.7123510373123402), FL2FXCONST_DBL(0.7135475117429202), + FL2FXCONST_DBL(0.7147444879452244), FL2FXCONST_DBL(0.7159419654989200), + FL2FXCONST_DBL(0.7171399439845538), FL2FXCONST_DBL(0.7183384229835486), + FL2FXCONST_DBL(0.7195374020782005), FL2FXCONST_DBL(0.7207368808516762), + FL2FXCONST_DBL(0.7219368588880097), FL2FXCONST_DBL(0.7231373357720997), + FL2FXCONST_DBL(0.7243383110897066), FL2FXCONST_DBL(0.7255397844274496), + FL2FXCONST_DBL(0.7267417553728043), FL2FXCONST_DBL(0.7279442235140992), + FL2FXCONST_DBL(0.7291471884405130), FL2FXCONST_DBL(0.7303506497420724), + FL2FXCONST_DBL(0.7315546070096487), FL2FXCONST_DBL(0.7327590598349553), + FL2FXCONST_DBL(0.7339640078105445), FL2FXCONST_DBL(0.7351694505298055), + FL2FXCONST_DBL(0.7363753875869610), FL2FXCONST_DBL(0.7375818185770647), + FL2FXCONST_DBL(0.7387887430959987), FL2FXCONST_DBL(0.7399961607404706), + FL2FXCONST_DBL(0.7412040711080108), FL2FXCONST_DBL(0.7424124737969701), + FL2FXCONST_DBL(0.7436213684065166), FL2FXCONST_DBL(0.7448307545366334), + FL2FXCONST_DBL(0.7460406317881158), FL2FXCONST_DBL(0.7472509997625686), + FL2FXCONST_DBL(0.7484618580624036), FL2FXCONST_DBL(0.7496732062908372), + FL2FXCONST_DBL(0.7508850440518872), FL2FXCONST_DBL(0.7520973709503704), + FL2FXCONST_DBL(0.7533101865919009), FL2FXCONST_DBL(0.7545234905828862), + FL2FXCONST_DBL(0.7557372825305252), FL2FXCONST_DBL(0.7569515620428062), + FL2FXCONST_DBL(0.7581663287285035), FL2FXCONST_DBL(0.7593815821971756), + FL2FXCONST_DBL(0.7605973220591619), FL2FXCONST_DBL(0.7618135479255810), + FL2FXCONST_DBL(0.7630302594083277), FL2FXCONST_DBL(0.7642474561200708), + FL2FXCONST_DBL(0.7654651376742505), FL2FXCONST_DBL(0.7666833036850760), + FL2FXCONST_DBL(0.7679019537675227), FL2FXCONST_DBL(0.7691210875373307), + FL2FXCONST_DBL(0.7703407046110011), FL2FXCONST_DBL(0.7715608046057948), + FL2FXCONST_DBL(0.7727813871397293), FL2FXCONST_DBL(0.7740024518315765), + FL2FXCONST_DBL(0.7752239983008605), FL2FXCONST_DBL(0.7764460261678551), + FL2FXCONST_DBL(0.7776685350535814), FL2FXCONST_DBL(0.7788915245798054), + FL2FXCONST_DBL(0.7801149943690360), FL2FXCONST_DBL(0.7813389440445223), + FL2FXCONST_DBL(0.7825633732302513), FL2FXCONST_DBL(0.7837882815509458), + FL2FXCONST_DBL(0.7850136686320621), FL2FXCONST_DBL(0.7862395340997874), + FL2FXCONST_DBL(0.7874658775810378), FL2FXCONST_DBL(0.7886926987034559), + FL2FXCONST_DBL(0.7899199970954088), FL2FXCONST_DBL(0.7911477723859853), + FL2FXCONST_DBL(0.7923760242049944), FL2FXCONST_DBL(0.7936047521829623), + FL2FXCONST_DBL(0.7948339559511308), FL2FXCONST_DBL(0.7960636351414546), + FL2FXCONST_DBL(0.7972937893865995), FL2FXCONST_DBL(0.7985244183199399), + FL2FXCONST_DBL(0.7997555215755570), FL2FXCONST_DBL(0.8009870987882359), + FL2FXCONST_DBL(0.8022191495934644), FL2FXCONST_DBL(0.8034516736274301), + FL2FXCONST_DBL(0.8046846705270185), FL2FXCONST_DBL(0.8059181399298110), + FL2FXCONST_DBL(0.8071520814740822), FL2FXCONST_DBL(0.8083864947987989), + FL2FXCONST_DBL(0.8096213795436166), FL2FXCONST_DBL(0.8108567353488784), + FL2FXCONST_DBL(0.8120925618556127), FL2FXCONST_DBL(0.8133288587055308), + FL2FXCONST_DBL(0.8145656255410253), FL2FXCONST_DBL(0.8158028620051674), + FL2FXCONST_DBL(0.8170405677417053), FL2FXCONST_DBL(0.8182787423950622), + FL2FXCONST_DBL(0.8195173856103341), FL2FXCONST_DBL(0.8207564970332875), + FL2FXCONST_DBL(0.8219960763103580), FL2FXCONST_DBL(0.8232361230886477), + FL2FXCONST_DBL(0.8244766370159234), FL2FXCONST_DBL(0.8257176177406150), + FL2FXCONST_DBL(0.8269590649118125), FL2FXCONST_DBL(0.8282009781792650), + FL2FXCONST_DBL(0.8294433571933784), FL2FXCONST_DBL(0.8306862016052132), + FL2FXCONST_DBL(0.8319295110664831), FL2FXCONST_DBL(0.8331732852295520), + FL2FXCONST_DBL(0.8344175237474336), FL2FXCONST_DBL(0.8356622262737878), + FL2FXCONST_DBL(0.8369073924629202), FL2FXCONST_DBL(0.8381530219697793), + FL2FXCONST_DBL(0.8393991144499545), FL2FXCONST_DBL(0.8406456695596752), + FL2FXCONST_DBL(0.8418926869558079), FL2FXCONST_DBL(0.8431401662958544), + FL2FXCONST_DBL(0.8443881072379507), FL2FXCONST_DBL(0.8456365094408642), + FL2FXCONST_DBL(0.8468853725639923), FL2FXCONST_DBL(0.8481346962673606), + FL2FXCONST_DBL(0.8493844802116208), FL2FXCONST_DBL(0.8506347240580492), + FL2FXCONST_DBL(0.8518854274685442), FL2FXCONST_DBL(0.8531365901056253), + FL2FXCONST_DBL(0.8543882116324307), FL2FXCONST_DBL(0.8556402917127157), + FL2FXCONST_DBL(0.8568928300108512), FL2FXCONST_DBL(0.8581458261918209), + FL2FXCONST_DBL(0.8593992799212207), FL2FXCONST_DBL(0.8606531908652563), + FL2FXCONST_DBL(0.8619075586907414), FL2FXCONST_DBL(0.8631623830650962), + FL2FXCONST_DBL(0.8644176636563452), FL2FXCONST_DBL(0.8656734001331161), + FL2FXCONST_DBL(0.8669295921646375), FL2FXCONST_DBL(0.8681862394207371), + FL2FXCONST_DBL(0.8694433415718407), FL2FXCONST_DBL(0.8707008982889695), + FL2FXCONST_DBL(0.8719589092437391), FL2FXCONST_DBL(0.8732173741083574), + FL2FXCONST_DBL(0.8744762925556232), FL2FXCONST_DBL(0.8757356642589241), + FL2FXCONST_DBL(0.8769954888922352), FL2FXCONST_DBL(0.8782557661301171), + FL2FXCONST_DBL(0.8795164956477146), FL2FXCONST_DBL(0.8807776771207545), + FL2FXCONST_DBL(0.8820393102255443), FL2FXCONST_DBL(0.8833013946389704), + FL2FXCONST_DBL(0.8845639300384969), FL2FXCONST_DBL(0.8858269161021629), + FL2FXCONST_DBL(0.8870903525085819), FL2FXCONST_DBL(0.8883542389369399), + FL2FXCONST_DBL(0.8896185750669933), FL2FXCONST_DBL(0.8908833605790678), + FL2FXCONST_DBL(0.8921485951540565), FL2FXCONST_DBL(0.8934142784734187), + FL2FXCONST_DBL(0.8946804102191776), FL2FXCONST_DBL(0.8959469900739191), + FL2FXCONST_DBL(0.8972140177207906), FL2FXCONST_DBL(0.8984814928434985), + FL2FXCONST_DBL(0.8997494151263077), FL2FXCONST_DBL(0.9010177842540390), + FL2FXCONST_DBL(0.9022865999120682), FL2FXCONST_DBL(0.9035558617863242), + FL2FXCONST_DBL(0.9048255695632878), FL2FXCONST_DBL(0.9060957229299895), + FL2FXCONST_DBL(0.9073663215740092), FL2FXCONST_DBL(0.9086373651834729), + FL2FXCONST_DBL(0.9099088534470528), FL2FXCONST_DBL(0.9111807860539647), + FL2FXCONST_DBL(0.9124531626939672), FL2FXCONST_DBL(0.9137259830573594), + FL2FXCONST_DBL(0.9149992468349805), FL2FXCONST_DBL(0.9162729537182071), + FL2FXCONST_DBL(0.9175471033989524), FL2FXCONST_DBL(0.9188216955696648), + FL2FXCONST_DBL(0.9200967299233258), FL2FXCONST_DBL(0.9213722061534494), + FL2FXCONST_DBL(0.9226481239540795), FL2FXCONST_DBL(0.9239244830197896), + FL2FXCONST_DBL(0.9252012830456805), FL2FXCONST_DBL(0.9264785237273793), + FL2FXCONST_DBL(0.9277562047610376), FL2FXCONST_DBL(0.9290343258433305), + FL2FXCONST_DBL(0.9303128866714547), FL2FXCONST_DBL(0.9315918869431275), + FL2FXCONST_DBL(0.9328713263565848), FL2FXCONST_DBL(0.9341512046105802), + FL2FXCONST_DBL(0.9354315214043836), FL2FXCONST_DBL(0.9367122764377792), + FL2FXCONST_DBL(0.9379934694110648), FL2FXCONST_DBL(0.9392751000250497), + FL2FXCONST_DBL(0.9405571679810542), FL2FXCONST_DBL(0.9418396729809072), + FL2FXCONST_DBL(0.9431226147269456), FL2FXCONST_DBL(0.9444059929220124), + FL2FXCONST_DBL(0.9456898072694558), FL2FXCONST_DBL(0.9469740574731275), + FL2FXCONST_DBL(0.9482587432373810), FL2FXCONST_DBL(0.9495438642670713), + FL2FXCONST_DBL(0.9508294202675522), FL2FXCONST_DBL(0.9521154109446763), + FL2FXCONST_DBL(0.9534018360047926), FL2FXCONST_DBL(0.9546886951547455), + FL2FXCONST_DBL(0.9559759881018738), FL2FXCONST_DBL(0.9572637145540087), + FL2FXCONST_DBL(0.9585518742194732), FL2FXCONST_DBL(0.9598404668070802), + FL2FXCONST_DBL(0.9611294920261317), FL2FXCONST_DBL(0.9624189495864168), + FL2FXCONST_DBL(0.9637088391982110), FL2FXCONST_DBL(0.9649991605722750), + FL2FXCONST_DBL(0.9662899134198524), FL2FXCONST_DBL(0.9675810974526697), + FL2FXCONST_DBL(0.9688727123829343), FL2FXCONST_DBL(0.9701647579233330), + FL2FXCONST_DBL(0.9714572337870316), FL2FXCONST_DBL(0.9727501396876727), + FL2FXCONST_DBL(0.9740434753393749), FL2FXCONST_DBL(0.9753372404567313), + FL2FXCONST_DBL(0.9766314347548087), FL2FXCONST_DBL(0.9779260579491460), + FL2FXCONST_DBL(0.9792211097557527), FL2FXCONST_DBL(0.9805165898911081), + FL2FXCONST_DBL(0.9818124980721600), FL2FXCONST_DBL(0.9831088340163232), + FL2FXCONST_DBL(0.9844055974414786), FL2FXCONST_DBL(0.9857027880659716), + FL2FXCONST_DBL(0.9870004056086111), FL2FXCONST_DBL(0.9882984497886684), + FL2FXCONST_DBL(0.9895969203258759), FL2FXCONST_DBL(0.9908958169404255), + FL2FXCONST_DBL(0.9921951393529680), FL2FXCONST_DBL(0.9934948872846116), + FL2FXCONST_DBL(0.9947950604569206), FL2FXCONST_DBL(0.9960956585919144), + FL2FXCONST_DBL(0.9973966814120665), FL2FXCONST_DBL(0.9986981286403025)}; + +const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14] = { + {FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), + FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), + FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), + FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366), + FL2FXCONST_DBL(0.7937005259840998), FL2FXCONST_DBL(0.5000000000000000), + FL2FXCONST_DBL(0.6299605249474366), FL2FXCONST_DBL(0.7937005259840998), + FL2FXCONST_DBL(0.5000000000000000), FL2FXCONST_DBL(0.6299605249474366)}, + + {FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), + FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), + FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), + FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408), + FL2FXCONST_DBL(0.9438743126816935), FL2FXCONST_DBL(0.5946035575013605), + FL2FXCONST_DBL(0.7491535384383408), FL2FXCONST_DBL(0.9438743126816935), + FL2FXCONST_DBL(0.5946035575013605), FL2FXCONST_DBL(0.7491535384383408)}, + + {FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), + FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), + FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), + FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393), + FL2FXCONST_DBL(0.5612310241546865), FL2FXCONST_DBL(0.7071067811865476), + FL2FXCONST_DBL(0.8908987181403393), FL2FXCONST_DBL(0.5612310241546865), + FL2FXCONST_DBL(0.7071067811865476), FL2FXCONST_DBL(0.8908987181403393)}, + + {FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), + FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), + FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), + FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477), + FL2FXCONST_DBL(0.6674199270850172), FL2FXCONST_DBL(0.8408964152537145), + FL2FXCONST_DBL(0.5297315471796477), FL2FXCONST_DBL(0.6674199270850172), + FL2FXCONST_DBL(0.8408964152537145), FL2FXCONST_DBL(0.5297315471796477)}}; + +const UCHAR FDKaacEnc_specExpTableComb[4][14] = { + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 3, 5, 6, 7, 9, 10, 11, 13, 14, 15, 17, 18}, + {1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 16, 17, 18}, + {1, 3, 4, 5, 7, 8, 9, 11, 12, 13, 15, 16, 17, 19}}; + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +const FIXP_WTB ELDAnalysis512[1536] = { + /* part 0 */ + WTC0(0xfac5a770), WTC0(0xfaafbab8), WTC0(0xfa996a40), WTC0(0xfa82bbd0), + WTC0(0xfa6bb538), WTC0(0xfa545c38), WTC0(0xfa3cb698), WTC0(0xfa24ca28), + WTC0(0xfa0c9ca8), WTC0(0xf9f433e8), WTC0(0xf9db9580), WTC0(0xf9c2c298), + WTC0(0xf9a9b800), WTC0(0xf9907250), WTC0(0xf976ee38), WTC0(0xf95d2b88), + WTC0(0xf9432d10), WTC0(0xf928f5c0), WTC0(0xf90e8868), WTC0(0xf8f3e400), + WTC0(0xf8d903a0), WTC0(0xf8bde238), WTC0(0xf8a27af0), WTC0(0xf886cde8), + WTC0(0xf86ae020), WTC0(0xf84eb6c0), WTC0(0xf83256f8), WTC0(0xf815c4b8), + WTC0(0xf7f902c0), WTC0(0xf7dc13b0), WTC0(0xf7befa60), WTC0(0xf7a1ba40), + WTC0(0xf78457c0), WTC0(0xf766d780), WTC0(0xf7493d90), WTC0(0xf72b8990), + WTC0(0xf70db5f0), WTC0(0xf6efbd30), WTC0(0xf6d19a20), WTC0(0xf6b352e0), + WTC0(0xf694f8c0), WTC0(0xf6769da0), WTC0(0xf6585310), WTC0(0xf63a28d0), + WTC0(0xf61c2c60), WTC0(0xf5fe6b10), WTC0(0xf5e0f250), WTC0(0xf5c3ceb0), + WTC0(0xf5a70be0), WTC0(0xf58ab5a0), WTC0(0xf56ed7b0), WTC0(0xf5537e40), + WTC0(0xf538b610), WTC0(0xf51e8bf0), WTC0(0xf5050c90), WTC0(0xf4ec4330), + WTC0(0xf4d439b0), WTC0(0xf4bcf9b0), WTC0(0xf4a68ce0), WTC0(0xf490fa80), + WTC0(0xf47c4760), WTC0(0xf4687830), WTC0(0xf4558f00), WTC0(0xf4434fc0), + WTC0(0xf4314070), WTC0(0xf41ee450), WTC0(0xf40bc130), WTC0(0xf3f799c0), + WTC0(0xf3e26d30), WTC0(0xf3cc3d70), WTC0(0xf3b50c80), WTC0(0xf39cdd60), + WTC0(0xf383b440), WTC0(0xf3699550), WTC0(0xf34e84c0), WTC0(0xf33286b0), + WTC0(0xf3159f10), WTC0(0xf2f7d1b0), WTC0(0xf2d92290), WTC0(0xf2b994d0), + WTC0(0xf2992ad0), WTC0(0xf277e6d0), WTC0(0xf255cb60), WTC0(0xf232dd00), + WTC0(0xf20f2240), WTC0(0xf1eaa1d0), WTC0(0xf1c56240), WTC0(0xf19f63d0), + WTC0(0xf178a0f0), WTC0(0xf15113a0), WTC0(0xf128b5c0), WTC0(0xf0ff7fd0), + WTC0(0xf0d56860), WTC0(0xf0aa6610), WTC0(0xf07e6fd0), WTC0(0xf0518190), + WTC0(0xf0239cd0), WTC0(0xeff4c320), WTC0(0xefc4f720), WTC0(0xef945080), + WTC0(0xef62fce0), WTC0(0xef312a40), WTC0(0xeeff05c0), WTC0(0xeecca2c0), + WTC0(0xee99faa0), WTC0(0xee6705a0), WTC0(0xee33bb60), WTC0(0xee000060), + WTC0(0xedcba660), WTC0(0xed967e80), WTC0(0xed605b80), WTC0(0xed293b40), + WTC0(0xecf146a0), WTC0(0xecb8a8a0), WTC0(0xec7f8bc0), WTC0(0xec461260), + WTC0(0xec0c5720), WTC0(0xebd27440), WTC0(0xeb988220), WTC0(0xeb5e7040), + WTC0(0xeb2404c0), WTC0(0xeae90440), WTC0(0xeaad33c0), WTC0(0xea7066c0), + WTC0(0xea327f60), WTC0(0xe9f36000), WTC0(0xe9b2ed60), WTC0(0xe9713920), + WTC0(0xe92e81e0), WTC0(0xe8eb08c0), WTC0(0xe8a70e60), WTC0(0xe862d8e0), + WTC0(0xe81eb340), WTC0(0xe7dae8a0), WTC0(0xe797c1a0), WTC0(0xe7554ca0), + WTC0(0xe7135dc0), WTC0(0xe6d1c6a0), WTC0(0xe6905720), WTC0(0xe64eb9c0), + WTC0(0xe60c7300), WTC0(0xe5c90600), WTC0(0xe583f920), WTC0(0xe53d1ce0), + WTC0(0xe4f48c80), WTC0(0xe4aa6640), WTC0(0xe45ecaa0), WTC0(0xe4120be0), + WTC0(0xe3c4ae60), WTC0(0xe3773860), WTC0(0xe32a2ea0), WTC0(0xe2ddeea0), + WTC0(0xe292af00), WTC0(0xe248a4a0), WTC0(0xe2000140), WTC0(0xe1b8b640), + WTC0(0xe1727440), WTC0(0xe12ce900), WTC0(0xe0e7c280), WTC0(0xe0a2b420), + WTC0(0xe05d76c0), WTC0(0xe017c360), WTC0(0xdfd15440), WTC0(0xdf8a0540), + WTC0(0xdf41d300), WTC0(0xdef8bb40), WTC0(0xdeaebd40), WTC0(0xde63e7c0), + WTC0(0xde185940), WTC0(0xddcc3180), WTC0(0xdd7f9000), WTC0(0xdd329e80), + WTC0(0xdce58e80), WTC0(0xdc989300), WTC0(0xdc4bde40), WTC0(0xdbff96c0), + WTC0(0xdbb3d780), WTC0(0xdb68bb80), WTC0(0xdb1e5c80), WTC0(0xdad4c380), + WTC0(0xda8be840), WTC0(0xda43c1c0), WTC0(0xd9fc4740), WTC0(0xd9b56640), + WTC0(0xd96f0440), WTC0(0xd9290600), WTC0(0xd8e35080), WTC0(0xd89dcd40), + WTC0(0xd8586b40), WTC0(0xd8131940), WTC0(0xd7cdc640), WTC0(0xd7886180), + WTC0(0xd742dc80), WTC0(0xd6fd2780), WTC0(0xd6b73400), WTC0(0xd670fd80), + WTC0(0xd62a8a40), WTC0(0xd5e3e080), WTC0(0xd59d0840), WTC0(0xd5562b80), + WTC0(0xd50f9540), WTC0(0xd4c992c0), WTC0(0xd4846f80), WTC0(0xd4405a80), + WTC0(0xd3fd6580), WTC0(0xd3bba140), WTC0(0xd37b1c80), WTC0(0xd33bb780), + WTC0(0xd2fd2400), WTC0(0xd2bf1240), WTC0(0xd2813300), WTC0(0xd2435ac0), + WTC0(0xd2057fc0), WTC0(0xd1c79a00), WTC0(0xd189a240), WTC0(0xd14b9dc0), + WTC0(0xd10d9e00), WTC0(0xd0cfb580), WTC0(0xd091f6c0), WTC0(0xd0548100), + WTC0(0xd0177f40), WTC0(0xcfdb1cc0), WTC0(0xcf9f84c0), WTC0(0xcf64d780), + WTC0(0xcf2b2b00), WTC0(0xcef29440), WTC0(0xcebb2640), WTC0(0xce84c000), + WTC0(0xce4f0bc0), WTC0(0xce19b200), WTC0(0xcde45d40), WTC0(0xcdaeedc0), + WTC0(0xcd7979c0), WTC0(0xcd4419c0), WTC0(0xcd0ee6c0), WTC0(0xccda0540), + WTC0(0xcca5a500), WTC0(0xcc71f640), WTC0(0xcc3f2800), WTC0(0xcc0d4300), + WTC0(0xcbdc2a00), WTC0(0xcbabbe80), WTC0(0xcb7be200), WTC0(0xcb4c8200), + WTC0(0xcb1d9800), WTC0(0xcaef1d40), WTC0(0xcac10bc0), WTC0(0xca936440), + WTC0(0xca662d00), WTC0(0xca396d40), WTC0(0xca0d2b80), WTC0(0xc9e16f80), + WTC0(0xc9b63f80), WTC0(0xc98ba2c0), WTC0(0xc961a000), WTC0(0xc9383ec0), + WTC0(0xc90a0440), WTC0(0xc8e0d280), WTC0(0xc8b73b80), WTC0(0xc88d4900), + WTC0(0xc86304c0), WTC0(0xc83878c0), WTC0(0xc80dae80), WTC0(0xc7e2afc0), + WTC0(0xc7b78640), WTC0(0xc78c3c40), WTC0(0xc760da80), WTC0(0xc7356640), + WTC0(0xc709de40), WTC0(0xc6de41c0), WTC0(0xc6b28fc0), WTC0(0xc686bd40), + WTC0(0xc65ab600), WTC0(0xc62e6580), WTC0(0xc601b880), WTC0(0xc5d4bac0), + WTC0(0xc5a79640), WTC0(0xc57a76c0), WTC0(0xc54d8780), WTC0(0xc520e840), + WTC0(0xc4f4acc0), WTC0(0xc4c8e880), WTC0(0xc49dad80), WTC0(0xc472e640), + WTC0(0xc44856c0), WTC0(0xc41dc140), WTC0(0xc3f2e940), WTC0(0xc3c7bc00), + WTC0(0xc39c4f00), WTC0(0xc370b9c0), WTC0(0xc34513c0), WTC0(0xc3197940), + WTC0(0xc2ee0a00), WTC0(0xc2c2e640), WTC0(0xc2982d80), WTC0(0xc26df5c0), + WTC0(0xc2444b00), WTC0(0xc21b3940), WTC0(0xc1f2cbc0), WTC0(0xc1cb05c0), + WTC0(0xc1a3e340), WTC0(0xc17d5f00), WTC0(0xc15773c0), WTC0(0xc1320940), + WTC0(0xc10cf480), WTC0(0xc0e80a00), WTC0(0xc0c31f00), WTC0(0xc09e2640), + WTC0(0xc0792ec0), WTC0(0xc0544940), WTC0(0xc02f86c0), WTC0(0xc00b04c0), + WTC0(0xbfe6ed01), WTC0(0xbfc36a01), WTC0(0xbfa0a581), WTC0(0xbf7eb581), + WTC0(0xbf5d9a81), WTC0(0xbf3d5501), WTC0(0xbf1de601), WTC0(0xbeff4801), + WTC0(0xbee17201), WTC0(0xbec45881), WTC0(0xbea7f301), WTC0(0xbe8c3781), + WTC0(0xbe712001), WTC0(0xbe56a381), WTC0(0xbe3cbc01), WTC0(0xbe236001), + WTC0(0xbe0a8581), WTC0(0xbdf22181), WTC0(0xbdda2a01), WTC0(0xbdc29a81), + WTC0(0xbdab7181), WTC0(0xbd94b001), WTC0(0xbd7e5581), WTC0(0xbd686681), + WTC0(0xbd52eb01), WTC0(0xbd3deb81), WTC0(0xbd297181), WTC0(0xbd158801), + WTC0(0xbd023f01), WTC0(0xbcefa601), WTC0(0xbcddcc81), WTC0(0xbcccbd01), + WTC0(0xbcbc7e01), WTC0(0xbcad1501), WTC0(0xbc9e8801), WTC0(0xbc90d481), + WTC0(0xbc83f201), WTC0(0xbc77d601), WTC0(0xbc6c7781), WTC0(0xbc61c401), + WTC0(0xbc57a301), WTC0(0xbc4dfb81), WTC0(0xbc44b481), WTC0(0xbc3bbc01), + WTC0(0xbc330781), WTC0(0xbc2a8c81), WTC0(0xbc224181), WTC0(0xbc1a2401), + WTC0(0xbc123b81), WTC0(0xbc0a8f01), WTC0(0xbc032601), WTC0(0xbbfc0f81), + WTC0(0xbbf56181), WTC0(0xbbef3301), WTC0(0xbbe99981), WTC0(0xbbe49d01), + WTC0(0xbbe03801), WTC0(0xbbdc6481), WTC0(0xbbd91b81), WTC0(0xbbd64d01), + WTC0(0xbbd3e101), WTC0(0xbbd1bd81), WTC0(0xbbcfca81), WTC0(0xbbce0601), + WTC0(0xbbcc8201), WTC0(0xbbcb5301), WTC0(0xbbca8d01), WTC0(0xbbca5081), + WTC0(0xbbcaca01), WTC0(0xbbcc2681), WTC0(0xbbce9181), WTC0(0xbbd21281), + WTC0(0xbbd68c81), WTC0(0xbbdbe201), WTC0(0xbbe1f401), WTC0(0xbbe89901), + WTC0(0xbbef9b81), WTC0(0xbbf6c601), WTC0(0xbbfde481), WTC0(0xbc04e381), + WTC0(0xbc0bcf81), WTC0(0xbc12b801), WTC0(0xbc19ab01), WTC0(0xbc20ae01), + WTC0(0xbc27bd81), WTC0(0xbc2ed681), WTC0(0xbc35f501), WTC0(0xbc3d1801), + WTC0(0xbc444081), WTC0(0xbc4b6e81), WTC0(0xbc52a381), WTC0(0xbc59df81), + WTC0(0xbc612301), WTC0(0xbc686e01), WTC0(0xbc6fc101), WTC0(0xbc771c01), + WTC0(0xbc7e7e01), WTC0(0xbc85e801), WTC0(0xbc8d5901), WTC0(0xbc94d201), + WTC0(0xbc9c5281), WTC0(0xbca3db01), WTC0(0xbcab6c01), WTC0(0xbcb30601), + WTC0(0xbcbaa801), WTC0(0xbcc25181), WTC0(0xbcca0301), WTC0(0xbcd1bb81), + WTC0(0xbcd97c81), WTC0(0xbce14601), WTC0(0xbce91801), WTC0(0xbcf0f381), + WTC0(0xbcf8d781), WTC0(0xbd00c381), WTC0(0xbd08b781), WTC0(0xbd10b381), + WTC0(0xbd18b781), WTC0(0xbd20c401), WTC0(0xbd28d981), WTC0(0xbd30f881), + WTC0(0xbd391f81), WTC0(0xbd414f01), WTC0(0xbd498601), WTC0(0xbd51c481), + WTC0(0xbd5a0b01), WTC0(0xbd625981), WTC0(0xbd6ab101), WTC0(0xbd731081), + WTC0(0xbd7b7781), WTC0(0xbd83e681), WTC0(0xbd8c5c01), WTC0(0xbd94d801), + WTC0(0xbd9d5b81), WTC0(0xbda5e601), WTC0(0xbdae7881), WTC0(0xbdb71201), + WTC0(0xbdbfb281), WTC0(0xbdc85981), WTC0(0xbdd10681), WTC0(0xbdd9b981), + WTC0(0xbde27201), WTC0(0xbdeb3101), WTC0(0xbdf3f701), WTC0(0xbdfcc301), + WTC0(0xbe059481), WTC0(0xbe0e6c01), WTC0(0xbe174781), WTC0(0xbe202801), + WTC0(0xbe290d01), WTC0(0xbe31f701), WTC0(0xbe3ae601), WTC0(0xbe43da81), + WTC0(0xbe4cd381), WTC0(0xbe55d001), WTC0(0xbe5ed081), WTC0(0xbe67d381), + WTC0(0xbe70da01), WTC0(0xbe79e481), WTC0(0xbe82f301), WTC0(0xbe8c0501), + WTC0(0xbe951a81), WTC0(0xbe9e3281), WTC0(0xbea74c81), WTC0(0xbeb06881), + WTC0(0xbeb98681), WTC0(0xbec2a781), WTC0(0xbecbca81), WTC0(0xbed4f081), + WTC0(0xbede1901), WTC0(0xbee74281), WTC0(0xbef06d01), WTC0(0xbef99901), + WTC0(0xbf02c581), WTC0(0xbf0bf381), WTC0(0xbf152381), WTC0(0xbf1e5501), + WTC0(0xbf278801), WTC0(0xbf30bb01), WTC0(0xbf39ee81), WTC0(0xbf432281), + WTC0(0xbf4c5681), WTC0(0xbf558b01), WTC0(0xbf5ec101), WTC0(0xbf67f801), + WTC0(0xbf712f01), WTC0(0xbf7a6681), WTC0(0xbf839d81), WTC0(0xbf8cd481), + WTC0(0xbf960b01), WTC0(0xbf9f4181), WTC0(0xbfa87901), WTC0(0xbfb1b101), + WTC0(0xbfbae981), WTC0(0xbfc42201), WTC0(0xbfcd5a01), WTC0(0xbfd69101), + WTC0(0xbfdfc781), WTC0(0xbfe8fc01), WTC0(0xbff22f81), WTC0(0xbffb6081), + /* part 1 */ + WTC1(0x80093e01), WTC1(0x801b9b01), WTC1(0x802df701), WTC1(0x80405101), + WTC1(0x8052a881), WTC1(0x8064fc81), WTC1(0x80774c81), WTC1(0x80899881), + WTC1(0x809bdf01), WTC1(0x80ae1f81), WTC1(0x80c05a01), WTC1(0x80d28d81), + WTC1(0x80e4bb81), WTC1(0x80f6e481), WTC1(0x81090981), WTC1(0x811b2981), + WTC1(0x812d4481), WTC1(0x813f5981), WTC1(0x81516701), WTC1(0x81636d81), + WTC1(0x81756d81), WTC1(0x81876781), WTC1(0x81995c01), WTC1(0x81ab4b01), + WTC1(0x81bd3401), WTC1(0x81cf1581), WTC1(0x81e0ee81), WTC1(0x81f2bf81), + WTC1(0x82048881), WTC1(0x82164a81), WTC1(0x82280581), WTC1(0x8239b981), + WTC1(0x824b6601), WTC1(0x825d0901), WTC1(0x826ea201), WTC1(0x82803101), + WTC1(0x8291b601), WTC1(0x82a33281), WTC1(0x82b4a601), WTC1(0x82c61101), + WTC1(0x82d77201), WTC1(0x82e8c801), WTC1(0x82fa1181), WTC1(0x830b4f81), + WTC1(0x831c8101), WTC1(0x832da781), WTC1(0x833ec381), WTC1(0x834fd481), + WTC1(0x8360d901), WTC1(0x8371d081), WTC1(0x8382ba01), WTC1(0x83939501), + WTC1(0x83a46181), WTC1(0x83b52101), WTC1(0x83c5d381), WTC1(0x83d67881), + WTC1(0x83e70f01), WTC1(0x83f79681), WTC1(0x84080d81), WTC1(0x84187401), + WTC1(0x8428ca01), WTC1(0x84391081), WTC1(0x84494881), WTC1(0x84597081), + WTC1(0x84698881), WTC1(0x84798f81), WTC1(0x84898481), WTC1(0x84996701), + WTC1(0x84a93801), WTC1(0x84b8f801), WTC1(0x84c8a701), WTC1(0x84d84601), + WTC1(0x84e7d381), WTC1(0x84f74e01), WTC1(0x8506b581), WTC1(0x85160981), + WTC1(0x85254a81), WTC1(0x85347901), WTC1(0x85439601), WTC1(0x8552a181), + WTC1(0x85619a01), WTC1(0x85707f81), WTC1(0x857f5101), WTC1(0x858e0e01), + WTC1(0x859cb781), WTC1(0x85ab4f01), WTC1(0x85b9d481), WTC1(0x85c84801), + WTC1(0x85d6a981), WTC1(0x85e4f801), WTC1(0x85f33281), WTC1(0x86015981), + WTC1(0x860f6e01), WTC1(0x861d7081), WTC1(0x862b6201), WTC1(0x86394301), + WTC1(0x86471281), WTC1(0x8654d001), WTC1(0x86627b01), WTC1(0x86701381), + WTC1(0x867d9a81), WTC1(0x868b1001), WTC1(0x86987581), WTC1(0x86a5ca81), + WTC1(0x86b30f01), WTC1(0x86c04381), WTC1(0x86cd6681), WTC1(0x86da7901), + WTC1(0x86e77b81), WTC1(0x86f46d81), WTC1(0x87014f81), WTC1(0x870e2301), + WTC1(0x871ae981), WTC1(0x8727a381), WTC1(0x87345381), WTC1(0x8740f681), + WTC1(0x874d8681), WTC1(0x8759fd01), WTC1(0x87665481), WTC1(0x87729701), + WTC1(0x877ede01), WTC1(0x878b4301), WTC1(0x8797dd81), WTC1(0x87a48b01), + WTC1(0x87b0ef01), WTC1(0x87bcab81), WTC1(0x87c76201), WTC1(0x87d0ca81), + WTC1(0x87fdd781), WTC1(0x881dd301), WTC1(0x88423301), WTC1(0x886a8a81), + WTC1(0x88962981), WTC1(0x88c45e81), WTC1(0x88f47901), WTC1(0x8925f101), + WTC1(0x89586901), WTC1(0x898b8301), WTC1(0x89bee581), WTC1(0x89f26101), + WTC1(0x8a25f301), WTC1(0x8a599a81), WTC1(0x8a8d5801), WTC1(0x8ac13381), + WTC1(0x8af53e81), WTC1(0x8b298b81), WTC1(0x8b5e2c81), WTC1(0x8b933001), + WTC1(0x8bc8a401), WTC1(0x8bfe9401), WTC1(0x8c350d01), WTC1(0x8c6c1b01), + WTC1(0x8ca3cb01), WTC1(0x8cdc2901), WTC1(0x8d154081), WTC1(0x8d4f1b01), + WTC1(0x8d89be81), WTC1(0x8dc53001), WTC1(0x8e017581), WTC1(0x8e3e9481), + WTC1(0x8e7c9301), WTC1(0x8ebb7581), WTC1(0x8efb4181), WTC1(0x8f3bfb01), + WTC1(0x8f7da401), WTC1(0x8fc03f01), WTC1(0x9003ce81), WTC1(0x90485401), + WTC1(0x908dd101), WTC1(0x90d44781), WTC1(0x911bb981), WTC1(0x91642781), + WTC1(0x91ad9281), WTC1(0x91f7f981), WTC1(0x92435d01), WTC1(0x928fbe01), + WTC1(0x92dd1b01), WTC1(0x932b7501), WTC1(0x937acb01), WTC1(0x93cb1c81), + WTC1(0x941c6901), WTC1(0x946eaf81), WTC1(0x94c1ee01), WTC1(0x95162381), + WTC1(0x956b4f81), WTC1(0x95c17081), WTC1(0x96188501), WTC1(0x96708b81), + WTC1(0x96c98381), WTC1(0x97236b01), WTC1(0x977e4181), WTC1(0x97da0481), + WTC1(0x9836b201), WTC1(0x98944901), WTC1(0x98f2c601), WTC1(0x99522801), + WTC1(0x99b26c81), WTC1(0x9a139101), WTC1(0x9a759301), WTC1(0x9ad87081), + WTC1(0x9b3c2801), WTC1(0x9ba0b701), WTC1(0x9c061b81), WTC1(0x9c6c5481), + WTC1(0x9cd35f81), WTC1(0x9d3b3b81), WTC1(0x9da3e601), WTC1(0x9e0d5e01), + WTC1(0x9e779f81), WTC1(0x9ee2a901), WTC1(0x9f4e7801), WTC1(0x9fbb0981), + WTC1(0xa0285d81), WTC1(0xa0967201), WTC1(0xa1054701), WTC1(0xa174da81), + WTC1(0xa1e52a81), WTC1(0xa2563501), WTC1(0xa2c7f801), WTC1(0xa33a7201), + WTC1(0xa3ada281), WTC1(0xa4218801), WTC1(0xa4962181), WTC1(0xa50b6e81), + WTC1(0xa5816e81), WTC1(0xa5f81f81), WTC1(0xa66f8201), WTC1(0xa6e79401), + WTC1(0xa7605601), WTC1(0xa7d9c681), WTC1(0xa853e501), WTC1(0xa8ceb201), + WTC1(0xa94a2c01), WTC1(0xa9c65401), WTC1(0xaa432981), WTC1(0xaac0ad01), + WTC1(0xab3edf01), WTC1(0xabbdc001), WTC1(0xac3d5001), WTC1(0xacbd9081), + WTC1(0xad3e8101), WTC1(0xadc02281), WTC1(0xae427481), WTC1(0xaec57801), + WTC1(0xaf492f01), WTC1(0xafcd9a81), WTC1(0xb052bc01), WTC1(0xb0d89401), + WTC1(0xb15f2381), WTC1(0xb1e66a01), WTC1(0xb26e6881), WTC1(0xb2f71f01), + WTC1(0xb3808d81), WTC1(0xb40ab501), WTC1(0xb4959501), WTC1(0xb5212e81), + WTC1(0x4a6cf67f), WTC1(0x49dffeff), WTC1(0x495265ff), WTC1(0x48c4277f), + WTC1(0x4835407f), WTC1(0x47a5aeff), WTC1(0x471570ff), WTC1(0x468484ff), + WTC1(0x45f2eaff), WTC1(0x4560a2ff), WTC1(0x44cdad7f), WTC1(0x443a0c7f), + WTC1(0x43a5c07f), WTC1(0x4310caff), WTC1(0x427b2bff), WTC1(0x41e4e3ff), + WTC1(0x414df2ff), WTC1(0x40b6557f), WTC1(0x401e06ff), WTC1(0x3f8503c0), + WTC1(0x3eeb4e00), WTC1(0x3e50ebc0), WTC1(0x3db5e680), WTC1(0x3d1a4680), + WTC1(0x3c7e10c0), WTC1(0x3be14cc0), WTC1(0x3b4402c0), WTC1(0x3aa63800), + WTC1(0x3a07e840), WTC1(0x39690880), WTC1(0x38c98700), WTC1(0x38295b40), + WTC1(0x37888a80), WTC1(0x36e71d40), WTC1(0x36451d80), WTC1(0x35a29400), + WTC1(0x34ff8800), WTC1(0x345c04c0), WTC1(0x33b81940), WTC1(0x3313d200), + WTC1(0x326f3800), WTC1(0x31ca5600), WTC1(0x31253840), WTC1(0x307fe8c0), + WTC1(0x2fda6e40), WTC1(0x2f34ce40), WTC1(0x2e8f0e40), WTC1(0x2de92ec0), + WTC1(0x2d432780), WTC1(0x2c9cea40), WTC1(0x2bf66300), WTC1(0x2b4f88c0), + WTC1(0x2aa864c0), WTC1(0x2a010240), WTC1(0x29596e40), WTC1(0x28b1ba80), + WTC1(0x2809ff40), WTC1(0x27625b80), WTC1(0x26baf580), WTC1(0x2613e7c0), + WTC1(0x256d3dc0), WTC1(0x24c70300), WTC1(0x24214380), WTC1(0x237c0800), + WTC1(0x22d75400), WTC1(0x22332a80), WTC1(0x218f8cc0), WTC1(0x20ec7e40), + WTC1(0x204a04c0), WTC1(0x1fa82540), WTC1(0x1f06e300), WTC1(0x1e664000), + WTC1(0x1dc63bc0), WTC1(0x1d26d3c0), WTC1(0x1c8803a0), WTC1(0x1be9cc40), + WTC1(0x1b4c34c0), WTC1(0x1aaf4480), WTC1(0x1a130260), WTC1(0x197774a0), + WTC1(0x18dca260), WTC1(0x184294e0), WTC1(0x17a95840), WTC1(0x1710fd80), + WTC1(0x16799ce0), WTC1(0x15e35340), WTC1(0x154e41a0), WTC1(0x14ba8360), + WTC1(0x14282be0), WTC1(0x13975100), WTC1(0x13080aa0), WTC1(0x127a6240), + WTC1(0x11ee50a0), WTC1(0x1163cc80), WTC1(0x10dacb20), WTC1(0x105333a0), + WTC1(0x0fccdb30), WTC1(0x0f478f40), WTC1(0x0ec31700), WTC1(0x0e3f4e80), + WTC1(0x0dbc27f0), WTC1(0x0d399000), WTC1(0x0cb76d00), WTC1(0x0c359d50), + WTC1(0x0bb3fd50), WTC1(0x0b326bd0), WTC1(0x0ab0ca80), WTC1(0x0a2f0dc0), + WTC1(0x09ad40c0), WTC1(0x092b7a90), WTC1(0x08a9db80), WTC1(0x08285c80), + WTC1(0x07a6c7b8), WTC1(0x0724e4e0), WTC1(0x06a27b80), WTC1(0x061f52f8), + WTC1(0x059b2ad0), WTC1(0x0515b568), WTC1(0x048ea058), WTC1(0x04066408), + WTC1(0x037e52d8), WTC1(0x02f7d3c8), WTC1(0x0274614c), WTC1(0x01f63008), + WTC1(0x0180403a), WTC1(0x0115c442), WTC1(0x00ba09e2), WTC1(0x006f077c), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfff36be1), WTC2(0xffdafbc1), WTC2(0xffc28035), WTC2(0xffa9fe8a), + WTC2(0xff917c08), WTC2(0xff78fdfc), WTC2(0xff6089af), WTC2(0xff48246c), + WTC2(0xff2fd37f), WTC2(0xff179c31), WTC2(0xfeff83b6), WTC2(0xfee78d18), + WTC2(0xfecfb93e), WTC2(0xfeb808f2), WTC2(0xfea07d06), WTC2(0xfe8916b4), + WTC2(0xfe71d7a0), WTC2(0xfe5ac174), WTC2(0xfe43d5d6), WTC2(0xfe2d167e), + WTC2(0xfe16852e), WTC2(0xfe0023a6), WTC2(0xfde9f3f8), WTC2(0xfdd3ff7c), + WTC2(0xfdbe56c0), WTC2(0xfda90aa8), WTC2(0xfd942b78), WTC2(0xfd7fbb20), + WTC2(0xfd6bad50), WTC2(0xfd57f510), WTC2(0xfd44857c), WTC2(0xfd3153fc), + WTC2(0xfd1e5840), WTC2(0xfd0b8a0c), WTC2(0xfcf8e180), WTC2(0xfce65eec), + WTC2(0xfcd40ad0), WTC2(0xfcc1ee0c), WTC2(0xfcb011e8), WTC2(0xfc9e896c), + WTC2(0xfc8d716c), WTC2(0xfc7ce720), WTC2(0xfc6d072c), WTC2(0xfc5de09c), + WTC2(0xfc4f74e8), WTC2(0xfc41c4e8), WTC2(0xfc34d0dc), WTC2(0xfc288a68), + WTC2(0xfc1cd49c), WTC2(0xfc1191e0), WTC2(0xfc06a4d0), WTC2(0xfbfbf3e8), + WTC2(0xfbf16990), WTC2(0xfbe6f068), WTC2(0xfbdc7428), WTC2(0xfbd1fc68), + WTC2(0xfbc7ac50), WTC2(0xfbbda868), WTC2(0xfbb41500), WTC2(0xfbab1438), + WTC2(0xfba2c5f8), WTC2(0xfb9b4a00), WTC2(0xfb94bfa8), WTC2(0xfb8f3b48), + WTC2(0xfb8ac638), WTC2(0xfb876970), WTC2(0xfb852d20), WTC2(0xfb840ae0), + WTC2(0xfb83ed60), WTC2(0xfb84bec0), WTC2(0xfb866918), WTC2(0xfb88d4a8), + WTC2(0xfb8be810), WTC2(0xfb8f89d0), WTC2(0xfb93a080), WTC2(0xfb981418), + WTC2(0xfb9ccdf0), WTC2(0xfba1b770), WTC2(0xfba6bae0), WTC2(0xfbabd5c0), + WTC2(0xfbb118d8), WTC2(0xfbb695c0), WTC2(0xfbbc5e90), WTC2(0xfbc29030), + WTC2(0xfbc95268), WTC2(0xfbd0cd78), WTC2(0xfbd929c8), WTC2(0xfbe294d0), + WTC2(0xfbed4108), WTC2(0xfbf96118), WTC2(0xfc0726c8), WTC2(0xfc16b064), + WTC2(0xfc280890), WTC2(0xfc3b3920), WTC2(0xfc504a98), WTC2(0xfc67271c), + WTC2(0xfc7f9a74), WTC2(0xfc996f18), WTC2(0xfcb46eb8), WTC2(0xfcd050b0), + WTC2(0xfcecba24), WTC2(0xfd094f64), WTC2(0xfd25b720), WTC2(0xfd41ce40), + WTC2(0xfd5da7f8), WTC2(0xfd7959d8), WTC2(0xfd94fb74), WTC2(0xfdb0d3fc), + WTC2(0xfdcd5a34), WTC2(0xfdeb06e4), WTC2(0xfe0a5184), WTC2(0xfe2b92c4), + WTC2(0xfe4f0486), WTC2(0xfe74df54), WTC2(0xfe9d5886), WTC2(0xfec85b92), + WTC2(0xfef58a16), WTC2(0xff248275), WTC2(0xff54e401), WTC2(0xff866330), + WTC2(0xffb8c99b), WTC2(0xffebe1c9), WTC2(0x001f786a), WTC2(0x00538bf9), + WTC2(0x00884cbc), WTC2(0x00bded23), WTC2(0x00f49f54), WTC2(0x012c8ee4), + WTC2(0x0165e0d2), WTC2(0x01a0b9d6), WTC2(0x01dd3d80), WTC2(0x021b74d4), + WTC2(0x025b4e48), WTC2(0x029cb730), WTC2(0x02df9d0c), WTC2(0x0323f1a4), + WTC2(0x0369ab00), WTC2(0x03b0bf5c), WTC2(0x03f925a0), WTC2(0x0442e3d8), + WTC2(0x048e0f40), WTC2(0x04dabdb0), WTC2(0x05290430), WTC2(0x0578e428), + WTC2(0x05ca4b60), WTC2(0x061d26c0), WTC2(0x067163d8), WTC2(0x06c6ff10), + WTC2(0x071e03b0), WTC2(0x07767da0), WTC2(0x07d07918), WTC2(0x082c08e0), + WTC2(0x08894660), WTC2(0x08e84b70), WTC2(0x094930b0), WTC2(0x09abf8d0), + WTC2(0x0a109020), WTC2(0x0a76e210), WTC2(0x0adeda50), WTC2(0x0b486b80), + WTC2(0x0bb38f00), WTC2(0x0c203e80), WTC2(0x0c8e73e0), WTC2(0x0cfe2c30), + WTC2(0x0d6f6820), WTC2(0x0de22850), WTC2(0x0e566d90), WTC2(0x0ecc3dd0), + WTC2(0x0f43a3a0), WTC2(0x0fbca9f0), WTC2(0x10375b80), WTC2(0x10b3be20), + WTC2(0x1131d280), WTC2(0x11b19960), WTC2(0x123313a0), WTC2(0x12b64380), + WTC2(0x133b2d00), WTC2(0x13c1d440), WTC2(0x144a3d60), WTC2(0x14d46900), + WTC2(0x15605480), WTC2(0x15edfd20), WTC2(0x167d6040), WTC2(0x170e7e80), + WTC2(0x17a15b80), WTC2(0x1835fb00), WTC2(0x18cc60a0), WTC2(0x19648dc0), + WTC2(0x19fe80e0), WTC2(0x1a9a38a0), WTC2(0x1b37b3e0), WTC2(0x1bd6f400), + WTC2(0x1c77fd20), WTC2(0x1d1ad400), WTC2(0x1dbf7c80), WTC2(0x1e65f820), + WTC2(0x1f0e4540), WTC2(0x1fb861e0), WTC2(0x20644cc0), WTC2(0x21120640), + WTC2(0x21c19240), WTC2(0x2272f480), WTC2(0x23263000), WTC2(0x23db4580), + WTC2(0x24923340), WTC2(0x254af700), WTC2(0x26058e80), WTC2(0x26c1fa00), + WTC2(0x27803d00), WTC2(0x28405a40), WTC2(0x29025500), WTC2(0x29c62d40), + WTC2(0x2a8be0c0), WTC2(0x2b536cc0), WTC2(0x2c1ccf80), WTC2(0x2ce80840), + WTC2(0x2db519c0), WTC2(0x2e840600), WTC2(0x2f54cf80), WTC2(0x302775c0), + WTC2(0x30fbf640), WTC2(0x31d24e00), WTC2(0x32aa7a00), WTC2(0x338479c0), + WTC2(0x34604e40), WTC2(0x353df900), WTC2(0x361d7ac0), WTC2(0x36fed200), + WTC2(0x37e1fb40), WTC2(0x38c6f240), WTC2(0x39adb2c0), WTC2(0x3a963a00), + WTC2(0x3b808740), WTC2(0x3c6c9880), WTC2(0x3d5a6cc0), WTC2(0x3e4a0040), + WTC2(0x3f3b4bc0), WTC2(0x402e48ff), WTC2(0x4122f17f), WTC2(0x42193f7f), + WTC2(0x43112eff), WTC2(0x440abbff), WTC2(0x4505e2ff), WTC2(0x46029e7f), + WTC2(0x4700e9ff), WTC2(0x4800bfff), WTC2(0x49021bff), WTC2(0x4a050eff), + WTC2(0x4b09bc7f), WTC2(0x4c104aff), WTC2(0x4d18df7f), WTC2(0x4e23a07f), + WTC2(0x4f30b2ff), WTC2(0x50403c7f), WTC2(0x515262ff), WTC2(0x52674b7f), + WTC2(0x001678b2), WTC2(0x00061a3b), WTC2(0xfffb4622), WTC2(0xfff5ea94), + WTC2(0xfff5f5b9), WTC2(0xfffb55bd), WTC2(0x0005f8cb), WTC2(0x0015cd0c), + WTC2(0x002ac0ac), WTC2(0x0044c1d5), WTC2(0x0063beb2), WTC2(0x0087a56d), + WTC2(0x00b06431), WTC2(0x00dde929), WTC2(0x01102280), WTC2(0x0146fe5e), + WTC2(0x01826af2), WTC2(0x01c25662), WTC2(0x0206aedc), WTC2(0x024f6288), + WTC2(0x029c5f94), WTC2(0x02ed9424), WTC2(0x0342ee6c), WTC2(0x039c5c90), + WTC2(0x03f9ccbc), WTC2(0x045b2d18), WTC2(0x04c06bd8), WTC2(0x05297718), + WTC2(0x05963d10), WTC2(0x0606abe8), WTC2(0x067ab1c0), WTC2(0x06f23cd0), + WTC2(0x076d3b40), WTC2(0x07eb9b38), WTC2(0x086d4ae0), WTC2(0x08f23860), + WTC2(0x097a51f0), WTC2(0x0a0585b0), WTC2(0x0a93c1d0), WTC2(0x0b24f470), + WTC2(0x0bb90bc0), WTC2(0x0c4ff5f0), WTC2(0x0ce9a130), WTC2(0x0d85fb90), + WTC2(0x0e24f360), WTC2(0x0ec676b0), WTC2(0x0f6a73b0), WTC2(0x1010d880), + WTC2(0x10b99360), WTC2(0x11649280), WTC2(0x1211c400), WTC2(0x12c115e0), + WTC2(0x137276a0), WTC2(0x1425d420), WTC2(0x14db1ca0), WTC2(0x15923e60), + WTC2(0x164b2780), WTC2(0x1705c620), WTC2(0x17c20860), WTC2(0x187fdca0), + WTC2(0x193f30e0), WTC2(0x19fff340), WTC2(0x1ac21200), WTC2(0x1b857b40), + WTC2(0x1c4a1d40), WTC2(0x1d0fe600), WTC2(0x1dd6c3e0), WTC2(0x1e9ea4e0), + WTC2(0x1f677740), WTC2(0x20312940), WTC2(0x20fba8c0), WTC2(0x21c6e440), + WTC2(0x2292c9c0), WTC2(0x235f4780), WTC2(0x242c4b80), WTC2(0x24f9c400), + WTC2(0x25c79f40), WTC2(0x2695cb40), WTC2(0x27643680), WTC2(0x2832cec0), + WTC2(0x29018240), WTC2(0x29d03f80), WTC2(0x2a9ef480), WTC2(0x2b6d8f00), + WTC2(0x2c3bfdc0), WTC2(0x2d0a2ec0), WTC2(0x2dd81000), WTC2(0x2ea58fc0), + WTC2(0x2f729c40), WTC2(0x303f2380), WTC2(0x310b1400), WTC2(0x31d65b80), + WTC2(0x32a0e840), WTC2(0x336aa8c0), WTC2(0x34338ac0), WTC2(0x34fb7cc0), + WTC2(0x35c26cc0), WTC2(0x36884900), WTC2(0x374cff80), WTC2(0x38107e80), + WTC2(0x38d2b440), WTC2(0x39938ec0), WTC2(0x3a52fc40), WTC2(0x3b10eb00), + WTC2(0x3bcd4900), WTC2(0x3c880480), WTC2(0x3d410bc0), WTC2(0x3df84d00), + WTC2(0x3eadb600), WTC2(0x3f613540), WTC2(0x4012b8ff), WTC2(0x40c22eff), + WTC2(0x416f85ff), WTC2(0x421aab7f), WTC2(0x42c38e7f), WTC2(0x436a1c7f), + WTC2(0x440e437f), WTC2(0x44aff27f), WTC2(0x454f167f), WTC2(0x45eb9eff), + WTC2(0x468578ff), WTC2(0x471c937f), WTC2(0x47b0dc7f), WTC2(0x484241ff), + WTC2(0x48d0b1ff), WTC2(0x495c1a7f), WTC2(0x49e46a7f), WTC2(0x4a698f7f), + WTC2(0x4aeb77ff), WTC2(0x4b6a11ff), WTC2(0x4be54b7f), WTC2(0x4c5d12ff), + WTC2(0x4cd155ff), WTC2(0x4d4203ff), WTC2(0x4daf09ff), WTC2(0x4e18567f), + WTC2(0x4e7dd77f), WTC2(0x4edf7b7f), WTC2(0x4f3d307f), WTC2(0x4f96e47f), + WTC2(0x4fec85ff), WTC2(0x503e02ff), WTC2(0x508b497f), WTC2(0x50d447ff), + WTC2(0x5118ec7f), WTC2(0x515924ff), WTC2(0x5194dfff), WTC2(0x51cc0b7f), + WTC2(0x51fe95ff), WTC2(0x522c6cff), WTC2(0x52557eff), WTC2(0x5279b9ff), + WTC2(0x52990c7f), WTC2(0x52b364ff), WTC2(0x52c8b07f), WTC2(0x52d8ddff), + WTC2(0x52e3db7f), WTC2(0x52e996ff), WTC2(0x52e9ff7f), WTC2(0x52e501ff), + WTC2(0x52da8cff), WTC2(0x52ca8f7f), WTC2(0x52b4f67f), WTC2(0x5299b07f), + WTC2(0x5278ac7f), WTC2(0x5251d77f), WTC2(0x52251fff), WTC2(0x51f274ff), + WTC2(0x51b9c37f), WTC2(0x517af9ff), WTC2(0x5136077f), WTC2(0x50ead8ff), + WTC2(0x50995cff), WTC2(0x504181ff), WTC2(0x4fe335ff), WTC2(0x4f7e677f), + WTC2(0x4f1303ff), WTC2(0x4ea0f9ff), WTC2(0x4e2837ff), WTC2(0x4da8ab7f), + WTC2(0x4d2242ff), WTC2(0x4c94ecff), WTC2(0x4c0096ff), WTC2(0x4b652f7f), + WTC2(0x4ac2a4ff), WTC2(0x4a18e4ff), WTC2(0x4967ddff), WTC2(0x48af7e7f), + WTC2(0x47efb3ff), WTC2(0x47286cff), WTC2(0x4659ad7f), WTC2(0x45856f7f), + WTC2(0x44afa3ff), WTC2(0x43dc507f), WTC2(0x430f657f), WTC2(0x424ad47f), + WTC2(0x418e927f), WTC2(0x40da7bff), WTC2(0x402e6f7f), WTC2(0x3f8a3100), + WTC2(0x3eed6f40), WTC2(0x3e57d700), WTC2(0x3dc914c0), WTC2(0x3d40cc40), + WTC2(0x3cbe98c0), WTC2(0x3c421540), WTC2(0x3bcadbc0), WTC2(0x3b588880), + WTC2(0x3aeab780), WTC2(0x3a810540), WTC2(0x3a1b0e00), WTC2(0x39b86d00), + WTC2(0x3958bcc0), WTC2(0x38fb9700), WTC2(0x38a095c0), WTC2(0x38473d80), + WTC2(0x37eeff40), WTC2(0x37974b40), WTC2(0x373f9500), WTC2(0x36e7ae00), + WTC2(0x368fc4c0), WTC2(0x36380b80), WTC2(0x35e0b300), WTC2(0x3589c140), + WTC2(0x35331180), WTC2(0x34dc7c80), WTC2(0x3485dc80), WTC2(0x342f1600), + WTC2(0x33d81780), WTC2(0x3380d0c0), WTC2(0x33293100), WTC2(0x32d11800), + WTC2(0x32785780), WTC2(0x321ec0c0), WTC2(0x31c42680), WTC2(0x316885c0), + WTC2(0x310c0580), WTC2(0x30aecec0), WTC2(0x30510940), WTC2(0x2ff2b8c0), + WTC2(0x2f93bf40), WTC2(0x2f33fc00), WTC2(0x2ed350c0), WTC2(0x2e71ba80), + WTC2(0x2e0f5340), WTC2(0x2dac35c0), WTC2(0x2d487c80), WTC2(0x2ce431c0), + WTC2(0x2c7f4fc0), WTC2(0x2c19d080), WTC2(0x2bb3ad80), WTC2(0x2b4ce080), + WTC2(0x2ae56340), WTC2(0x2a7d2f80), WTC2(0x2a143f00), WTC2(0x29aa8b40)}; + +const FIXP_WTB ELDAnalysis480[1440] = { + WTC0(0xfacfbef0), WTC0(0xfab88c18), WTC0(0xfaa0e520), WTC0(0xfa88d110), + WTC0(0xfa7056e8), WTC0(0xfa577db0), WTC0(0xfa3e4c70), WTC0(0xfa24ca28), + WTC0(0xfa0afde0), WTC0(0xf9f0eea0), WTC0(0xf9d6a2c8), WTC0(0xf9bc1ab8), + WTC0(0xf9a15230), WTC0(0xf9864510), WTC0(0xf96af058), WTC0(0xf94f55c0), + WTC0(0xf93378e0), WTC0(0xf9175d80), WTC0(0xf8fb0468), WTC0(0xf8de68b8), + WTC0(0xf8c18438), WTC0(0xf8a450d8), WTC0(0xf886cde8), WTC0(0xf8690148), + WTC0(0xf84af148), WTC0(0xf82ca410), WTC0(0xf80e1e18), WTC0(0xf7ef62a0), + WTC0(0xf7d074e0), WTC0(0xf7b15870), WTC0(0xf7921240), WTC0(0xf772a7a0), + WTC0(0xf7531e50), WTC0(0xf7337820), WTC0(0xf713afd0), WTC0(0xf6f3bea0), + WTC0(0xf6d39dc0), WTC0(0xf6b352e0), WTC0(0xf692f280), WTC0(0xf6729250), + WTC0(0xf65247a0), WTC0(0xf63224c0), WTC0(0xf6123a00), WTC0(0xf5f297c0), + WTC0(0xf5d34dd0), WTC0(0xf5b46b10), WTC0(0xf595fd90), WTC0(0xf5781390), + WTC0(0xf55abba0), WTC0(0xf53e0510), WTC0(0xf521ff70), WTC0(0xf506ba30), + WTC0(0xf4ec4330), WTC0(0xf4d2a680), WTC0(0xf4b9efe0), WTC0(0xf4a22ac0), + WTC0(0xf48b5f70), WTC0(0xf4759310), WTC0(0xf460cde0), WTC0(0xf44cfcc0), + WTC0(0xf439aff0), WTC0(0xf4264e00), WTC0(0xf4123d90), WTC0(0xf3fd1370), + WTC0(0xf3e6be00), WTC0(0xf3cf41a0), WTC0(0xf3b6a030), WTC0(0xf39cdd60), + WTC0(0xf381fe00), WTC0(0xf3660760), WTC0(0xf348fe70), WTC0(0xf32ae820), + WTC0(0xf30bc940), WTC0(0xf2eba690), WTC0(0xf2ca8480), WTC0(0xf2a86670), + WTC0(0xf2854f40), WTC0(0xf2614190), WTC0(0xf23c41e0), WTC0(0xf21657a0), + WTC0(0xf1ef8ae0), WTC0(0xf1c7e3e0), WTC0(0xf19f63d0), WTC0(0xf1760450), + WTC0(0xf14bbdf0), WTC0(0xf1208960), WTC0(0xf0f45cd0), WTC0(0xf0c72ce0), + WTC0(0xf098ee00), WTC0(0xf06996f0), WTC0(0xf0392620), WTC0(0xf0079e10), + WTC0(0xefd4ffc0), WTC0(0xefa15ca0), WTC0(0xef6ce600), WTC0(0xef37d460), + WTC0(0xef025f80), WTC0(0xeecca2c0), WTC0(0xee969760), WTC0(0xee603440), + WTC0(0xee296d20), WTC0(0xedf21c00), WTC0(0xedba07e0), WTC0(0xed80f640), + WTC0(0xed46bf40), WTC0(0xed0b7b00), WTC0(0xeccf5fc0), WTC0(0xec92a120), + WTC0(0xec556d60), WTC0(0xec17e700), WTC0(0xebda2d40), WTC0(0xeb9c5fa0), + WTC0(0xeb5e7040), WTC0(0xeb201b20), WTC0(0xeae117c0), WTC0(0xeaa12000), + WTC0(0xea600180), WTC0(0xea1d9940), WTC0(0xe9d9c160), WTC0(0xe99468a0), + WTC0(0xe94dc040), WTC0(0xe9061940), WTC0(0xe8bdc140), WTC0(0xe8750ae0), + WTC0(0xe82c4fa0), WTC0(0xe7e3ea40), WTC0(0xe79c35e0), WTC0(0xe7554ca0), + WTC0(0xe70efc00), WTC0(0xe6c90c20), WTC0(0xe6833f00), WTC0(0xe63d2300), + WTC0(0xe5f620a0), WTC0(0xe5ad9dc0), WTC0(0xe5632080), WTC0(0xe5169da0), + WTC0(0xe4c83e60), WTC0(0xe4782400), WTC0(0xe4269840), WTC0(0xe3d42dc0), + WTC0(0xe38188c0), WTC0(0xe32f4be0), WTC0(0xe2ddeea0), WTC0(0xe28db520), + WTC0(0xe23ee000), WTC0(0xe1f1a580), WTC0(0xe1a5e3a0), WTC0(0xe15b35a0), + WTC0(0xe1113860), WTC0(0xe0c78a00), WTC0(0xe07dd0e0), WTC0(0xe033b7c0), + WTC0(0xdfe8e680), WTC0(0xdf9d1fc0), WTC0(0xdf5055c0), WTC0(0xdf0287c0), + WTC0(0xdeb3b340), WTC0(0xde63e7c0), WTC0(0xde134a00), WTC0(0xddc20000), + WTC0(0xdd703180), WTC0(0xdd1e1280), WTC0(0xdccbe080), WTC0(0xdc79d980), + WTC0(0xdc283600), WTC0(0xdbd71e00), WTC0(0xdb86b140), WTC0(0xdb3710c0), + WTC0(0xdae850c0), WTC0(0xda9a6bc0), WTC0(0xda4d5640), WTC0(0xda010640), + WTC0(0xd9b56640), WTC0(0xd96a5700), WTC0(0xd91fb700), WTC0(0xd8d56600), + WTC0(0xd88b4a40), WTC0(0xd8414f00), WTC0(0xd7f75f80), WTC0(0xd7ad6740), + WTC0(0xd76352c0), WTC0(0xd7191040), WTC0(0xd6ce8c80), WTC0(0xd683bd00), + WTC0(0xd638a5c0), WTC0(0xd5ed4f80), WTC0(0xd5a1c240), WTC0(0xd5562b80), + WTC0(0xd50ae500), WTC0(0xd4c04c80), WTC0(0xd476bb40), WTC0(0xd42e62c0), + WTC0(0xd3e75680), WTC0(0xd3a1ad00), WTC0(0xd35d6780), WTC0(0xd31a4300), + WTC0(0xd2d7dc00), WTC0(0xd295d080), WTC0(0xd253d8c0), WTC0(0xd211df40), + WTC0(0xd1cfdbc0), WTC0(0xd18dc480), WTC0(0xd14b9dc0), WTC0(0xd1097c80), + WTC0(0xd0c77700), WTC0(0xd085a500), WTC0(0xd0442f40), WTC0(0xd0034a80), + WTC0(0xcfc32c00), WTC0(0xcf840400), WTC0(0xcf45f400), WTC0(0xcf0913c0), + WTC0(0xcecd8000), WTC0(0xce932c80), WTC0(0xce59bf40), WTC0(0xce20cd40), + WTC0(0xcde7ec40), WTC0(0xcdaeedc0), WTC0(0xcd75ea00), WTC0(0xcd3cfec0), + WTC0(0xcd044b40), WTC0(0xcccbff00), WTC0(0xcc945480), WTC0(0xcc5d8780), + WTC0(0xcc27c3c0), WTC0(0xcbf2fc40), WTC0(0xcbbf0a00), WTC0(0xcb8bc7c0), + WTC0(0xcb591880), WTC0(0xcb26f0c0), WTC0(0xcaf54980), WTC0(0xcac41ac0), + WTC0(0xca936440), WTC0(0xca632d80), WTC0(0xca337f00), WTC0(0xca046180), + WTC0(0xc9d5dd40), WTC0(0xc9a7fa80), WTC0(0xc97ac200), WTC0(0xc94e3c00), + WTC0(0xc91d1840), WTC0(0xc8f15980), WTC0(0xc8c52340), WTC0(0xc8988100), + WTC0(0xc86b7f00), WTC0(0xc83e28c0), WTC0(0xc8108a80), WTC0(0xc7e2afc0), + WTC0(0xc7b4a480), WTC0(0xc7867480), WTC0(0xc7582b40), WTC0(0xc729cc80), + WTC0(0xc6fb5700), WTC0(0xc6ccca40), WTC0(0xc69e2180), WTC0(0xc66f49c0), + WTC0(0xc64029c0), WTC0(0xc610a740), WTC0(0xc5e0bfc0), WTC0(0xc5b09e80), + WTC0(0xc5807900), WTC0(0xc5508440), WTC0(0xc520e840), WTC0(0xc4f1bdc0), + WTC0(0xc4c31d00), WTC0(0xc4951780), WTC0(0xc4678a00), WTC0(0xc43a28c0), + WTC0(0xc40ca800), WTC0(0xc3deccc0), WTC0(0xc3b09940), WTC0(0xc3822c00), + WTC0(0xc353a0c0), WTC0(0xc3251740), WTC0(0xc2f6b500), WTC0(0xc2c8a140), + WTC0(0xc29b02c0), WTC0(0xc26df5c0), WTC0(0xc2418940), WTC0(0xc215cbc0), + WTC0(0xc1eaca00), WTC0(0xc1c08680), WTC0(0xc196fb00), WTC0(0xc16e22c0), + WTC0(0xc145f040), WTC0(0xc11e3a80), WTC0(0xc0f6cc00), WTC0(0xc0cf6ec0), + WTC0(0xc0a802c0), WTC0(0xc0809280), WTC0(0xc0593340), WTC0(0xc031f880), + WTC0(0xc00b04c0), WTC0(0xbfe48981), WTC0(0xbfbebb81), WTC0(0xbf99cb01), + WTC0(0xbf75cc81), WTC0(0xbf52c101), WTC0(0xbf30a901), WTC0(0xbf0f8301), + WTC0(0xbeef4601), WTC0(0xbecfe601), WTC0(0xbeb15701), WTC0(0xbe938c81), + WTC0(0xbe767e81), WTC0(0xbe5a2301), WTC0(0xbe3e7201), WTC0(0xbe236001), + WTC0(0xbe08e181), WTC0(0xbdeee981), WTC0(0xbdd56b81), WTC0(0xbdbc6381), + WTC0(0xbda3d081), WTC0(0xbd8bb281), WTC0(0xbd740b81), WTC0(0xbd5ce281), + WTC0(0xbd464281), WTC0(0xbd303581), WTC0(0xbd1ac801), WTC0(0xbd060c81), + WTC0(0xbcf21601), WTC0(0xbcdef701), WTC0(0xbcccbd01), WTC0(0xbcbb7001), + WTC0(0xbcab1781), WTC0(0xbc9bb901), WTC0(0xbc8d5101), WTC0(0xbc7fd301), + WTC0(0xbc733401), WTC0(0xbc676501), WTC0(0xbc5c4c81), WTC0(0xbc51cb01), + WTC0(0xbc47c281), WTC0(0xbc3e1981), WTC0(0xbc34c081), WTC0(0xbc2bab01), + WTC0(0xbc22cd81), WTC0(0xbc1a2401), WTC0(0xbc11b681), WTC0(0xbc098d81), + WTC0(0xbc01b381), WTC0(0xbbfa3c01), WTC0(0xbbf34281), WTC0(0xbbece281), + WTC0(0xbbe73201), WTC0(0xbbe23281), WTC0(0xbbdddb01), WTC0(0xbbda2501), + WTC0(0xbbd70201), WTC0(0xbbd45601), WTC0(0xbbd20301), WTC0(0xbbcfea81), + WTC0(0xbbce0601), WTC0(0xbbcc6b01), WTC0(0xbbcb3201), WTC0(0xbbca7481), + WTC0(0xbbca5d01), WTC0(0xbbcb2281), WTC0(0xbbccfc81), WTC0(0xbbd01301), + WTC0(0xbbd45881), WTC0(0xbbd9a781), WTC0(0xbbdfdb81), WTC0(0xbbe6c801), + WTC0(0xbbee2f81), WTC0(0xbbf5d181), WTC0(0xbbfd6c01), WTC0(0xbc04e381), + WTC0(0xbc0c4581), WTC0(0xbc13a481), WTC0(0xbc1b1081), WTC0(0xbc228f01), + WTC0(0xbc2a1a81), WTC0(0xbc31af01), WTC0(0xbc394901), WTC0(0xbc40e881), + WTC0(0xbc488e81), WTC0(0xbc503b81), WTC0(0xbc57f101), WTC0(0xbc5fae81), + WTC0(0xbc677501), WTC0(0xbc6f4401), WTC0(0xbc771c01), WTC0(0xbc7efc81), + WTC0(0xbc86e581), WTC0(0xbc8ed701), WTC0(0xbc96d101), WTC0(0xbc9ed481), + WTC0(0xbca6e101), WTC0(0xbcaef701), WTC0(0xbcb71701), WTC0(0xbcbf4001), + WTC0(0xbcc77181), WTC0(0xbccfac01), WTC0(0xbcd7ef01), WTC0(0xbce03b81), + WTC0(0xbce89281), WTC0(0xbcf0f381), WTC0(0xbcf95e81), WTC0(0xbd01d281), + WTC0(0xbd0a4f81), WTC0(0xbd12d581), WTC0(0xbd1b6501), WTC0(0xbd23ff01), + WTC0(0xbd2ca281), WTC0(0xbd355081), WTC0(0xbd3e0801), WTC0(0xbd46c801), + WTC0(0xbd4f9101), WTC0(0xbd586281), WTC0(0xbd613d81), WTC0(0xbd6a2201), + WTC0(0xbd731081), WTC0(0xbd7c0781), WTC0(0xbd850701), WTC0(0xbd8e0e01), + WTC0(0xbd971c81), WTC0(0xbda03381), WTC0(0xbda95301), WTC0(0xbdb27b01), + WTC0(0xbdbbab01), WTC0(0xbdc4e301), WTC0(0xbdce2181), WTC0(0xbdd76701), + WTC0(0xbde0b301), WTC0(0xbdea0681), WTC0(0xbdf36101), WTC0(0xbdfcc301), + WTC0(0xbe062b81), WTC0(0xbe0f9a01), WTC0(0xbe190d81), WTC0(0xbe228681), + WTC0(0xbe2c0501), WTC0(0xbe358901), WTC0(0xbe3f1381), WTC0(0xbe48a301), + WTC0(0xbe523781), WTC0(0xbe5bd001), WTC0(0xbe656c01), WTC0(0xbe6f0c01), + WTC0(0xbe78b001), WTC0(0xbe825801), WTC0(0xbe8c0501), WTC0(0xbe95b581), + WTC0(0xbe9f6901), WTC0(0xbea91f01), WTC0(0xbeb2d681), WTC0(0xbebc9181), + WTC0(0xbec64e81), WTC0(0xbed00f81), WTC0(0xbed9d281), WTC0(0xbee39801), + WTC0(0xbeed5f01), WTC0(0xbef72681), WTC0(0xbf00ef81), WTC0(0xbf0aba01), + WTC0(0xbf148681), WTC0(0xbf1e5501), WTC0(0xbf282501), WTC0(0xbf31f501), + WTC0(0xbf3bc601), WTC0(0xbf459681), WTC0(0xbf4f6801), WTC0(0xbf593a01), + WTC0(0xbf630d81), WTC0(0xbf6ce201), WTC0(0xbf76b701), WTC0(0xbf808b81), + WTC0(0xbf8a5f81), WTC0(0xbf943301), WTC0(0xbf9e0701), WTC0(0xbfa7dc01), + WTC0(0xbfb1b101), WTC0(0xbfbb8701), WTC0(0xbfc55c81), WTC0(0xbfcf3181), + WTC0(0xbfd90601), WTC0(0xbfe2d901), WTC0(0xbfecaa81), WTC0(0xbff67a01), + /* part 1 */ + WTC1(0x80130981), WTC1(0x80269f81), WTC1(0x803a3381), WTC1(0x804dc481), + WTC1(0x80615281), WTC1(0x8074dc01), WTC1(0x80886081), WTC1(0x809bdf01), + WTC1(0x80af5701), WTC1(0x80c2c781), WTC1(0x80d63101), WTC1(0x80e99401), + WTC1(0x80fcf181), WTC1(0x81104a01), WTC1(0x81239d81), WTC1(0x8136ea01), + WTC1(0x814a2f81), WTC1(0x815d6c01), WTC1(0x8170a181), WTC1(0x8183cf81), + WTC1(0x8196f781), WTC1(0x81aa1981), WTC1(0x81bd3401), WTC1(0x81d04681), + WTC1(0x81e34f81), WTC1(0x81f64f01), WTC1(0x82094581), WTC1(0x821c3401), + WTC1(0x822f1b01), WTC1(0x8241fa01), WTC1(0x8254cf01), WTC1(0x82679901), + WTC1(0x827a5801), WTC1(0x828d0b01), WTC1(0x829fb401), WTC1(0x82b25301), + WTC1(0x82c4e801), WTC1(0x82d77201), WTC1(0x82e9ef01), WTC1(0x82fc5f01), + WTC1(0x830ec081), WTC1(0x83211501), WTC1(0x83335c81), WTC1(0x83459881), + WTC1(0x8357c701), WTC1(0x8369e781), WTC1(0x837bf801), WTC1(0x838df801), + WTC1(0x839fe801), WTC1(0x83b1c881), WTC1(0x83c39a81), WTC1(0x83d55d01), + WTC1(0x83e70f01), WTC1(0x83f8b001), WTC1(0x840a3e81), WTC1(0x841bb981), + WTC1(0x842d2281), WTC1(0x843e7a81), WTC1(0x844fc081), WTC1(0x8460f581), + WTC1(0x84721701), WTC1(0x84832481), WTC1(0x84941d81), WTC1(0x84a50201), + WTC1(0x84b5d301), WTC1(0x84c69101), WTC1(0x84d73c01), WTC1(0x84e7d381), + WTC1(0x84f85581), WTC1(0x8508c181), WTC1(0x85191801), WTC1(0x85295881), + WTC1(0x85398481), WTC1(0x85499d01), WTC1(0x8559a081), WTC1(0x85698e81), + WTC1(0x85796601), WTC1(0x85892681), WTC1(0x8598d081), WTC1(0x85a86581), + WTC1(0x85b7e601), WTC1(0x85c75201), WTC1(0x85d6a981), WTC1(0x85e5eb81), + WTC1(0x85f51681), WTC1(0x86042c01), WTC1(0x86132c01), WTC1(0x86221801), + WTC1(0x8630f181), WTC1(0x863fb701), WTC1(0x864e6901), WTC1(0x865d0581), + WTC1(0x866b8d81), WTC1(0x867a0081), WTC1(0x86886001), WTC1(0x8696ad01), + WTC1(0x86a4e781), WTC1(0x86b30f01), WTC1(0x86c12401), WTC1(0x86cf2601), + WTC1(0x86dd1481), WTC1(0x86eaf081), WTC1(0x86f8ba81), WTC1(0x87067281), + WTC1(0x87141b01), WTC1(0x8721b481), WTC1(0x872f4201), WTC1(0x873cc201), + WTC1(0x874a2f01), WTC1(0x87578181), WTC1(0x8764b101), WTC1(0x8771c601), + WTC1(0x877ede01), WTC1(0x878c1881), WTC1(0x87998f01), WTC1(0x87a70e81), + WTC1(0x87b42481), WTC1(0x87c05e81), WTC1(0x87cb5101), WTC1(0x87d4ac81), + WTC1(0x87e73d81), WTC1(0x88124281), WTC1(0x88353501), WTC1(0x885f8481), + WTC1(0x888d3181), WTC1(0x88be1681), WTC1(0x88f13801), WTC1(0x8925f101), + WTC1(0x895bcd01), WTC1(0x89925a81), WTC1(0x89c92f81), WTC1(0x8a001f01), + WTC1(0x8a372881), WTC1(0x8a6e4a01), WTC1(0x8aa58681), WTC1(0x8adcee01), + WTC1(0x8b149701), WTC1(0x8b4c9701), WTC1(0x8b850281), WTC1(0x8bbde981), + WTC1(0x8bf75b01), WTC1(0x8c316681), WTC1(0x8c6c1b01), WTC1(0x8ca78781), + WTC1(0x8ce3ba81), WTC1(0x8d20c301), WTC1(0x8d5eaa01), WTC1(0x8d9d7781), + WTC1(0x8ddd3201), WTC1(0x8e1de001), WTC1(0x8e5f8881), WTC1(0x8ea23201), + WTC1(0x8ee5e301), WTC1(0x8f2aa101), WTC1(0x8f706f01), WTC1(0x8fb74f81), + WTC1(0x8fff4601), WTC1(0x90485401), WTC1(0x90927b81), WTC1(0x90ddc001), + WTC1(0x912a2201), WTC1(0x9177a301), WTC1(0x91c64301), WTC1(0x92160301), + WTC1(0x9266e281), WTC1(0x92b8e101), WTC1(0x930bff81), WTC1(0x93603d01), + WTC1(0x93b59901), WTC1(0x940c1281), WTC1(0x9463a881), WTC1(0x94bc5981), + WTC1(0x95162381), WTC1(0x95710601), WTC1(0x95ccff01), WTC1(0x962a0c81), + WTC1(0x96882e01), WTC1(0x96e76101), WTC1(0x9747a481), WTC1(0x97a8f681), + WTC1(0x980b5501), WTC1(0x986ebd81), WTC1(0x98d32d81), WTC1(0x9938a281), + WTC1(0x999f1981), WTC1(0x9a069001), WTC1(0x9a6f0381), WTC1(0x9ad87081), + WTC1(0x9b42d581), WTC1(0x9bae2f81), WTC1(0x9c1a7c81), WTC1(0x9c87ba81), + WTC1(0x9cf5e701), WTC1(0x9d650081), WTC1(0x9dd50481), WTC1(0x9e45f081), + WTC1(0x9eb7c101), WTC1(0x9f2a7281), WTC1(0x9f9e0301), WTC1(0xa0127081), + WTC1(0xa087b981), WTC1(0xa0fddd81), WTC1(0xa174da81), WTC1(0xa1ecae01), + WTC1(0xa2655581), WTC1(0xa2dece81), WTC1(0xa3591801), WTC1(0xa3d43001), + WTC1(0xa4501601), WTC1(0xa4ccc901), WTC1(0xa54a4701), WTC1(0xa5c89001), + WTC1(0xa647a301), WTC1(0xa6c77e01), WTC1(0xa7482101), WTC1(0xa7c98b01), + WTC1(0xa84bbb81), WTC1(0xa8ceb201), WTC1(0xa9526d81), WTC1(0xa9d6ef01), + WTC1(0xaa5c3601), WTC1(0xaae24301), WTC1(0xab691681), WTC1(0xabf0b181), + WTC1(0xac791401), WTC1(0xad023f01), WTC1(0xad8c3301), WTC1(0xae16f001), + WTC1(0xaea27681), WTC1(0xaf2ec901), WTC1(0xafbbe801), WTC1(0xb049d601), + WTC1(0xb0d89401), WTC1(0xb1682281), WTC1(0xb1f88181), WTC1(0xb289b181), + WTC1(0xb31bb301), WTC1(0xb3ae8601), WTC1(0xb4422b81), WTC1(0xb4d6a381), + WTC1(0x4a5a327f), WTC1(0x49c4adff), WTC1(0x492e637f), WTC1(0x48974f7f), + WTC1(0x47ff6d7f), WTC1(0x4766baff), WTC1(0x46cd35ff), WTC1(0x4632dd7f), + WTC1(0x4597b0ff), WTC1(0x44fbb1ff), WTC1(0x445eeaff), WTC1(0x43c165ff), + WTC1(0x4323227f), WTC1(0x4284277f), WTC1(0x41e48aff), WTC1(0x4144557f), + WTC1(0x40a3867f), WTC1(0x4001f5ff), WTC1(0x3f5f5d80), WTC1(0x3ebbad00), + WTC1(0x3e16ee40), WTC1(0x3d713d00), WTC1(0x3ccab700), WTC1(0x3c236500), + WTC1(0x3b7b5800), WTC1(0x3ad2ecc0), WTC1(0x3a2a6540), WTC1(0x3981b7c0), + WTC1(0x38d8ba00), WTC1(0x382f01c0), WTC1(0x37846240), WTC1(0x36d8eb00), + WTC1(0x362c9ec0), WTC1(0x357f7a00), WTC1(0x34d18340), WTC1(0x3422c900), + WTC1(0x33736c40), WTC1(0x32c39040), WTC1(0x32134280), WTC1(0x31629280), + WTC1(0x30b1a000), WTC1(0x30008380), WTC1(0x2f4f4240), WTC1(0x2e9df180), + WTC1(0x2decc780), WTC1(0x2d3bd640), WTC1(0x2c8b0cc0), WTC1(0x2bda3080), + WTC1(0x2b28ec80), WTC1(0x2a773500), WTC1(0x29c51b40), WTC1(0x291293c0), + WTC1(0x285f9280), WTC1(0x27ac35c0), WTC1(0x26f8ab40), WTC1(0x26454c00), + WTC1(0x25925600), WTC1(0x24dfd580), WTC1(0x242ddd40), WTC1(0x237c87c0), + WTC1(0x22cbe240), WTC1(0x221bef40), WTC1(0x216cb040), WTC1(0x20be2800), + WTC1(0x20105c80), WTC1(0x1f6352a0), WTC1(0x1eb71240), WTC1(0x1e0ba140), + WTC1(0x1d60fe40), WTC1(0x1cb723e0), WTC1(0x1c0e0300), WTC1(0x1b6596c0), + WTC1(0x1abde8a0), WTC1(0x1a16fbe0), WTC1(0x1970c680), WTC1(0x18cb4840), + WTC1(0x18268e20), WTC1(0x1782a0c0), WTC1(0x16df8960), WTC1(0x163d6300), + WTC1(0x159c52c0), WTC1(0x14fc87e0), WTC1(0x145e2c80), WTC1(0x13c15b60), + WTC1(0x13263240), WTC1(0x128cd9a0), WTC1(0x11f562a0), WTC1(0x115fc1c0), + WTC1(0x10cbf160), WTC1(0x1039f200), WTC1(0x0fa9a080), WTC1(0x0f1abd90), + WTC1(0x0e8d01d0), WTC1(0x0e003330), WTC1(0x0d743590), WTC1(0x0ce8ef40), + WTC1(0x0c5e1900), WTC1(0x0bd35d70), WTC1(0x0b488eb0), WTC1(0x0abd8410), + WTC1(0x0a320a00), WTC1(0x09a60e70), WTC1(0x0919ab00), WTC1(0x088d0de0), + WTC1(0x080065e0), WTC1(0x07739710), WTC1(0x06e65808), WTC1(0x06588348), + WTC1(0x05ca0ae0), WTC1(0x053aaaf8), WTC1(0x04a9faf0), WTC1(0x0417f698), + WTC1(0x03859ff4), WTC1(0x02f49be4), WTC1(0x0266b668), WTC1(0x01de554e), + WTC1(0x015f50ca), WTC1(0x00eb7e5d), WTC1(0x00904f24), WTC1(0x00212889), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), WTC1(0x00000000), + /* part 2 */ + WTC2(0xfffece02), WTC2(0xffe4c3df), WTC2(0xffcaaa55), WTC2(0xffb087d1), + WTC2(0xff9662bf), WTC2(0xff7c418b), WTC2(0xff622aa0), WTC2(0xff48246c), + WTC2(0xff2e355a), WTC2(0xff1463db), WTC2(0xfefab608), WTC2(0xfee12f0a), + WTC2(0xfec7cfd2), WTC2(0xfeae995a), WTC2(0xfe958cc4), WTC2(0xfe7cabce), + WTC2(0xfe63f882), WTC2(0xfe4b74e0), WTC2(0xfe3322f6), WTC2(0xfe1b04dc), + WTC2(0xfe031ccc), WTC2(0xfdeb6cf0), WTC2(0xfdd3ff7c), WTC2(0xfdbce834), + WTC2(0xfda63bb8), WTC2(0xfd900c68), WTC2(0xfd7a590c), WTC2(0xfd6511b4), + WTC2(0xfd5026c0), WTC2(0xfd3b8954), WTC2(0xfd272df0), WTC2(0xfd130adc), + WTC2(0xfcff15ac), WTC2(0xfceb4a68), WTC2(0xfcd7b110), WTC2(0xfcc454d0), + WTC2(0xfcb14064), WTC2(0xfc9e896c), WTC2(0xfc8c5264), WTC2(0xfc7abef0), + WTC2(0xfc69f078), WTC2(0xfc59f5e8), WTC2(0xfc4acfec), WTC2(0xfc3c8060), + WTC2(0xfc2f0264), WTC2(0xfc223b7c), WTC2(0xfc160714), WTC2(0xfc0a4150), + WTC2(0xfbfec920), WTC2(0xfbf38320), WTC2(0xfbe855d0), WTC2(0xfbdd2740), + WTC2(0xfbd1fc68), WTC2(0xfbc6fea0), WTC2(0xfbbc5a48), WTC2(0xfbb23b48), + WTC2(0xfba8ca78), WTC2(0xfba02e50), WTC2(0xfb988de0), WTC2(0xfb920b40), + WTC2(0xfb8cb870), WTC2(0xfb889f68), WTC2(0xfb85cbe8), WTC2(0xfb843dd0), + WTC2(0xfb83df78), WTC2(0xfb8495d0), WTC2(0xfb864660), WTC2(0xfb88d4a8), + WTC2(0xfb8c21e8), WTC2(0xfb900f28), WTC2(0xfb947dc0), WTC2(0xfb9950c0), + WTC2(0xfb9e6d08), WTC2(0xfba3b658), WTC2(0xfba91908), WTC2(0xfbae9e08), + WTC2(0xfbb45bd0), WTC2(0xfbba66f8), WTC2(0xfbc0dcf0), WTC2(0xfbc7ead8), + WTC2(0xfbcfc200), WTC2(0xfbd89330), WTC2(0xfbe294d0), WTC2(0xfbee03d0), + WTC2(0xfbfb1de8), WTC2(0xfc0a1da4), WTC2(0xfc1b22e0), WTC2(0xfc2e38f0), + WTC2(0xfc436d48), WTC2(0xfc5abf7c), WTC2(0xfc74024c), WTC2(0xfc8ef2e8), + WTC2(0xfcab51ac), WTC2(0xfcc8d024), WTC2(0xfce704f0), WTC2(0xfd0580cc), + WTC2(0xfd23d4d0), WTC2(0xfd41ce40), WTC2(0xfd5f81b0), WTC2(0xfd7d08f0), + WTC2(0xfd9a8560), WTC2(0xfdb85938), WTC2(0xfdd71798), WTC2(0xfdf753b8), + WTC2(0xfe1993ee), WTC2(0xfe3e30f8), WTC2(0xfe656cba), WTC2(0xfe8f8fdc), + WTC2(0xfebca8a4), WTC2(0xfeec590e), WTC2(0xff1e285c), WTC2(0xff51a0b7), + WTC2(0xff866330), WTC2(0xffbc2cbb), WTC2(0xfff2bbff), WTC2(0x0029d79d), + WTC2(0x00618a22), WTC2(0x009a1185), WTC2(0x00d3aa8c), WTC2(0x010e8ff6), + WTC2(0x014af29e), WTC2(0x0188fe56), WTC2(0x01c8e108), WTC2(0x020ab3c4), + WTC2(0x024e68a8), WTC2(0x0293e824), WTC2(0x02db1bc8), WTC2(0x0323f1a4), + WTC2(0x036e5d6c), WTC2(0x03ba5320), WTC2(0x0407c938), WTC2(0x0456cad0), + WTC2(0x04a77288), WTC2(0x04f9db88), WTC2(0x054e1888), WTC2(0x05a41ef0), + WTC2(0x05fbd6e0), WTC2(0x065528c0), WTC2(0x06b00838), WTC2(0x070c7ee0), + WTC2(0x076a9bb0), WTC2(0x07ca6d10), WTC2(0x082c08e0), WTC2(0x088f8da0), + WTC2(0x08f51ac0), WTC2(0x095ccc20), WTC2(0x09c69f70), WTC2(0x0a327b40), + WTC2(0x0aa046d0), WTC2(0x0b0febb0), WTC2(0x0b815dd0), WTC2(0x0bf49600), + WTC2(0x0c698c50), WTC2(0x0ce03ba0), WTC2(0x0d58a380), WTC2(0x0dd2c510), + WTC2(0x0e4ea110), WTC2(0x0ecc3dd0), WTC2(0x0f4ba800), WTC2(0x0fcced10), + WTC2(0x10501960), WTC2(0x10d532a0), WTC2(0x115c39c0), WTC2(0x11e52fa0), + WTC2(0x12701560), WTC2(0x12fcef20), WTC2(0x138bc200), WTC2(0x141c9300), + WTC2(0x14af64a0), WTC2(0x154434e0), WTC2(0x15db0020), WTC2(0x1673c360), + WTC2(0x170e7e80), WTC2(0x17ab35e0), WTC2(0x1849ee40), WTC2(0x18eaaba0), + WTC2(0x198d6f00), WTC2(0x1a3236a0), WTC2(0x1ad90080), WTC2(0x1b81cc60), + WTC2(0x1c2c9da0), WTC2(0x1cd97980), WTC2(0x1d8865c0), WTC2(0x1e396540), + WTC2(0x1eec7700), WTC2(0x1fa198c0), WTC2(0x2058c840), WTC2(0x21120640), + WTC2(0x21cd5700), WTC2(0x228abec0), WTC2(0x234a4180), WTC2(0x240bdf80), + WTC2(0x24cf95c0), WTC2(0x259561c0), WTC2(0x265d4200), WTC2(0x27273840), + WTC2(0x27f348c0), WTC2(0x28c17700), WTC2(0x2991c500), WTC2(0x2a643080), + WTC2(0x2b38b680), WTC2(0x2c0f53c0), WTC2(0x2ce80840), WTC2(0x2dc2d680), + WTC2(0x2e9fc100), WTC2(0x2f7ecac0), WTC2(0x305ff280), WTC2(0x314334c0), + WTC2(0x32288e00), WTC2(0x330ffb80), WTC2(0x33f97d80), WTC2(0x34e515c0), + WTC2(0x35d2c5c0), WTC2(0x36c28d00), WTC2(0x37b467c0), WTC2(0x38a85080), + WTC2(0x399e4240), WTC2(0x3a963a00), WTC2(0x3b903600), WTC2(0x3c8c3480), + WTC2(0x3d8a3380), WTC2(0x3e8a2dc0), WTC2(0x3f8c1b40), WTC2(0x408ff2ff), + WTC2(0x4195ae7f), WTC2(0x429d477f), WTC2(0x43a6b87f), WTC2(0x44b1fdff), + WTC2(0x45bf11ff), WTC2(0x46cdee7f), WTC2(0x47de8cff), WTC2(0x48f0e77f), + WTC2(0x4a050eff), WTC2(0x4b1b2dff), WTC2(0x4c3372ff), WTC2(0x4d4e0bff), + WTC2(0x4e6b257f), WTC2(0x4f8aedff), WTC2(0x50ad92ff), WTC2(0x51d341ff), + WTC2(0x002006a9), WTC2(0x000bfb36), WTC2(0xfffe45ac), WTC2(0xfff6d064), + WTC2(0xfff585bc), WTC2(0xfffa500d), WTC2(0x000519b4), WTC2(0x0015cd0c), + WTC2(0x002c5470), WTC2(0x00489a3b), WTC2(0x006a88c8), WTC2(0x00920a74), + WTC2(0x00bf0999), WTC2(0x00f17092), WTC2(0x012929bc), WTC2(0x01661f70), + WTC2(0x01a83c0c), WTC2(0x01ef69e8), WTC2(0x023b9364), WTC2(0x028ca2d4), + WTC2(0x02e2829c), WTC2(0x033d1d10), WTC2(0x039c5c90), WTC2(0x04002b78), + WTC2(0x04687418), WTC2(0x04d520e0), WTC2(0x05461c18), WTC2(0x05bb5020), + WTC2(0x0634a758), WTC2(0x06b20c20), WTC2(0x073368c8), WTC2(0x07b8a7b0), + WTC2(0x0841b340), WTC2(0x08ce75b0), WTC2(0x095ed980), WTC2(0x09f2c900), + WTC2(0x0a8a2e80), WTC2(0x0b24f470), WTC2(0x0bc30510), WTC2(0x0c644ad0), + WTC2(0x0d08b010), WTC2(0x0db01f10), WTC2(0x0e5a8250), WTC2(0x0f07c400), + WTC2(0x0fb7cea0), WTC2(0x106a8c80), WTC2(0x111fe800), WTC2(0x11d7cb60), + WTC2(0x12922120), WTC2(0x134ed3a0), WTC2(0x140dcd00), WTC2(0x14cef7e0), + WTC2(0x15923e60), WTC2(0x16578b00), WTC2(0x171ec820), WTC2(0x17e7e020), + WTC2(0x18b2bd20), WTC2(0x197f49c0), WTC2(0x1a4d7040), WTC2(0x1b1d1b00), + WTC2(0x1bee3460), WTC2(0x1cc0a6a0), WTC2(0x1d945c40), WTC2(0x1e693f80), + WTC2(0x1f3f3ac0), WTC2(0x20163880), WTC2(0x20ee22c0), WTC2(0x21c6e440), + WTC2(0x22a06740), WTC2(0x237a9600), WTC2(0x24555ac0), WTC2(0x2530a040), + WTC2(0x260c5080), WTC2(0x26e85600), WTC2(0x27c49b00), WTC2(0x28a10a00), + WTC2(0x297d8d80), WTC2(0x2a5a0f80), WTC2(0x2b367a80), WTC2(0x2c12b8c0), + WTC2(0x2ceeb500), WTC2(0x2dca5940), WTC2(0x2ea58fc0), WTC2(0x2f804340), + WTC2(0x305a5dc0), WTC2(0x3133ca00), WTC2(0x320c7200), WTC2(0x32e44000), + WTC2(0x33bb1ec0), WTC2(0x3490f880), WTC2(0x3565b7c0), WTC2(0x36394640), + WTC2(0x370b8f00), WTC2(0x37dc7c00), WTC2(0x38abf7c0), WTC2(0x3979ecc0), + WTC2(0x3a464500), WTC2(0x3b10eb00), WTC2(0x3bd9c940), WTC2(0x3ca0c9c0), + WTC2(0x3d65d740), WTC2(0x3e28dc00), WTC2(0x3ee9c240), WTC2(0x3fa87480), + WTC2(0x4064dcff), WTC2(0x411ee67f), WTC2(0x41d67a7f), WTC2(0x428b847f), + WTC2(0x433ded7f), WTC2(0x43eda0ff), WTC2(0x449a887f), WTC2(0x45448f7f), + WTC2(0x45eb9eff), WTC2(0x468fa1ff), WTC2(0x473082ff), WTC2(0x47ce2c7f), + WTC2(0x4868887f), WTC2(0x48ff80ff), WTC2(0x499300ff), WTC2(0x4a22f2ff), + WTC2(0x4aaf407f), WTC2(0x4b37d47f), WTC2(0x4bbc997f), WTC2(0x4c3d78ff), + WTC2(0x4cba5e7f), WTC2(0x4d33337f), WTC2(0x4da7e27f), WTC2(0x4e18567f), + WTC2(0x4e8478ff), WTC2(0x4eec347f), WTC2(0x4f4f737f), WTC2(0x4fae20ff), + WTC2(0x500825ff), WTC2(0x505d6dff), WTC2(0x50ade37f), WTC2(0x50f96f7f), + WTC2(0x513ffdff), WTC2(0x518177ff), WTC2(0x51bdc87f), WTC2(0x51f4d9ff), + WTC2(0x5226967f), WTC2(0x5252e87f), WTC2(0x5279b9ff), WTC2(0x529af5ff), + WTC2(0x52b6867f), WTC2(0x52cc55ff), WTC2(0x52dc4eff), WTC2(0x52e65aff), + WTC2(0x52ea657f), WTC2(0x52e857ff), WTC2(0x52e01d7f), WTC2(0x52d19fff), + WTC2(0x52bcc9ff), WTC2(0x52a1857f), WTC2(0x527fbd7f), WTC2(0x52575b7f), + WTC2(0x52284a7f), WTC2(0x51f274ff), WTC2(0x51b5c47f), WTC2(0x5172247f), + WTC2(0x51277dff), WTC2(0x50d5bc7f), WTC2(0x507cc9ff), WTC2(0x501c90ff), + WTC2(0x4fb4fb7f), WTC2(0x4f45f3ff), WTC2(0x4ecf64ff), WTC2(0x4e5138ff), + WTC2(0x4dcb597f), WTC2(0x4d3db1ff), WTC2(0x4ca82bff), WTC2(0x4c0ab27f), + WTC2(0x4b652f7f), WTC2(0x4ab78d7f), WTC2(0x4a01b67f), WTC2(0x4943957f), + WTC2(0x487d12ff), WTC2(0x47ae1f7f), WTC2(0x46d68f7f), WTC2(0x45f7187f), + WTC2(0x4513597f), WTC2(0x4430467f), WTC2(0x4352d2ff), WTC2(0x427e6bff), + WTC2(0x41b390ff), WTC2(0x40f2077f), WTC2(0x4039a87f), WTC2(0x3f8a3100), + WTC2(0x3ee33e00), WTC2(0x3e446ac0), WTC2(0x3dad5180), WTC2(0x3d1d7fc0), + WTC2(0x3c947b00), WTC2(0x3c11c7c0), WTC2(0x3b94ebc0), WTC2(0x3b1d6dc0), + WTC2(0x3aaad480), WTC2(0x3a3ca740), WTC2(0x39d26c40), WTC2(0x396ba8c0), + WTC2(0x3907e080), WTC2(0x38a69800), WTC2(0x38473d80), WTC2(0x37e923c0), + WTC2(0x378b9b80), WTC2(0x372e0380), WTC2(0x36d03a80), WTC2(0x36727f00), + WTC2(0x36150e40), WTC2(0x35b81540), WTC2(0x355b8000), WTC2(0x34ff1dc0), + WTC2(0x34a2bfc0), WTC2(0x34463e80), WTC2(0x33e982c0), WTC2(0x338c7880), + WTC2(0x332f0bc0), WTC2(0x32d11800), WTC2(0x327265c0), WTC2(0x3212bbc0), + WTC2(0x31b1e740), WTC2(0x314fef00), WTC2(0x30ed0540), WTC2(0x30895c80), + WTC2(0x30251880), WTC2(0x2fc02880), WTC2(0x2f5a6480), WTC2(0x2ef3a480), + WTC2(0x2e8bd640), WTC2(0x2e231100), WTC2(0x2db97680), WTC2(0x2d4f2700), + WTC2(0x2ce431c0), WTC2(0x2c789080), WTC2(0x2c0c3bc0), WTC2(0x2b9f2bc0), + WTC2(0x2b315940), WTC2(0x2ac2bc00), WTC2(0x2a534cc0), WTC2(0x29e303c0)}; + +const FIXP_WTB ELDAnalysis256[768] = { + WTC(0xfababde8), WTC(0xfa8e1e6a), WTC(0xfa6012a9), WTC(0xfa30c8dd), + WTC(0xfa006f4b), WTC(0xf9cf32c4), WTC(0xf99d1cc8), WTC(0xf96a148d), + WTC(0xf936184d), WTC(0xf9013d5b), WTC(0xf8cb7b67), WTC(0xf894ace0), + WTC(0xf85cd28e), WTC(0xf82413f8), WTC(0xf7ea90af), WTC(0xf7b05ee6), + WTC(0xf7759b0b), WTC(0xf73a671f), WTC(0xf6febea3), WTC(0xf6c27a0e), + WTC(0xf685ca33), WTC(0xf6493907), WTC(0xf60d437b), WTC(0xf5d2551f), + WTC(0xf598d273), WTC(0xf561199e), WTC(0xf52b8c6f), WTC(0xf4f8907d), + WTC(0xf4c87fdf), WTC(0xf49ba806), WTC(0xf4724286), WTC(0xf44c6127), + WTC(0xf4282435), WTC(0xf401ceae), WTC(0xf3d775a1), WTC(0xf3a91477), + WTC(0xf376c33f), WTC(0xf340a328), WTC(0xf306d4d6), WTC(0xf2c9775c), + WTC(0xf288a3ed), WTC(0xf2446e2a), WTC(0xf1fcfa45), WTC(0xf1b27b2d), + WTC(0xf164f3f4), WTC(0xf114365c), WTC(0xf0c00532), WTC(0xf06817a9), + WTC(0xf00c4ea4), WTC(0xefacbc7f), WTC(0xef4a205f), WTC(0xeee5dc33), + WTC(0xee808a0d), WTC(0xee19eeb2), WTC(0xedb12f6e), WTC(0xed44e8eb), + WTC(0xecd50a13), WTC(0xec62d8dd), WTC(0xebef68b2), WTC(0xeb7b805c), + WTC(0xeb069af4), WTC(0xea8eef1c), WTC(0xea131c86), WTC(0xe99234c6), + WTC(0xe90cd9c2), WTC(0xe884f65b), WTC(0xe7fcbd6d), WTC(0xe7767300), + WTC(0xe6f289d0), WTC(0xe66f958a), WTC(0xe5eae99f), WTC(0xe560c403), + WTC(0xe4cfaaa1), WTC(0xe43887dc), WTC(0xe39dedc4), WTC(0xe303f190), + WTC(0xe26d7f5d), WTC(0xe1dc34ff), WTC(0xe14f9ced), WTC(0xe0c53cd0), + WTC(0xe03ab085), WTC(0xdfadc948), WTC(0xdf1d640c), WTC(0xde896bb6), + WTC(0xddf256ad), WTC(0xdd591e3d), WTC(0xdcbf0aec), WTC(0xdc25ab0a), + WTC(0xdb8e334c), WTC(0xdaf97794), WTC(0xda67bed9), WTC(0xd9d8c524), + WTC(0xd94bfa62), WTC(0xd8c089b5), WTC(0xd835c151), WTC(0xd7ab1704), + WTC(0xd7200906), WTC(0xd69420dc), WTC(0xd6073c0d), WTC(0xd5799615), + WTC(0xd4ec7c87), WTC(0xd46241c9), WTC(0xd3dc5bde), WTC(0xd35b4a79), + WTC(0xd2de1032), WTC(0xd26246f5), WTC(0xd1e68ed2), WTC(0xd16aa0a4), + WTC(0xd0eea5d2), WTC(0xd073302b), WTC(0xcff93749), WTC(0xcf820f45), + WTC(0xcf0ebb30), WTC(0xce9fd702), WTC(0xce34596c), WTC(0xcdc9a803), + WTC(0xcd5ec5d6), WTC(0xccf468ec), WTC(0xcc8bb41e), WTC(0xcc2619cc), + WTC(0xcbc3e090), WTC(0xcb6422f5), WTC(0xcb064d2f), WTC(0xcaaa2a6d), + WTC(0xca4fbdc9), WTC(0xc9f73c43), WTC(0xc9a0dc9b), WTC(0xc94cdd02), + WTC(0xc8f578a4), WTC(0xc8a24d15), WTC(0xc84dc71f), WTC(0xc7f83516), + WTC(0xc7a1e4b9), WTC(0xc74b22b1), WTC(0xc6f41284), WTC(0xc69cabc1), + WTC(0xc644986d), WTC(0xc5eb4167), WTC(0xc5910312), WTC(0xc5372c7f), + WTC(0xc4deba2e), WTC(0xc4883eca), WTC(0xc43310f0), WTC(0xc3dd5c5a), + WTC(0xc3868802), WTC(0xc32f431d), WTC(0xc2d86c9e), WTC(0xc28300a6), + WTC(0xc22fae33), WTC(0xc1ded3f7), WTC(0xc1908d7d), WTC(0xc144b0ed), + WTC(0xc0fa7cee), WTC(0xc0b0a3b5), WTC(0xc066b8d3), WTC(0xc01d3b32), + WTC(0xbfd5161c), WTC(0xbf8f92af), WTC(0xbf4d5cea), WTC(0xbf0e7d5e), + WTC(0xbed2ce3a), WTC(0xbe9a0062), WTC(0xbe63cec2), WTC(0xbe2ffd2f), + WTC(0xbdfe4565), WTC(0xbdce5568), WTC(0xbda003df), WTC(0xbd735018), + WTC(0xbd485b2c), WTC(0xbd1f69bd), WTC(0xbcf8db7c), WTC(0xbcd52b0a), + WTC(0xbcb4ae4a), WTC(0xbc979382), WTC(0xbc7dcbab), WTC(0xbc6709dc), + WTC(0xbc52c1b1), WTC(0xbc402f2b), WTC(0xbc2ec37b), WTC(0xbc1e2cb3), + WTC(0xbc0e5d5f), WTC(0xbbff8f23), WTC(0xbbf238d2), WTC(0xbbe707d4), + WTC(0xbbde3c63), WTC(0xbbd7a658), WTC(0xbbd2c7f0), WTC(0xbbcee18b), + WTC(0xbbcbdebb), WTC(0xbbca5ab1), WTC(0xbbcb5622), WTC(0xbbd032e4), + WTC(0xbbd91d4d), WTC(0xbbe53757), WTC(0xbbf32f54), WTC(0xbc016781), + WTC(0xbc0f433a), WTC(0xbc1d2aa4), WTC(0xbc2b4912), WTC(0xbc3985df), + WTC(0xbc47d6b9), WTC(0xbc564099), WTC(0xbc64c78a), WTC(0xbc736d96), + WTC(0xbc823210), WTC(0xbc911484), WTC(0xbca015b8), WTC(0xbcaf37eb), + WTC(0xbcbe7bc3), WTC(0xbccdde4d), WTC(0xbcdd6037), WTC(0xbced049a), + WTC(0xbcfccc81), WTC(0xbd0cb482), WTC(0xbd1cbcaa), WTC(0xbd2ce7ea), + WTC(0xbd3d363b), WTC(0xbd4da445), WTC(0xbd5e312d), WTC(0xbd6edfd1), + WTC(0xbd7fae14), WTC(0xbd90991b), WTC(0xbda19fcf), WTC(0xbdb2c464), + WTC(0xbdc4053b), WTC(0xbdd55f4b), WTC(0xbde6d0a0), WTC(0xbdf85c51), + WTC(0xbe09ffa3), WTC(0xbe1bb724), WTC(0xbe2d8160), WTC(0xbe3f5f98), + WTC(0xbe515144), WTC(0xbe6351a9), WTC(0xbe755ebd), WTC(0xbe877b8e), + WTC(0xbe99a63d), WTC(0xbeabda45), WTC(0xbebe16b0), WTC(0xbed05d1c), + WTC(0xbee2ada9), WTC(0xbef502e2), WTC(0xbf075c40), WTC(0xbf19bc0b), + WTC(0xbf2c217f), WTC(0xbf3e887a), WTC(0xbf50f09d), WTC(0xbf635c77), + WTC(0xbf75cac0), WTC(0xbf883905), WTC(0xbf9aa62b), WTC(0xbfad14f1), + WTC(0xbfbf85c7), WTC(0xbfd1f592), WTC(0xbfe461fc), WTC(0xbff6c86a), + WTC(0x80126c8d), WTC(0x80372448), WTC(0x805bd2fd), WTC(0x80807315), + WTC(0x80a4fffa), WTC(0x80c9748d), WTC(0x80edd08b), WTC(0x81121a23), + WTC(0x81364fde), WTC(0x815a6b16), WTC(0x817e6b36), WTC(0x81a25433), + WTC(0x81c625c8), WTC(0x81e9d801), WTC(0x820d6a5c), WTC(0x8230e060), + WTC(0x825438c0), WTC(0x82776ac7), WTC(0x829a7555), WTC(0x82bd5ca3), + WTC(0x82e01e80), WTC(0x8302b200), WTC(0x83251590), WTC(0x83474d79), + WTC(0x8369566f), WTC(0x838b2957), WTC(0x83acc2d9), WTC(0x83ce27c1), + WTC(0x83ef54b9), WTC(0x841042d1), WTC(0x8430ef15), WTC(0x84515e84), + WTC(0x84718e32), WTC(0x84917804), WTC(0x84b11a25), WTC(0x84d0788d), + WTC(0x84ef9322), WTC(0x850e61ec), WTC(0x852ce400), WTC(0x854b1e0a), + WTC(0x85690f2c), WTC(0x8586b207), WTC(0x85a4057b), WTC(0x85c1107d), + WTC(0x85ddd335), WTC(0x85fa485e), WTC(0x86167172), WTC(0x8632549d), + WTC(0x864df388), WTC(0x8669497e), WTC(0x86845757), WTC(0x869f2218), + WTC(0x86b9ab5a), WTC(0x86d3f1bf), WTC(0x86edf68f), WTC(0x8707baf1), + WTC(0x872147e0), WTC(0x873aa6fc), WTC(0x8753c571), WTC(0x876c76e6), + WTC(0x87850ab7), WTC(0x879e373b), WTC(0x87b6ea37), WTC(0x87cc4188), + WTC(0x880d4300), WTC(0x8855e9ff), WTC(0x88acfca0), WTC(0x890d0f94), + WTC(0x8971e7d5), WTC(0x89d8a0c1), WTC(0x8a3fc425), WTC(0x8aa74105), + WTC(0x8b0f5b93), WTC(0x8b78a107), WTC(0x8be38bb3), WTC(0x8c508092), + WTC(0x8cbfe384), WTC(0x8d3214f1), WTC(0x8da75d21), WTC(0x8e1fe96c), + WTC(0x8e9be76a), WTC(0x8f1b806c), WTC(0x8f9ed314), WTC(0x9025f26a), + WTC(0x90b0ecea), WTC(0x913fd0eb), WTC(0x91d2a684), WTC(0x92696dea), + WTC(0x93042868), WTC(0x93a2d456), WTC(0x94456d20), WTC(0x94ebe9e5), + WTC(0x95964178), WTC(0x96446a05), WTC(0x96f65958), WTC(0x97ac059a), + WTC(0x98656089), WTC(0x99225a80), WTC(0x99e2e2e8), WTC(0x9aa6e666), + WTC(0x9b6e54b8), WTC(0x9c391d99), WTC(0x9d07338a), WTC(0x9dd8888d), + WTC(0x9ead0b5c), WTC(0x9f84a871), WTC(0xa05f4fb3), WTC(0xa13cf913), + WTC(0xa21d9891), WTC(0xa3011e27), WTC(0xa3e77eb4), WTC(0xa4d0b190), + WTC(0xa5bcb0d7), WTC(0xa6ab750c), WTC(0xa79cf884), WTC(0xa89135cb), + WTC(0xa9882a44), WTC(0xaa81d578), WTC(0xab7e39a6), WTC(0xac7d5a36), + WTC(0xad7f3ba5), WTC(0xae83dfed), WTC(0xaf8b4e16), WTC(0xb095911c), + WTC(0xb1a2afd1), WTC(0xb2b2ac9f), WTC(0xb3c58807), WTC(0xb4db4d5e), + WTC(0x4a268ead), WTC(0x490b5ba7), WTC(0x47ed8d30), WTC(0x46cd10c5), + WTC(0x45a9dcc1), WTC(0x4483f267), WTC(0x435b5aeb), WTC(0x42301d12), + WTC(0x41023a15), WTC(0x3fd19bf1), WTC(0x3e9e31e1), WTC(0x3d682986), + WTC(0x3c2fc001), WTC(0x3af52d8f), WTC(0x39b88b7d), WTC(0x38798642), + WTC(0x3737e6d3), WTC(0x35f3e98a), WTC(0x34add45c), WTC(0x33660083), + WTC(0x321ccf3a), WTC(0x30d2963e), WTC(0x2f87a28f), WTC(0x2e3c22cd), + WTC(0x2cf010e5), WTC(0x2ba2ffe5), WTC(0x2a54ba93), WTC(0x290596f5), + WTC(0x27b62806), WTC(0x266762b8), WTC(0x251a11b1), WTC(0x23ce94f9), + WTC(0x22852ddb), WTC(0x213df340), WTC(0x1ff90185), WTC(0x1eb67d94), + WTC(0x1d767485), WTC(0x1c38d477), WTC(0x1afda747), WTC(0x19c5248b), + WTC(0x188f8259), WTC(0x175d0d40), WTC(0x162e5320), WTC(0x150436cd), + WTC(0x13df8d3f), WTC(0x12c102f1), WTC(0x11a8dd65), WTC(0x1096d490), + WTC(0x0f8a1755), WTC(0x0e811dcd), WTC(0x0d7acb9a), WTC(0x0c767d00), + WTC(0x0b7334d9), WTC(0x0a6fef31), WTC(0x096c5a87), WTC(0x08691adb), + WTC(0x0765e395), WTC(0x06610309), WTC(0x0558a0d2), WTC(0x044a946c), + WTC(0x033acb52), WTC(0x0234706f), WTC(0x014939dc), WTC(0x00928577), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffe73593), WTC(0xffb63fcf), WTC(0xff853c1f), WTC(0xff5454d7), + WTC(0xff23b44b), WTC(0xfef38417), WTC(0xfec3dc9a), WTC(0xfe94c511), + WTC(0xfe664753), WTC(0xfe387086), WTC(0xfe0b4e63), WTC(0xfddef15c), + WTC(0xfdb3a3f6), WTC(0xfd89e611), WTC(0xfd61c750), WTC(0xfd3ae585), + WTC(0xfd14ec09), WTC(0xfcef9b06), WTC(0xfccaf509), WTC(0xfca74180), + WTC(0xfc8518a3), WTC(0xfc655c7a), WTC(0xfc488545), WTC(0xfc2e9998), + WTC(0xfc1726bb), WTC(0xfc01463f), WTC(0xfbec2c64), WTC(0xfbd735ce), + WTC(0xfbc29e8e), WTC(0xfbaf8042), WTC(0xfb9eeba0), WTC(0xfb91dc05), + WTC(0xfb88f420), WTC(0xfb8479eb), WTC(0xfb84398b), WTC(0xfb87884b), + WTC(0xfb8da8bf), WTC(0xfb95d020), WTC(0xfb9f3e49), WTC(0xfba9448a), + WTC(0xfbb3cf10), WTC(0xfbbf67e7), WTC(0xfbccf65d), WTC(0xfbddba58), + WTC(0xfbf31f46), WTC(0xfc0eb236), WTC(0xfc3164f0), WTC(0xfc5b8269), + WTC(0xfc8c5bcd), WTC(0xfcc248ee), WTC(0xfcfb056c), WTC(0xfd33cc26), + WTC(0xfd6b84ee), WTC(0xfda2d9e7), WTC(0xfddc03fb), WTC(0xfe1aaf57), + WTC(0xfe61a0af), WTC(0xfeb28df7), WTC(0xff0cd343), WTC(0xff6d8388), + WTC(0xffd24331), WTC(0x00396fe3), WTC(0x00a2fb3e), WTC(0x01107050), + WTC(0x01831900), WTC(0x01fc2377), WTC(0x027bd1fc), WTC(0x03019a2d), + WTC(0x038d0a88), WTC(0x041dd88f), WTC(0x04b43495), WTC(0x0550c1ef), + WTC(0x05f38bd6), WTC(0x069c0523), WTC(0x074a114e), WTC(0x07fe0ceb), + WTC(0x08b88e33), WTC(0x097a5965), WTC(0x0a438318), WTC(0x0b137046), + WTC(0x0be9b5ab), WTC(0x0cc61fa9), WTC(0x0da897b2), WTC(0x0e9123b3), + WTC(0x0f7ff200), WTC(0x10755696), WTC(0x11717f94), WTC(0x127474a0), + WTC(0x137e489d), WTC(0x148f1b02), WTC(0x15a6f15e), WTC(0x16c5b7c9), + WTC(0x17eb72b1), WTC(0x19183e51), WTC(0x1a4c2444), WTC(0x1b871b1c), + WTC(0x1cc92e92), WTC(0x1e127ffc), WTC(0x1f6319b9), WTC(0x20baef78), + WTC(0x221a0861), WTC(0x23807f94), WTC(0x24ee5a89), WTC(0x2663898d), + WTC(0x27e0101e), WTC(0x2964058d), WTC(0x2aef6bcf), WTC(0x2c8230fc), + WTC(0x2e1c545b), WTC(0x2fbde72b), WTC(0x3166e76f), WTC(0x33173f5d), + WTC(0x34cee8c3), WTC(0x368debe1), WTC(0x38543d4f), WTC(0x3a21bd94), + WTC(0x3bf6576f), WTC(0x3dd1ff07), WTC(0x3fb4948e), WTC(0x419de414), + WTC(0x438dc202), WTC(0x45840e7d), WTC(0x4780a435), WTC(0x4983609f), + WTC(0x4b8cc548), WTC(0x4d9df796), WTC(0x4fb81f46), WTC(0x51dc8690), + WTC(0x000d970d), WTC(0xfff7ea67), WTC(0xfff7fc3d), WTC(0x000d3de2), + WTC(0x003720ad), WTC(0x007515f1), WTC(0x00c68f04), WTC(0x012afd3b), + WTC(0x01a1d1ec), WTC(0x022a7e69), WTC(0x02c47408), WTC(0x036f2420), + WTC(0x042a0001), WTC(0x04f47905), WTC(0x05ce007e), WTC(0x06b607be), + WTC(0x07ac0028), WTC(0x08af5b01), WTC(0x09bf89a7), WTC(0x0adbfd6d), + WTC(0x0c042798), WTC(0x0d377997), WTC(0x0e7564b5), WTC(0x0fbd5a3a), + WTC(0x110ecb85), WTC(0x126929fb), WTC(0x13cbe6e6), WTC(0x15367376), + WTC(0x16a8413f), WTC(0x1820c15f), WTC(0x199f6568), WTC(0x1b239e6b), + WTC(0x1cacdde2), WTC(0x1e3a951a), WTC(0x1fcc356f), WTC(0x2161301f), + WTC(0x22f8f6b7), WTC(0x2492fa4a), WTC(0x262eac3f), WTC(0x27cb7e20), + WTC(0x2968e0c4), WTC(0x2b064625), WTC(0x2ca31f1a), WTC(0x2e3edd2a), + WTC(0x2fd8f19f), WTC(0x3170ce00), WTC(0x3305e32c), WTC(0x3497a2df), + WTC(0x36257e78), WTC(0x37aee70b), WTC(0x39334e05), WTC(0x3ab22498), + WTC(0x3c2adc2c), WTC(0x3d9ce645), WTC(0x3f07b3ef), WTC(0x406ab6ca), + WTC(0x41c56001), WTC(0x4317214a), WTC(0x445f6b34), WTC(0x459daf5d), + WTC(0x46d15f56), WTC(0x47f9ed71), WTC(0x4916d11f), WTC(0x4a275770), + WTC(0x4b2b2fff), WTC(0x4c219eae), WTC(0x4d0a20cb), WTC(0x4de4288e), + WTC(0x4eaf263d), WTC(0x4f6a8bb8), WTC(0x5015ca33), WTC(0x50b052dd), + WTC(0x51399757), WTC(0x51b108c6), WTC(0x5216190a), WTC(0x5268387c), + WTC(0x52a6d933), WTC(0x52d16c19), WTC(0x52e7628b), WTC(0x52e82ea3), + WTC(0x52d3407d), WTC(0x52a80a28), WTC(0x5265fd43), WTC(0x520c8a1d), + WTC(0x519b22c8), WTC(0x511138e0), WTC(0x506e3c82), WTC(0x4fb1a037), + WTC(0x4edad4e3), WTC(0x4de94c2d), WTC(0x4cdc76d8), WTC(0x4bb3c683), + WTC(0x4a6eacd2), WTC(0x490c9abe), WTC(0x478d04f1), WTC(0x45f00420), + WTC(0x4445673f), WTC(0x42ac0d2e), WTC(0x41338364), WTC(0x3fdb5b58), + WTC(0x3ea1c30f), WTC(0x3d842780), WTC(0x3c7fa763), WTC(0x3b911b96), + WTC(0x3ab560bf), WTC(0x39e95908), WTC(0x3929debb), WTC(0x3873bd4d), + WTC(0x37c31db2), WTC(0x3713a59c), WTC(0x3663deb2), WTC(0x35b52f23), + WTC(0x3507c61e), WTC(0x345a7f42), WTC(0x33ac7e0c), WTC(0x32fd366f), + WTC(0x324baa28), WTC(0x319674e9), WTC(0x30dd7e1a), WTC(0x3021f3e8), + WTC(0x2f63f903), WTC(0x2ea2a1aa), WTC(0x2dddd97b), WTC(0x2d166985), + WTC(0x2c4ca42f), WTC(0x2b805cca), WTC(0x2ab162aa), WTC(0x29df7b17), +}; + +const FIXP_WTB ELDAnalysis240[720] = { + WTC(0xfab9477b), WTC(0xfa899344), WTC(0xfa5845dd), WTC(0xfa259762), + WTC(0xf9f1c005), WTC(0xf9bcefe6), WTC(0xf9871e8b), WTC(0xf9503397), + WTC(0xf9183f47), WTC(0xf8df4eac), WTC(0xf8a53ba7), WTC(0xf869f0be), + WTC(0xf82d9759), WTC(0xf7f0593e), WTC(0xf7b2520a), WTC(0xf773a37c), + WTC(0xf73475ce), WTC(0xf6f4bedd), WTC(0xf6b455a8), WTC(0xf6739525), + WTC(0xf6332510), WTC(0xf5f3938b), WTC(0xf5b56073), WTC(0xf57900bd), + WTC(0xf53ee82d), WTC(0xf5079149), WTC(0xf4d36ffc), WTC(0xf4a2e526), + WTC(0xf4763d91), WTC(0xf44d9872), WTC(0xf426eaed), WTC(0xf3fdc161), + WTC(0xf3d001ff), WTC(0xf39dafcc), WTC(0xf366eb43), WTC(0xf32bdcdc), + WTC(0xf2ecab80), WTC(0xf2a97b34), WTC(0xf26265ae), WTC(0xf2178a6f), + WTC(0xf1c92458), WTC(0xf17752b9), WTC(0xf121e6ac), WTC(0xf0c89a63), + WTC(0xf06b15ef), WTC(0xf0092e86), WTC(0xefa2fd42), WTC(0xef397ebc), + WTC(0xeece51c6), WTC(0xee61e8b6), WTC(0xedf3d92e), WTC(0xed82c330), + WTC(0xed0d58bb), WTC(0xec94891b), WTC(0xec19d435), WTC(0xeb9e4e4e), + WTC(0xeb221000), WTC(0xeaa32422), WTC(0xea1fb440), WTC(0xe99695d2), + WTC(0xe90859ab), WTC(0xe8775114), WTC(0xe7e62b37), WTC(0xe7578147), + WTC(0xe6cb3ac1), WTC(0xe63f5696), WTC(0xe5afe916), WTC(0xe519090f), + WTC(0xe47aab0d), WTC(0xe3d6c2d0), WTC(0xe331dae7), WTC(0xe29031e1), + WTC(0xe1f40926), WTC(0xe15d87d2), WTC(0xe0c9d727), WTC(0xe0360ad5), + WTC(0xdf9f81af), WTC(0xdf04f9f9), WTC(0xde66697f), WTC(0xddc48ca1), + WTC(0xdd20a42a), WTC(0xdc7c6853), WTC(0xdbd9a476), WTC(0xdb398a8c), + WTC(0xda9cd7c2), WTC(0xda0365cf), WTC(0xd96cad85), WTC(0xd8d7b7a3), + WTC(0xd8439e8c), WTC(0xd7afb73d), WTC(0xd71b6347), WTC(0xd686149a), + WTC(0xd5efab2c), WTC(0xd558877e), WTC(0xd4c29dbc), WTC(0xd430a0aa), + WTC(0xd3a3d490), WTC(0xd31c588f), WTC(0xd297e075), WTC(0xd213ef33), + WTC(0xd18fd566), WTC(0xd10b8d3f), WTC(0xd087b250), WTC(0xd0054ef2), + WTC(0xcf85f94a), WTC(0xcf0af5f7), WTC(0xce94faf5), WTC(0xce229409), + WTC(0xcdb0b5f8), WTC(0xcd3ec554), WTC(0xcccdbf58), WTC(0xcc5f39d5), + WTC(0xcbf49ef5), WTC(0xcb8d5f73), WTC(0xcb28801c), WTC(0xcac5a265), + WTC(0xca64ad2e), WTC(0xca05d7fd), WTC(0xc9a96602), WTC(0xc94f9f79), + WTC(0xc8f2b954), WTC(0xc899e795), WTC(0xc83f94aa), WTC(0xc7e41f63), + WTC(0xc787e69f), WTC(0xc72b3fd0), WTC(0xc6ce3f0f), WTC(0xc670c175), + WTC(0xc61224cf), WTC(0xc5b21fec), WTC(0xc55202a4), WTC(0xc4f3353a), + WTC(0xc4968597), WTC(0xc43b93f2), WTC(0xc3e03d26), WTC(0xc383a011), + WTC(0xc3268aed), WTC(0xc2ca1039), WTC(0xc26f5bcc), WTC(0xc21726c9), + WTC(0xc1c1d5b2), WTC(0xc16f66ba), WTC(0xc11f76d9), WTC(0xc0d0a9f6), + WTC(0xc081cddb), WTC(0xc0333180), WTC(0xbfe5bb54), WTC(0xbf9aee90), + WTC(0xbf53d587), WTC(0xbf108855), WTC(0xbed0de05), WTC(0xbe9477d7), + WTC(0xbe5b030f), WTC(0xbe243642), WTC(0xbdefb72f), WTC(0xbdbd29df), + WTC(0xbd8c71ab), WTC(0xbd5d99cb), WTC(0xbd30e375), WTC(0xbd06afcc), + WTC(0xbcdf8c7f), WTC(0xbcbbf704), WTC(0xbc9c307e), WTC(0xbc803b86), + WTC(0xbc67c0c7), WTC(0xbc521d3d), WTC(0xbc3e6561), WTC(0xbc2bf2cb), + WTC(0xbc1a6872), WTC(0xbc09ce15), WTC(0xbbfa764f), WTC(0xbbed1356), + WTC(0xbbe257fa), WTC(0xbbda4099), WTC(0xbbd46a31), WTC(0xbbcffa76), + WTC(0xbbcc766d), WTC(0xbbca782f), WTC(0xbbcb16c7), WTC(0xbbcff77c), + WTC(0xbbd978e6), WTC(0xbbe68e5f), WTC(0xbbf593ed), WTC(0xbc04a834), + WTC(0xbc136941), WTC(0xbc2252c3), WTC(0xbc31723d), WTC(0xbc40ab92), + WTC(0xbc4ffe2d), WTC(0xbc5f7072), WTC(0xbc6f0520), WTC(0xbc7ebd23), + WTC(0xbc8e9746), WTC(0xbc9e942f), WTC(0xbcaeb633), WTC(0xbcbefe8b), + WTC(0xbccf69bb), WTC(0xbcdff92e), WTC(0xbcf0b04f), WTC(0xbd018ebd), + WTC(0xbd129192), WTC(0xbd23b9b8), WTC(0xbd350afb), WTC(0xbd46820e), + WTC(0xbd581bfc), WTC(0xbd69db11), WTC(0xbd7bbf57), WTC(0xbd8dc584), + WTC(0xbd9feaad), WTC(0xbdb231a4), WTC(0xbdc498ea), WTC(0xbdd71cd1), + WTC(0xbde9bb57), WTC(0xbdfc77d9), WTC(0xbe0f4e93), WTC(0xbe223ae5), + WTC(0xbe353cf5), WTC(0xbe485689), WTC(0xbe5b8329), WTC(0xbe6ebe88), + WTC(0xbe820afd), WTC(0xbe956811), WTC(0xbea8d109), WTC(0xbebc4352), + WTC(0xbecfc0fb), WTC(0xbee34a07), WTC(0xbef6d884), WTC(0xbf0a6bb1), + WTC(0xbf1e0685), WTC(0xbf31a685), WTC(0xbf45483c), WTC(0xbf58eb6b), + WTC(0xbf6c9376), WTC(0xbf803c90), WTC(0xbf93e4b9), WTC(0xbfa78d05), + WTC(0xbfbb3830), WTC(0xbfcee339), WTC(0xbfe28aa9), WTC(0xbff62b89), + WTC(0x8013a5f4), WTC(0x803acfd6), WTC(0x8061eec7), WTC(0x8088fc73), + WTC(0x80aff270), WTC(0x80d6cbe5), WTC(0x80fd8c2a), WTC(0x812437a8), + WTC(0x814ac94f), WTC(0x81713adc), WTC(0x81979098), WTC(0x81bdccb7), + WTC(0x81e3e738), WTC(0x8209dd04), WTC(0x822fb23a), WTC(0x825565bb), + WTC(0x827aed94), WTC(0x82a04909), WTC(0x82c57c85), WTC(0x82ea831c), + WTC(0x830f539d), WTC(0x8333eeba), WTC(0x8358585a), WTC(0x837c882e), + WTC(0x83a07742), WTC(0x83c428a5), WTC(0x83e79c4c), WTC(0x840aca65), + WTC(0x842dad81), WTC(0x84504ac0), WTC(0x84729fb1), WTC(0x8494a4f1), + WTC(0x84b65932), WTC(0x84d7c0f8), WTC(0x84f8d936), WTC(0x85199a59), + WTC(0x853a05a1), WTC(0x855a2023), WTC(0x8579e46e), WTC(0x85994d55), + WTC(0x85b86190), WTC(0x85d723e6), WTC(0x85f58fa9), WTC(0x8613a3ce), + WTC(0x863167b5), WTC(0x864eddfe), WTC(0x866c0138), WTC(0x8688d2e4), + WTC(0x86a55901), WTC(0x86c19497), WTC(0x86dd8390), WTC(0x86f9288f), + WTC(0x871487e0), WTC(0x872fadd0), WTC(0x874a9a1e), WTC(0x876519d0), + WTC(0x877f471e), WTC(0x8799fb36), WTC(0x87b48b97), WTC(0x87cba021), + WTC(0x880f67ae), WTC(0x885e0f91), WTC(0x88bc84cd), WTC(0x89244640), + WTC(0x8990a45d), WTC(0x89fe6766), WTC(0x8a6c9065), WTC(0x8adb31e6), + WTC(0x8b4ad5b3), WTC(0x8bbc2068), WTC(0x8c2f93ff), WTC(0x8ca5a922), + WTC(0x8d1ed72d), WTC(0x8d9b7ddb), WTC(0x8e1bd6cc), WTC(0x8ea01924), + WTC(0x8f287716), WTC(0x8fb5143e), WTC(0x9046074e), WTC(0x90db612b), + WTC(0x91753263), WTC(0x92138094), WTC(0x92b64cf3), WTC(0x935d96c9), + WTC(0x94095a56), WTC(0x94b98fd4), WTC(0x956e2a87), WTC(0x96271ff6), + WTC(0x96e46309), WTC(0x97a5e80d), WTC(0x986b9e55), WTC(0x993572af), + WTC(0x9a0350ce), WTC(0x9ad52154), WTC(0x9baad10f), WTC(0x9c844cdd), + WTC(0x9d618437), WTC(0x9e4265b2), WTC(0x9f26d9ad), WTC(0xa00ec9b0), + WTC(0xa0fa2916), WTC(0xa1e8ec20), WTC(0xa2daffa4), WTC(0xa3d05468), + WTC(0xa4c8e007), WTC(0xa5c49ae4), WTC(0xa6c37c24), WTC(0xa7c57d03), + WTC(0xa8ca9750), WTC(0xa9d2c7f2), WTC(0xaade0f6f), WTC(0xabec7177), + WTC(0xacfdf2b1), WTC(0xae129740), WTC(0xaf2a6321), WTC(0xb04563a6), + WTC(0xb163a2e6), WTC(0xb28524c4), WTC(0xb3a9eaf7), WTC(0xb4d1ff1b), + WTC(0x4a1d2880), WTC(0x48eee56e), WTC(0x47bda882), WTC(0x46895c79), + WTC(0x4551f8a1), WTC(0x4417817b), WTC(0x42da023d), WTC(0x419980ca), + WTC(0x4055f463), WTC(0x3f0f3b51), WTC(0x3dc56e18), WTC(0x3c78d943), + WTC(0x3b29bf3d), WTC(0x39d84ea0), WTC(0x3884337d), WTC(0x372d2371), + WTC(0x35d364ea), WTC(0x34774cef), WTC(0x33194d3a), WTC(0x31b9d586), + WTC(0x30594fcf), WTC(0x2ef80b63), WTC(0x2d9630d5), WTC(0x2c337c00), + WTC(0x2acf6a9e), WTC(0x296a3205), WTC(0x28046825), WTC(0x269f1752), + WTC(0x253b5314), WTC(0x23d9993f), WTC(0x227a3c77), WTC(0x211d59a0), + WTC(0x1fc314fd), WTC(0x1e6b9834), WTC(0x1d16eb58), WTC(0x1bc4f82e), + WTC(0x1a75e481), WTC(0x1929f389), WTC(0x17e16ee3), WTC(0x169cd758), + WTC(0x155d1ae5), WTC(0x14235182), WTC(0x12f051de), WTC(0x11c4993b), + WTC(0x109fdf4c), WTC(0x0f81351c), WTC(0x0e66c5e6), WTC(0x0d4f4b16), + WTC(0x0c39f013), WTC(0x0b25765d), WTC(0x0a10c51e), WTC(0x08fbee35), + WTC(0x07e7986f), WTC(0x06d25fe7), WTC(0x05ba1b52), WTC(0x049c33b7), + WTC(0x0379ceb9), WTC(0x025ee7c7), WTC(0x015edc1c), WTC(0x00978deb), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffe59474), WTC(0xffb158f8), WTC(0xff7d1275), WTC(0xff48f44c), + WTC(0xff1531e3), WTC(0xfee1faa9), WTC(0xfeaf626e), WTC(0xfe7d7227), + WTC(0xfe4c383f), WTC(0xfe1bc4ff), WTC(0xfdec297f), WTC(0xfdbd9f6c), + WTC(0xfd90bbf0), WTC(0xfd65ba73), WTC(0xfd3c2d32), WTC(0xfd13ab35), + WTC(0xfcebe811), WTC(0xfcc4eeae), WTC(0xfc9f1d64), WTC(0xfc7b48b0), + WTC(0xfc5a7282), WTC(0xfc3cef9b), WTC(0xfc229f4c), WTC(0xfc0a9e29), + WTC(0xfbf3dccb), WTC(0xfbdd80c3), WTC(0xfbc7556c), WTC(0xfbb289cf), + WTC(0xfba06f99), WTC(0xfb923aca), WTC(0xfb88bb57), WTC(0xfb84457f), + WTC(0xfb848c2e), WTC(0xfb88bd28), WTC(0xfb8feda1), WTC(0xfb9928eb), + WTC(0xfba38b9e), WTC(0xfbae711c), WTC(0xfbba3538), WTC(0xfbc7af9d), + WTC(0xfbd8485e), WTC(0xfbeda238), WTC(0xfc099de4), WTC(0xfc2d981f), + WTC(0xfc59fd0d), WTC(0xfc8e1583), WTC(0xfcc7e0d7), WTC(0xfd048d03), + WTC(0xfd40dfaf), WTC(0xfd7c1d35), WTC(0xfdb767cc), WTC(0xfdf64a9f), + WTC(0xfe3d0242), WTC(0xfe8e3316), WTC(0xfeead2b9), WTC(0xff4fff8c), + WTC(0xffba7b11), WTC(0x00281cae), WTC(0x009847d1), WTC(0x010cb653), + WTC(0x01870639), WTC(0x02089db5), WTC(0x0291b571), WTC(0x0321a4c1), + WTC(0x03b7eda0), WTC(0x04544c7f), WTC(0x04f74134), WTC(0x05a16810), + WTC(0x06525829), WTC(0x070994d4), WTC(0x07c767ba), WTC(0x088c69b8), + WTC(0x09598634), WTC(0x0a2f14ca), WTC(0x0b0c677b), WTC(0x0bf0f576), + WTC(0x0cdc7f73), WTC(0x0dceed54), WTC(0x0ec84a00), WTC(0x0fc8db86), + WTC(0x10d10278), WTC(0x11e0e05e), WTC(0x12f880cc), WTC(0x1418049b), + WTC(0x153f86b3), WTC(0x166ef5a3), WTC(0x17a64878), WTC(0x18e59dde), + WTC(0x1a2d088b), WTC(0x1b7c7e41), WTC(0x1cd40ab7), WTC(0x1e33d542), + WTC(0x1f9be7a5), WTC(0x210c344f), WTC(0x2284cb85), WTC(0x2405ca48), + WTC(0x258f2b7f), WTC(0x2720e063), WTC(0x28bafd49), WTC(0x2a5d950c), + WTC(0x2c0896e4), WTC(0x2dbbf7d4), WTC(0x2f77ca28), WTC(0x313c1273), + WTC(0x3308b7e4), WTC(0x34ddb0ec), WTC(0x36bb06b7), WTC(0x38a0a935), + WTC(0x3a8e7270), WTC(0x3c844ca9), WTC(0x3e82267e), WTC(0x4087ccfa), + WTC(0x42950352), WTC(0x44a99ce7), WTC(0x46c57093), WTC(0x48e84dbe), + WTC(0x4b127506), WTC(0x4d452d29), WTC(0x4f81e066), WTC(0x51ca11c4), + WTC(0x000c82e8), WTC(0xfff6f40c), WTC(0xfffa1260), WTC(0x001530bf), + WTC(0x0047a202), WTC(0x0090b903), WTC(0x00efc89f), WTC(0x016423af), + WTC(0x01ed1d0e), WTC(0x028a0796), WTC(0x033a3620), WTC(0x03fcfb89), + WTC(0x04d1aaaa), WTC(0x05b7965c), WTC(0x06ae1179), WTC(0x07b46ee8), + WTC(0x08ca0173), WTC(0x09ee1c00), WTC(0x0b201162), WTC(0x0c5f346e), + WTC(0x0daad808), WTC(0x0f024f17), WTC(0x1064ec4b), WTC(0x11d202c4), + WTC(0x1348e514), WTC(0x14c8e62f), WTC(0x1651590a), WTC(0x17e19051), + WTC(0x1978df27), WTC(0x1b169812), WTC(0x1cba0e15), WTC(0x1e629407), + WTC(0x200f7cd4), WTC(0x21c01b29), WTC(0x2373c228), WTC(0x2529c453), + WTC(0x26e174b9), WTC(0x289a262f), WTC(0x2a532bba), WTC(0x2c0bd7b2), + WTC(0x2dc37d92), WTC(0x2f796fce), WTC(0x312d017a), WTC(0x32dd8513), + WTC(0x348a4dde), WTC(0x3632aeb3), WTC(0x37d5fa29), WTC(0x39738334), + WTC(0x3b0a9c99), WTC(0x3c9a9926), WTC(0x3e22cc21), WTC(0x3fa287dc), + WTC(0x41191f89), WTC(0x4285e5fc), WTC(0x43e82e02), WTC(0x453f4a40), + WTC(0x468a8dd9), WTC(0x47c94c23), WTC(0x48fadc7c), WTC(0x4a1e75f9), + WTC(0x4b339ecf), WTC(0x4c3981b1), WTC(0x4d2f7cd3), WTC(0x4e14e381), + WTC(0x4ee90804), WTC(0x4fab3d6a), WTC(0x505ad6bd), WTC(0x50f726a3), + WTC(0x517f7fea), WTC(0x51f335fd), WTC(0x52519b0f), WTC(0x529a01f2), + WTC(0x52cbbe31), WTC(0x52e621d9), WTC(0x52e880aa), WTC(0x52d22c7a), + WTC(0x52a278a5), WTC(0x5258b880), WTC(0x51f43e1d), WTC(0x51745c38), + WTC(0x50d8669e), WTC(0x501faf0e), WTC(0x4f49897e), WTC(0x4e554804), + WTC(0x4d423d9e), WTC(0x4c0fbd8b), WTC(0x4abd1a4d), WTC(0x4949a698), + WTC(0x47b4b7f9), WTC(0x45fe2b6d), WTC(0x44375019), WTC(0x4284e96e), + WTC(0x40f7efa2), WTC(0x3f8f8b33), WTC(0x3e494311), WTC(0x3d21e35b), + WTC(0x3c15c621), WTC(0x3b2115f3), WTC(0x3a4008aa), WTC(0x396ed2a6), + WTC(0x38a99a1d), WTC(0x37ec1177), WTC(0x3730f154), WTC(0x36756c15), + WTC(0x35bafb0d), WTC(0x35020093), WTC(0x34492381), WTC(0x338f6226), + WTC(0x32d40a34), WTC(0x3215bd73), WTC(0x315302ce), WTC(0x308c7c41), + WTC(0x2fc3532f), WTC(0x2ef6de8f), WTC(0x2e265a7f), WTC(0x2d527bfd), + WTC(0x2c7bf035), WTC(0x2ba2975b), WTC(0x2ac63552), WTC(0x29e686ca), +}; + +const FIXP_WTB ELDAnalysis128[384] = { + WTC(0xfaa49e98), WTC(0xfa48929f), WTC(0xf9e7eb39), WTC(0xf983b829), + WTC(0xf91bc5cb), WTC(0xf8b0376f), WTC(0xf8408d62), WTC(0xf7cd8c1e), + WTC(0xf7580da3), WTC(0xf6e0b0dc), WTC(0xf667753c), WTC(0xf5efa4cf), + WTC(0xf57cb6de), WTC(0xf511b62b), WTC(0xf4b1a860), WTC(0xf45ee8f8), + WTC(0xf415710d), WTC(0xf3c0c4f3), WTC(0xf35c2af9), WTC(0xf2e89620), + WTC(0xf266f3cb), WTC(0xf1d819bf), WTC(0xf13cff2f), WTC(0xf09489d2), + WTC(0xefdcfa80), WTC(0xef182059), WTC(0xee4d6c60), WTC(0xed7b8da7), + WTC(0xec9c27b1), WTC(0xebb57d0d), WTC(0xeacb3918), WTC(0xe9d35591), + WTC(0xe8c9176e), WTC(0xe7b93e42), WTC(0xe6b10e47), WTC(0xe5a6b875), + WTC(0xe484c345), WTC(0xe3509f1b), WTC(0xe224254c), WTC(0xe10a4e18), + WTC(0xdff4a668), WTC(0xded3d881), WTC(0xdda5ed98), WTC(0xdc722d13), + WTC(0xdb437360), WTC(0xda1fefed), WTC(0xd90623b2), WTC(0xd7f070f5), + WTC(0xd6da361b), WTC(0xd5c0786f), WTC(0xd4a6e188), WTC(0xd39b37b4), + WTC(0xd2a01ff2), WTC(0xd1a8a05c), WTC(0xd0b0cf47), WTC(0xcfbd3527), + WTC(0xced6b8d7), WTC(0xcdff0a66), WTC(0xcd2978a4), WTC(0xcc587183), + WTC(0xcb93bfdb), WTC(0xcad80773), WTC(0xca233c2b), WTC(0xc9768b5e), + WTC(0xc8cc130c), WTC(0xc8231acd), WTC(0xc7768de4), WTC(0xc6c86bdf), + WTC(0xc6181aa1), WTC(0xc563f6ce), WTC(0xc4b33a2a), WTC(0xc4085fcf), + WTC(0xc35ae72e), WTC(0xc2ad7adf), WTC(0xc206ed94), WTC(0xc16a5744), + WTC(0xc0d59625), WTC(0xc041e21b), WTC(0xbfb1ee05), WTC(0xbf2d82ea), + WTC(0xbeb60fe9), WTC(0xbe499da8), WTC(0xbde61891), WTC(0xbd8975b6), + WTC(0xbd339d36), WTC(0xbce6a08b), WTC(0xbca5b2f9), WTC(0xbc721002), + WTC(0xbc494d41), WTC(0xbc266160), WTC(0xbc06d14f), WTC(0xbbec52c7), + WTC(0xbbdaaf79), WTC(0xbbd0be99), WTC(0xbbcae139), WTC(0xbbcd359c), + WTC(0xbbded5d3), WTC(0xbbfa58cf), WTC(0xbc162f9d), WTC(0xbc326534), + WTC(0xbc4f081c), WTC(0xbc6c1678), WTC(0xbc899f93), WTC(0xbca7a263), + WTC(0xbcc62954), WTC(0xbce52ddc), WTC(0xbd04bc7f), WTC(0xbd24cd8f), + WTC(0xbd456998), WTC(0xbd668428), WTC(0xbd88207c), WTC(0xbdaa2e4b), + WTC(0xbdccaf3e), WTC(0xbdef932c), WTC(0xbe12d936), WTC(0xbe366dd6), + WTC(0xbe5a4fd9), WTC(0xbe7e6b49), WTC(0xbea2bf3f), WTC(0xbec738b5), + WTC(0xbeebd791), WTC(0xbf108b49), WTC(0xbf3554aa), WTC(0xbf5a25cf), + WTC(0xbf7f020b), WTC(0xbfa3dd25), WTC(0xbfc8be1e), WTC(0xbfed95f6), + WTC(0x8024c933), WTC(0x806e24fb), WTC(0x80b73d96), WTC(0x80fff78c), + WTC(0x8148612f), WTC(0x8190626e), WTC(0x81d8030a), WTC(0x821f28e1), + WTC(0x8265d6be), WTC(0x82abed56), WTC(0x82f16e40), WTC(0x833636d2), + WTC(0x837a470a), WTC(0x83bd7be6), WTC(0x83ffd415), WTC(0x84412e66), + WTC(0x84818c4f), WTC(0x84c0d18c), WTC(0x84ff0429), WTC(0x853c09a5), + WTC(0x8577eacf), WTC(0x85b29402), WTC(0x85ec17bf), WTC(0x86246b50), + WTC(0x865ba7d7), WTC(0x8691c4c0), WTC(0x86c6d72a), WTC(0x86fae06c), + WTC(0x872dfcd1), WTC(0x87602c6a), WTC(0x87918a27), WTC(0x87c22ef8), + WTC(0x882f7c20), WTC(0x88dc38ab), WTC(0x89a52f47), WTC(0x8a737635), + WTC(0x8b43d08d), WTC(0x8c19be9f), WTC(0x8cf89ce7), WTC(0x8de337e9), + WTC(0x8edb3e02), WTC(0x8fe1e815), WTC(0x90f7e107), WTC(0x921d8b95), + WTC(0x9353008c), WTC(0x94982fd7), WTC(0x95ecdc6d), WTC(0x9750b87f), + WTC(0x98c36ad6), WTC(0x9a447674), WTC(0x9bd34e9c), WTC(0x9d6f76fa), + WTC(0x9f18780d), WTC(0xa0cdc487), WTC(0xa28eff8e), WTC(0xa45bbe4b), + WTC(0xa633baaf), WTC(0xa816bff0), WTC(0xaa04a90d), WTC(0xabfd7205), + WTC(0xae01356b), WTC(0xb0101477), WTC(0xb22a5244), WTC(0xb4500b02), + WTC(0x499946f3), WTC(0x475da5af), WTC(0x45173dce), WTC(0x42c610ad), + WTC(0x406a44b0), WTC(0x3e037ce8), WTC(0x3b92b806), WTC(0x39195cd0), + WTC(0x36962f17), WTC(0x340a1b28), WTC(0x3177cde6), WTC(0x2ee1f20d), + WTC(0x2c49b0d6), WTC(0x29ad3d74), WTC(0x270e9ec1), WTC(0x2474132f), + WTC(0x21e14a01), WTC(0x1f57704e), WTC(0x1cd758ce), WTC(0x1a610d48), + WTC(0x17f5db88), WTC(0x1598a188), WTC(0x134f7a40), WTC(0x111f1ca0), + WTC(0x0f053b83), WTC(0x0cf871db), WTC(0x0af19e60), WTC(0x08eaa56d), + WTC(0x06e3c473), WTC(0x04d25cc9), WTC(0x02b59b4d), WTC(0x00e5bc4c), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffcebf14), WTC(0xff6cc249), WTC(0xff0b8bda), WTC(0xfeac3e5f), + WTC(0xfe4f4638), WTC(0xfdf5052f), WTC(0xfd9e8cf4), WTC(0xfd4e34ea), + WTC(0xfd023142), WTC(0xfcb8f6f7), WTC(0xfc74e090), WTC(0xfc3b33e8), + WTC(0xfc0c1254), WTC(0xfbe1b2eb), WTC(0xfbb8ce73), WTC(0xfb97e511), + WTC(0xfb86273d), WTC(0xfb857a3e), WTC(0xfb918813), WTC(0xfba43692), + WTC(0xfbb96f24), WTC(0xfbd4dcc3), WTC(0xfc000cd5), WTC(0xfc458653), + WTC(0xfca6cd98), WTC(0xfd178c8e), WTC(0xfd872979), WTC(0xfdfa721e), + WTC(0xfe88c77c), WTC(0xff3c8b5c), WTC(0x00059ebc), WTC(0x00d91db0), + WTC(0x01bec555), WTC(0x02bdfb80), WTC(0x03d4c846), WTC(0x0501ad53), + WTC(0x064719b2), WTC(0x07a34a2b), WTC(0x0918814b), WTC(0x0aaaaa6b), + WTC(0x0c5728b9), WTC(0x0e1c1a0f), WTC(0x0ff9ccd1), WTC(0x11f21ffb), + WTC(0x1405d073), WTC(0x1635776b), WTC(0x1880f4e5), WTC(0x1ae8bdcb), + WTC(0x1d6cede3), WTC(0x200e1d93), WTC(0x22cc56fd), WTC(0x25a80858), + WTC(0x28a11bdd), WTC(0x2bb7e363), WTC(0x2eec2f0f), WTC(0x323e298d), + WTC(0x35ad7f0b), WTC(0x393a1989), WTC(0x3ce34a65), WTC(0x40a8683d), + WTC(0x44881c94), WTC(0x48813cb3), WTC(0x4c94523d), WTC(0x50c8eff0), + WTC(0x00000000), WTC(0x00000000), WTC(0x0053a1ea), WTC(0x00f67066), + WTC(0x01e3f61b), WTC(0x0317bdaf), WTC(0x048d51ca), WTC(0x06403d11), + WTC(0x082c0a34), WTC(0x0a4c43d2), WTC(0x0c9c748e), WTC(0x0f182718), + WTC(0x11bae616), WTC(0x14803c1b), WTC(0x1763b3e6), WTC(0x1a60d832), + WTC(0x1d73336b), WTC(0x20965068), WTC(0x23c5b9d6), WTC(0x26fcfa1a), + WTC(0x2a379c30), WTC(0x2d712a75), WTC(0x30a52fba), WTC(0x33cf36a9), + WTC(0x36eaca15), WTC(0x39f3743b), WTC(0x3ce4bfc2), WTC(0x3fba37b8), + WTC(0x426f6671), WTC(0x44ffd6e8), WTC(0x47671326), WTC(0x49a0b2d0), + WTC(0x4ba81be1), WTC(0x4d78fd1e), WTC(0x4f0ed503), WTC(0x50652e28), + WTC(0x51779351), WTC(0x52418fbe), WTC(0x52bead75), WTC(0x52ea76cc), + WTC(0x52c07793), WTC(0x523c3918), WTC(0x5159470e), WTC(0x50132b36), + WTC(0x4e657128), WTC(0x4c4ba31d), WTC(0x49c14b60), WTC(0x46c1e9e4), + WTC(0x4374e179), WTC(0x408377b1), WTC(0x3e0fa0aa), WTC(0x3c05d584), + WTC(0x3a4d9888), WTC(0x38cdd8fa), WTC(0x376b75c4), WTC(0x360c51a7), + WTC(0x34b12fdc), WTC(0x33550d9f), WTC(0x31f1955c), WTC(0x307ffcb2), + WTC(0x2f03c44d), WTC(0x2d7a6b86), WTC(0x2be6d3d4), WTC(0x2a48d219), +}; + +const FIXP_WTB ELDAnalysis120[360] = { + WTC(0xfaa1a40a), WTC(0xfa3f173d), WTC(0xf9d7760c), WTC(0xf96bcc12), + WTC(0xf8fbe82c), WTC(0xf887bb26), WTC(0xf80f131a), WTC(0xf7930d03), + WTC(0xf714aeaf), WTC(0xf693f5a1), WTC(0xf613385b), WTC(0xf596ef0e), + WTC(0xf522dcc4), WTC(0xf4bab1f6), WTC(0xf461700c), WTC(0xf412e1fe), + WTC(0xf3b769b1), WTC(0xf349eaca), WTC(0xf2cb9164), WTC(0xf23d6d7b), + WTC(0xf1a0ab28), WTC(0xf0f5c20f), WTC(0xf03aadd9), WTC(0xef6e8c66), + WTC(0xee984910), WTC(0xedbbcbf8), WTC(0xecd1435b), WTC(0xebdc1b77), + WTC(0xeae31338), WTC(0xe9dbea9a), WTC(0xe8c005ea), WTC(0xe79e7068), + WTC(0xe6856dce), WTC(0xe5657c79), WTC(0xe42928e9), WTC(0xe2e0756e), + WTC(0xe1a83cf5), WTC(0xe0801fab), WTC(0xdf52bfeb), WTC(0xde15d1b1), + WTC(0xdcce71ba), WTC(0xdb8931bf), WTC(0xda4fbbe8), WTC(0xd9220a98), + WTC(0xd7f9af0c), WTC(0xd6d0e1df), WTC(0xd5a41f15), WTC(0xd4790330), + WTC(0xd35f84b8), WTC(0xd255e881), WTC(0xd14daf00), WTC(0xd04638e2), + WTC(0xcf47dff7), WTC(0xce5b8850), WTC(0xcd77b1d6), WTC(0xcc960ec0), + WTC(0xcbc0a6a4), WTC(0xcaf6d4f7), WTC(0xca34fa7d), WTC(0xc97c26c0), + WTC(0xc8c6868a), WTC(0xc811f873), WTC(0xc7599db8), WTC(0xc69f9780), + WTC(0xc5e24043), WTC(0xc5226384), WTC(0xc468f547), WTC(0xc3b20be9), + WTC(0xc2f826f0), WTC(0xc242ea02), WTC(0xc19844ae), WTC(0xc0f80714), + WTC(0xc05a6da1), WTC(0xbfbfe6d3), WTC(0xbf31b5b4), WTC(0xbeb24843), + WTC(0xbe3f4cb4), WTC(0xbdd63599), WTC(0xbd74c6b2), WTC(0xbd1b7128), + WTC(0xbccd4b41), WTC(0xbc8dc08e), WTC(0xbc5ca2bd), WTC(0xbc3509f1), + WTC(0xbc11f904), WTC(0xbbf37848), WTC(0xbbddfb6b), WTC(0xbbd214ea), + WTC(0xbbcb3a11), WTC(0xbbcce581), WTC(0xbbdfa6ba), WTC(0xbbfd2fa5), + WTC(0xbc1ad516), WTC(0xbc390c16), WTC(0xbc57b323), WTC(0xbc76dd1f), + WTC(0xbc969172), WTC(0xbcb6d611), WTC(0xbcd7ac8e), WTC(0xbcf91af9), + WTC(0xbd1b20bd), WTC(0xbd3dc1f5), WTC(0xbd60f678), WTC(0xbd84bec7), + WTC(0xbda909c0), WTC(0xbdcdd76e), WTC(0xbdf3161c), WTC(0xbe18c1e5), + WTC(0xbe3ec6c5), WTC(0xbe651f19), WTC(0xbe8bb78b), WTC(0xbeb288e1), + WTC(0xbed9848b), WTC(0xbf00a16f), WTC(0xbf27d681), WTC(0xbf4f1958), + WTC(0xbf76680e), WTC(0xbf9db85c), WTC(0xbfc50e09), WTC(0xbfec5bdf), + WTC(0x80273bdb), WTC(0x807577de), WTC(0x80c3630d), WTC(0x8110e4cb), + WTC(0x815e05da), WTC(0x81aab20f), WTC(0x81f6e68e), WTC(0x824290d0), + WTC(0x828da04c), WTC(0x82d8061f), WTC(0x8321a740), WTC(0x836a77f9), + WTC(0x83b2574f), WTC(0x83f93cc1), WTC(0x843f04a6), WTC(0x8483acd1), + WTC(0x84c71639), WTC(0x850944da), WTC(0x854a1d3a), WTC(0x8589a437), + WTC(0x85c7ccf9), WTC(0x8604a42f), WTC(0x86402cfb), WTC(0x867a740d), + WTC(0x86b37ff2), WTC(0x86eb5f6f), WTC(0x87222109), WTC(0x8757eb5f), + WTC(0x878c8341), WTC(0x87c0be51), WTC(0x88345fca), WTC(0x88ef97fb), + WTC(0x89c778c5), WTC(0x8aa3cc20), WTC(0x8b833d56), WTC(0x8c6a42a9), + WTC(0x8d5cb787), WTC(0x8e5d7787), WTC(0x8f6e3c5b), WTC(0x90902640), + WTC(0x91c3ca28), WTC(0x9309622d), WTC(0x9460e7d0), WTC(0x95ca1ad2), + WTC(0x97449dff), WTC(0x98d00612), WTC(0x9a6bbc19), WTC(0x9c17164d), + WTC(0x9dd180fc), WTC(0x9f9a6304), WTC(0xa1711f56), WTC(0xa355425e), + WTC(0xa5465846), WTC(0xa744190f), WTC(0xa94e4ca9), WTC(0xab64dcf0), + WTC(0xad87e068), WTC(0xafb77bfa), WTC(0xb1f3fb2b), WTC(0xb43d885c), + WTC(0x49866451), WTC(0x4723e56b), WTC(0x44b51e8d), WTC(0x423a2180), + WTC(0x3fb2fe0f), WTC(0x3d1f78f2), WTC(0x3a8153b7), WTC(0x37d906ff), + WTC(0x35259e7e), WTC(0x3269ba18), WTC(0x2fa8c1ea), WTC(0x2ce4fbab), + WTC(0x2a1cebd5), WTC(0x27519ac1), WTC(0x248a2de9), WTC(0x21cb7a79), + WTC(0x1f16fc13), WTC(0x1c6d9a50), WTC(0x19cf83c1), WTC(0x173e9943), + WTC(0x14bf6a71), WTC(0x12598f74), WTC(0x100fe27f), WTC(0x0ddab46a), + WTC(0x0bafab9d), WTC(0x09864fc7), WTC(0x075d3ac8), WTC(0x052c0fc2), + WTC(0x02ea842b), WTC(0x00f21d19), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), WTC(0x00000000), + WTC(0xffcb7b4d), WTC(0xff62fb20), WTC(0xfefb82e2), WTC(0xfe965482), + WTC(0xfe33e4bf), WTC(0xfdd4b9b5), WTC(0xfd7b04ec), WTC(0xfd27cfe4), + WTC(0xfcd84cfd), WTC(0xfc8ce1d4), WTC(0xfc4b45e1), WTC(0xfc1666da), + WTC(0xfbe8af26), WTC(0xfbbcad9e), WTC(0xfb98c6ad), WTC(0xfb85dd87), + WTC(0xfb86355b), WTC(0xfb94589b), WTC(0xfba8ed8a), WTC(0xfbc0a735), + WTC(0xfbe23f8d), WTC(0xfc1a92c4), WTC(0xfc73315f), WTC(0xfce611a1), + WTC(0xfd5e94d9), WTC(0xfdd61cab), WTC(0xfe6427fd), WTC(0xff1c92da), + WTC(0xfff10542), WTC(0x00d1d58a), WTC(0x01c6daab), WTC(0x02d8dbc3), + WTC(0x040557a6), WTC(0x054b6f91), WTC(0x06ad2b2b), WTC(0x0828f4c5), + WTC(0x09c348d1), WTC(0x0b7dcb56), WTC(0x0d54d98e), WTC(0x0f47a599), + WTC(0x1157fa1b), WTC(0x138743ae), WTC(0x15d6423f), WTC(0x1844f0ae), + WTC(0x1ad3c273), WTC(0x1d82e65c), WTC(0x205306e1), WTC(0x23443d5c), + WTC(0x2656fae8), WTC(0x298b3a5a), WTC(0x2ce13a7d), WTC(0x3058e0e3), + WTC(0x33f22950), WTC(0x37acd0b2), WTC(0x3b885e6b), WTC(0x3f840412), + WTC(0x439e65ee), WTC(0x47d6014e), WTC(0x4c2aa857), WTC(0x50a46876), + WTC(0xfffe9b02), WTC(0x0004ac61), WTC(0x0069639d), WTC(0x0127578b), + WTC(0x02391efe), WTC(0x039950cc), WTC(0x054283bf), WTC(0x072f4eba), + WTC(0x095a488c), WTC(0x0bbe0802), WTC(0x0e5523f9), WTC(0x111a332e), + WTC(0x1407cca2), WTC(0x171886f5), WTC(0x1a46f927), WTC(0x1d8db9e1), + WTC(0x20e7600d), WTC(0x244e82a3), WTC(0x27bdb846), WTC(0x2b2f97a8), + WTC(0x2e9eb7ea), WTC(0x3205afd1), WTC(0x355f161c), WTC(0x38a581d7), + WTC(0x3bd3894a), WTC(0x3ee3c398), WTC(0x41d0c7ae), WTC(0x44952cb8), + WTC(0x472b8856), WTC(0x498e7eee), WTC(0x4bb88245), WTC(0x4da44d9f), + WTC(0x4f4c6b7d), WTC(0x50ab7298), WTC(0x51bbfa11), WTC(0x527898fb), + WTC(0x52dbe5f2), WTC(0x52e07778), WTC(0x5280e51f), WTC(0x51b7c4f1), + WTC(0x507fadc7), WTC(0x4ed336dd), WTC(0x4cacf749), WTC(0x4a078534), + WTC(0x46dd6dcc), WTC(0x43599e22), WTC(0x403f48da), WTC(0x3db1ed89), + WTC(0x3b98bd24), WTC(0x39d5b003), WTC(0x384a3292), WTC(0x36d328ff), + WTC(0x355e63a6), WTC(0x33ec69d8), WTC(0x32755ebd), WTC(0x30f01fce), + WTC(0x2f5d9646), WTC(0x2dbcc615), WTC(0x2c0fa145), WTC(0x2a56ce53), +}; diff --git a/fdk-aac/libAACenc/src/aacEnc_rom.h b/fdk-aac/libAACenc/src/aacEnc_rom.h new file mode 100644 index 0000000..fd50cab --- /dev/null +++ b/fdk-aac/libAACenc/src/aacEnc_rom.h @@ -0,0 +1,217 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + \author Markus Lohwasser +*/ + +#ifndef AACENC_ROM_H +#define AACENC_ROM_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "psy_configuration.h" +#include "FDK_tools_rom.h" +#include "FDK_lpc.h" + +/* + Huffman Tables +*/ +extern const ULONG FDKaacEnc_huff_ltab1_2[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab3_4[3][3][3][3]; +extern const ULONG FDKaacEnc_huff_ltab5_6[9][9]; +extern const ULONG FDKaacEnc_huff_ltab7_8[8][8]; +extern const ULONG FDKaacEnc_huff_ltab9_10[13][13]; +extern const UCHAR FDKaacEnc_huff_ltab11[17][17]; +extern const UCHAR FDKaacEnc_huff_ltabscf[121]; +extern const USHORT FDKaacEnc_huff_ctab1[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab2[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab3[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab4[3][3][3][3]; +extern const USHORT FDKaacEnc_huff_ctab5[9][9]; +extern const USHORT FDKaacEnc_huff_ctab6[9][9]; +extern const USHORT FDKaacEnc_huff_ctab7[8][8]; +extern const USHORT FDKaacEnc_huff_ctab8[8][8]; +extern const USHORT FDKaacEnc_huff_ctab9[13][13]; +extern const USHORT FDKaacEnc_huff_ctab10[13][13]; +extern const USHORT FDKaacEnc_huff_ctab11[21][17]; +extern const ULONG FDKaacEnc_huff_ctabscf[121]; + +/* + quantizer +*/ +#define MANT_DIGITS 9 +#define MANT_SIZE (1 << MANT_DIGITS) + +#if defined(ARCH_PREFER_MULT_32x16) +#define FIXP_QTD FIXP_SGL +#define QTC FX_DBL2FXCONST_SGL +#else +#define FIXP_QTD FIXP_DBL +#define QTC +#endif + +extern const FIXP_QTD FDKaacEnc_mTab_3_4[MANT_SIZE]; +extern const FIXP_QTD FDKaacEnc_quantTableQ[4]; +extern const FIXP_QTD FDKaacEnc_quantTableE[4]; + +extern const FIXP_DBL FDKaacEnc_mTab_4_3Elc[512]; +extern const FIXP_DBL FDKaacEnc_specExpMantTableCombElc[4][14]; +extern const UCHAR FDKaacEnc_specExpTableComb[4][14]; + +/* + table to count used number of bits +*/ +extern const SHORT FDKaacEnc_sideInfoTabLong[]; +extern const SHORT FDKaacEnc_sideInfoTabShort[]; + +/* + Psy Configuration constants +*/ +extern const SFB_PARAM_LONG p_FDKaacEnc_8000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_11025_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_12000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_16000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_22050_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_24000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_32000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_44100_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_48000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_64000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_88200_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_128; +extern const SFB_PARAM_LONG p_FDKaacEnc_96000_long_1024; +extern const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_128; + +/* + TNS filter coefficients +*/ +extern const FIXP_LPC FDKaacEnc_tnsEncCoeff3[8]; +extern const FIXP_LPC FDKaacEnc_tnsCoeff3Borders[8]; +extern const FIXP_LPC FDKaacEnc_tnsEncCoeff4[16]; +extern const FIXP_LPC FDKaacEnc_tnsCoeff4Borders[16]; + +#define WTC0 WTC +#define WTC1 WTC +#define WTC2 WTC + +extern const FIXP_WTB ELDAnalysis512[1536]; +extern const FIXP_WTB ELDAnalysis480[1440]; +extern const FIXP_WTB ELDAnalysis256[768]; +extern const FIXP_WTB ELDAnalysis240[720]; +extern const FIXP_WTB ELDAnalysis128[384]; +extern const FIXP_WTB ELDAnalysis120[360]; + +#endif /* #ifndef AACENC_ROM_H */ diff --git a/fdk-aac/libAACenc/src/aacenc.cpp b/fdk-aac/libAACenc/src/aacenc.cpp new file mode 100644 index 0000000..372df31 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc.cpp @@ -0,0 +1,1057 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: fast aac coder functions + +*******************************************************************************/ + +#include "aacenc.h" + +#include "bitenc.h" +#include "interface.h" +#include "psy_configuration.h" +#include "psy_main.h" +#include "qc_main.h" +#include "bandwidth.h" +#include "channel_map.h" +#include "tns_func.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + +#define BITRES_MAX_LD 4000 +#define BITRES_MIN_LD 500 +#define BITRATE_MAX_LD 70000 /* Max assumed bitrate for bitres calculation */ +#define BITRATE_MIN_LD 12000 /* Min assumed bitrate for bitres calculation */ + +INT FDKaacEnc_CalcBitsPerFrame(const INT bitRate, const INT frameLength, + const INT samplingRate) { + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength && + (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) { + shift++; + } + + return (bitRate * (frameLength >> shift)) / (samplingRate >> shift); +} + +INT FDKaacEnc_CalcBitrate(const INT bitsPerFrame, const INT frameLength, + const INT samplingRate) { + int shift = 0; + while ((frameLength & ~((1 << (shift + 1)) - 1)) == frameLength && + (samplingRate & ~((1 << (shift + 1)) - 1)) == samplingRate) { + shift++; + } + + return (bitsPerFrame * (samplingRate >> shift)) / (frameLength >> shift); +} + +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary( + INT bitRate, INT framelength, INT ancillaryRate, INT *ancillaryBitsPerFrame, + INT sampleRate); + +INT FDKaacEnc_LimitBitrate(HANDLE_TRANSPORTENC hTpEnc, AUDIO_OBJECT_TYPE aot, + INT coreSamplingRate, INT frameLength, INT nChannels, + INT nChannelsEff, INT bitRate, INT averageBits, + INT *pAverageBitsPerFrame, + AACENC_BITRATE_MODE bitrateMode, INT nSubFrames) { + INT transportBits, prevBitRate, averageBitsPerFrame, minBitrate = 0, iter = 0; + INT minBitsPerFrame = 40 * nChannels; + if (isLowDelay(aot)) { + minBitrate = 8000 * nChannelsEff; + } + + do { + prevBitRate = bitRate; + averageBitsPerFrame = + FDKaacEnc_CalcBitsPerFrame(bitRate, frameLength, coreSamplingRate) / + nSubFrames; + + if (pAverageBitsPerFrame != NULL) { + *pAverageBitsPerFrame = averageBitsPerFrame; + } + + if (hTpEnc != NULL) { + transportBits = transportEnc_GetStaticBits(hTpEnc, averageBitsPerFrame); + } else { + /* Assume some worst case */ + transportBits = 208; + } + + bitRate = fMax(bitRate, + fMax(minBitrate, + FDKaacEnc_CalcBitrate((minBitsPerFrame + transportBits), + frameLength, coreSamplingRate))); + FDK_ASSERT(bitRate >= 0); + + bitRate = fMin(bitRate, FDKaacEnc_CalcBitrate( + (nChannelsEff * MIN_BUFSIZE_PER_EFF_CHAN), + frameLength, coreSamplingRate)); + FDK_ASSERT(bitRate >= 0); + + } while (prevBitRate != bitRate && iter++ < 3); + + //fprintf(stderr, "FDKaacEnc_LimitBitrate(): bitRate=%d\n", bitRate); + return bitRate; +} + +typedef struct { + AACENC_BITRATE_MODE bitrateMode; + int chanBitrate[2]; /* mono/stereo settings */ +} CONFIG_TAB_ENTRY_VBR; + +static const CONFIG_TAB_ENTRY_VBR configTabVBR[] = { + {AACENC_BR_MODE_CBR, {0, 0}}, + {AACENC_BR_MODE_VBR_1, {32000, 20000}}, + {AACENC_BR_MODE_VBR_2, {40000, 32000}}, + {AACENC_BR_MODE_VBR_3, {56000, 48000}}, + {AACENC_BR_MODE_VBR_4, {72000, 64000}}, + {AACENC_BR_MODE_VBR_5, {112000, 96000}}}; + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + + ------------------------------------------------------------------------------*/ +INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode, + CHANNEL_MODE channelMode) { + INT bitrate = 0; + INT monoStereoMode = 0; /* default mono */ + + if (FDKaacEnc_GetMonoStereoMode(channelMode) == EL_MODE_STEREO) { + monoStereoMode = 1; + } + + switch (bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + bitrate = configTabVBR[bitrateMode].chanBitrate[monoStereoMode]; + break; + case AACENC_BR_MODE_INVALID: + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + default: + bitrate = 0; + break; + } + + /* convert channel bitrate to overall bitrate*/ + bitrate *= FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff; + + return bitrate; +} + +/** + * \brief Convert encoder bitreservoir value for transport library. + * + * \param hAacEnc Encoder handle + * + * \return Corrected bitreservoir level used in transport library. + */ +static INT FDKaacEnc_EncBitresToTpBitres(const HANDLE_AAC_ENC hAacEnc) { + INT transportBitreservoir = 0; + + switch (hAacEnc->bitrateMode) { + case AACENC_BR_MODE_CBR: + transportBitreservoir = + hAacEnc->qcKernel->bitResTot; /* encoder bitreservoir level */ + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + transportBitreservoir = FDK_INT_MAX; /* signal variable bitrate */ + break; + case AACENC_BR_MODE_SFR: + transportBitreservoir = 0; /* super framing and fixed framing */ + break; /* without bitreservoir signaling */ + default: + case AACENC_BR_MODE_INVALID: + transportBitreservoir = 0; /* invalid configuration*/ + } + + if (hAacEnc->config->audioMuxVersion == 2) { + transportBitreservoir = + MIN_BUFSIZE_PER_EFF_CHAN * hAacEnc->channelMapping.nChannelsEff; + } + + return transportBitreservoir; +} + +INT FDKaacEnc_GetBitReservoirState(const HANDLE_AAC_ENC hAacEncoder) { + return FDKaacEnc_EncBitresToTpBitres(hAacEncoder); +} + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config) { + /* make the preinitialization of the structs flexible */ + FDKmemclear(config, sizeof(AACENC_CONFIG)); + + /* default ancillary */ + config->anc_Rate = 0; /* no ancillary data */ + config->ancDataBitRate = 0; /* no additional consumed bitrate */ + + /* default configurations */ + config->bitRate = -1; /* bitrate must be set*/ + config->averageBits = + -1; /* instead of bitrate/s we can configure bits/superframe */ + config->bitrateMode = + AACENC_BR_MODE_CBR; /* set bitrate mode to constant bitrate */ + config->bandWidth = 0; /* get bandwidth from table */ + config->useTns = TNS_ENABLE_MASK; /* tns enabled completly */ + config->usePns = + 1; /* depending on channelBitrate this might be set to 0 later */ + config->useIS = 1; /* Intensity Stereo Configuration */ + config->useMS = 1; /* MS Stereo tool */ + config->framelength = -1; /* Framesize not configured */ + config->syntaxFlags = 0; /* default syntax with no specialities */ + config->epConfig = -1; /* no ER syntax -> no additional error protection */ + config->nSubFrames = 1; /* default, no sub frames */ + config->channelOrder = CH_ORDER_MPEG; /* Use MPEG channel ordering. */ + config->channelMode = MODE_UNKNOWN; + config->minBitsPerFrame = -1; /* minum number of bits in each AU */ + config->maxBitsPerFrame = -1; /* minum number of bits in each AU */ + config->audioMuxVersion = -1; /* audio mux version not configured */ + config->downscaleFactor = + 1; /* downscale factor for ELD reduced delay mode, 1 is normal ELD */ +} + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open(HANDLE_AAC_ENC *phAacEnc, const INT nElements, + const INT nChannels, const INT nSubFrames) { + AAC_ENCODER_ERROR ErrorStatus; + AAC_ENC *hAacEnc = NULL; + UCHAR *dynamicRAM = NULL; + + if (phAacEnc == NULL) { + return AAC_ENC_INVALID_HANDLE; + } + + /* allocate encoder structure */ + hAacEnc = GetRam_aacEnc_AacEncoder(); + if (hAacEnc == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + FDKmemclear(hAacEnc, sizeof(AAC_ENC)); + + if (NULL == (hAacEnc->dynamic_RAM = GetAACdynamic_RAM())) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + dynamicRAM = (UCHAR *)hAacEnc->dynamic_RAM; + + /* allocate the Psy aud Psy Out structure */ + ErrorStatus = + FDKaacEnc_PsyNew(&hAacEnc->psyKernel, nElements, nChannels, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + ErrorStatus = FDKaacEnc_PsyOutNew(hAacEnc->psyOut, nElements, nChannels, + nSubFrames, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* allocate the Q&C Out structure */ + ErrorStatus = FDKaacEnc_QCOutNew(hAacEnc->qcOut, nElements, nChannels, + nSubFrames, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* allocate the Q&C kernel */ + ErrorStatus = FDKaacEnc_QCNew(&hAacEnc->qcKernel, nElements, dynamicRAM); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + hAacEnc->maxChannels = nChannels; + hAacEnc->maxElements = nElements; + hAacEnc->maxFrames = nSubFrames; + +bail: + *phAacEnc = hAacEnc; + return ErrorStatus; +} + +AAC_ENCODER_ERROR FDKaacEnc_Initialize( + HANDLE_AAC_ENC hAacEnc, + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, ULONG initFlags) { + AAC_ENCODER_ERROR ErrorStatus; + INT psyBitrate, tnsMask; // INT profile = 1; + CHANNEL_MAPPING *cm = NULL; + + INT mbfac_e, qbw; + FIXP_DBL mbfac, bw_ratio; + QC_INIT qcInit; + INT averageBitsPerFrame = 0; + int bitresMin = 0; /* the bitreservoir is always big for AAC-LC */ + const CHANNEL_MODE prevChannelMode = hAacEnc->encoderMode; + + if (config == NULL) return AAC_ENC_INVALID_HANDLE; + + /******************* sanity checks *******************/ + + /* check config structure */ + if (config->nChannels < 1 || config->nChannels > (8)) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + /* check sample rate */ + switch (config->sampleRate) { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + case 24000: + case 32000: + case 44100: + case 48000: + case 64000: + case 88200: + case 96000: + break; + default: + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* bitrate has to be set */ + if (config->bitRate == -1) { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + INT superframe_size = 110*8*(config->bitRate/8000); + INT frames_per_superframe = 6; + INT staticBits = 0; + if((config->syntaxFlags & AC_DAB) && hTpEnc) { + staticBits = transportEnc_GetStaticBits(hTpEnc, 0); + switch(config->sampleRate) { + case 48000: + frames_per_superframe=6; + break; + case 32000: + frames_per_superframe=4; + break; + case 24000: + frames_per_superframe=3; + break; + case 16000: + frames_per_superframe=2; + break; + } + + //config->nSubFrames = frames_per_superframe; + //fprintf(stderr, "DAB+ superframe size=%d\n", superframe_size); + config->bitRate = (superframe_size - 16*(frames_per_superframe-1) - staticBits) * 1000/120; + //fprintf(stderr, "DAB+ tuned bitrate=%d\n", config->bitRate); + config->maxBitsPerFrame = (superframe_size - 16*(frames_per_superframe-1) - staticBits) / frames_per_superframe; + config->maxBitsPerFrame += 7; /*padding*/ + //config->bitreservoir=(superframe_size - 16*(frames_per_superframe-1) - staticBits - 2*8)/frames_per_superframe; + //fprintf(stderr, "DAB+ tuned maxBitsPerFrame=%d\n", (superframe_size - 16*(frames_per_superframe-1) - staticBits)/frames_per_superframe); + } + + /* check bit rate */ + + if (FDKaacEnc_LimitBitrate( + hTpEnc, config->audioObjectType, config->sampleRate, + config->framelength, config->nChannels, + FDKaacEnc_GetChannelModeConfiguration(config->channelMode) + ->nChannelsEff, + config->bitRate, config->averageBits, &averageBitsPerFrame, + config->bitrateMode, config->nSubFrames) != config->bitRate && + !(AACENC_BR_MODE_IS_VBR(config->bitrateMode))) { + return AAC_ENC_UNSUPPORTED_BITRATE; + } + + if (config->syntaxFlags & AC_ER_VCB11) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + if (config->syntaxFlags & AC_ER_HCR) { + return AAC_ENC_UNSUPPORTED_ER_FORMAT; + } + + /* check frame length */ + switch (config->framelength) { + case 1024: + case 960: + if (isLowDelay(config->audioObjectType)) { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + case 128: + case 256: + case 512: + case 120: + case 240: + case 480: + if (!isLowDelay(config->audioObjectType)) { + return AAC_ENC_INVALID_FRAME_LENGTH; + } + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + if (config->anc_Rate != 0) { + ErrorStatus = FDKaacEnc_InitCheckAncillary( + config->bitRate, config->framelength, config->anc_Rate, + &hAacEnc->ancillaryBitsPerFrame, config->sampleRate); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* update estimated consumed bitrate */ + config->ancDataBitRate += + FDKaacEnc_CalcBitrate(hAacEnc->ancillaryBitsPerFrame, + config->framelength, config->sampleRate); + } + + /* maximal allowed DSE bytes in frame */ + config->maxAncBytesPerAU = + fMin((256), fMax(0, FDKaacEnc_CalcBitsPerFrame( + (config->bitRate - (config->nChannels * 8000)), + config->framelength, config->sampleRate) >> + 3)); + + /* bind config to hAacEnc->config */ + hAacEnc->config = config; + + /* set hAacEnc->bitrateMode */ + hAacEnc->bitrateMode = config->bitrateMode; + + hAacEnc->encoderMode = config->channelMode; + + ErrorStatus = FDKaacEnc_InitChannelMapping( + hAacEnc->encoderMode, config->channelOrder, &hAacEnc->channelMapping); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + cm = &hAacEnc->channelMapping; + + ErrorStatus = FDKaacEnc_DetermineBandWidth( + config->bandWidth, config->bitRate - config->ancDataBitRate, + hAacEnc->bitrateMode, config->sampleRate, config->framelength, cm, + hAacEnc->encoderMode, &hAacEnc->config->bandWidth); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + hAacEnc->bandwidth90dB = (INT)hAacEnc->config->bandWidth; + + tnsMask = config->useTns ? TNS_ENABLE_MASK : 0x0; + psyBitrate = config->bitRate - config->ancDataBitRate; + + if ((hAacEnc->encoderMode != prevChannelMode) || (initFlags != 0)) { + /* Reinitialize psych states in case of channel configuration change ore if + * full reset requested. */ + ErrorStatus = FDKaacEnc_psyInit(hAacEnc->psyKernel, hAacEnc->psyOut, + hAacEnc->maxFrames, hAacEnc->maxChannels, + config->audioObjectType, cm); + if (ErrorStatus != AAC_ENC_OK) goto bail; + } + + ErrorStatus = FDKaacEnc_psyMainInit( + hAacEnc->psyKernel, config->audioObjectType, cm, config->sampleRate, + config->framelength, psyBitrate, tnsMask, hAacEnc->bandwidth90dB, + config->usePns, config->useIS, config->useMS, config->syntaxFlags, + initFlags); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + ErrorStatus = FDKaacEnc_QCOutInit(hAacEnc->qcOut, hAacEnc->maxFrames, cm); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + qcInit.channelMapping = &hAacEnc->channelMapping; + qcInit.sceCpe = 0; + + if (AACENC_BR_MODE_IS_VBR(config->bitrateMode)) { + qcInit.averageBits = (averageBitsPerFrame + 7) & ~7; + qcInit.bitRes = MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff; + qcInit.maxBits = MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff; + qcInit.maxBits = (config->maxBitsPerFrame != -1) + ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) + : qcInit.maxBits; + qcInit.maxBits = fixMax(qcInit.maxBits, (averageBitsPerFrame + 7) & ~7); + qcInit.minBits = + (config->minBitsPerFrame != -1) ? config->minBitsPerFrame : 0; + qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7); + } else { + INT bitreservoir = -1; /* default bitrservoir size*/ + if (isLowDelay(config->audioObjectType)) { + INT brPerChannel = config->bitRate / config->nChannels; + brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); + + /* bitreservoir = + * (maxBitRes-minBitRes)/(maxBitRate-minBitrate)*(bitRate-minBitrate)+minBitRes; + */ + FIXP_DBL slope = fDivNorm( + (brPerChannel - BITRATE_MIN_LD), + BITRATE_MAX_LD - BITRATE_MIN_LD); /* calc slope for interpolation */ + bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD - BITRES_MIN_LD)) + + BITRES_MIN_LD; /* interpolate */ + bitreservoir = bitreservoir & ~7; /* align to bytes */ + bitresMin = BITRES_MIN_LD; + } + + int maxBitres; + qcInit.averageBits = (averageBitsPerFrame + 7) & ~7; + maxBitres = + (MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff) - qcInit.averageBits; + qcInit.bitRes = + (bitreservoir != -1) ? fMin(bitreservoir, maxBitres) : maxBitres; + + qcInit.maxBits = fixMin(MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff, + ((averageBitsPerFrame + 7) & ~7) + qcInit.bitRes); + qcInit.maxBits = (config->maxBitsPerFrame != -1) + ? fixMin(qcInit.maxBits, config->maxBitsPerFrame) + : qcInit.maxBits; + qcInit.maxBits = + fixMin(MIN_BUFSIZE_PER_EFF_CHAN * cm->nChannelsEff, + fixMax(qcInit.maxBits, (averageBitsPerFrame + 7 + 8) & ~7)); + + qcInit.minBits = fixMax( + 0, ((averageBitsPerFrame - 1) & ~7) - qcInit.bitRes - + transportEnc_GetStaticBits( + hTpEnc, ((averageBitsPerFrame + 7) & ~7) + qcInit.bitRes)); + qcInit.minBits = (config->minBitsPerFrame != -1) + ? fixMax(qcInit.minBits, config->minBitsPerFrame) + : qcInit.minBits; + qcInit.minBits = fixMin( + qcInit.minBits, (averageBitsPerFrame - + transportEnc_GetStaticBits(hTpEnc, qcInit.maxBits)) & + ~7); + } + + qcInit.sampleRate = config->sampleRate; + qcInit.isLowDelay = isLowDelay(config->audioObjectType) ? 1 : 0; + qcInit.nSubFrames = config->nSubFrames; + qcInit.padding.paddingRest = config->sampleRate; + + if (qcInit.bitRes >= bitresMin * config->nChannels) { + qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */ + } else if (qcInit.bitRes > 0) { + qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */ + } else { + qcInit.bitResMode = AACENC_BR_MODE_DISABLED; /* disabled bitreservoir */ + } + + /* Configure bitrate distribution strategy. */ + switch (config->channelMode) { + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + qcInit.bitDistributionMode = 0; /* over all elements bitrate estimation */ + break; + case MODE_1: + case MODE_2: + default: /* all non mpeg defined channel modes */ + qcInit.bitDistributionMode = 1; /* element-wise bit bitrate estimation */ + } /* config->channelMode */ + + /* Calc meanPe: qcInit.meanPe = 10.0f * FRAME_LEN_LONG * + * hAacEnc->bandwidth90dB/(config->sampleRate/2.0f); */ + bw_ratio = + fDivNorm((FIXP_DBL)(10 * config->framelength * hAacEnc->bandwidth90dB), + (FIXP_DBL)(config->sampleRate), &qbw); + qcInit.meanPe = + fMax((INT)scaleValue(bw_ratio, qbw + 1 - (DFRACT_BITS - 1)), 1); + + /* Calc maxBitFac, scale it to 24 bit accuracy */ + mbfac = fDivNorm(qcInit.maxBits, qcInit.averageBits / qcInit.nSubFrames, + &mbfac_e); + qcInit.maxBitFac = scaleValue(mbfac, -(DFRACT_BITS - 1 - 24 - mbfac_e)); + + switch (config->bitrateMode) { + case AACENC_BR_MODE_CBR: + qcInit.bitrateMode = QCDATA_BR_MODE_CBR; + break; + case AACENC_BR_MODE_VBR_1: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_1; + break; + case AACENC_BR_MODE_VBR_2: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_2; + break; + case AACENC_BR_MODE_VBR_3: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_3; + break; + case AACENC_BR_MODE_VBR_4: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_4; + break; + case AACENC_BR_MODE_VBR_5: + qcInit.bitrateMode = QCDATA_BR_MODE_VBR_5; + break; + case AACENC_BR_MODE_SFR: + qcInit.bitrateMode = QCDATA_BR_MODE_SFR; + break; + case AACENC_BR_MODE_FF: + qcInit.bitrateMode = QCDATA_BR_MODE_FF; + break; + default: + ErrorStatus = AAC_ENC_UNSUPPORTED_BITRATE_MODE; + goto bail; + } + + qcInit.invQuant = (config->useRequant) ? 2 : 0; + + /* maxIterations should be set to the maximum number of requantization + * iterations that are allowed before the crash recovery functionality is + * activated. This setting should be adjusted to the processing power + * available, i.e. to the processing power headroom in one frame that is still + * left after normal encoding without requantization. Please note that if + * activated this functionality is used most likely only in cases where the + * encoder is operating beyond recommended settings, i.e. the audio quality is + * suboptimal anyway. Activating the crash recovery does not further reduce + * audio quality significantly in these cases. */ + if (isLowDelay(config->audioObjectType)) { + qcInit.maxIterations = 2; + } else { + qcInit.maxIterations = 5; + } + + qcInit.bitrate = config->bitRate - config->ancDataBitRate; + + qcInit.staticBits = transportEnc_GetStaticBits( + hTpEnc, qcInit.averageBits / qcInit.nSubFrames); + + ErrorStatus = FDKaacEnc_QCInit(hAacEnc->qcKernel, &qcInit, initFlags); + if (ErrorStatus != AAC_ENC_OK) goto bail; + + /* Map virtual aot's to intern aot used in bitstream writer. */ + switch (hAacEnc->config->audioObjectType) { + case AOT_MP2_AAC_LC: + hAacEnc->aot = AOT_AAC_LC; + break; + case AOT_MP2_SBR: + hAacEnc->aot = AOT_SBR; + break; + default: + hAacEnc->aot = hAacEnc->config->audioObjectType; + } + + /* common things */ + + return AAC_ENC_OK; + +bail: + + return ErrorStatus; +} + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encodes one frame + returns: error code + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( + HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, INT_PCM *RESTRICT inputBuffer, + const UINT inputBufferBufSize, INT *nOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]) { + AAC_ENCODER_ERROR ErrorStatus; + int el, n, c = 0; + UCHAR extPayloadUsed[MAX_TOTAL_EXT_PAYLOADS]; + + CHANNEL_MAPPING *cm = &hAacEnc->channelMapping; + + PSY_OUT *psyOut = hAacEnc->psyOut[c]; + QC_OUT *qcOut = hAacEnc->qcOut[c]; + + FDKmemclear(extPayloadUsed, MAX_TOTAL_EXT_PAYLOADS * sizeof(UCHAR)); + + qcOut->elementExtBits = 0; /* sum up all extended bit of each element */ + qcOut->staticBits = 0; /* sum up side info bits of each element */ + qcOut->totalNoRedPe = 0; /* sum up PE */ + + /* advance psychoacoustics */ + for (el = 0; el < cm->nElements; el++) { + ELEMENT_INFO elInfo = cm->elInfo[el]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + int ch; + + /* update pointer!*/ + for (ch = 0; ch < elInfo.nChannelsInEl; ch++) { + PSY_OUT_CHANNEL *psyOutChan = + psyOut->psyOutElement[el]->psyOutChannel[ch]; + QC_OUT_CHANNEL *qcOutChan = qcOut->qcElement[el]->qcOutChannel[ch]; + + psyOutChan->mdctSpectrum = qcOutChan->mdctSpectrum; + psyOutChan->sfbSpreadEnergy = qcOutChan->sfbSpreadEnergy; + psyOutChan->sfbEnergy = qcOutChan->sfbEnergy; + psyOutChan->sfbEnergyLdData = qcOutChan->sfbEnergyLdData; + psyOutChan->sfbMinSnrLdData = qcOutChan->sfbMinSnrLdData; + psyOutChan->sfbThresholdLdData = qcOutChan->sfbThresholdLdData; + } + + ErrorStatus = FDKaacEnc_psyMain( + elInfo.nChannelsInEl, hAacEnc->psyKernel->psyElement[el], + hAacEnc->psyKernel->psyDynamic, hAacEnc->psyKernel->psyConf, + psyOut->psyOutElement[el], inputBuffer, inputBufferBufSize, + cm->elInfo[el].ChannelIndex, cm->nChannels); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* FormFactor, Pe and staticBitDemand calculation */ + ErrorStatus = FDKaacEnc_QCMainPrepare( + &elInfo, hAacEnc->qcKernel->hAdjThr->adjThrStateElem[el], + psyOut->psyOutElement[el], qcOut->qcElement[el], hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /*-------------------------------------------- */ + + qcOut->qcElement[el]->extBitsUsed = 0; + qcOut->qcElement[el]->nExtensions = 0; + /* reset extension payload */ + FDKmemclear(&qcOut->qcElement[el]->extension, + (1) * sizeof(QC_OUT_EXTENSION)); + + for (n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++) { + if (!extPayloadUsed[n] && (extPayload[n].associatedChElement == el) && + (extPayload[n].dataSize > 0) && (extPayload[n].pData != NULL)) { + int idx = qcOut->qcElement[el]->nExtensions++; + + qcOut->qcElement[el]->extension[idx].type = + extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->qcElement[el]->extension[idx].nPayloadBits = + extPayload[n].dataSize; + qcOut->qcElement[el]->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the + * data with the current bitstream syntax: */ + qcOut->qcElement[el]->extBitsUsed += FDKaacEnc_writeExtensionData( + NULL, &qcOut->qcElement[el]->extension[idx], 0, 0, + hAacEnc->config->syntaxFlags, hAacEnc->aot, + hAacEnc->config->epConfig); + extPayloadUsed[n] = 1; + } + } + + /* sum up extension and static bits for all channel elements */ + qcOut->elementExtBits += qcOut->qcElement[el]->extBitsUsed; + qcOut->staticBits += qcOut->qcElement[el]->staticBitsUsed; + + /* sum up pe */ + qcOut->totalNoRedPe += qcOut->qcElement[el]->peData.pe; + } + } + + qcOut->nExtensions = 0; + qcOut->globalExtBits = 0; + + /* reset extension payload */ + FDKmemclear(&qcOut->extension, (2 + 2) * sizeof(QC_OUT_EXTENSION)); + + /* Add extension payload not assigned to an channel element + (Ancillary data is the only supported type up to now) */ + for (n = 0; n < MAX_TOTAL_EXT_PAYLOADS; n++) { + if (!extPayloadUsed[n] && (extPayload[n].associatedChElement == -1) && + (extPayload[n].pData != NULL)) { + UINT payloadBits = 0; + + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + if (hAacEnc->ancillaryBitsPerFrame) { + /* granted frame dse bitrate */ + payloadBits = hAacEnc->ancillaryBitsPerFrame; + } else { + /* write anc data if bitrate constraint fulfilled */ + if ((extPayload[n].dataSize >> 3) <= + hAacEnc->config->maxAncBytesPerAU) { + payloadBits = extPayload[n].dataSize; + } + } + payloadBits = fixMin(extPayload[n].dataSize, payloadBits); + } else { + payloadBits = extPayload[n].dataSize; + } + + if (payloadBits > 0) { + int idx = qcOut->nExtensions++; + + qcOut->extension[idx].type = + extPayload[n].dataType; /* Perform a sanity check on the type? */ + qcOut->extension[idx].nPayloadBits = payloadBits; + qcOut->extension[idx].pPayload = extPayload[n].pData; + /* Now ask the bitstream encoder how many bits we need to encode the + * data with the current bitstream syntax: */ + qcOut->globalExtBits += FDKaacEnc_writeExtensionData( + NULL, &qcOut->extension[idx], 0, 0, hAacEnc->config->syntaxFlags, + hAacEnc->aot, hAacEnc->config->epConfig); + if (extPayload[n].dataType == EXT_DATA_ELEMENT) { + /* substract the processed bits */ + extPayload[n].dataSize -= payloadBits; + } + extPayloadUsed[n] = 1; + } + } + } + + if (!(hAacEnc->config->syntaxFlags & (AC_SCALABLE | AC_ER))) { + qcOut->globalExtBits += EL_ID_BITS; /* add bits for ID_END */ + } + + /* build bitstream all nSubFrames */ + { + INT totalBits = 0; /* Total AU bits */ + ; + INT avgTotalBits = 0; + + /*-------------------------------------------- */ + /* Get average total bits */ + /*-------------------------------------------- */ + { + /* frame wise bitrate adaption */ + FDKaacEnc_AdjustBitrate( + hAacEnc->qcKernel, cm, &avgTotalBits, hAacEnc->config->bitRate, + hAacEnc->config->sampleRate, hAacEnc->config->framelength); + + /* adjust super frame bitrate */ + avgTotalBits *= hAacEnc->config->nSubFrames; + } + + /* Make first estimate of transport header overhead. + Take maximum possible frame size into account to prevent bitreservoir + underrun. */ + hAacEnc->qcKernel->globHdrBits = transportEnc_GetStaticBits( + hTpEnc, avgTotalBits + hAacEnc->qcKernel->bitResTot); + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + ErrorStatus = FDKaacEnc_QCMain( + hAacEnc->qcKernel, hAacEnc->psyOut, hAacEnc->qcOut, avgTotalBits, cm, + hAacEnc->aot, hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_updateFillBits( + cm, hAacEnc->qcKernel, hAacEnc->qcKernel->elementBits, hAacEnc->qcOut); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /*-------------------------------------------- */ + ErrorStatus = FDKaacEnc_FinalizeBitConsumption( + cm, hAacEnc->qcKernel, qcOut, qcOut->qcElement, hTpEnc, hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + /*-------------------------------------------- */ + totalBits += qcOut->totalBits; + + /*-------------------------------------------- */ + FDKaacEnc_updateBitres(cm, hAacEnc->qcKernel, hAacEnc->qcOut); + + /*-------------------------------------------- */ + + /* for ( all sub frames ) ... */ + /* write bitstream header */ + if (TRANSPORTENC_OK != + transportEnc_WriteAccessUnit(hTpEnc, totalBits, + FDKaacEnc_EncBitresToTpBitres(hAacEnc), + cm->nChannelsEff)) { + return AAC_ENC_UNKNOWN; + } + + /* write bitstream */ + ErrorStatus = FDKaacEnc_WriteBitstream( + hTpEnc, cm, qcOut, psyOut, hAacEnc->qcKernel, hAacEnc->aot, + hAacEnc->config->syntaxFlags, hAacEnc->config->epConfig); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* transportEnc_EndAccessUnit() is being called inside + * FDKaacEnc_WriteBitstream() */ + if (TRANSPORTENC_OK != transportEnc_GetFrame(hTpEnc, nOutBytes)) { + return AAC_ENC_UNKNOWN; + } + + } /* -end- if (curFrame==hAacEnc->qcKernel->nSubFrames) */ + + /*-------------------------------------------- */ + return AAC_ENC_OK; +} + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close(HANDLE_AAC_ENC *phAacEnc) /* encoder handle */ +{ + if (*phAacEnc == NULL) { + return; + } + AAC_ENC *hAacEnc = (AAC_ENC *)*phAacEnc; + + if (hAacEnc->dynamic_RAM != NULL) FreeAACdynamic_RAM(&hAacEnc->dynamic_RAM); + + FDKaacEnc_PsyClose(&hAacEnc->psyKernel, hAacEnc->psyOut); + + FDKaacEnc_QCClose(&hAacEnc->qcKernel, hAacEnc->qcOut); + + FreeRam_aacEnc_AacEncoder(phAacEnc); +} + +/* The following functions are in this source file only for convenience and */ +/* need not be visible outside of a possible encoder library. */ + +/* basic defines for ancillary data */ +#define MAX_ANCRATE 19200 /* ancillary rate >= 19200 isn't valid */ + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_InitCheckAncillary + description: initialize and check ancillary data struct + return: if success or NULL if error + + ---------------------------------------------------------------------------*/ +static AAC_ENCODER_ERROR FDKaacEnc_InitCheckAncillary( + INT bitRate, INT framelength, INT ancillaryRate, INT *ancillaryBitsPerFrame, + INT sampleRate) { + /* don't use negative ancillary rates */ + if (ancillaryRate < -1) return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + + /* check if ancillary rate is ok */ + if ((ancillaryRate != (-1)) && (ancillaryRate != 0)) { + /* ancRate <= 15% of bitrate && ancRate < 19200 */ + if ((ancillaryRate >= MAX_ANCRATE) || + ((ancillaryRate * 20) > (bitRate * 3))) { + return AAC_ENC_UNSUPPORTED_ANC_BITRATE; + } + } else if (ancillaryRate == -1) { + /* if no special ancRate is requested but a ancillary file is + stated, then generate a ancillary rate matching to the bitrate */ + if (bitRate >= (MAX_ANCRATE * 10)) { + /* ancillary rate is 19199 */ + ancillaryRate = (MAX_ANCRATE - 1); + } else { /* 10% of bitrate */ + ancillaryRate = bitRate / 10; + } + } + + /* make ancillaryBitsPerFrame byte align */ + *ancillaryBitsPerFrame = + FDKaacEnc_CalcBitsPerFrame(ancillaryRate, framelength, sampleRate) & ~0x7; + + return AAC_ENC_OK; +} diff --git a/fdk-aac/libAACenc/src/aacenc.h b/fdk-aac/libAACenc/src/aacenc.h new file mode 100644 index 0000000..291ea54 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc.h @@ -0,0 +1,394 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: fast aac coder interface library functions + +*******************************************************************************/ + +#ifndef AACENC_H +#define AACENC_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "tpenc_lib.h" + +#include "sbr_encoder.h" + +#define MIN_BUFSIZE_PER_EFF_CHAN 6144 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * AAC-LC error codes. + */ +typedef enum { + AAC_ENC_OK = 0x0000, /*!< All fine. */ + + AAC_ENC_UNKNOWN = 0x0002, /*!< Error condition is of unknown reason, or from + another module. */ + + /* initialization errors */ + aac_enc_init_error_start = 0x2000, + AAC_ENC_INVALID_HANDLE = 0x2020, /*!< The handle passed to the function call + was invalid (probably NULL). */ + AAC_ENC_INVALID_FRAME_LENGTH = + 0x2080, /*!< Invalid frame length (must be 1024 or 960). */ + AAC_ENC_INVALID_N_CHANNELS = + 0x20e0, /*!< Invalid amount of audio input channels. */ + AAC_ENC_INVALID_SFB_TABLE = 0x2140, /*!< Internal encoder error. */ + + AAC_ENC_UNSUPPORTED_AOT = + 0x3000, /*!< The Audio Object Type (AOT) is not supported. */ + AAC_ENC_UNSUPPORTED_FILTERBANK = + 0x3010, /*!< Filterbank type is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE = + 0x3020, /*!< The chosen bitrate is not supported. */ + AAC_ENC_UNSUPPORTED_BITRATE_MODE = + 0x3028, /*!< Unsupported bit rate mode (CBR or VBR). */ + AAC_ENC_UNSUPPORTED_ANC_BITRATE = + 0x3040, /*!< Unsupported ancillay bitrate. */ + AAC_ENC_UNSUPPORTED_ANC_MODE = 0x3060, + AAC_ENC_UNSUPPORTED_TRANSPORT_TYPE = + 0x3080, /*!< The bitstream format is not supported. */ + AAC_ENC_UNSUPPORTED_ER_FORMAT = + 0x30a0, /*!< The error resilience tool format is not supported. */ + AAC_ENC_UNSUPPORTED_EPCONFIG = + 0x30c0, /*!< The error protection format is not supported. */ + AAC_ENC_UNSUPPORTED_CHANNELCONFIG = + 0x30e0, /*!< The channel configuration (either number or arrangement) is + not supported. */ + AAC_ENC_UNSUPPORTED_SAMPLINGRATE = + 0x3100, /*!< Sample rate of audio input is not supported. */ + AAC_ENC_NO_MEMORY = 0x3120, /*!< Could not allocate memory. */ + AAC_ENC_PE_INIT_TABLE_NOT_FOUND = 0x3140, /*!< Internal encoder error. */ + + aac_enc_init_error_end, + + /* encode errors */ + aac_enc_error_start = 0x4000, + AAC_ENC_QUANT_ERROR = 0x4020, /*!< Too many bits used in quantization. */ + AAC_ENC_WRITTEN_BITS_ERROR = + 0x4040, /*!< Unexpected number of written bits, differs to + calculated number of bits. */ + AAC_ENC_PNS_TABLE_ERROR = 0x4060, /*!< PNS level out of range. */ + AAC_ENC_GLOBAL_GAIN_TOO_HIGH = 0x4080, /*!< Internal quantizer error. */ + AAC_ENC_BITRES_TOO_LOW = 0x40a0, /*!< Too few bits in bit reservoir. */ + AAC_ENC_BITRES_TOO_HIGH = 0x40a1, /*!< Too many bits in bit reservoir. */ + AAC_ENC_INVALID_CHANNEL_BITRATE = 0x4100, + AAC_ENC_INVALID_ELEMENTINFO_TYPE = 0x4120, /*!< Internal encoder error. */ + + AAC_ENC_WRITE_SCAL_ERROR = 0x41e0, /*!< Error writing scalefacData. */ + AAC_ENC_WRITE_SEC_ERROR = 0x4200, /*!< Error writing sectionData. */ + AAC_ENC_WRITE_SPEC_ERROR = 0x4220, /*!< Error writing spectralData. */ + aac_enc_error_end + +} AAC_ENCODER_ERROR; +/*-------------------------- defines --------------------------------------*/ + +#define ANC_DATA_BUFFERSIZE 1024 /* ancBuffer size */ + +#define MAX_TOTAL_EXT_PAYLOADS ((((8)) * (1)) + (2 + 2)) + +typedef enum { + AACENC_BR_MODE_INVALID = -1, /*!< Invalid bitrate mode. */ + AACENC_BR_MODE_CBR = 0, /*!< Constant bitrate mode. */ + AACENC_BR_MODE_VBR_1 = 1, /*!< Variable bitrate mode, very low bitrate. */ + AACENC_BR_MODE_VBR_2 = 2, /*!< Variable bitrate mode, low bitrate. */ + AACENC_BR_MODE_VBR_3 = 3, /*!< Variable bitrate mode, medium bitrate. */ + AACENC_BR_MODE_VBR_4 = 4, /*!< Variable bitrate mode, high bitrate. */ + AACENC_BR_MODE_VBR_5 = 5, /*!< Variable bitrate mode, very high bitrate. */ + AACENC_BR_MODE_FF = 6, /*!< Fixed frame mode. */ + AACENC_BR_MODE_SFR = 7 /*!< Superframe mode. */ + +} AACENC_BITRATE_MODE; + +#define AACENC_BR_MODE_IS_VBR(brMode) ((brMode >= 1) && (brMode <= 5)) + +typedef enum { + + CH_ORDER_MPEG = + 0, /*!< MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE) */ + CH_ORDER_WAV, /*!< WAV fileformat channel ordering (e. g. 5.1: L, R, C, LFE, + SL, SR) */ + CH_ORDER_WG4 /*!< WG4 fileformat channel ordering (e. g. 5.1: L, R, SL, SR, C, LFE) */ + +} CHANNEL_ORDER; + +/*-------------------- structure definitions ------------------------------*/ + +struct AACENC_CONFIG { + INT sampleRate; /* encoder sample rate */ + INT bitRate; /* encoder bit rate in bits/sec */ + INT ancDataBitRate; /* additional bits consumed by anc data or sbr have to be + consiedered while configuration */ + + INT nSubFrames; /* number of frames in super frame (not ADTS/LATM subframes !) + */ + AUDIO_OBJECT_TYPE audioObjectType; /* Audio Object Type */ + + INT averageBits; /* encoder bit rate in bits/superframe */ + AACENC_BITRATE_MODE bitrateMode; /* encoder bitrate mode (CBR/VBR) */ + INT nChannels; /* number of channels to process */ + CHANNEL_ORDER channelOrder; /* input Channel ordering scheme. */ + INT bandWidth; /* targeted audio bandwidth in Hz */ + CHANNEL_MODE channelMode; /* encoder channel mode configuration */ + INT framelength; /* used frame size */ + + UINT syntaxFlags; /* bitstreams syntax configuration */ + SCHAR epConfig; /* error protection configuration */ + + INT anc_Rate; /* ancillary rate, 0 (disabled), -1 (default) else desired rate + */ + UINT maxAncBytesPerAU; + INT minBitsPerFrame; /* minimum number of bits in AU */ + INT maxBitsPerFrame; /* maximum number of bits in AU */ + + INT audioMuxVersion; /* audio mux version in loas/latm transport format */ + + UINT sbrRatio; /* sbr sampling rate ratio: dual- or single-rate */ + + UCHAR useTns; /* flag: use temporal noise shaping */ + UCHAR usePns; /* flag: use perceptual noise substitution */ + UCHAR useIS; /* flag: use intensity coding */ + UCHAR useMS; /* flag: use ms stereo tool */ + + UCHAR useRequant; /* flag: use afterburner */ + + UINT downscaleFactor; +}; + +typedef struct { + UCHAR *pData; /* pointer to extension payload data */ + UINT dataSize; /* extension payload data size in bits */ + EXT_PAYLOAD_TYPE dataType; /* extension payload data type */ + INT associatedChElement; /* number of the channel element the data is assigned + to */ +} AACENC_EXT_PAYLOAD; + +typedef struct AAC_ENC *HANDLE_AAC_ENC; + +/** + * \brief Calculate framesize in bits for given bit rate, frame length and + * sampling rate. + * + * \param bitRate Ttarget bitrate in bits per second. + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Framesize in bits per frame. + */ +INT FDKaacEnc_CalcBitsPerFrame(const INT bitRate, const INT frameLength, + const INT samplingRate); + +/** + * \brief Calculate bitrate in bits per second for given framesize, frame length + * and sampling rate. + * + * \param bitsPerFrame Framesize in bits per frame + * \param frameLength Number of audio samples in one frame. + * \param samplingRate Sampling rate in Hz. + * + * \return Bitrate in bits per second. + */ +INT FDKaacEnc_CalcBitrate(const INT bitsPerFrame, const INT frameLength, + const INT samplingRate); + +/** + * \brief Limit given bit rate to a valid value + * \param hTpEnc transport encoder handle + * \param aot audio object type + * \param coreSamplingRate the sample rate to be used for the AAC encoder + * \param frameLength the frameLength to be used for the AAC encoder + * \param nChannels number of total channels + * \param nChannelsEff number of effective channels + * \param bitRate the initial bit rate value for which the closest valid bit + * rate value is searched for + * \param averageBits average bits per frame for fixed framing. Set to -1 if not + * available. + * \param optional pointer where the current bits per frame are stored into. + * \param bitrateMode the current bit rate mode + * \param nSubFrames number of sub frames for super framing (not transport + * frames). + * \return a valid bit rate value as close as possible or identical to bitRate + */ +INT FDKaacEnc_LimitBitrate(HANDLE_TRANSPORTENC hTpEnc, AUDIO_OBJECT_TYPE aot, + INT coreSamplingRate, INT frameLength, INT nChannels, + INT nChannelsEff, INT bitRate, INT averageBits, + INT *pAverageBitsPerFrame, + AACENC_BITRATE_MODE bitrateMode, INT nSubFrames); + +/** + * \brief Get current state of the bit reservoir + * \param hAacEncoder encoder handle + * \return bit reservoir state in bits + */ +INT FDKaacEnc_GetBitReservoirState(const HANDLE_AAC_ENC hAacEncoder); + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_GetVBRBitrate + description: Get VBR bitrate from vbr quality + input params: int vbrQuality (VBR0, VBR1, VBR2) + channelMode + returns: vbr bitrate + +------------------------------------------------------------------------------*/ +INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode, + CHANNEL_MODE channelMode); + +/*----------------------------------------------------------------------------- + + functionname: FDKaacEnc_AacInitDefaultConfig + description: gives reasonable default configuration + returns: --- + + ------------------------------------------------------------------------------*/ +void FDKaacEnc_AacInitDefaultConfig(AACENC_CONFIG *config); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Open + description: allocate and initialize a new encoder instance + returns: 0 if success + + ---------------------------------------------------------------------------*/ +AAC_ENCODER_ERROR FDKaacEnc_Open( + HANDLE_AAC_ENC + *phAacEnc, /* pointer to an encoder handle, initialized on return */ + const INT nElements, /* number of maximal elements in instance to support */ + const INT nChannels, /* number of maximal channels in instance to support */ + const INT nSubFrames); /* support superframing in instance */ + +AAC_ENCODER_ERROR FDKaacEnc_Initialize( + HANDLE_AAC_ENC + hAacEncoder, /* pointer to an encoder handle, initialized on return */ + AACENC_CONFIG *config, /* pre-initialized config struct */ + HANDLE_TRANSPORTENC hTpEnc, ULONG initFlags); + +/*--------------------------------------------------------------------------- + + functionname: FDKaacEnc_EncodeFrame + description: encode one frame + returns: 0 if success + + ---------------------------------------------------------------------------*/ + +AAC_ENCODER_ERROR FDKaacEnc_EncodeFrame( + HANDLE_AAC_ENC hAacEnc, /* encoder handle */ + HANDLE_TRANSPORTENC hTpEnc, INT_PCM *inputBuffer, + const UINT inputBufferBufSize, INT *numOutBytes, + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]); + +/*--------------------------------------------------------------------------- + + functionname:FDKaacEnc_Close + description: delete encoder instance + returns: + + ---------------------------------------------------------------------------*/ + +void FDKaacEnc_Close(HANDLE_AAC_ENC *phAacEnc); /* encoder handle */ + +#ifdef __cplusplus +} +#endif + +#endif /* AACENC_H */ diff --git a/fdk-aac/libAACenc/src/aacenc_lib.cpp b/fdk-aac/libAACenc/src/aacenc_lib.cpp new file mode 100644 index 0000000..aaa6c74 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc_lib.cpp @@ -0,0 +1,2575 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: FDK HE-AAC Encoder interface library functions + +*******************************************************************************/ +#include +#include "aacenc_lib.h" +#include "FDK_audio.h" +#include "aacenc.h" + +#include "aacEnc_ram.h" +#include "FDK_core.h" /* FDK_tools versioning info */ + +/* Encoder library info */ +#define AACENCODER_LIB_VL0 4 +#define AACENCODER_LIB_VL1 0 +#define AACENCODER_LIB_VL2 0 +#define AACENCODER_LIB_TITLE "AAC Encoder" +#ifdef __ANDROID__ +#define AACENCODER_LIB_BUILD_DATE "" +#define AACENCODER_LIB_BUILD_TIME "" +#else +#define AACENCODER_LIB_BUILD_DATE __DATE__ +#define AACENCODER_LIB_BUILD_TIME __TIME__ +#endif + +#include "pcm_utils.h" + +#include "sbr_encoder.h" +#include "../src/sbrenc_ram.h" +#include "channel_map.h" + +#include "psy_const.h" +#include "bitenc.h" + +#include "tpenc_lib.h" + +#include "metadata_main.h" +#include "mps_main.h" +#include "sacenc_lib.h" + +#define SBL(fl) \ + (fl / \ + 8) /*!< Short block length (hardcoded to 8 short blocks per long block) */ +#define BSLA(fl) \ + (4 * SBL(fl) + SBL(fl) / 2) /*!< AAC block switching look-ahead */ +#define DELAY_AAC(fl) (fl + BSLA(fl)) /*!< MDCT + blockswitching */ +#define DELAY_AACLD(fl) (fl) /*!< MDCT delay (no framing delay included) */ +#define DELAY_AACELD(fl) \ + ((fl) / 2) /*!< ELD FB delay (no framing delay included) */ + +#define MAX_DS_DELAY (100) /*!< Maximum downsampler delay in SBR. */ +#define INPUTBUFFER_SIZE \ + (2 * (1024) + MAX_DS_DELAY + 1537) /*!< Audio input samples + downsampler \ + delay + sbr/aac delay compensation */ + +#define DEFAULT_HEADER_PERIOD_REPETITION_RATE \ + 10 /*!< Default header repetition rate used in transport library and for SBR \ + header. */ + +//////////////////////////////////////////////////////////////////////////////////// +/** + * Flags to characterize encoder modules to be supported in present instance. + */ +enum { + ENC_MODE_FLAG_AAC = 0x0001, + ENC_MODE_FLAG_SBR = 0x0002, + ENC_MODE_FLAG_PS = 0x0004, + ENC_MODE_FLAG_SAC = 0x0008, + ENC_MODE_FLAG_META = 0x0010 +}; + +//////////////////////////////////////////////////////////////////////////////////// +typedef struct { + AUDIO_OBJECT_TYPE userAOT; /*!< Audio Object Type. */ + UINT userSamplerate; /*!< Sampling frequency. */ + UINT nChannels; /*!< will be set via channelMode. */ + CHANNEL_MODE userChannelMode; + UINT userBitrate; + UINT userBitrateMode; + UINT userBandwidth; + UINT userAfterburner; + UINT userFramelength; + UINT userAncDataRate; + UINT userPeakBitrate; + + UCHAR userTns; /*!< Use TNS coding. */ + UCHAR userPns; /*!< Use PNS coding. */ + UCHAR userIntensity; /*!< Use Intensity coding. */ + + TRANSPORT_TYPE userTpType; /*!< Transport type */ + UCHAR userTpSignaling; /*!< Extension AOT signaling mode. */ + UCHAR userTpNsubFrames; /*!< Number of sub frames in a transport frame for + LOAS/LATM or ADTS (default 1). */ + UCHAR userTpAmxv; /*!< AudioMuxVersion to be used for LATM (default 0). */ + UCHAR userTpProtection; + UCHAR userTpHeaderPeriod; /*!< Parameter used to configure LATM/LOAS SMC rate. + Moreover this parameters is used to configure + repetition rate of PCE in raw_data_block. */ + + UCHAR userErTools; /*!< Use VCB11, HCR and/or RVLC ER tool. */ + UINT userPceAdditions; /*!< Configure additional bits in PCE. */ + + UCHAR userMetaDataMode; /*!< Meta data library configuration. */ + + UCHAR userSbrEnabled; /*!< Enable SBR for ELD. */ + UINT userSbrRatio; /*!< SBR sampling rate ratio. Dual- or single-rate. */ + + UINT userDownscaleFactor; + +} USER_PARAM; + +/** + * SBR extenxion payload struct provides buffers to be filled in SBR encoder + * library. + */ +typedef struct { + UCHAR data[(1)][(8)][MAX_PAYLOAD_SIZE]; /*!< extension payload data buffer */ + UINT dataSize[(1)][(8)]; /*!< extension payload data size in bits */ +} SBRENC_EXT_PAYLOAD; + +//////////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + Structure Definitions +****************************************************************************/ + +typedef struct AACENC_CONFIG *HANDLE_AACENC_CONFIG; + +struct AACENCODER { + USER_PARAM extParam; + CODER_CONFIG coderConfig; + + /* AAC */ + AACENC_CONFIG aacConfig; + HANDLE_AAC_ENC hAacEnc; + + /* SBR */ + HANDLE_SBR_ENCODER hEnvEnc; /* SBR encoder */ + SBRENC_EXT_PAYLOAD *pSbrPayload; /* SBR extension payload */ + + /* Meta Data */ + HANDLE_FDK_METADATA_ENCODER hMetadataEnc; + INT metaDataAllowed; /* Signal whether chosen configuration allows metadata. + Necessary for delay compensation. Metadata mode is a + separate parameter. */ + + HANDLE_MPS_ENCODER hMpsEnc; + + /* Transport */ + HANDLE_TRANSPORTENC hTpEnc; + + INT_PCM + *inputBuffer; /* Internal input buffer. Input source for AAC encoder */ + UCHAR *outBuffer; /* Internal bitstream buffer */ + + INT inputBufferSize; /* Size of internal input buffer */ + INT inputBufferSizePerChannel; /* Size of internal input buffer per channel */ + INT outBufferInBytes; /* Size of internal bitstream buffer*/ + + INT inputBufferOffset; /* Where to write new input samples. */ + + INT nSamplesToRead; /* number of input samples neeeded for encoding one frame + */ + INT nSamplesRead; /* number of input samples already in input buffer */ + INT nZerosAppended; /* appended zeros at end of file*/ + INT nDelay; /* codec delay */ + INT nDelayCore; /* codec delay, w/o the SBR decoder delay */ + + AACENC_EXT_PAYLOAD extPayload[MAX_TOTAL_EXT_PAYLOADS]; + + ULONG InitFlags; /* internal status to treggier re-initialization */ + + /* Memory allocation info. */ + INT nMaxAacElements; + INT nMaxAacChannels; + INT nMaxSbrElements; + INT nMaxSbrChannels; + + UINT encoder_modis; + + /* Capability flags */ + UINT CAPF_tpEnc; +}; + +typedef struct { + /* input */ + ULONG nChannels; /*!< Number of audio channels. */ + ULONG samplingRate; /*!< Encoder output sampling rate. */ + ULONG bitrateRange; /*!< Lower bitrate range for config entry. */ + + /* output*/ + UCHAR sbrMode; /*!< 0: ELD sbr off, + 1: ELD with downsampled sbr, + 2: ELD with dualrate sbr. */ + CHANNEL_MODE chMode; /*!< Channel mode. */ + +} ELD_SBR_CONFIGURATOR; + +/** + * \brief This table defines ELD/SBR default configurations. + */ +static const ELD_SBR_CONFIGURATOR eldSbrAutoConfigTab[] = { + {1, 48000, 0, 2, MODE_1}, {1, 48000, 64000, 0, MODE_1}, + + {1, 44100, 0, 2, MODE_1}, {1, 44100, 64000, 0, MODE_1}, + + {1, 32000, 0, 2, MODE_1}, {1, 32000, 28000, 1, MODE_1}, + {1, 32000, 56000, 0, MODE_1}, + + {1, 24000, 0, 1, MODE_1}, {1, 24000, 40000, 0, MODE_1}, + + {1, 16000, 0, 1, MODE_1}, {1, 16000, 28000, 0, MODE_1}, + + {1, 15999, 0, 0, MODE_1}, + + {2, 48000, 0, 2, MODE_2}, {2, 48000, 44000, 2, MODE_2}, + {2, 48000, 128000, 0, MODE_2}, + + {2, 44100, 0, 2, MODE_2}, {2, 44100, 44000, 2, MODE_2}, + {2, 44100, 128000, 0, MODE_2}, + + {2, 32000, 0, 2, MODE_2}, {2, 32000, 32000, 2, MODE_2}, + {2, 32000, 68000, 1, MODE_2}, {2, 32000, 96000, 0, MODE_2}, + + {2, 24000, 0, 1, MODE_2}, {2, 24000, 48000, 1, MODE_2}, + {2, 24000, 80000, 0, MODE_2}, + + {2, 16000, 0, 1, MODE_2}, {2, 16000, 32000, 1, MODE_2}, + {2, 16000, 64000, 0, MODE_2}, + + {2, 15999, 0, 0, MODE_2} + +}; + +/* + * \brief Configure SBR for ELD configuration. + * + * This function finds default SBR configuration for ELD based on number of + * channels, sampling rate and bitrate. + * + * \param nChannels Number of audio channels. + * \param samplingRate Audio signal sampling rate. + * \param bitrate Encoder bitrate. + * + * \return - pointer to eld sbr configuration. + * - NULL, on failure. + */ +static const ELD_SBR_CONFIGURATOR *eldSbrConfigurator(const ULONG nChannels, + const ULONG samplingRate, + const ULONG bitrate) { + int i; + const ELD_SBR_CONFIGURATOR *pSetup = NULL; + + for (i = 0; + i < (int)(sizeof(eldSbrAutoConfigTab) / sizeof(ELD_SBR_CONFIGURATOR)); + i++) { + if ((nChannels == eldSbrAutoConfigTab[i].nChannels) && + (samplingRate <= eldSbrAutoConfigTab[i].samplingRate) && + (bitrate >= eldSbrAutoConfigTab[i].bitrateRange)) { + pSetup = &eldSbrAutoConfigTab[i]; + } + } + + return pSetup; +} + +static inline INT isSbrActive(const HANDLE_AACENC_CONFIG hAacConfig) { + INT sbrUsed = 0; + + /* Note: Even if implicit signalling was selected, The AOT itself here is not + * AOT_AAC_LC */ + if ((hAacConfig->audioObjectType == AOT_SBR) || + (hAacConfig->audioObjectType == AOT_PS) || + (hAacConfig->audioObjectType == AOT_MP2_SBR) || + (hAacConfig->audioObjectType == AOT_DABPLUS_SBR) || + (hAacConfig->audioObjectType == AOT_DABPLUS_PS)) { + sbrUsed = 1; + } + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD && + (hAacConfig->syntaxFlags & AC_SBR_PRESENT)) { + sbrUsed = 1; + } + + return (sbrUsed); +} + +static inline INT isPsActive(const AUDIO_OBJECT_TYPE audioObjectType) { + INT psUsed = 0; + + if ((audioObjectType == AOT_PS) || + (audioObjectType == AOT_DABPLUS_PS)) { + psUsed = 1; + } + + return (psUsed); +} + +static CHANNEL_MODE GetCoreChannelMode( + const CHANNEL_MODE channelMode, const AUDIO_OBJECT_TYPE audioObjectType) { + CHANNEL_MODE mappedChannelMode = channelMode; + if ((isPsActive(audioObjectType) && (channelMode == MODE_2)) || + (channelMode == MODE_212)) { + mappedChannelMode = MODE_1; + } + return mappedChannelMode; +} + +static SBR_PS_SIGNALING getSbrSignalingMode( + const AUDIO_OBJECT_TYPE audioObjectType, const TRANSPORT_TYPE transportType, + const UCHAR transportSignaling, const UINT sbrRatio) + +{ + SBR_PS_SIGNALING sbrSignaling; + + if (transportType == TT_UNKNOWN || sbrRatio == 0) { + sbrSignaling = SIG_UNKNOWN; /* Needed parameters have not been set */ + return sbrSignaling; + } else { + sbrSignaling = + SIG_EXPLICIT_HIERARCHICAL; /* default: explicit hierarchical signaling + */ + } + + if ((audioObjectType == AOT_AAC_LC) || (audioObjectType == AOT_SBR) || + (audioObjectType == AOT_PS) || (audioObjectType == AOT_MP2_AAC_LC) || + (audioObjectType == AOT_MP2_SBR) || + (audioObjectType == AOT_DABPLUS_SBR) || + (audioObjectType == AOT_DABPLUS_PS)) { + switch (transportType) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + sbrSignaling = SIG_IMPLICIT; /* For MPEG-2 transport types, only + implicit signaling is possible */ + break; + + case TT_MP4_RAW: + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + case TT_MP4_LOAS: + default: + if (transportSignaling == 0xFF) { + /* Defaults */ + sbrSignaling = SIG_EXPLICIT_HIERARCHICAL; + } else { + /* User set parameters */ + /* Attention: Backward compatible explicit signaling does only work + * with AMV1 for LATM/LOAS */ + sbrSignaling = (SBR_PS_SIGNALING)transportSignaling; + } + break; + } + } + + return sbrSignaling; +} + +/**************************************************************************** + Allocate Encoder +****************************************************************************/ + +H_ALLOC_MEM(_AacEncoder, AACENCODER) +C_ALLOC_MEM(_AacEncoder, struct AACENCODER, 1) + +/* + * Map Encoder specific config structures to CODER_CONFIG. + */ +static void FDKaacEnc_MapConfig(CODER_CONFIG *const cc, + const USER_PARAM *const extCfg, + const SBR_PS_SIGNALING sbrSignaling, + const HANDLE_AACENC_CONFIG hAacConfig) { + AUDIO_OBJECT_TYPE transport_AOT = AOT_NULL_OBJECT; + FDKmemclear(cc, sizeof(CODER_CONFIG)); + + cc->flags = 0; + + cc->samplesPerFrame = hAacConfig->framelength; + cc->samplingRate = hAacConfig->sampleRate; + cc->extSamplingRate = extCfg->userSamplerate; + + /* Map virtual aot to transport aot. */ + switch (hAacConfig->audioObjectType) { + case AOT_MP2_AAC_LC: + case AOT_DABPLUS_AAC_LC: + transport_AOT = AOT_AAC_LC; + break; + case AOT_MP2_SBR: + case AOT_DABPLUS_SBR: + transport_AOT = AOT_SBR; + cc->flags |= CC_SBR; + break; + case AOT_DABPLUS_PS: + transport_AOT = AOT_PS; + cc->flags |= CC_SBR; + break; + default: + transport_AOT = hAacConfig->audioObjectType; + } + + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + cc->flags |= (hAacConfig->syntaxFlags & AC_SBR_PRESENT) ? CC_SBR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_LD_MPS) ? CC_SAC : 0; + } + + /* transport type is usually AAC-LC. */ + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->aot = AOT_AAC_LC; + } else { + cc->aot = transport_AOT; + } + + /* Configure extension aot. */ + if (sbrSignaling == SIG_IMPLICIT) { + cc->extAOT = AOT_NULL_OBJECT; /* implicit */ + } else { + if ((sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) && + ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS))) { + cc->extAOT = AOT_SBR; /* explicit backward compatible */ + } else { + cc->extAOT = transport_AOT; /* explicit hierarchical */ + } + } + + if ((transport_AOT == AOT_SBR) || (transport_AOT == AOT_PS)) { + cc->sbrPresent = 1; + if (transport_AOT == AOT_PS) { + cc->psPresent = 1; + } + } + cc->sbrSignaling = sbrSignaling; + + if (hAacConfig->downscaleFactor > 1) { + cc->downscaleSamplingRate = cc->samplingRate; + cc->samplingRate *= hAacConfig->downscaleFactor; + cc->extSamplingRate *= hAacConfig->downscaleFactor; + } + + cc->bitRate = hAacConfig->bitRate; + cc->noChannels = hAacConfig->nChannels; + cc->flags |= CC_IS_BASELAYER; + cc->channelMode = hAacConfig->channelMode; + +if (extCfg->userTpType == TT_DABPLUS && hAacConfig->nSubFrames==1) { + switch(hAacConfig->sampleRate) { + case 48000: + cc->nSubFrames=6; + break; + case 32000: + cc->nSubFrames=4; + break; + case 24000: + cc->nSubFrames=3; + break; + case 16000: + cc->nSubFrames=2; + break; + } + //fprintf(stderr, "hAacConfig->nSubFrames=%d hAacConfig->sampleRate=%d\n", hAacConfig->nSubFrames, hAacConfig->sampleRate); + } else { + cc->nSubFrames = (hAacConfig->nSubFrames > 1 && extCfg->userTpNsubFrames == 1) + ? hAacConfig->nSubFrames + : extCfg->userTpNsubFrames; + } + + cc->flags |= (extCfg->userTpProtection) ? CC_PROTECTION : 0; + + if (extCfg->userTpHeaderPeriod != 0xFF) { + cc->headerPeriod = extCfg->userTpHeaderPeriod; + } else { /* auto-mode */ + switch (extCfg->userTpType) { + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP1: + cc->headerPeriod = DEFAULT_HEADER_PERIOD_REPETITION_RATE; + break; + default: + cc->headerPeriod = 0; + } + } + + /* Mpeg-4 signaling for transport library. */ + switch (hAacConfig->audioObjectType) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + cc->flags &= ~CC_MPEG_ID; /* Required for ADTS. */ + cc->extAOT = AOT_NULL_OBJECT; + break; + default: + cc->flags |= CC_MPEG_ID; + } + + /* ER-tools signaling. */ + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_VCB11) ? CC_VCB11 : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_HCR) ? CC_HCR : 0; + cc->flags |= (hAacConfig->syntaxFlags & AC_ER_RVLC) ? CC_RVLC : 0; + + /* Matrix mixdown coefficient configuration. */ + if ((extCfg->userPceAdditions & 0x1) && (hAacConfig->epConfig == -1) && + ((cc->channelMode == MODE_1_2_2) || (cc->channelMode == MODE_1_2_2_1))) { + cc->matrixMixdownA = ((extCfg->userPceAdditions >> 1) & 0x3) + 1; + cc->flags |= (extCfg->userPceAdditions >> 3) & 0x1 ? CC_PSEUDO_SURROUND : 0; + } else { + cc->matrixMixdownA = 0; + } + + cc->channelConfigZero = 0; +} + +/* + * Validate prefilled pointers within buffer descriptor. + * + * \param pBufDesc Pointer to buffer descriptor + + * \return - AACENC_OK, all fine. + * - AACENC_INVALID_HANDLE, on missing pointer initializiation. + * - AACENC_UNSUPPORTED_PARAMETER, on incorrect buffer descriptor + initialization. + */ +static AACENC_ERROR validateBufDesc(const AACENC_BufDesc *pBufDesc) { + AACENC_ERROR err = AACENC_OK; + + if (pBufDesc != NULL) { + int i; + if ((pBufDesc->bufferIdentifiers == NULL) || (pBufDesc->bufSizes == NULL) || + (pBufDesc->bufElSizes == NULL) || (pBufDesc->bufs == NULL)) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + for (i = 0; i < pBufDesc->numBufs; i++) { + if (pBufDesc->bufs[i] == NULL) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + } + } else { + err = AACENC_INVALID_HANDLE; + } +bail: + return err; +} + +/* + * Examine buffer descriptor regarding choosen identifier. + * + * \param pBufDesc Pointer to buffer descriptor + * \param identifier Buffer identifier to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx(const AACENC_BufDesc *pBufDesc, + const AACENC_BufferIdentifier identifier) { + INT i, idx = -1; + + if (pBufDesc != NULL) { + for (i = 0; i < pBufDesc->numBufs; i++) { + if ((AACENC_BufferIdentifier)pBufDesc->bufferIdentifiers[i] == + identifier) { + idx = i; + break; + } + } + } + return idx; +} + +/**************************************************************************** + Function Declarations +****************************************************************************/ + +AAC_ENCODER_ERROR aacEncDefaultConfig(HANDLE_AACENC_CONFIG hAacConfig, + USER_PARAM *config) { + /* make reasonable default settings */ + FDKaacEnc_AacInitDefaultConfig(hAacConfig); + + /* clear configuration structure and copy default settings */ + FDKmemclear(config, sizeof(USER_PARAM)); + + /* copy encoder configuration settings */ + config->nChannels = hAacConfig->nChannels; + config->userAOT = hAacConfig->audioObjectType = AOT_AAC_LC; + config->userSamplerate = hAacConfig->sampleRate; + config->userChannelMode = hAacConfig->channelMode; + config->userBitrate = hAacConfig->bitRate; + config->userBitrateMode = hAacConfig->bitrateMode; + config->userPeakBitrate = (UINT)-1; + config->userBandwidth = hAacConfig->bandWidth; + config->userTns = hAacConfig->useTns; + config->userPns = hAacConfig->usePns; + config->userIntensity = hAacConfig->useIS; + config->userAfterburner = hAacConfig->useRequant; + config->userFramelength = (UINT)-1; + + config->userDownscaleFactor = 1; + + /* initialize transport parameters */ + config->userTpType = TT_UNKNOWN; + config->userTpAmxv = 0; + config->userTpSignaling = 0xFF; /* choose signaling automatically */ + config->userTpNsubFrames = 1; + config->userTpProtection = 0; /* not crc protected*/ + config->userTpHeaderPeriod = 0xFF; /* header period in auto mode */ + config->userPceAdditions = 0; /* no matrix mixdown coefficient */ + config->userMetaDataMode = 0; /* do not embed any meta data info */ + + config->userAncDataRate = 0; + + /* SBR rate is set to 0 here, which means it should be set automatically + in FDKaacEnc_AdjustEncSettings() if the user did not set a rate + expilicitely. */ + config->userSbrRatio = 0; + + /* SBR enable set to -1 means to inquire ELD audio configurator for reasonable + * configuration. */ + config->userSbrEnabled = (UCHAR)-1; + + return AAC_ENC_OK; +} + +static void aacEncDistributeSbrBits(CHANNEL_MAPPING *channelMapping, + SBR_ELEMENT_INFO *sbrElInfo, INT bitRate) { + INT codebits = bitRate; + int el; + + /* Copy Element info */ + for (el = 0; el < channelMapping->nElements; el++) { + sbrElInfo[el].ChannelIndex[0] = channelMapping->elInfo[el].ChannelIndex[0]; + sbrElInfo[el].ChannelIndex[1] = channelMapping->elInfo[el].ChannelIndex[1]; + sbrElInfo[el].elType = channelMapping->elInfo[el].elType; + sbrElInfo[el].bitRate = + fMultIfloor(channelMapping->elInfo[el].relativeBits, bitRate); + sbrElInfo[el].instanceTag = channelMapping->elInfo[el].instanceTag; + sbrElInfo[el].nChannelsInEl = channelMapping->elInfo[el].nChannelsInEl; + sbrElInfo[el].fParametricStereo = 0; + sbrElInfo[el].fDualMono = 0; + + codebits -= sbrElInfo[el].bitRate; + } + sbrElInfo[0].bitRate += codebits; +} + +static INT aacEncoder_LimitBitrate(const HANDLE_TRANSPORTENC hTpEnc, + const INT samplingRate, + const INT frameLength, const INT nChannels, + const CHANNEL_MODE channelMode, INT bitRate, + const INT nSubFrames, const INT sbrActive, + const INT sbrDownSampleRate, + const UINT syntaxFlags, + const AUDIO_OBJECT_TYPE aot) { + INT coreSamplingRate; + CHANNEL_MAPPING cm; + + FDKaacEnc_InitChannelMapping(channelMode, CH_ORDER_MPEG, &cm); + + if (sbrActive) { + coreSamplingRate = + samplingRate >> + (sbrEncoder_IsSingleRatePossible(aot) ? (sbrDownSampleRate - 1) : 1); + } else { + coreSamplingRate = samplingRate; + } + + /* Limit bit rate in respect to the core coder */ + bitRate = FDKaacEnc_LimitBitrate(hTpEnc, aot, coreSamplingRate, frameLength, + nChannels, cm.nChannelsEff, bitRate, -1, + NULL, AACENC_BR_MODE_INVALID, nSubFrames); + + /* Limit bit rate in respect to available SBR modes if active */ + if (sbrActive) { + int numIterations = 0; + INT initialBitrate, adjustedBitrate; + adjustedBitrate = bitRate; + + /* Find total bitrate which provides valid configuration for each SBR + * element. */ + do { + int e; + SBR_ELEMENT_INFO sbrElInfo[((8))]; + FDK_ASSERT(cm.nElements <= ((8))); + + initialBitrate = adjustedBitrate; + + /* Get bit rate for each SBR element */ + aacEncDistributeSbrBits(&cm, sbrElInfo, initialBitrate); + + for (e = 0; e < cm.nElements; e++) { + INT sbrElementBitRateIn, sbrBitRateOut; + + if (cm.elInfo[e].elType != ID_SCE && cm.elInfo[e].elType != ID_CPE) { + continue; + } + sbrElementBitRateIn = sbrElInfo[e].bitRate; + + sbrBitRateOut = sbrEncoder_LimitBitRate(sbrElementBitRateIn, + cm.elInfo[e].nChannelsInEl, + coreSamplingRate, aot); + + if (sbrBitRateOut == 0) { + return 0; + } + + /* If bitrates don't match, distribution and limiting needs to be + determined again. Abort element loop and restart with adapted + bitrate. */ + if (sbrElementBitRateIn != sbrBitRateOut) { + if (sbrElementBitRateIn < sbrBitRateOut) { + adjustedBitrate = fMax(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut + 8), + cm.elInfo[e].relativeBits)); + break; + } + + if (sbrElementBitRateIn > sbrBitRateOut) { + adjustedBitrate = fMin(initialBitrate, + (INT)fDivNorm((FIXP_DBL)(sbrBitRateOut - 8), + cm.elInfo[e].relativeBits)); + break; + } + + } /* sbrElementBitRateIn != sbrBitRateOut */ + + } /* elements */ + + numIterations++; /* restrict iteration to worst case of num elements */ + + } while ((initialBitrate != adjustedBitrate) && + (numIterations <= cm.nElements)); + + /* Unequal bitrates mean that no reasonable bitrate configuration found. */ + bitRate = (initialBitrate == adjustedBitrate) ? adjustedBitrate : 0; + } + + /* Limit bit rate in respect to available MPS modes if active */ + if ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS) && + (channelMode == MODE_1)) { + bitRate = FDK_MpegsEnc_GetClosestBitRate( + aot, MODE_212, samplingRate, (sbrActive) ? sbrDownSampleRate : 0, + bitRate); + } + + //fprintf(stderr, "aacEncoder_LimitBitrate(): bitRate=%d\n", bitRate); + return bitRate; +} + +/* + * \brief Get CBR bitrate + * + * \hAacConfig Internal encoder config + * \return Bitrate + */ +static INT FDKaacEnc_GetCBRBitrate(const HANDLE_AACENC_CONFIG hAacConfig, + const INT userSbrRatio) { + INT bitrate = FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff * + hAacConfig->sampleRate; + + if (isPsActive(hAacConfig->audioObjectType)) { + bitrate = 1 * bitrate; /* 0.5 bit per sample */ + } else if (isSbrActive(hAacConfig)) { + if ((userSbrRatio == 2) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType != AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 2)) >> 1; /* 0.625 bits per sample */ + } + if ((userSbrRatio == 1) || + ((userSbrRatio == 0) && + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD))) { + bitrate = (bitrate + (bitrate >> 3)); /* 1.125 bits per sample */ + } + } else { + bitrate = bitrate + (bitrate >> 1); /* 1.5 bits per sample */ + } + + return bitrate; +} + +/* + * \brief Consistency check of given USER_PARAM struct and + * copy back configuration from public struct into internal + * encoder configuration struct. + * + * \hAacEncoder Internal encoder config which is to be updated + * \param config User provided config (public struct) + * \return returns always AAC_ENC_OK + */ +static AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder, + USER_PARAM *config) { + AACENC_ERROR err = AACENC_OK; + + /* Get struct pointers. */ + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + /* Encoder settings update. */ + hAacConfig->sampleRate = config->userSamplerate; + if (config->userDownscaleFactor > 1) { + hAacConfig->useTns = 0; + hAacConfig->usePns = 0; + hAacConfig->useIS = 0; + } else { + hAacConfig->useTns = config->userTns; + hAacConfig->usePns = config->userPns; + hAacConfig->useIS = config->userIntensity; + } + + hAacConfig->audioObjectType = config->userAOT; + hAacConfig->channelMode = + GetCoreChannelMode(config->userChannelMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode)->nChannels; + hAacConfig->bitrateMode = (AACENC_BITRATE_MODE)config->userBitrateMode; + hAacConfig->bandWidth = config->userBandwidth; + hAacConfig->useRequant = config->userAfterburner; + + hAacConfig->anc_Rate = config->userAncDataRate; + hAacConfig->syntaxFlags = 0; + hAacConfig->epConfig = -1; + + if (hAacConfig->audioObjectType != AOT_ER_AAC_ELD && + config->userDownscaleFactor > 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + */ + } + if (config->userDownscaleFactor > 1 && config->userSbrEnabled == 1) { + return AACENC_INVALID_CONFIG; /* downscaling only allowed for AOT_ER_AAC_ELD + w/o SBR */ + } + if (config->userDownscaleFactor > 1 && config->userChannelMode == 128) { + return AACENC_INVALID_CONFIG; /* disallow downscaling for AAC-ELDv2 */ + } + + if (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) { + hAacConfig->audioMuxVersion = config->userTpAmxv; + } else { + hAacConfig->audioMuxVersion = -1; + } + + /* Adapt internal AOT when necessary. */ + switch (config->userAOT) { + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacConfig->usePns = 0; + FDK_FALLTHROUGH; + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_ADTS; + hAacConfig->framelength = (config->userFramelength != (UINT)-1) + ? config->userFramelength + : 1024; + if (hAacConfig->framelength != 1024 && hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + break; + + case AOT_DABPLUS_SBR: + case AOT_DABPLUS_PS: + hAacConfig->syntaxFlags |= ((config->userSbrEnabled) ? AC_SBR_PRESENT : 0); + case AOT_DABPLUS_AAC_LC: + config->userTpType = (config->userTpType!=TT_UNKNOWN) ? config->userTpType : TT_DABPLUS; + hAacConfig->framelength = (config->userFramelength!=(UINT)-1) ? config->userFramelength : 960; + if (hAacConfig->framelength != 960) { + return AACENC_INVALID_CONFIG; + } + config->userTpSignaling=2; + if(config->userTpType == TT_DABPLUS) + hAacConfig->syntaxFlags |= AC_DAB; + break; + + case AOT_ER_AAC_LD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER | AC_LD; + hAacConfig->syntaxFlags |= + ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = + (config->userFramelength != (UINT)-1) ? config->userFramelength : 512; + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480) { + return AACENC_INVALID_CONFIG; + } + break; + case AOT_ER_AAC_ELD: + hAacConfig->epConfig = 0; + hAacConfig->syntaxFlags |= AC_ER | AC_ELD; + hAacConfig->syntaxFlags |= + ((config->userErTools & 0x1) ? AC_ER_VCB11 : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x2) ? AC_ER_HCR : 0); + hAacConfig->syntaxFlags |= ((config->userErTools & 0x4) ? AC_ER_RVLC : 0); + hAacConfig->syntaxFlags |= + ((config->userSbrEnabled == 1) ? AC_SBR_PRESENT : 0); + hAacConfig->syntaxFlags |= + ((config->userChannelMode == MODE_212) ? AC_LD_MPS : 0); + config->userTpType = + (config->userTpType != TT_UNKNOWN) ? config->userTpType : TT_MP4_LOAS; + hAacConfig->framelength = + (config->userFramelength != (UINT)-1) ? config->userFramelength : 512; + + hAacConfig->downscaleFactor = config->userDownscaleFactor; + + switch (config->userDownscaleFactor) { + case 1: + break; + case 2: + case 4: + hAacConfig->syntaxFlags |= AC_ELD_DOWNSCALE; + break; + default: + return AACENC_INVALID_CONFIG; + } + + if (hAacConfig->framelength != 512 && hAacConfig->framelength != 480 && + hAacConfig->framelength != 256 && hAacConfig->framelength != 240 && + hAacConfig->framelength != 128 && hAacConfig->framelength != 120) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + + /* Initialize SBR parameters */ + if ((config->userSbrRatio == 0) && (isSbrActive(hAacConfig))) { + /* Automatic SBR ratio configuration + * - downsampled SBR for ELD + * - otherwise always dualrate SBR + */ + if (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) { + hAacConfig->sbrRatio = ((hAacConfig->syntaxFlags & AC_LD_MPS) && + (hAacConfig->sampleRate >= 27713)) + ? 2 + : 1; + } else { + hAacConfig->sbrRatio = 2; + } + } else { + /* SBR ratio has been set by the user, so use it. */ + hAacConfig->sbrRatio = isSbrActive(hAacConfig) ? config->userSbrRatio : 0; + } + + /* Set default bitrate */ + hAacConfig->bitRate = config->userBitrate; + + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + /* Set default bitrate if no external bitrate declared. */ + if (config->userBitrate == (UINT)-1) { + hAacConfig->bitRate = + FDKaacEnc_GetCBRBitrate(hAacConfig, config->userSbrRatio); + } + hAacConfig->averageBits = -1; + break; + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* Get bitrate in VBR configuration */ + /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. + */ + hAacConfig->bitRate = FDKaacEnc_GetVBRBitrate(hAacConfig->bitrateMode, + hAacConfig->channelMode); + break; + default: + return AACENC_INVALID_CONFIG; + } + + /* set bitreservoir size */ + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + case AACENC_BR_MODE_CBR: + if ((INT)config->userPeakBitrate != -1) { + hAacConfig->maxBitsPerFrame = + (FDKaacEnc_CalcBitsPerFrame( + fMax(hAacConfig->bitRate, (INT)config->userPeakBitrate), + hAacConfig->framelength, hAacConfig->sampleRate) + + 7) & + ~7; + } else { + hAacConfig->maxBitsPerFrame = -1; + } + if (hAacConfig->audioMuxVersion == 2) { + hAacConfig->minBitsPerFrame = + fMin(32 * 8, FDKaacEnc_CalcBitsPerFrame(hAacConfig->bitRate, + hAacConfig->framelength, + hAacConfig->sampleRate)) & + ~7; + } + break; + default: + return AACENC_INVALID_CONFIG; + } + + /* Max bits per frame limitation depending on transport format. */ + if ((config->userTpNsubFrames > 1)) { + int maxFrameLength = 8 * hAacEncoder->outBufferInBytes; + switch (config->userTpType) { + case TT_MP4_LOAS: + maxFrameLength = + fMin(maxFrameLength, 8 * (1 << 13)) / config->userTpNsubFrames; + break; + case TT_MP4_ADTS: + maxFrameLength = fMin(maxFrameLength, 8 * ((1 << 13) - 1)) / + config->userTpNsubFrames; + break; + default: + maxFrameLength = -1; + } + if (maxFrameLength != -1) { + if (hAacConfig->maxBitsPerFrame > maxFrameLength) { + return AACENC_INVALID_CONFIG; + } else if (hAacConfig->maxBitsPerFrame == -1) { + hAacConfig->maxBitsPerFrame = maxFrameLength; + } + } + } + + if ((hAacConfig->audioObjectType == AOT_ER_AAC_ELD) && + !(hAacConfig->syntaxFlags & AC_ELD_DOWNSCALE) && + (config->userSbrEnabled == (UCHAR)-1) && (config->userSbrRatio == 0) && + ((hAacConfig->syntaxFlags & AC_LD_MPS) == 0)) { + const ELD_SBR_CONFIGURATOR *pConfig = NULL; + + if (NULL != + (pConfig = eldSbrConfigurator( + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels, + hAacConfig->sampleRate, hAacConfig->bitRate))) { + hAacConfig->syntaxFlags |= (pConfig->sbrMode == 0) ? 0 : AC_SBR_PRESENT; + hAacConfig->syntaxFlags |= (pConfig->chMode == MODE_212) ? AC_LD_MPS : 0; + hAacConfig->channelMode = + GetCoreChannelMode(pConfig->chMode, hAacConfig->audioObjectType); + hAacConfig->nChannels = + FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannels; + hAacConfig->sbrRatio = + (pConfig->sbrMode == 0) ? 0 : (pConfig->sbrMode == 1) ? 1 : 2; + } + } + + { + UCHAR tpSignaling = + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio); + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (config->userTpType == TT_MP4_LATM_MCP1 || + config->userTpType == TT_MP4_LATM_MCP0 || + config->userTpType == TT_MP4_LOAS) && + (tpSignaling == 1) && (config->userTpAmxv == 0)) { + /* For backward compatible explicit signaling, AMV1 has to be active */ + return AACENC_INVALID_CONFIG; + } + + if ((hAacConfig->audioObjectType == AOT_AAC_LC || + hAacConfig->audioObjectType == AOT_SBR || + hAacConfig->audioObjectType == AOT_PS) && + (tpSignaling == 0) && (hAacConfig->sbrRatio == 1)) { + /* Downsampled SBR has to be signaled explicitely (for transmission of SBR + * sampling fequency) */ + return AACENC_INVALID_CONFIG; + } + } + + switch (hAacConfig->bitrateMode) { + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + /* We need the frame length to call aacEncoder_LimitBitrate() */ + if (0 >= (hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, hAacConfig->sampleRate, hAacConfig->framelength, + hAacConfig->nChannels, hAacConfig->channelMode, + hAacConfig->bitRate, hAacConfig->nSubFrames, + isSbrActive(hAacConfig), hAacConfig->sbrRatio, + hAacConfig->syntaxFlags, hAacConfig->audioObjectType))) { + return AACENC_INVALID_CONFIG; + } + break; + default: + break; + } + +#if 0 // TODO Is this still needed? + /* We need the frame length to call aacEncoder_LimitBitrate() */ + hAacConfig->bitRate = aacEncoder_LimitBitrate( + NULL, + hAacConfig->sampleRate, + hAacConfig->framelength, + hAacConfig->nChannels, + hAacConfig->channelMode, + hAacConfig->bitRate, + hAacConfig->nSubFrames, + isSbrActive(hAacConfig), + hAacConfig->sbrRatio, + hAacConfig->audioObjectType + ); +#endif + +/* Configure PNS */ + if (AACENC_BR_MODE_IS_VBR(hAacConfig->bitrateMode) /* VBR without PNS. */ + || (hAacConfig->useTns == 0)) /* TNS required. */ + { + hAacConfig->usePns = 0; + } + + if (hAacConfig->epConfig >= 0) { + hAacConfig->syntaxFlags |= AC_ER; + if (((INT)hAacConfig->channelMode < 1) || + ((INT)hAacConfig->channelMode > 14)) { + return AACENC_INVALID_CONFIG; /* Channel config 0 not supported. */ + } + } + + if ((hAacConfig->syntaxFlags & AC_LD_MPS) == 0) { + if (FDKaacEnc_DetermineEncoderMode(&hAacConfig->channelMode, + hAacConfig->nChannels) != AAC_ENC_OK) { + return AACENC_INVALID_CONFIG; /* nChannels doesn't match chMode, this is + just a check-up */ + } + } + + if ((hAacConfig->nChannels > hAacEncoder->nMaxAacChannels) || + ((FDKaacEnc_GetChannelModeConfiguration(hAacConfig->channelMode) + ->nChannelsEff > hAacEncoder->nMaxSbrChannels) && + isSbrActive(hAacConfig))) { + return AACENC_INVALID_CONFIG; /* not enough channels allocated */ + } + + /* Meta data restriction. */ + switch (hAacConfig->audioObjectType) { + /* Allow metadata support */ + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_MP2_AAC_LC: + case AOT_MP2_SBR: + hAacEncoder->metaDataAllowed = 1; + if (!((((INT)hAacConfig->channelMode >= 1) && + ((INT)hAacConfig->channelMode <= 14)) || + (MODE_7_1_REAR_SURROUND == hAacConfig->channelMode) || + (MODE_7_1_FRONT_CENTER == hAacConfig->channelMode))) { + config->userMetaDataMode = 0; + } + break; + /* Prohibit metadata support */ + default: + hAacEncoder->metaDataAllowed = 0; + } + + return err; +} + +static INT aacenc_SbrCallback(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, + const INT elementIndex, const UCHAR harmonicSbr, + const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; + + sbrEncoder_GetHeader(hAacEncoder->hEnvEnc, hBs, elementIndex, 0); + + return 0; +} + +INT aacenc_SscCallback(void *self, HANDLE_FDK_BITSTREAM hBs, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged) { + HANDLE_AACENCODER hAacEncoder = (HANDLE_AACENCODER)self; + + return (FDK_MpegsEnc_WriteSpatialSpecificConfig(hAacEncoder->hMpsEnc, hBs)); +} + +static AACENC_ERROR aacEncInit(HANDLE_AACENCODER hAacEncoder, ULONG InitFlags, + USER_PARAM *config) { + AACENC_ERROR err = AACENC_OK; + + INT aacBufferOffset = 0; + HANDLE_SBR_ENCODER *hSbrEncoder = &hAacEncoder->hEnvEnc; + HANDLE_AACENC_CONFIG hAacConfig = &hAacEncoder->aacConfig; + + hAacEncoder->nZerosAppended = 0; /* count appended zeros */ + + INT frameLength = hAacConfig->framelength; + + if ((InitFlags & AACENC_INIT_CONFIG)) { + CHANNEL_MODE prevChMode = hAacConfig->channelMode; + + /* Verify settings and update: config -> heAacEncoder */ + if ((err = FDKaacEnc_AdjustEncSettings(hAacEncoder, config)) != AACENC_OK) { + return err; + } + frameLength = hAacConfig->framelength; /* adapt temporal framelength */ + + /* Seamless channel reconfiguration in sbr not fully implemented */ + if ((prevChMode != hAacConfig->channelMode) && isSbrActive(hAacConfig)) { + InitFlags |= AACENC_INIT_STATES; + } + } + + /* Clear input buffer */ + if (InitFlags == AACENC_INIT_ALL) { + FDKmemclear(hAacEncoder->inputBuffer, + sizeof(INT_PCM) * hAacEncoder->inputBufferSize); + } + + if ((InitFlags & AACENC_INIT_CONFIG)) { + aacBufferOffset = 0; + switch (hAacConfig->audioObjectType) { + case AOT_ER_AAC_LD: + hAacEncoder->nDelay = DELAY_AACLD(hAacConfig->framelength); + break; + case AOT_ER_AAC_ELD: + hAacEncoder->nDelay = DELAY_AACELD(hAacConfig->framelength); + break; + default: + hAacEncoder->nDelay = + DELAY_AAC(hAacConfig->framelength); /* AAC encoder delay */ + } + + hAacConfig->ancDataBitRate = 0; + } + + if ((NULL != hAacEncoder->hEnvEnc) && isSbrActive(hAacConfig) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES))) { + INT sbrError; + UINT initFlag = 0; + SBR_ELEMENT_INFO sbrElInfo[(8)]; + CHANNEL_MAPPING channelMapping; + CHANNEL_MODE channelMode = isPsActive(hAacConfig->audioObjectType) + ? config->userChannelMode + : hAacConfig->channelMode; + INT numChannels = isPsActive(hAacConfig->audioObjectType) + ? config->nChannels + : hAacConfig->nChannels; + + if (FDKaacEnc_InitChannelMapping(channelMode, hAacConfig->channelOrder, + &channelMapping) != AAC_ENC_OK) { + return AACENC_INIT_ERROR; + } + + /* Check return value and if the SBR encoder can handle enough elements */ + if (channelMapping.nElements > (8)) { + return AACENC_INIT_ERROR; + } + + aacEncDistributeSbrBits(&channelMapping, sbrElInfo, hAacConfig->bitRate); + + initFlag += (InitFlags & AACENC_INIT_STATES) ? 1 : 0; + + /* Let the SBR encoder take a look at the configuration and change if + * required. */ + sbrError = sbrEncoder_Init( + *hSbrEncoder, sbrElInfo, channelMapping.nElements, + hAacEncoder->inputBuffer, hAacEncoder->inputBufferSizePerChannel, + &hAacConfig->bandWidth, &aacBufferOffset, &numChannels, + hAacConfig->syntaxFlags, &hAacConfig->sampleRate, &hAacConfig->sbrRatio, + &frameLength, hAacConfig->audioObjectType, &hAacEncoder->nDelay, + (hAacConfig->audioObjectType == AOT_ER_AAC_ELD) ? 1 : TRANS_FAC, + (config->userTpHeaderPeriod != 0xFF) + ? config->userTpHeaderPeriod + : DEFAULT_HEADER_PERIOD_REPETITION_RATE, + initFlag); + + /* Suppress AOT reconfiguration and check error status. */ + if ((sbrError) || (numChannels != hAacConfig->nChannels)) { + return AACENC_INIT_SBR_ERROR; + } + + if (numChannels == 1) { + hAacConfig->channelMode = MODE_1; + } + + /* Never use PNS if SBR is active */ + if (hAacConfig->usePns) { + hAacConfig->usePns = 0; + } + + /* estimated bitrate consumed by SBR or PS */ + hAacConfig->ancDataBitRate = sbrEncoder_GetEstimateBitrate(*hSbrEncoder); + + } /* sbr initialization */ + + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + int coreCoderDelay = DELAY_AACELD(hAacConfig->framelength); + + if (isSbrActive(hAacConfig)) { + coreCoderDelay = hAacConfig->sbrRatio * coreCoderDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } + + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Init(hAacEncoder->hMpsEnc, hAacConfig->audioObjectType, + config->userSamplerate, hAacConfig->bitRate, + isSbrActive(hAacConfig) ? hAacConfig->sbrRatio : 0, + frameLength, /* for dual rate sbr this value is + already multiplied by 2 */ + hAacEncoder->inputBufferSizePerChannel, + coreCoderDelay)) { + return AACENC_INIT_MPS_ERROR; + } + } + hAacEncoder->nDelay = + fMax(FDK_MpegsEnc_GetDelay(hAacEncoder->hMpsEnc), hAacEncoder->nDelay); + + /* + * Initialize Transport - Module. + */ + if ((InitFlags & AACENC_INIT_TRANSPORT)) { + UINT flags = 0; + + FDKaacEnc_MapConfig( + &hAacEncoder->coderConfig, config, + getSbrSignalingMode(hAacConfig->audioObjectType, config->userTpType, + config->userTpSignaling, hAacConfig->sbrRatio), + hAacConfig); + + /* create flags for transport encoder */ + if (config->userTpAmxv != 0) { + flags |= TP_FLAG_LATM_AMV; + } + /* Clear output buffer */ + FDKmemclear(hAacEncoder->outBuffer, + hAacEncoder->outBufferInBytes * sizeof(UCHAR)); + + /* Initialize Bitstream encoder */ + if (transportEnc_Init(hAacEncoder->hTpEnc, hAacEncoder->outBuffer, + hAacEncoder->outBufferInBytes, config->userTpType, + &hAacEncoder->coderConfig, flags) != 0) { + return AACENC_INIT_TP_ERROR; + } + + } /* transport initialization */ + + /* + * Initialize AAC - Core. + */ + if ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES)) { + if (FDKaacEnc_Initialize( + hAacEncoder->hAacEnc, hAacConfig, hAacEncoder->hTpEnc, + (InitFlags & AACENC_INIT_STATES) ? 1 : 0) != AAC_ENC_OK) { + return AACENC_INIT_AAC_ERROR; + } + + } /* aac initialization */ + + /* + * Initialize Meta Data - Encoder. + */ + if (hAacEncoder->hMetadataEnc && (hAacEncoder->metaDataAllowed != 0) && + ((InitFlags & AACENC_INIT_CONFIG) || (InitFlags & AACENC_INIT_STATES))) { + INT inputDataDelay = DELAY_AAC(hAacConfig->framelength); + + if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + inputDataDelay = hAacConfig->sbrRatio * inputDataDelay + + sbrEncoder_GetInputDataDelay(*hSbrEncoder); + } + + if (FDK_MetadataEnc_Init(hAacEncoder->hMetadataEnc, + ((InitFlags & AACENC_INIT_STATES) ? 1 : 0), + config->userMetaDataMode, inputDataDelay, + frameLength, config->userSamplerate, + config->nChannels, config->userChannelMode, + hAacConfig->channelOrder) != 0) { + return AACENC_INIT_META_ERROR; + } + + hAacEncoder->nDelay += FDK_MetadataEnc_GetDelay(hAacEncoder->hMetadataEnc); + } + + /* Get custom delay, i.e. the codec delay w/o the decoder's SBR- or MPS delay + */ + if ((hAacEncoder->hMpsEnc != NULL) && (hAacConfig->syntaxFlags & AC_LD_MPS)) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, FDK_MpegsEnc_GetDecDelay(hAacEncoder->hMpsEnc)); + } else if (isSbrActive(hAacConfig) && hSbrEncoder != NULL) { + hAacEncoder->nDelayCore = + hAacEncoder->nDelay - + fMax(0, sbrEncoder_GetSbrDecDelay(hAacEncoder->hEnvEnc)); + } else { + hAacEncoder->nDelayCore = hAacEncoder->nDelay; + } + + /* + * Update pointer to working buffer. + */ + if ((InitFlags & AACENC_INIT_CONFIG)) { + hAacEncoder->inputBufferOffset = aacBufferOffset; + + hAacEncoder->nSamplesToRead = frameLength * config->nChannels; + + } /* parameter changed */ + + return AACENC_OK; +} + +AACENC_ERROR aacEncOpen(HANDLE_AACENCODER *phAacEncoder, const UINT encModules, + const UINT maxChannels) { + AACENC_ERROR err = AACENC_OK; + HANDLE_AACENCODER hAacEncoder = NULL; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + hAacEncoder = Get_AacEncoder(); + + if (hAacEncoder == NULL) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + FDKmemclear(hAacEncoder, sizeof(AACENCODER)); + + /* Specify encoder modules to be allocated. */ + if (encModules == 0) { + C_ALLOC_SCRATCH_START(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; + FDKinitLibInfo(*pLibInfo); + aacEncGetLibInfo(*pLibInfo); + + hAacEncoder->encoder_modis = ENC_MODE_FLAG_AAC; + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_HQ) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SBR; + } + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_SBRENC) & CAPF_SBR_PS_MPEG) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_PS; + } + if (FDKlibInfo_getCapabilities(*pLibInfo, FDK_AACENC) & CAPF_AAC_DRC) { + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_META; + } + hAacEncoder->encoder_modis |= ENC_MODE_FLAG_SAC; + + C_ALLOC_SCRATCH_END(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + } else { + hAacEncoder->encoder_modis = encModules; + } + + /* Determine max channel configuration. */ + if (maxChannels == 0) { + hAacEncoder->nMaxAacChannels = (8); + hAacEncoder->nMaxSbrChannels = (8); + } else { + hAacEncoder->nMaxAacChannels = (maxChannels & 0x00FF); + if ((hAacEncoder->encoder_modis & ENC_MODE_FLAG_SBR)) { + hAacEncoder->nMaxSbrChannels = (maxChannels & 0xFF00) + ? (maxChannels >> 8) + : hAacEncoder->nMaxAacChannels; + } + + if ((hAacEncoder->nMaxAacChannels > (8)) || + (hAacEncoder->nMaxSbrChannels > (8))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + } /* maxChannels==0 */ + + /* Max number of elements could be tuned any more. */ + hAacEncoder->nMaxAacElements = fixMin(((8)), hAacEncoder->nMaxAacChannels); + hAacEncoder->nMaxSbrElements = fixMin((8), hAacEncoder->nMaxSbrChannels); + + /* In case of memory overlay, allocate memory out of libraries */ + + if (hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR | ENC_MODE_FLAG_PS)) + hAacEncoder->inputBufferSizePerChannel = INPUTBUFFER_SIZE; + else + hAacEncoder->inputBufferSizePerChannel = (1024); + + hAacEncoder->inputBufferSize = + hAacEncoder->nMaxAacChannels * hAacEncoder->inputBufferSizePerChannel; + + if (NULL == (hAacEncoder->inputBuffer = (INT_PCM *)FDKcalloc( + hAacEncoder->inputBufferSize, sizeof(INT_PCM)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Open SBR Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_SBR) { + if (sbrEncoder_Open( + &hAacEncoder->hEnvEnc, hAacEncoder->nMaxSbrElements, + hAacEncoder->nMaxSbrChannels, + (hAacEncoder->encoder_modis & ENC_MODE_FLAG_PS) ? 1 : 0)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + if (NULL == (hAacEncoder->pSbrPayload = (SBRENC_EXT_PAYLOAD *)FDKcalloc( + 1, sizeof(SBRENC_EXT_PAYLOAD)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_SBR) */ + + /* Open Aac Encoder */ + if (FDKaacEnc_Open(&hAacEncoder->hAacEnc, hAacEncoder->nMaxAacElements, + hAacEncoder->nMaxAacChannels, (1)) != AAC_ENC_OK) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Bitstream output buffer */ + hAacEncoder->outBufferInBytes = + 1 << (DFRACT_BITS - CntLeadingZeros(fixMax( + 1, ((1) * hAacEncoder->nMaxAacChannels * 6144) >> + 2))); /* buffer has to be 2^n */ + if (NULL == (hAacEncoder->outBuffer = (UCHAR *)FDKcalloc( + hAacEncoder->outBufferInBytes, sizeof(UCHAR)))) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + + /* Open Meta Data Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_META) { + if (FDK_MetadataEnc_Open(&hAacEncoder->hMetadataEnc, + (UINT)hAacEncoder->nMaxAacChannels)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (encoder_modis&ENC_MODE_FLAG_META) */ + + /* Open MPEG Surround Encoder */ + if (hAacEncoder->encoder_modis & ENC_MODE_FLAG_SAC) { + if (MPS_ENCODER_OK != FDK_MpegsEnc_Open(&hAacEncoder->hMpsEnc)) { + err = AACENC_MEMORY_ERROR; + goto bail; + } + } /* (hAacEncoder->encoder_modis&ENC_MODE_FLAG_SAC) */ + + /* Open Transport Encoder */ + if (transportEnc_Open(&hAacEncoder->hTpEnc) != 0) { + err = AACENC_MEMORY_ERROR; + goto bail; + } else { + C_ALLOC_SCRATCH_START(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + + LIB_INFO(*pLibInfo) + [FDK_MODULE_LAST] = (LIB_INFO(*)[FDK_MODULE_LAST])_pLibInfo; + + FDKinitLibInfo(*pLibInfo); + transportEnc_GetLibInfo(*pLibInfo); + + /* Get capabilty flag for transport encoder. */ + hAacEncoder->CAPF_tpEnc = FDKlibInfo_getCapabilities(*pLibInfo, FDK_TPENC); + + C_ALLOC_SCRATCH_END(_pLibInfo, LIB_INFO, FDK_MODULE_LAST) + } + if (transportEnc_RegisterSbrCallback(hAacEncoder->hTpEnc, aacenc_SbrCallback, + hAacEncoder) != 0) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } + if (transportEnc_RegisterSscCallback(hAacEncoder->hTpEnc, aacenc_SscCallback, + hAacEncoder) != 0) { + err = AACENC_INIT_TP_ERROR; + goto bail; + } + + /* Initialize encoder instance with default parameters. */ + aacEncDefaultConfig(&hAacEncoder->aacConfig, &hAacEncoder->extParam); + + /* Initialize headerPeriod in coderConfig for aacEncoder_GetParam(). */ + hAacEncoder->coderConfig.headerPeriod = + hAacEncoder->extParam.userTpHeaderPeriod; + + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + + /* Return encoder instance */ + *phAacEncoder = hAacEncoder; + + return err; + +bail: + aacEncClose(&hAacEncoder); + + return err; +} + +AACENC_ERROR aacEncClose(HANDLE_AACENCODER *phAacEncoder) { + AACENC_ERROR err = AACENC_OK; + + if (phAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + if (*phAacEncoder != NULL) { + HANDLE_AACENCODER hAacEncoder = *phAacEncoder; + + if (hAacEncoder->inputBuffer != NULL) { + FDKfree(hAacEncoder->inputBuffer); + hAacEncoder->inputBuffer = NULL; + } + if (hAacEncoder->outBuffer != NULL) { + FDKfree(hAacEncoder->outBuffer); + hAacEncoder->outBuffer = NULL; + } + + if (hAacEncoder->hEnvEnc) { + sbrEncoder_Close(&hAacEncoder->hEnvEnc); + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKfree(hAacEncoder->pSbrPayload); + hAacEncoder->pSbrPayload = NULL; + } + if (hAacEncoder->hAacEnc) { + FDKaacEnc_Close(&hAacEncoder->hAacEnc); + } + + transportEnc_Close(&hAacEncoder->hTpEnc); + + if (hAacEncoder->hMetadataEnc) { + FDK_MetadataEnc_Close(&hAacEncoder->hMetadataEnc); + } + if (hAacEncoder->hMpsEnc) { + FDK_MpegsEnc_Close(&hAacEncoder->hMpsEnc); + } + + Free_AacEncoder(phAacEncoder); + } + +bail: + return err; +} + +AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, + const AACENC_BufDesc *inBufDesc, + const AACENC_BufDesc *outBufDesc, + const AACENC_InArgs *inargs, + AACENC_OutArgs *outargs) { + AACENC_ERROR err = AACENC_OK; + INT i, nBsBytes = 0; + INT outBytes[(1)]; + int nExtensions = 0; + int ancDataExtIdx = -1; + + /* deal with valid encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* + * Adjust user settings and trigger reinitialization. + */ + if (hAacEncoder->InitFlags != 0) { + err = + aacEncInit(hAacEncoder, hAacEncoder->InitFlags, &hAacEncoder->extParam); + + if (err != AACENC_OK) { + /* keep init flags alive! */ + goto bail; + } + hAacEncoder->InitFlags = AACENC_INIT_NONE; + } + + if (outargs != NULL) { + FDKmemclear(outargs, sizeof(AACENC_OutArgs)); + } + + if (outBufDesc != NULL) { + for (i = 0; i < outBufDesc->numBufs; i++) { + if (outBufDesc->bufs[i] != NULL) { + FDKmemclear(outBufDesc->bufs[i], outBufDesc->bufSizes[i]); + } + } + } + + /* + * If only encoder handle given, independent (re)initialization can be + * triggered. + */ + if ((inBufDesc == NULL) && (outBufDesc == NULL) && (inargs == NULL) && + (outargs == NULL)) { + goto bail; + } + + /* check if buffer descriptors are filled out properly. */ + if ((inargs == NULL) || (outargs == NULL) || + ((AACENC_OK != validateBufDesc(inBufDesc)) && + (inargs->numInSamples > 0)) || + (AACENC_OK != validateBufDesc(outBufDesc))) { + err = AACENC_UNSUPPORTED_PARAMETER; + goto bail; + } + + /* reset buffer wich signals number of valid bytes in output bitstream buffer + */ + FDKmemclear(outBytes, hAacEncoder->aacConfig.nSubFrames * sizeof(INT)); + + /* + * Manage incoming audio samples. + */ + if ((inBufDesc != NULL) && (inargs->numInSamples > 0) && + (getBufDescIdx(inBufDesc, IN_AUDIO_DATA) != -1)) { + /* Fetch data until nSamplesToRead reached */ + INT idx = getBufDescIdx(inBufDesc, IN_AUDIO_DATA); + INT newSamples = + fixMax(0, fixMin(inargs->numInSamples, hAacEncoder->nSamplesToRead - + hAacEncoder->nSamplesRead)); + INT_PCM *pIn = + hAacEncoder->inputBuffer + + (hAacEncoder->inputBufferOffset + hAacEncoder->nSamplesRead) / + hAacEncoder->aacConfig.nChannels; + + /* Copy new input samples to internal buffer */ + if (inBufDesc->bufElSizes[idx] == (INT)sizeof(INT_PCM)) { + FDK_deinterleave((INT_PCM *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else if (inBufDesc->bufElSizes[idx] > (INT)sizeof(INT_PCM)) { + FDK_deinterleave((LONG *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } else { + FDK_deinterleave((SHORT *)inBufDesc->bufs[idx], pIn, + hAacEncoder->extParam.nChannels, + newSamples / hAacEncoder->extParam.nChannels, + hAacEncoder->inputBufferSizePerChannel); + } + hAacEncoder->nSamplesRead += newSamples; + + /* Number of fetched input buffer samples. */ + outargs->numInSamples = newSamples; + } + + /* input buffer completely filled ? */ + if (hAacEncoder->nSamplesRead < hAacEncoder->nSamplesToRead) { + /* - eof reached and flushing enabled, or + - return to main and wait for further incoming audio samples */ + if (inargs->numInSamples == -1) { + if ((hAacEncoder->nZerosAppended < hAacEncoder->nDelay)) { + int nZeros = (hAacEncoder->nSamplesToRead - hAacEncoder->nSamplesRead) / + hAacEncoder->extParam.nChannels; + + FDK_ASSERT(nZeros >= 0); + + /* clear out until end-of-buffer */ + if (nZeros) { + for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) { + FDKmemclear(hAacEncoder->inputBuffer + + i * hAacEncoder->inputBufferSizePerChannel + + (hAacEncoder->inputBufferOffset + + hAacEncoder->nSamplesRead) / + hAacEncoder->extParam.nChannels, + sizeof(INT_PCM) * nZeros); + } + hAacEncoder->nZerosAppended += nZeros; + hAacEncoder->nSamplesRead = hAacEncoder->nSamplesToRead; + } + } else { /* flushing completed */ + err = AACENC_ENCODE_EOF; /* eof reached */ + goto bail; + } + } else { /* inargs->numInSamples!= -1 */ + goto bail; /* not enough samples in input buffer and no flushing enabled + */ + } + } + + /* init payload */ + FDKmemclear(hAacEncoder->extPayload, + sizeof(AACENC_EXT_PAYLOAD) * MAX_TOTAL_EXT_PAYLOADS); + for (i = 0; i < MAX_TOTAL_EXT_PAYLOADS; i++) { + hAacEncoder->extPayload[i].associatedChElement = -1; + } + if (hAacEncoder->pSbrPayload != NULL) { + FDKmemclear(hAacEncoder->pSbrPayload, sizeof(*hAacEncoder->pSbrPayload)); + } + + /* + * Calculate Meta Data info. + */ + if ((hAacEncoder->hMetadataEnc != NULL) && + (hAacEncoder->metaDataAllowed != 0)) { + const AACENC_MetaData *pMetaData = NULL; + AACENC_EXT_PAYLOAD *pMetaDataExtPayload = NULL; + UINT nMetaDataExtensions = 0; + INT matrix_mixdown_idx = 0; + + /* New meta data info available ? */ + if (getBufDescIdx(inBufDesc, IN_METADATA_SETUP) != -1) { + pMetaData = + (AACENC_MetaData *) + inBufDesc->bufs[getBufDescIdx(inBufDesc, IN_METADATA_SETUP)]; + } + + FDK_MetadataEnc_Process( + hAacEncoder->hMetadataEnc, + hAacEncoder->inputBuffer + hAacEncoder->inputBufferOffset / + hAacEncoder->coderConfig.noChannels, + hAacEncoder->inputBufferSizePerChannel, hAacEncoder->nSamplesRead, + pMetaData, &pMetaDataExtPayload, &nMetaDataExtensions, + &matrix_mixdown_idx); + + for (i = 0; i < (INT)nMetaDataExtensions; + i++) { /* Get meta data extension payload. */ + hAacEncoder->extPayload[nExtensions++] = pMetaDataExtPayload[i]; + } + + if ((matrix_mixdown_idx != -1) && + ((hAacEncoder->extParam.userChannelMode == MODE_1_2_2) || + (hAacEncoder->extParam.userChannelMode == MODE_1_2_2_1))) { + /* Set matrix mixdown coefficient. */ + UINT pceValue = (UINT)((0 << 3) | ((matrix_mixdown_idx & 0x3) << 1) | 1); + if (hAacEncoder->extParam.userPceAdditions != pceValue) { + hAacEncoder->extParam.userPceAdditions = pceValue; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + } + } + + /* + * Encode MPS data. + */ + if ((hAacEncoder->hMpsEnc != NULL) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + AACENC_EXT_PAYLOAD mpsExtensionPayload; + FDKmemclear(&mpsExtensionPayload, sizeof(AACENC_EXT_PAYLOAD)); + + if (MPS_ENCODER_OK != + FDK_MpegsEnc_Process( + hAacEncoder->hMpsEnc, + hAacEncoder->inputBuffer + hAacEncoder->inputBufferOffset / + hAacEncoder->coderConfig.noChannels, + hAacEncoder->nSamplesRead, &mpsExtensionPayload)) { + err = AACENC_ENCODE_ERROR; + goto bail; + } + + if ((mpsExtensionPayload.pData != NULL) && + ((mpsExtensionPayload.dataSize != 0))) { + hAacEncoder->extPayload[nExtensions++] = mpsExtensionPayload; + } + } + + if ((NULL != hAacEncoder->hEnvEnc) && (NULL != hAacEncoder->pSbrPayload) && + isSbrActive(&hAacEncoder->aacConfig)) { + INT nPayload = 0; + + /* + * Encode SBR data. + */ + if (sbrEncoder_EncodeFrame(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, + hAacEncoder->pSbrPayload->dataSize[nPayload], + hAacEncoder->pSbrPayload->data[nPayload])) { + err = AACENC_ENCODE_ERROR; + goto bail; + } else { + /* Add SBR extension payload */ + for (i = 0; i < (8); i++) { + if (hAacEncoder->pSbrPayload->dataSize[nPayload][i] > 0) { + hAacEncoder->extPayload[nExtensions].pData = + hAacEncoder->pSbrPayload->data[nPayload][i]; + { + hAacEncoder->extPayload[nExtensions].dataSize = + hAacEncoder->pSbrPayload->dataSize[nPayload][i]; + hAacEncoder->extPayload[nExtensions].associatedChElement = i; + } + hAacEncoder->extPayload[nExtensions].dataType = + EXT_SBR_DATA; /* Once SBR Encoder supports SBR CRC set + EXT_SBR_DATA_CRC */ + nExtensions++; /* or EXT_SBR_DATA according to configuration. */ + FDK_ASSERT(nExtensions <= MAX_TOTAL_EXT_PAYLOADS); + } + } + nPayload++; + } + } /* sbrEnabled */ + + if ((inargs->numAncBytes > 0) && + (getBufDescIdx(inBufDesc, IN_ANCILLRY_DATA) != -1)) { + INT idx = getBufDescIdx(inBufDesc, IN_ANCILLRY_DATA); + hAacEncoder->extPayload[nExtensions].dataSize = inargs->numAncBytes * 8; + hAacEncoder->extPayload[nExtensions].pData = (UCHAR *)inBufDesc->bufs[idx]; + hAacEncoder->extPayload[nExtensions].dataType = EXT_DATA_ELEMENT; + hAacEncoder->extPayload[nExtensions].associatedChElement = -1; + ancDataExtIdx = nExtensions; /* store index */ + nExtensions++; + } + + /* + * Encode AAC - Core. + */ + if (FDKaacEnc_EncodeFrame(hAacEncoder->hAacEnc, hAacEncoder->hTpEnc, + hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel, outBytes, + hAacEncoder->extPayload) != AAC_ENC_OK) { + err = AACENC_ENCODE_ERROR; + goto bail; + } + + if (ancDataExtIdx >= 0) { + outargs->numAncBytes = + inargs->numAncBytes - + (hAacEncoder->extPayload[ancDataExtIdx].dataSize >> 3); + } + + /* samples exhausted */ + hAacEncoder->nSamplesRead -= hAacEncoder->nSamplesToRead; + + /* + * Delay balancing buffer handling + */ + if (isSbrActive(&hAacEncoder->aacConfig)) { + sbrEncoder_UpdateBuffers(hAacEncoder->hEnvEnc, hAacEncoder->inputBuffer, + hAacEncoder->inputBufferSizePerChannel); + } + + /* + * Make bitstream public + */ + if ((outBufDesc != NULL) && (outBufDesc->numBufs >= 1)) { + INT bsIdx = getBufDescIdx(outBufDesc, OUT_BITSTREAM_DATA); + INT auIdx = getBufDescIdx(outBufDesc, OUT_AU_SIZES); + + for (i = 0, nBsBytes = 0; i < hAacEncoder->aacConfig.nSubFrames; i++) { + nBsBytes += outBytes[i]; + + if (auIdx != -1) { + ((INT *)outBufDesc->bufs[auIdx])[i] = outBytes[i]; + } + } + + if ((bsIdx != -1) && (outBufDesc->bufSizes[bsIdx] >= nBsBytes)) { + FDKmemcpy(outBufDesc->bufs[bsIdx], hAacEncoder->outBuffer, + sizeof(UCHAR) * nBsBytes); + outargs->numOutBytes = nBsBytes; + outargs->bitResState = + FDKaacEnc_GetBitReservoirState(hAacEncoder->hAacEnc); + } else { + /* output buffer too small, can't write valid bitstream */ + err = AACENC_ENCODE_ERROR; + goto bail; + } + } + +bail: + if (err == AACENC_ENCODE_ERROR) { + /* All encoder modules have to be initialized */ + hAacEncoder->InitFlags = AACENC_INIT_ALL; + } + + return err; +} + +static AAC_ENCODER_ERROR aacEncGetConf(HANDLE_AACENCODER hAacEncoder, + UINT *size, UCHAR *confBuffer) { + FDK_BITSTREAM tmpConf; + UINT confType; + UCHAR buf[64]; + int err; + + /* Init bit buffer */ + FDKinitBitStream(&tmpConf, buf, 64, 0, BS_WRITER); + + /* write conf in tmp buffer */ + err = transportEnc_GetConf(hAacEncoder->hTpEnc, &hAacEncoder->coderConfig, + &tmpConf, &confType); + + /* copy data to outbuffer: length in bytes */ + FDKbyteAlign(&tmpConf, 0); + + /* Check buffer size */ + if (FDKgetValidBits(&tmpConf) > ((*size) << 3)) return AAC_ENC_UNKNOWN; + + FDKfetchBuffer(&tmpConf, confBuffer, size); + + if (err != 0) + return AAC_ENC_UNKNOWN; + else + return AAC_ENC_OK; +} + +AACENC_ERROR aacEncGetLibInfo(LIB_INFO *info) { + int i = 0; + + if (info == NULL) { + return AACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo(info); + transportEnc_GetLibInfo(info); + sbrEncoder_GetLibInfo(info); + FDK_MpegsEnc_GetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return AACENC_INIT_ERROR; + } + + info[i].module_id = FDK_AACENC; + info[i].build_date = AACENCODER_LIB_BUILD_DATE; + info[i].build_time = AACENCODER_LIB_BUILD_TIME; + info[i].title = AACENCODER_LIB_TITLE; + info[i].version = + LIB_VERSION(AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2); + ; + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0 | CAPF_AAC_1024 | CAPF_AAC_LC | CAPF_AAC_960| CAPF_AAC_512 | + CAPF_AAC_480 | CAPF_AAC_DRC | CAPF_AAC_ELD_DOWNSCALE; + /* End of flags */ + + return AACENC_OK; +} + +AACENC_ERROR aacEncoder_SetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param, const UINT value) { + AACENC_ERROR err = AACENC_OK; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + err = AACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) { + case AACENC_AOT: + if (settings->userAOT != (AUDIO_OBJECT_TYPE)value) { + /* check if AOT matches the allocated modules */ + switch (value) { + case AOT_PS: + case AOT_DABPLUS_PS: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_PS))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + FDK_FALLTHROUGH; + case AOT_SBR: + case AOT_MP2_SBR: + case AOT_DABPLUS_SBR: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_SBR))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + FDK_FALLTHROUGH; + case AOT_AAC_LC: + case AOT_MP2_AAC_LC: + case AOT_DABPLUS_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + if (!(hAacEncoder->encoder_modis & (ENC_MODE_FLAG_AAC))) { + err = AACENC_INVALID_CONFIG; + goto bail; + } + break; + default: + err = AACENC_INVALID_CONFIG; + goto bail; + } /* switch value */ + settings->userAOT = (AUDIO_OBJECT_TYPE)value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATE: + if (settings->userBitrate != value) { + settings->userBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_BITRATEMODE: + if (settings->userBitrateMode != value) { + switch (value) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 7: + case 8: + settings->userBitrateMode = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } /* switch value */ + } + break; + case AACENC_SAMPLERATE: + if (settings->userSamplerate != value) { + if (!((value == 8000) || (value == 11025) || (value == 12000) || + (value == 16000) || (value == 22050) || (value == 24000) || + (value == 32000) || (value == 44100) || (value == 48000) || + (value == 64000) || (value == 88200) || (value == 96000))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSamplerate = value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_CHANNELMODE: + if (settings->userChannelMode != (CHANNEL_MODE)value) { + if (((CHANNEL_MODE)value == MODE_212) && + (NULL != hAacEncoder->hMpsEnc)) { + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = 2; + } else { + const CHANNEL_MODE_CONFIG_TAB *pConfig = + FDKaacEnc_GetChannelModeConfiguration((CHANNEL_MODE)value); + if (pConfig == NULL) { + err = AACENC_INVALID_CONFIG; + break; + } + if ((pConfig->nElements > hAacEncoder->nMaxAacElements) || + (pConfig->nChannelsEff > hAacEncoder->nMaxAacChannels)) { + err = AACENC_INVALID_CONFIG; + break; + } + + settings->userChannelMode = (CHANNEL_MODE)value; + settings->nChannels = pConfig->nChannels; + } + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + if (!((value >= 1) && (value <= 6))) { + hAacEncoder->InitFlags |= AACENC_INIT_STATES; + } + } + break; + case AACENC_BANDWIDTH: + if (settings->userBandwidth != value) { + settings->userBandwidth = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_CHANNELORDER: + if (hAacEncoder->aacConfig.channelOrder != (CHANNEL_ORDER)value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + hAacEncoder->aacConfig.channelOrder = (CHANNEL_ORDER)value; + hAacEncoder->nSamplesRead = 0; /* reset internal inputbuffer */ + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AFTERBURNER: + if (settings->userAfterburner != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userAfterburner = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_GRANULE_LENGTH: + if (settings->userFramelength != value) { + switch (value) { + case 1024: + case 960: + case 512: + case 480: + case 256: + case 240: + case 128: + case 120: + if ((value << 1) == 480 || (value << 1) == 512) { + settings->userDownscaleFactor = 2; + } else if ((value << 2) == 480 || (value << 2) == 512) { + settings->userDownscaleFactor = 4; + } + settings->userFramelength = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + break; + default: + err = AACENC_INVALID_CONFIG; + break; + } + } + break; + case AACENC_SBR_RATIO: + if (settings->userSbrRatio != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userSbrRatio = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SBR_MODE: + if ((settings->userSbrEnabled != value) && + (NULL != hAacEncoder->hEnvEnc)) { + settings->userSbrEnabled = value; + hAacEncoder->InitFlags |= + AACENC_INIT_CONFIG | AACENC_INIT_STATES | AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TRANSMUX: + if (settings->userTpType != (TRANSPORT_TYPE)value) { + TRANSPORT_TYPE type = (TRANSPORT_TYPE)value; + UINT flags = hAacEncoder->CAPF_tpEnc; + + if (!(((type == TT_MP4_ADIF) && (flags & CAPF_ADIF)) || + ((type == TT_MP4_ADTS) && (flags & CAPF_ADTS)) || + ((type == TT_MP4_LATM_MCP0) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LATM_MCP1) && + ((flags & CAPF_LATM) && (flags & CAPF_RAWPACKETS))) || + ((type == TT_MP4_LOAS) && (flags & CAPF_LOAS)) || + ((type == TT_MP4_RAW) && (flags & CAPF_RAWPACKETS)) || + ((type == TT_DABPLUS) && ((flags & CAPF_DAB_AAC) && (flags & CAPF_RAWPACKETS))) )) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpType = (TRANSPORT_TYPE)value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_SIGNALING_MODE: + if (settings->userTpSignaling != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpSignaling = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_PROTECTION: + if (settings->userTpProtection != value) { + if (!((value == 0) || (value == 1))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpProtection = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_HEADER_PERIOD: + if (settings->userTpHeaderPeriod != value) { + if (!(((INT)value >= 0) && (value <= 255))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpHeaderPeriod = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_AUDIOMUXVER: + if (settings->userTpAmxv != value) { + if (!((value == 0) || (value == 1) || (value == 2))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpAmxv = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_TPSUBFRAMES: + if (settings->userTpNsubFrames != value) { + if (!((value >= 1) && (value <= 6))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userTpNsubFrames = value; + hAacEncoder->InitFlags |= AACENC_INIT_TRANSPORT; + } + break; + case AACENC_ANCILLARY_BITRATE: + if (settings->userAncDataRate != value) { + settings->userAncDataRate = value; + } + break; + case AACENC_CONTROL_STATE: + if (hAacEncoder->InitFlags != value) { + if (value & AACENC_RESET_INBUFFER) { + hAacEncoder->nSamplesRead = 0; + } + hAacEncoder->InitFlags = value; + } + break; + case AACENC_METADATA_MODE: + if ((UINT)settings->userMetaDataMode != value) { + if (!(((INT)value >= 0) && ((INT)value <= 3))) { + err = AACENC_INVALID_CONFIG; + break; + } + settings->userMetaDataMode = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG; + } + break; + case AACENC_PEAK_BITRATE: + if (settings->userPeakBitrate != value) { + settings->userPeakBitrate = value; + hAacEncoder->InitFlags |= AACENC_INIT_CONFIG | AACENC_INIT_TRANSPORT; + } + break; + default: + err = AACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ + +bail: + return err; +} + +UINT aacEncoder_GetParam(const HANDLE_AACENCODER hAacEncoder, + const AACENC_PARAM param) { + UINT value = 0; + USER_PARAM *settings = &hAacEncoder->extParam; + + /* check encoder handle */ + if (hAacEncoder == NULL) { + goto bail; + } + + /* apply param value */ + switch (param) { + case AACENC_AOT: + value = (UINT)hAacEncoder->aacConfig.audioObjectType; + break; + case AACENC_BITRATE: + switch (hAacEncoder->aacConfig.bitrateMode) { + case AACENC_BR_MODE_CBR: + value = (UINT)hAacEncoder->aacConfig.bitRate; + break; + default: + value = (UINT)-1; + } + break; + case AACENC_BITRATEMODE: + value = (UINT)((hAacEncoder->aacConfig.bitrateMode != AACENC_BR_MODE_FF) + ? hAacEncoder->aacConfig.bitrateMode + : AACENC_BR_MODE_CBR); + break; + case AACENC_SAMPLERATE: + value = (UINT)hAacEncoder->coderConfig.extSamplingRate; + break; + case AACENC_CHANNELMODE: + if ((MODE_1 == hAacEncoder->aacConfig.channelMode) && + (hAacEncoder->aacConfig.syntaxFlags & AC_LD_MPS)) { + value = MODE_212; + } else { + value = (UINT)hAacEncoder->aacConfig.channelMode; + } + break; + case AACENC_BANDWIDTH: + value = (UINT)hAacEncoder->aacConfig.bandWidth; + break; + case AACENC_CHANNELORDER: + value = (UINT)hAacEncoder->aacConfig.channelOrder; + break; + case AACENC_AFTERBURNER: + value = (UINT)hAacEncoder->aacConfig.useRequant; + break; + case AACENC_GRANULE_LENGTH: + value = (UINT)hAacEncoder->aacConfig.framelength; + break; + case AACENC_SBR_RATIO: + value = isSbrActive(&hAacEncoder->aacConfig) + ? hAacEncoder->aacConfig.sbrRatio + : 0; + break; + case AACENC_SBR_MODE: + value = + (UINT)(hAacEncoder->aacConfig.syntaxFlags & AC_SBR_PRESENT) ? 1 : 0; + break; + case AACENC_TRANSMUX: + value = (UINT)settings->userTpType; + break; + case AACENC_SIGNALING_MODE: + value = (UINT)getSbrSignalingMode( + hAacEncoder->aacConfig.audioObjectType, settings->userTpType, + settings->userTpSignaling, hAacEncoder->aacConfig.sbrRatio); + break; + case AACENC_PROTECTION: + value = (UINT)settings->userTpProtection; + break; + case AACENC_HEADER_PERIOD: + value = (UINT)hAacEncoder->coderConfig.headerPeriod; + break; + case AACENC_AUDIOMUXVER: + value = (UINT)hAacEncoder->aacConfig.audioMuxVersion; + break; + case AACENC_TPSUBFRAMES: + value = (UINT)settings->userTpNsubFrames; + break; + case AACENC_ANCILLARY_BITRATE: + value = (UINT)hAacEncoder->aacConfig.anc_Rate; + break; + case AACENC_CONTROL_STATE: + value = (UINT)hAacEncoder->InitFlags; + break; + case AACENC_METADATA_MODE: + value = (hAacEncoder->metaDataAllowed == 0) + ? 0 + : (UINT)settings->userMetaDataMode; + break; + case AACENC_PEAK_BITRATE: + value = (UINT)-1; /* peak bitrate parameter is meaningless */ + if (((INT)hAacEncoder->extParam.userPeakBitrate != -1)) { + value = + (UINT)(fMax((INT)hAacEncoder->extParam.userPeakBitrate, + hAacEncoder->aacConfig + .bitRate)); /* peak bitrate parameter is in use */ + } + break; + + default: + // err = MPS_INVALID_PARAMETER; + break; + } /* switch(param) */ + +bail: + return value; +} + +AACENC_ERROR aacEncInfo(const HANDLE_AACENCODER hAacEncoder, + AACENC_InfoStruct *pInfo) { + AACENC_ERROR err = AACENC_OK; + + FDKmemclear(pInfo, sizeof(AACENC_InfoStruct)); + pInfo->confSize = 64; /* pre-initialize */ + + pInfo->maxOutBufBytes = ((hAacEncoder->nMaxAacChannels * 6144) + 7) >> 3; + pInfo->maxAncBytes = hAacEncoder->aacConfig.maxAncBytesPerAU; + pInfo->inBufFillLevel = + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; + pInfo->inputChannels = hAacEncoder->extParam.nChannels; + pInfo->frameLength = + hAacEncoder->nSamplesToRead / hAacEncoder->extParam.nChannels; + pInfo->nDelay = hAacEncoder->nDelay; + pInfo->nDelayCore = hAacEncoder->nDelayCore; + + /* Get encoder configuration */ + if (aacEncGetConf(hAacEncoder, &pInfo->confSize, &pInfo->confBuf[0]) != + AAC_ENC_OK) { + err = AACENC_INIT_ERROR; + goto bail; + } +bail: + return err; +} diff --git a/fdk-aac/libAACenc/src/aacenc_pns.cpp b/fdk-aac/libAACenc/src/aacenc_pns.cpp new file mode 100644 index 0000000..f0571d6 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc_pns.cpp @@ -0,0 +1,541 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns.c + +*******************************************************************************/ + +#include "aacenc_pns.h" + +#include "psy_data.h" +#include "pnsparam.h" +#include "noisedet.h" +#include "bit_cnt.h" +#include "interface.h" + +/* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ +static const FIXP_DBL minCorrelationEnergy = + FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ +/* noiseCorrelationThresh = 0.6^2 */ +static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); + +static void FDKaacEnc_FDKaacEnc_noiseDetection( + PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, + const INT *sfbOffset, INT tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality); + +static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *pnsFlag, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg); + +/***************************************************************************** + + functionname: initPnsConfiguration + description: fill pnsConf with pns parameters + returns: error status + input: PNS Config struct (modified) + bitrate, samplerate, usePns, + number of sfb's, pointer to sfb offset + output: error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration( + PNS_CONFIG *pnsConf, INT bitRate, INT sampleRate, INT usePns, INT sfbCnt, + const INT *sfbOffset, const INT numChan, const INT isLC) { + AAC_ENCODER_ERROR ErrorStatus; + + /* init noise detection */ + ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np, bitRate, sampleRate, sfbCnt, + sfbOffset, &usePns, numChan, isLC); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + pnsConf->minCorrelationEnergy = minCorrelationEnergy; + pnsConf->noiseCorrelationThresh = noiseCorrelationThresh; + + pnsConf->usePns = usePns; + + return AAC_ENC_OK; +} + +/***************************************************************************** + + functionname: FDKaacEnc_PnsDetect + description: do decision, if PNS shall used or not + returns: + input: pns config structure + pns data structure (modified), + lastWindowSequence (long or short blocks) + sfbActive + pointer to Sfb Energy, Threshold, Offset + pointer to mdct Spectrum + length of each group + pointer to tonality calculated in chaosmeasure + tns order and prediction gain + calculated noiseNrg at active PNS + output: pnsFlag in pns data structure + +*****************************************************************************/ +void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, + const INT lastWindowSequence, const INT sfbActive, + const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, + INT tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg) + +{ + int sfb; + int startNoiseSfb; + + /* Reset pns info. */ + FDKmemclear(pnsData->pnsFlag, sizeof(pnsData->pnsFlag)); + for (sfb = 0; sfb < MAX_GROUPED_SFB; sfb++) { + noiseNrg[sfb] = NO_NOISE_PNS; + } + + /* Disable PNS and skip detection in certain cases. */ + if (pnsConf->usePns == 0) { + return; + } else { + /* AAC - LC core encoder */ + if ((pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && + (lastWindowSequence == SHORT_WINDOW)) { + return; + } + /* AAC - (E)LD core encoder */ + if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && + (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) && + (lastWindowSequence != LONG_WINDOW)) { + return; + } + } + + /* + call noise detection + */ + FDKaacEnc_FDKaacEnc_noiseDetection( + pnsConf, pnsData, sfbActive, sfbOffset, tnsOrder, tnsPredictionGain, + tnsActive, mdctSpectrum, sfbMaxScaleSpec, sfbtonality); + + /* set startNoiseSfb (long) */ + startNoiseSfb = pnsConf->np.startSfb; + + /* Set noise substitution status */ + for (sfb = 0; sfb < sfbActive; sfb++) { + /* No PNS below startNoiseSfb */ + if (sfb < startNoiseSfb) { + pnsData->pnsFlag[sfb] = 0; + continue; + } + + /* + do noise substitution if + fuzzy measure is high enough + sfb freq > minimum sfb freq + signal in coder band is not masked + */ + + if ((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && + ((sfbThresholdLdData[sfb] + + FL2FXCONST_DBL(0.5849625f / + 64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ + < sfbEnergyLdData[sfb])) { + /* + mark in psyout flag array that we will code + this band with PNS + */ + pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ + } else { + pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ + } + + /* no PNS if LTP is active */ + } + + /* avoid PNS holes */ + if ((pnsData->noiseFuzzyMeasure[0] > FL2FXCONST_SGL(0.5f)) && + (pnsData->pnsFlag[1])) { + pnsData->pnsFlag[0] = 1; + } + + for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { + if ((pnsData->noiseFuzzyMeasure[sfb] > pnsConf->np.gapFillThr) && + (pnsData->pnsFlag[sfb - 1]) && (pnsData->pnsFlag[sfb + 1])) { + pnsData->pnsFlag[sfb] = 1; + } + } + + if (maxSfbPerGroup > 0) { + /* avoid PNS hole */ + if ((pnsData->noiseFuzzyMeasure[maxSfbPerGroup - 1] > + pnsConf->np.gapFillThr) && + (pnsData->pnsFlag[maxSfbPerGroup - 2])) { + pnsData->pnsFlag[maxSfbPerGroup - 1] = 1; + } + /* avoid single PNS band */ + if (pnsData->pnsFlag[maxSfbPerGroup - 2] == 0) { + pnsData->pnsFlag[maxSfbPerGroup - 1] = 0; + } + } + + /* avoid single PNS bands */ + if (pnsData->pnsFlag[1] == 0) { + pnsData->pnsFlag[0] = 0; + } + + for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { + if ((pnsData->pnsFlag[sfb - 1] == 0) && (pnsData->pnsFlag[sfb + 1] == 0)) { + pnsData->pnsFlag[sfb] = 0; + } + } + + /* + calculate noiseNrg's + */ + FDKaacEnc_CalcNoiseNrgs(sfbActive, pnsData->pnsFlag, sfbEnergyLdData, + noiseNrg); +} + +/***************************************************************************** + + functionname:FDKaacEnc_FDKaacEnc_noiseDetection + description: wrapper for noisedet.c + returns: + input: pns config structure + pns data structure (modified), + sfbActive + tns order and prediction gain + pointer to mdct Spectrumand Sfb Energy + pointer to Sfb tonality + output: noiseFuzzyMeasure in structure pnsData + flags tonal / nontonal + +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_noiseDetection( + PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, + const INT *sfbOffset, int tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality) { + INT condition = TRUE; + if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY)) { + condition = (tnsOrder > 3); + } + /* + no PNS if heavy TNS activity + clear pnsData->noiseFuzzyMeasure + */ + if ((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) && + (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition && + !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && + (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && + (tnsActive))) { + /* clear all noiseFuzzyMeasure */ + FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive * sizeof(FIXP_SGL)); + } else { + /* + call noise detection, output in pnsData->noiseFuzzyMeasure, + use real mdct spectral data + */ + FDKaacEnc_noiseDetect(mdctSpectrum, sfbMaxScaleSpec, sfbActive, sfbOffset, + pnsData->noiseFuzzyMeasure, &pnsConf->np, + sfbtonality); + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_CalcNoiseNrgs + description: Calculate the NoiseNrg's + returns: + input: sfbActive + if pnsFlag calculate NoiseNrg + pointer to sfbEnergy and groupLen + pointer to noiseNrg (modified) + output: noiseNrg's in pnsFlaged sfb's + +*****************************************************************************/ + +static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg) { + int sfb; + INT tmp = (-LOG_NORM_PCM) << 2; + + for (sfb = 0; sfb < sfbActive; sfb++) { + if (pnsFlag[sfb]) { + INT nrg = (-sfbEnergyLdData[sfb] + FL2FXCONST_DBL(0.5f / 64.0f)) >> + (DFRACT_BITS - 1 - 7); + noiseNrg[sfb] = tmp - nrg; + } + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_CodePnsChannel + description: Execute pns decission + returns: + input: sfbActive + pns config structure + use PNS if pnsFlag + pointer to Sfb Energy, noiseNrg, Threshold + output: set sfbThreshold high to code pe with 0, + noiseNrg marks flag for pns coding + +*****************************************************************************/ + +void FDKaacEnc_CodePnsChannel(const INT sfbActive, PNS_CONFIG *pnsConf, + INT *RESTRICT pnsFlag, + FIXP_DBL *RESTRICT sfbEnergyLdData, + INT *RESTRICT noiseNrg, + FIXP_DBL *RESTRICT sfbThresholdLdData) { + INT sfb; + INT lastiNoiseEnergy = 0; + INT firstPNSband = 1; /* TRUE for first PNS-coded band */ + + /* no PNS */ + if (!pnsConf->usePns) { + for (sfb = 0; sfb < sfbActive; sfb++) { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + return; + } + + /* code PNS */ + for (sfb = 0; sfb < sfbActive; sfb++) { + if (pnsFlag[sfb]) { + /* high sfbThreshold causes pe = 0 */ + if (noiseNrg[sfb] != NO_NOISE_PNS) + sfbThresholdLdData[sfb] = + sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f / LD_DATA_SCALING); + + /* set noiseNrg in valid region */ + if (!firstPNSband) { + INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy; + + if (deltaiNoiseEnergy > CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV; + else if (deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV) + noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV; + } else { + firstPNSband = 0; + } + lastiNoiseEnergy = noiseNrg[sfb]; + } else { + /* no PNS coding */ + noiseNrg[sfb] = NO_NOISE_PNS; + } + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_PreProcessPnsChannelPair + description: Calculate the correlation of noise in a channel pair + + returns: + input: sfbActive + pointer to sfb energies left, right and mid channel + pns config structure + pns data structure left and right (modified) + + output: noiseEnergyCorrelation in pns data structure + +*****************************************************************************/ + +void FDKaacEnc_PreProcessPnsChannelPair( + const INT sfbActive, FIXP_DBL *RESTRICT sfbEnergyLeft, + FIXP_DBL *RESTRICT sfbEnergyRight, FIXP_DBL *RESTRICT sfbEnergyLeftLD, + FIXP_DBL *RESTRICT sfbEnergyRightLD, FIXP_DBL *RESTRICT sfbEnergyMid, + PNS_CONFIG *RESTRICT pnsConf, PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight) { + INT sfb; + FIXP_DBL ccf; + + if (!pnsConf->usePns) return; + + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = + pnsDataLeft->noiseEnergyCorrelation; + FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = + pnsDataRight->noiseEnergyCorrelation; + + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL quot = (sfbEnergyLeftLD[sfb] >> 1) + (sfbEnergyRightLD[sfb] >> 1); + + if (quot < FL2FXCONST_DBL(-32.0f / (float)LD_DATA_SCALING)) + ccf = FL2FXCONST_DBL(0.0f); + else { + FIXP_DBL accu = + sfbEnergyMid[sfb] - + (((sfbEnergyLeft[sfb] >> 1) + (sfbEnergyRight[sfb] >> 1)) >> 1); + INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0; + accu = fixp_abs(accu); + + ccf = CalcLdData(accu) + + FL2FXCONST_DBL((float)1.0f / (float)LD_DATA_SCALING) - + quot; /* ld(accu*2) = ld(accu) + 1 */ + ccf = (ccf >= FL2FXCONST_DBL(0.0)) + ? ((FIXP_DBL)MAXVAL_DBL) + : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf); + } + + pNoiseEnergyCorrelationL[sfb] = ccf; + pNoiseEnergyCorrelationR[sfb] = ccf; + } +} + +/***************************************************************************** + + functionname:FDKaacEnc_PostProcessPnsChannelPair + description: if PNS used at left and right channel, + use msMask to flag correlation + returns: + input: sfbActive + pns config structure + pns data structure left and right (modified) + pointer to msMask, flags correlation by pns coding (modified) + Digest of MS coding + output: pnsFlag in pns data structure, + msFlag in msMask (flags correlation) + +*****************************************************************************/ + +void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, + INT *RESTRICT msMask, INT *msDigest) { + INT sfb; + + if (!pnsConf->usePns) return; + + for (sfb = 0; sfb < sfbActive; sfb++) { + /* + MS post processing + */ + if (msMask[sfb]) { + if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { + /* AAC only: Standard */ + /* do this to avoid ms flags in layers that should not have it */ + if (pnsDataLeft->noiseEnergyCorrelation[sfb] <= + pnsConf->noiseCorrelationThresh) { + msMask[sfb] = 0; + *msDigest = MS_SOME; + } + } else { + /* + No PNS coding + */ + pnsDataLeft->pnsFlag[sfb] = 0; + pnsDataRight->pnsFlag[sfb] = 0; + } + } + + /* + Use MS flag to signal noise correlation if + pns is active in both channels + */ + if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { + if (pnsDataLeft->noiseEnergyCorrelation[sfb] > + pnsConf->noiseCorrelationThresh) { + msMask[sfb] = 1; + *msDigest = MS_SOME; + } + } + } +} diff --git a/fdk-aac/libAACenc/src/aacenc_pns.h b/fdk-aac/libAACenc/src/aacenc_pns.h new file mode 100644 index 0000000..4938fcf --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc_pns.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns.h + +*******************************************************************************/ + +#ifndef AACENC_PNS_H +#define AACENC_PNS_H + +#include "common_fix.h" +#include "pnsparam.h" + +#define NO_NOISE_PNS FDK_INT_MIN + +typedef struct { + NOISEPARAMS np; + FIXP_DBL minCorrelationEnergy; + FIXP_DBL noiseCorrelationThresh; + INT usePns; +} PNS_CONFIG; + +typedef struct { + FIXP_SGL noiseFuzzyMeasure[MAX_GROUPED_SFB]; + FIXP_DBL noiseEnergyCorrelation[MAX_GROUPED_SFB]; + INT pnsFlag[MAX_GROUPED_SFB]; +} PNS_DATA; + +#endif /* AACENC_PNS_H */ diff --git a/fdk-aac/libAACenc/src/aacenc_tns.cpp b/fdk-aac/libAACenc/src/aacenc_tns.cpp new file mode 100644 index 0000000..3436150 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc_tns.cpp @@ -0,0 +1,1210 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Groeschel, Tobias Chalupka + + Description: Temporal noise shaping + +*******************************************************************************/ + +#include "aacenc_tns.h" +#include "psy_const.h" +#include "psy_configuration.h" +#include "tns_func.h" +#include "aacEnc_rom.h" +#include "aacenc_tns.h" +#include "FDK_lpc.h" + +#define FILTER_DIRECTION 0 /* 0 = up, 1 = down */ + +static const FIXP_DBL acfWindowLong[12 + 3 + 1] = { + 0x7fffffff, 0x7fb80000, 0x7ee00000, 0x7d780000, 0x7b800000, 0x78f80000, + 0x75e00000, 0x72380000, 0x6e000000, 0x69380000, 0x63e00000, 0x5df80000, + 0x57800000, 0x50780000, 0x48e00000, 0x40b80000}; + +static const FIXP_DBL acfWindowShort[4 + 3 + 1] = { + 0x7fffffff, 0x7e000000, 0x78000000, 0x6e000000, + 0x60000000, 0x4e000000, 0x38000000, 0x1e000000}; + +typedef struct { + INT bitRateFrom[2]; /* noneSbr=0, useSbr=1 */ + INT bitRateTo[2]; /* noneSbr=0, useSbr=1 */ + TNS_PARAMETER_TABULATED paramTab[2]; /* mono=0, stereo=1 */ + +} TNS_INFO_TAB; + +#define TNS_TIMERES_SCALE (1) +#define FL2_TIMERES_FIX(a) (FL2FXCONST_DBL(a / (float)(1 << TNS_TIMERES_SCALE))) + +static const TNS_INFO_TAB tnsInfoTab[] = { + {{16000, 13500}, + {32000, 28000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 12}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 12}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.2f)}, + 1}}}, + {{32001, 28001}, + {60000, 52000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 10}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 10}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}}}, + {{60001, 52001}, + {384000, 384000}, + {{{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 8}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}, + {{1, 1}, + {1437, 1500}, + {1400, 600}, + {12, 8}, + {FILTER_DIRECTION, FILTER_DIRECTION}, + {3, 1}, + {FL2_TIMERES_FIX(0.4f), FL2_TIMERES_FIX(1.0f)}, + 1}}}}; + +typedef struct { + INT samplingRate; + SCHAR maxBands[2]; /* long=0; short=1 */ + +} TNS_MAX_TAB_ENTRY; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab1024[] = { + {96000, {31, 9}}, {88200, {31, 9}}, {64000, {34, 10}}, {48000, {40, 14}}, + {44100, {42, 14}}, {32000, {51, 14}}, {24000, {46, 14}}, {22050, {46, 14}}, + {16000, {42, 14}}, {12000, {42, 14}}, {11025, {42, 14}}, {8000, {39, 14}}}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab960[] = +{ + { 96000, { 31, 9}}, + { 88200, { 31, 9}}, + { 64000, { 34, 10}}, + { 48000, { 49, 14}}, + { 44100, { 49, 14}}, + { 32000, { 49, 14}}, + { 24000, { 46, 15}}, + { 22050, { 46, 14}}, + { 16000, { 46, 15}}, + { 12000, { 42, 15}}, + { 11025, { 42, 15}}, + { 8000, { 40, 15}} +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab120[] = { + {48000, {12, -1}}, /* 48000 */ + {44100, {12, -1}}, /* 44100 */ + {32000, {15, -1}}, /* 32000 */ + {24000, {15, -1}}, /* 24000 */ + {22050, {15, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab128[] = { + {48000, {12, -1}}, /* 48000 */ + {44100, {12, -1}}, /* 44100 */ + {32000, {15, -1}}, /* 32000 */ + {24000, {15, -1}}, /* 24000 */ + {22050, {15, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab240[] = { + {96000, {22, -1}}, /* 96000 */ + {48000, {22, -1}}, /* 48000 */ + {44100, {22, -1}}, /* 44100 */ + {32000, {21, -1}}, /* 32000 */ + {24000, {21, -1}}, /* 24000 */ + {22050, {21, -1}} /* 22050 */ +}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab256[] = { + {96000, {25, -1}}, /* 96000 */ + {48000, {25, -1}}, /* 48000 */ + {44100, {25, -1}}, /* 44100 */ + {32000, {24, -1}}, /* 32000 */ + {24000, {24, -1}}, /* 24000 */ + {22050, {24, -1}} /* 22050 */ +}; +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab480[] = {{48000, {31, -1}}, + {44100, {32, -1}}, + {32000, {37, -1}}, + {24000, {30, -1}}, + {22050, {30, -1}}}; + +static const TNS_MAX_TAB_ENTRY tnsMaxBandsTab512[] = {{48000, {31, -1}}, + {44100, {32, -1}}, + {32000, {37, -1}}, + {24000, {31, -1}}, + {22050, {31, -1}}}; + +static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index, + const INT order, const INT bitsPerCoeff); + +static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor, + const INT order, const INT bitsPerCoeff); + +static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize, + const INT samplingRate, + const INT transformResolution, + const FIXP_DBL timeResolution, + const INT timeResolution_e); + +static const TNS_PARAMETER_TABULATED *FDKaacEnc_GetTnsParam(const INT bitRate, + const INT channels, + const INT sbrLd) { + int i; + const TNS_PARAMETER_TABULATED *tnsConfigTab = NULL; + + for (i = 0; i < (int)(sizeof(tnsInfoTab) / sizeof(TNS_INFO_TAB)); i++) { + if ((bitRate >= tnsInfoTab[i].bitRateFrom[sbrLd ? 1 : 0]) && + bitRate <= tnsInfoTab[i].bitRateTo[sbrLd ? 1 : 0]) { + tnsConfigTab = &tnsInfoTab[i].paramTab[(channels == 1) ? 0 : 1]; + } + } + + return tnsConfigTab; +} + +static INT getTnsMaxBands(const INT sampleRate, const INT granuleLength, + const INT isShortBlock) { + int i; + INT numBands = -1; + const TNS_MAX_TAB_ENTRY *pMaxBandsTab = NULL; + int maxBandsTabSize = 0; + + switch (granuleLength) { + case 960: + pMaxBandsTab = tnsMaxBandsTab960; + maxBandsTabSize = sizeof(tnsMaxBandsTab960) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 1024: + pMaxBandsTab = tnsMaxBandsTab1024; + maxBandsTabSize = sizeof(tnsMaxBandsTab1024) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 120: + pMaxBandsTab = tnsMaxBandsTab120; + maxBandsTabSize = sizeof(tnsMaxBandsTab120) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 128: + pMaxBandsTab = tnsMaxBandsTab128; + maxBandsTabSize = sizeof(tnsMaxBandsTab128) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 240: + pMaxBandsTab = tnsMaxBandsTab240; + maxBandsTabSize = sizeof(tnsMaxBandsTab240) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 256: + pMaxBandsTab = tnsMaxBandsTab256; + maxBandsTabSize = sizeof(tnsMaxBandsTab256) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 480: + pMaxBandsTab = tnsMaxBandsTab480; + maxBandsTabSize = sizeof(tnsMaxBandsTab480) / sizeof(TNS_MAX_TAB_ENTRY); + break; + case 512: + pMaxBandsTab = tnsMaxBandsTab512; + maxBandsTabSize = sizeof(tnsMaxBandsTab512) / sizeof(TNS_MAX_TAB_ENTRY); + break; + default: + numBands = -1; + } + + if (pMaxBandsTab != NULL) { + for (i = 0; i < maxBandsTabSize; i++) { + numBands = pMaxBandsTab[i].maxBands[(!isShortBlock) ? 0 : 1]; + if (sampleRate >= pMaxBandsTab[i].samplingRate) { + break; + } + } + } + + return numBands; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_FreqToBandWidthRounding + + Returns index of nearest band border + + \param frequency + \param sampling frequency + \param total number of bands + \param pointer to table of band borders + + \return band border +****************************************************************************/ + +INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs, + const INT numOfBands, + const INT *bandStartOffset) { + INT lineNumber, band; + + /* assert(freq >= 0); */ + lineNumber = (freq * bandStartOffset[numOfBands] * 4 / fs + 1) / 2; + + /* freq > fs/2 */ + if (lineNumber >= bandStartOffset[numOfBands]) return numOfBands; + + /* find band the line number lies in */ + for (band = 0; band < numOfBands; band++) { + if (bandStartOffset[band + 1] > lineNumber) break; + } + + /* round to nearest band border */ + if (lineNumber - bandStartOffset[band] > + bandStartOffset[band + 1] - lineNumber) { + band++; + } + + return (band); +} + +/***************************************************************************** + + functionname: FDKaacEnc_InitTnsConfiguration + description: fill TNS_CONFIG structure with sensible content + returns: + input: bitrate, samplerate, number of channels, + blocktype (long or short), + TNS Config struct (modified), + psy config struct, + tns active flag + output: + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration( + INT bitRate, INT sampleRate, INT channels, INT blockType, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tC, PSY_CONFIGURATION *pC, + INT active, INT useTnsPeak) { + int i; + // float acfTimeRes = (blockType == SHORT_WINDOW) ? 0.125f : 0.046875f; + + if (channels <= 0) return (AAC_ENCODER_ERROR)1; + + tC->isLowDelay = isLowDelay; + + /* initialize TNS filter flag, order, and coefficient resolution (in bits per + * coeff) */ + tC->tnsActive = (active) ? TRUE : FALSE; + tC->maxOrder = (blockType == SHORT_WINDOW) ? 5 : 12; /* maximum: 7, 20 */ + if (bitRate < 16000) tC->maxOrder -= 2; + tC->coefRes = (blockType == SHORT_WINDOW) ? 3 : 4; + + /* LPC stop line: highest MDCT line to be coded, but do not go beyond + * TNS_MAX_BANDS! */ + tC->lpcStopBand = getTnsMaxBands(sampleRate, granuleLength, + (blockType == SHORT_WINDOW) ? 1 : 0); + + if (tC->lpcStopBand < 0) { + return (AAC_ENCODER_ERROR)1; + } + + tC->lpcStopBand = fMin(tC->lpcStopBand, pC->sfbActive); + tC->lpcStopLine = pC->sfbOffset[tC->lpcStopBand]; + + switch (granuleLength) { + case 960: + case 1024: + /* TNS start line: skip lower MDCT lines to prevent artifacts due to + * filter mismatch */ + if (blockType == SHORT_WINDOW) { + tC->lpcStartBand[LOFILT] = 0; + } else { + tC->lpcStartBand[LOFILT] = + (sampleRate < 9391) ? 2 : ((sampleRate < 18783) ? 4 : 8); + } + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + i = tC->lpcStopBand; + while (pC->sfbOffset[i] > + (tC->lpcStartLine[LOFILT] + + (tC->lpcStopLine - tC->lpcStartLine[LOFILT]) / 4)) + i--; + tC->lpcStartBand[HIFILT] = i; + tC->lpcStartLine[HIFILT] = pC->sfbOffset[i]; + + tC->confTab.threshOn[HIFILT] = 1437; + tC->confTab.threshOn[LOFILT] = 1500; + + tC->confTab.tnsLimitOrder[HIFILT] = tC->maxOrder; + tC->confTab.tnsLimitOrder[LOFILT] = fMax(0, tC->maxOrder - 7); + + tC->confTab.tnsFilterDirection[HIFILT] = FILTER_DIRECTION; + tC->confTab.tnsFilterDirection[LOFILT] = FILTER_DIRECTION; + + tC->confTab.acfSplit[HIFILT] = + -1; /* signal Merged4to2QuartersAutoCorrelation in + FDKaacEnc_MergedAutoCorrelation*/ + tC->confTab.acfSplit[LOFILT] = + -1; /* signal Merged4to2QuartersAutoCorrelation in + FDKaacEnc_MergedAutoCorrelation */ + + tC->confTab.filterEnabled[HIFILT] = 1; + tC->confTab.filterEnabled[LOFILT] = 1; + tC->confTab.seperateFiltersAllowed = 1; + + /* compute autocorrelation window based on maximum filter order for given + * block type */ + /* for (i = 0; i <= tC->maxOrder + 3; i++) { + float acfWinTemp = acfTimeRes * i; + acfWindow[i] = FL2FXCONST_DBL(1.0f - acfWinTemp * acfWinTemp); + } + */ + if (blockType == SHORT_WINDOW) { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowShort, + fMin((LONG)sizeof(acfWindowShort), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowShort, + fMin((LONG)sizeof(acfWindowShort), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + } else { + FDKmemcpy(tC->acfWindow[HIFILT], acfWindowLong, + fMin((LONG)sizeof(acfWindowLong), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + FDKmemcpy(tC->acfWindow[LOFILT], acfWindowLong, + fMin((LONG)sizeof(acfWindowLong), + (LONG)sizeof(tC->acfWindow[HIFILT]))); + } + break; + case 480: + case 512: { + const TNS_PARAMETER_TABULATED *pCfg = + FDKaacEnc_GetTnsParam(bitRate, channels, ldSbrPresent); + if (pCfg != NULL) { + FDKmemcpy(&(tC->confTab), pCfg, sizeof(tC->confTab)); + + tC->lpcStartBand[HIFILT] = FDKaacEnc_FreqToBandWidthRounding( + pCfg->filterStartFreq[HIFILT], sampleRate, pC->sfbCnt, + pC->sfbOffset); + tC->lpcStartLine[HIFILT] = pC->sfbOffset[tC->lpcStartBand[HIFILT]]; + tC->lpcStartBand[LOFILT] = FDKaacEnc_FreqToBandWidthRounding( + pCfg->filterStartFreq[LOFILT], sampleRate, pC->sfbCnt, + pC->sfbOffset); + tC->lpcStartLine[LOFILT] = pC->sfbOffset[tC->lpcStartBand[LOFILT]]; + + FDKaacEnc_CalcGaussWindow( + tC->acfWindow[HIFILT], tC->maxOrder + 1, sampleRate, granuleLength, + pCfg->tnsTimeResolution[HIFILT], TNS_TIMERES_SCALE); + FDKaacEnc_CalcGaussWindow( + tC->acfWindow[LOFILT], tC->maxOrder + 1, sampleRate, granuleLength, + pCfg->tnsTimeResolution[LOFILT], TNS_TIMERES_SCALE); + } else { + tC->tnsActive = + FALSE; /* no configuration available, disable tns tool */ + } + } break; + default: + tC->tnsActive = FALSE; /* no configuration available, disable tns tool */ + } + + return AAC_ENC_OK; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_ScaleUpSpectrum + + Scales up spectrum lines in a given frequency section + + \param scaled spectrum + \param original spectrum + \param frequency line to start scaling + \param frequency line to enc scaling + + \return scale factor + +****************************************************************************/ +static inline INT FDKaacEnc_ScaleUpSpectrum(FIXP_DBL *dest, const FIXP_DBL *src, + const INT startLine, + const INT stopLine) { + INT i, scale; + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.f); + + /* Get highest value in given spectrum */ + for (i = startLine; i < stopLine; i++) { + maxVal = fixMax(maxVal, fixp_abs(src[i])); + } + scale = CountLeadingBits(maxVal); + + /* Scale spectrum according to highest value */ + for (i = startLine; i < stopLine; i++) { + dest[i] = src[i] << scale; + } + + return scale; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_CalcAutoCorrValue + + Calculate autocorellation value for one lag + + \param pointer to spectrum + \param start line + \param stop line + \param lag to be calculated + \param scaling of the lag + +****************************************************************************/ +static inline FIXP_DBL FDKaacEnc_CalcAutoCorrValue(const FIXP_DBL *spectrum, + const INT startLine, + const INT stopLine, + const INT lag, + const INT scale) { + int i; + FIXP_DBL result = FL2FXCONST_DBL(0.f); + + /* This versions allows to save memory accesses, when computing pow2 */ + /* It is of interest for ARM, XTENSA without parallel memory access */ + if (lag == 0) { + for (i = startLine; i < stopLine; i++) { + result += (fPow2(spectrum[i]) >> scale); + } + } else { + for (i = startLine; i < (stopLine - lag); i++) { + result += (fMult(spectrum[i], spectrum[i + lag]) >> scale); + } + } + + return result; +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_AutoCorrNormFac + + Autocorrelation function for 1st and 2nd half of the spectrum + + \param pointer to spectrum + \param pointer to autocorrelation window + \param filter start line + +****************************************************************************/ +static inline FIXP_DBL FDKaacEnc_AutoCorrNormFac(const FIXP_DBL value, + const INT scale, INT *sc) { +#define HLM_MIN_NRG 0.0000000037252902984619140625f /* 2^-28 */ +#define MAX_INV_NRGFAC (1.f / HLM_MIN_NRG) + + FIXP_DBL retValue; + FIXP_DBL A, B; + + if (scale >= 0) { + A = value; + B = FL2FXCONST_DBL(HLM_MIN_NRG) >> fixMin(DFRACT_BITS - 1, scale); + } else { + A = value >> fixMin(DFRACT_BITS - 1, (-scale)); + B = FL2FXCONST_DBL(HLM_MIN_NRG); + } + + if (A > B) { + int shift = 0; + FIXP_DBL tmp = invSqrtNorm2(value, &shift); + + retValue = fMult(tmp, tmp); + *sc += (2 * shift); + } else { + /* MAX_INV_NRGFAC*FDKpow(2,-28) = 1/2^-28 * 2^-28 = 1.0 */ + retValue = + /*FL2FXCONST_DBL(MAX_INV_NRGFAC*FDKpow(2,-28))*/ (FIXP_DBL)MAXVAL_DBL; + *sc += scale + 28; + } + + return retValue; +} + +static void FDKaacEnc_MergedAutoCorrelation( + const FIXP_DBL *spectrum, const INT isLowDelay, + const FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1], + const INT lpcStartLine[MAX_NUM_OF_FILTERS], const INT lpcStopLine, + const INT maxOrder, const INT acfSplit[MAX_NUM_OF_FILTERS], FIXP_DBL *_rxx1, + FIXP_DBL *_rxx2) { + int i, idx0, idx1, idx2, idx3, idx4, lag; + FIXP_DBL rxx1_0, rxx2_0, rxx3_0, rxx4_0; + + /* buffer for temporal spectrum */ + C_ALLOC_SCRATCH_START(pSpectrum, FIXP_DBL, (1024)) + + /* MDCT line indices separating the 1st, 2nd, 3rd, and 4th analysis quarters + */ + if ((acfSplit[LOFILT] == -1) || (acfSplit[HIFILT] == -1)) { + /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the + * spectrum */ + idx0 = lpcStartLine[LOFILT]; + i = lpcStopLine - lpcStartLine[LOFILT]; + idx1 = idx0 + i / 4; + idx2 = idx0 + i / 2; + idx3 = idx0 + i * 3 / 4; + idx4 = lpcStopLine; + } else { + FDK_ASSERT(acfSplit[LOFILT] == 1); + FDK_ASSERT(acfSplit[HIFILT] == 3); + i = (lpcStopLine - lpcStartLine[HIFILT]) / 3; + idx0 = lpcStartLine[LOFILT]; + idx1 = lpcStartLine[HIFILT]; + idx2 = idx1 + i; + idx3 = idx2 + i; + idx4 = lpcStopLine; + } + + /* copy spectrum to temporal buffer and scale up as much as possible */ + INT sc1 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx0, idx1); + INT sc2 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx1, idx2); + INT sc3 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx2, idx3); + INT sc4 = FDKaacEnc_ScaleUpSpectrum(pSpectrum, spectrum, idx3, idx4); + + /* get scaling values for summation */ + INT nsc1, nsc2, nsc3, nsc4; + for (nsc1 = 1; (1 << nsc1) < (idx1 - idx0); nsc1++) + ; + for (nsc2 = 1; (1 << nsc2) < (idx2 - idx1); nsc2++) + ; + for (nsc3 = 1; (1 << nsc3) < (idx3 - idx2); nsc3++) + ; + for (nsc4 = 1; (1 << nsc4) < (idx4 - idx3); nsc4++) + ; + + /* compute autocorrelation value at lag zero, i. e. energy, for each quarter + */ + rxx1_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, 0, nsc1); + rxx2_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx1, idx2, 0, nsc2); + rxx3_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx2, idx3, 0, nsc3); + rxx4_0 = FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx3, idx4, 0, nsc4); + + /* compute energy normalization factors, i. e. 1/energy (saves some divisions) + */ + if (rxx1_0 != FL2FXCONST_DBL(0.f)) { + INT sc_fac1 = -1; + FIXP_DBL fac1 = + FDKaacEnc_AutoCorrNormFac(rxx1_0, ((-2 * sc1) + nsc1), &sc_fac1); + _rxx1[0] = scaleValue(fMult(rxx1_0, fac1), sc_fac1); + + if (isLowDelay) { + for (lag = 1; lag <= maxOrder; lag++) { + /* compute energy-normalized and windowed autocorrelation values at this + * lag */ + FIXP_DBL x1 = + FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); + _rxx1[lag] = + fMult(scaleValue(fMult(x1, fac1), sc_fac1), acfWindow[LOFILT][lag]); + } + } else { + for (lag = 1; lag <= maxOrder; lag++) { + if ((3 * lag) <= maxOrder + 3) { + FIXP_DBL x1 = + FDKaacEnc_CalcAutoCorrValue(pSpectrum, idx0, idx1, lag, nsc1); + _rxx1[lag] = fMult(scaleValue(fMult(x1, fac1), sc_fac1), + acfWindow[LOFILT][3 * lag]); + } + } + } + } + + /* auto corr over upper 3/4 of spectrum */ + if (!((rxx2_0 == FL2FXCONST_DBL(0.f)) && (rxx3_0 == FL2FXCONST_DBL(0.f)) && + (rxx4_0 == FL2FXCONST_DBL(0.f)))) { + FIXP_DBL fac2, fac3, fac4; + fac2 = fac3 = fac4 = FL2FXCONST_DBL(0.f); + INT sc_fac2, sc_fac3, sc_fac4; + sc_fac2 = sc_fac3 = sc_fac4 = 0; + + if (rxx2_0 != FL2FXCONST_DBL(0.f)) { + fac2 = FDKaacEnc_AutoCorrNormFac(rxx2_0, ((-2 * sc2) + nsc2), &sc_fac2); + sc_fac2 -= 2; + } + if (rxx3_0 != FL2FXCONST_DBL(0.f)) { + fac3 = FDKaacEnc_AutoCorrNormFac(rxx3_0, ((-2 * sc3) + nsc3), &sc_fac3); + sc_fac3 -= 2; + } + if (rxx4_0 != FL2FXCONST_DBL(0.f)) { + fac4 = FDKaacEnc_AutoCorrNormFac(rxx4_0, ((-2 * sc4) + nsc4), &sc_fac4); + sc_fac4 -= 2; + } + + _rxx2[0] = scaleValue(fMult(rxx2_0, fac2), sc_fac2) + + scaleValue(fMult(rxx3_0, fac3), sc_fac3) + + scaleValue(fMult(rxx4_0, fac4), sc_fac4); + + for (lag = 1; lag <= maxOrder; lag++) { + /* merge quarters 2, 3, 4 into one autocorrelation; quarter 1 stays + * separate */ + FIXP_DBL x2 = scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx1, idx2, lag, nsc2), + fac2), + sc_fac2) + + scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx2, idx3, lag, nsc3), + fac3), + sc_fac3) + + scaleValue(fMult(FDKaacEnc_CalcAutoCorrValue( + pSpectrum, idx3, idx4, lag, nsc4), + fac4), + sc_fac4); + + _rxx2[lag] = fMult(x2, acfWindow[HIFILT][lag]); + } + } + + C_ALLOC_SCRATCH_END(pSpectrum, FIXP_DBL, (1024)) +} + +/***************************************************************************** + functionname: FDKaacEnc_TnsDetect + description: do decision, if TNS shall be used or not + returns: + input: tns data structure (modified), + tns config structure, + scalefactor size and table, + spectrum, + subblock num, blocktype, + sfb-wise energy. + +*****************************************************************************/ +INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC, + TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum, + INT subBlockNumber, INT blockType) { + /* autocorrelation function for 1st, 2nd, 3rd, and 4th quarter of the + * spectrum. */ + FIXP_DBL rxx1[TNS_MAX_ORDER + 1]; /* higher part */ + FIXP_DBL rxx2[TNS_MAX_ORDER + 1]; /* lower part */ + FIXP_LPC parcor_tmp[TNS_MAX_ORDER]; + + int i; + + FDKmemclear(rxx1, sizeof(rxx1)); + FDKmemclear(rxx2, sizeof(rxx2)); + + TNS_SUBBLOCK_INFO *tsbi = + (blockType == SHORT_WINDOW) + ? &tnsData->dataRaw.Short.subBlockInfo[subBlockNumber] + : &tnsData->dataRaw.Long.subBlockInfo; + + tnsData->filtersMerged = FALSE; + + tsbi->tnsActive[HIFILT] = FALSE; + tsbi->predictionGain[HIFILT] = 1000; + tsbi->tnsActive[LOFILT] = FALSE; + tsbi->predictionGain[LOFILT] = 1000; + + tnsInfo->numOfFilters[subBlockNumber] = 0; + tnsInfo->coefRes[subBlockNumber] = tC->coefRes; + for (i = 0; i < tC->maxOrder; i++) { + tnsInfo->coef[subBlockNumber][HIFILT][i] = + tnsInfo->coef[subBlockNumber][LOFILT][i] = 0; + } + + tnsInfo->length[subBlockNumber][HIFILT] = + tnsInfo->length[subBlockNumber][LOFILT] = 0; + tnsInfo->order[subBlockNumber][HIFILT] = + tnsInfo->order[subBlockNumber][LOFILT] = 0; + + if ((tC->tnsActive) && (tC->maxOrder > 0)) { + int sumSqrCoef; + + FDKaacEnc_MergedAutoCorrelation( + spectrum, tC->isLowDelay, tC->acfWindow, tC->lpcStartLine, + tC->lpcStopLine, tC->maxOrder, tC->confTab.acfSplit, rxx1, rxx2); + + /* compute higher TNS filter coefficients in lattice form (ParCor) with + * LeRoux-Gueguen/Schur algorithm */ + { + FIXP_DBL predictionGain_m; + INT predictionGain_e; + + CLpc_AutoToParcor(rxx2, 0, parcor_tmp, tC->confTab.tnsLimitOrder[HIFILT], + &predictionGain_m, &predictionGain_e); + tsbi->predictionGain[HIFILT] = + (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31); + } + + /* non-linear quantization of TNS lattice coefficients with given resolution + */ + FDKaacEnc_Parcor2Index(parcor_tmp, tnsInfo->coef[subBlockNumber][HIFILT], + tC->confTab.tnsLimitOrder[HIFILT], tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute sum(abs(coefs)) + */ + for (i = tC->confTab.tnsLimitOrder[HIFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][HIFILT][i] * + tnsInfo->coef[subBlockNumber][HIFILT][i]; + } + + tnsInfo->direction[subBlockNumber][HIFILT] = + tC->confTab.tnsFilterDirection[HIFILT]; + tnsInfo->length[subBlockNumber][HIFILT] = sfbCnt - tC->lpcStartBand[HIFILT]; + + /* disable TNS if predictionGain is less than 3dB or sumSqrCoef is too small + */ + if ((tsbi->predictionGain[HIFILT] > tC->confTab.threshOn[HIFILT]) || + (sumSqrCoef > (tC->confTab.tnsLimitOrder[HIFILT] / 2 + 2))) { + tsbi->tnsActive[HIFILT] = TRUE; + tnsInfo->numOfFilters[subBlockNumber]++; + + /* compute second filter for lower quarter; only allowed for long windows! + */ + if ((blockType != SHORT_WINDOW) && (tC->confTab.filterEnabled[LOFILT]) && + (tC->confTab.seperateFiltersAllowed)) { + /* compute second filter for lower frequencies */ + + /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen + * algorithm */ + INT predGain; + { + FIXP_DBL predictionGain_m; + INT predictionGain_e; + + CLpc_AutoToParcor(rxx1, 0, parcor_tmp, + tC->confTab.tnsLimitOrder[LOFILT], + &predictionGain_m, &predictionGain_e); + predGain = + (INT)fMultNorm(predictionGain_m, predictionGain_e, 1000, 31, 31); + } + + /* non-linear quantization of TNS lattice coefficients with given + * resolution */ + FDKaacEnc_Parcor2Index(parcor_tmp, + tnsInfo->coef[subBlockNumber][LOFILT], + tC->confTab.tnsLimitOrder[LOFILT], tC->coefRes); + + /* reduce filter order by truncating trailing zeros, compute + * sum(abs(coefs)) */ + for (i = tC->confTab.tnsLimitOrder[LOFILT] - 1; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][LOFILT][i] != 0) { + break; + } + } + tnsInfo->order[subBlockNumber][LOFILT] = i + 1; + + sumSqrCoef = 0; + for (; i >= 0; i--) { + sumSqrCoef += tnsInfo->coef[subBlockNumber][LOFILT][i] * + tnsInfo->coef[subBlockNumber][LOFILT][i]; + } + + tnsInfo->direction[subBlockNumber][LOFILT] = + tC->confTab.tnsFilterDirection[LOFILT]; + tnsInfo->length[subBlockNumber][LOFILT] = + tC->lpcStartBand[HIFILT] - tC->lpcStartBand[LOFILT]; + + /* filter lower quarter if gain is high enough, but not if it's too high + */ + if (((predGain > tC->confTab.threshOn[LOFILT]) && + (predGain < (16000 * tC->confTab.tnsLimitOrder[LOFILT]))) || + ((sumSqrCoef > 9) && + (sumSqrCoef < 22 * tC->confTab.tnsLimitOrder[LOFILT]))) { + /* compare lower to upper filter; if they are very similar, merge them + */ + tsbi->tnsActive[LOFILT] = TRUE; + sumSqrCoef = 0; + for (i = 0; i < tC->confTab.tnsLimitOrder[LOFILT]; i++) { + sumSqrCoef += fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i] - + tnsInfo->coef[subBlockNumber][LOFILT][i]); + } + if ((sumSqrCoef < 2) && + (tnsInfo->direction[subBlockNumber][LOFILT] == + tnsInfo->direction[subBlockNumber][HIFILT])) { + tnsData->filtersMerged = TRUE; + tnsInfo->length[subBlockNumber][HIFILT] = + sfbCnt - tC->lpcStartBand[LOFILT]; + for (; i < tnsInfo->order[subBlockNumber][HIFILT]; i++) { + if (fAbs(tnsInfo->coef[subBlockNumber][HIFILT][i]) > 1) { + break; + } + } + for (i--; i >= 0; i--) { + if (tnsInfo->coef[subBlockNumber][HIFILT][i] != 0) { + break; + } + } + if (i < tnsInfo->order[subBlockNumber][HIFILT]) { + tnsInfo->order[subBlockNumber][HIFILT] = i + 1; + } + } else { + tnsInfo->numOfFilters[subBlockNumber]++; + } + } /* filter lower part */ + tsbi->predictionGain[LOFILT] = predGain; + + } /* second filter allowed */ + } /* if predictionGain > 1437 ... */ + } /* maxOrder > 0 && tnsActive */ + + return 0; +} + +/***************************************************************************/ +/*! + \brief FDKaacLdEnc_TnsSync + + synchronize TNS parameters when TNS gain difference small (relative) + + \param pointer to TNS data structure (destination) + \param pointer to TNS data structure (source) + \param pointer to TNS config structure + \param number of sub-block + \param block type + + \return void +****************************************************************************/ +void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, const INT blockTypeSrc, + const TNS_CONFIG *tC) { + int i, w, absDiff, nWindows; + TNS_SUBBLOCK_INFO *sbInfoDest; + const TNS_SUBBLOCK_INFO *sbInfoSrc; + + /* if one channel contains short blocks and the other not, do not synchronize + */ + if ((blockTypeSrc == SHORT_WINDOW && blockTypeDest != SHORT_WINDOW) || + (blockTypeDest == SHORT_WINDOW && blockTypeSrc != SHORT_WINDOW)) { + return; + } + + if (blockTypeDest != SHORT_WINDOW) { + sbInfoDest = &tnsDataDest->dataRaw.Long.subBlockInfo; + sbInfoSrc = &tnsDataSrc->dataRaw.Long.subBlockInfo; + nWindows = 1; + } else { + sbInfoDest = &tnsDataDest->dataRaw.Short.subBlockInfo[0]; + sbInfoSrc = &tnsDataSrc->dataRaw.Short.subBlockInfo[0]; + nWindows = 8; + } + + for (w = 0; w < nWindows; w++) { + const TNS_SUBBLOCK_INFO *pSbInfoSrcW = sbInfoSrc + w; + TNS_SUBBLOCK_INFO *pSbInfoDestW = sbInfoDest + w; + INT doSync = 1, absDiffSum = 0; + + /* if TNS is active in at least one channel, check if ParCor coefficients of + * higher filter are similar */ + if (pSbInfoDestW->tnsActive[HIFILT] || pSbInfoSrcW->tnsActive[HIFILT]) { + for (i = 0; i < tC->maxOrder; i++) { + absDiff = fAbs(tnsInfoDest->coef[w][HIFILT][i] - + tnsInfoSrc->coef[w][HIFILT][i]); + absDiffSum += absDiff; + /* if coefficients diverge too much between channels, do not synchronize + */ + if ((absDiff > 1) || (absDiffSum > 2)) { + doSync = 0; + break; + } + } + + if (doSync) { + /* if no significant difference was detected, synchronize coefficient + * sets */ + if (pSbInfoSrcW->tnsActive[HIFILT]) { + /* no dest filter, or more dest than source filters: use one dest + * filter */ + if ((!pSbInfoDestW->tnsActive[HIFILT]) || + ((pSbInfoDestW->tnsActive[HIFILT]) && + (tnsInfoDest->numOfFilters[w] > tnsInfoSrc->numOfFilters[w]))) { + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 1; + } + tnsDataDest->filtersMerged = tnsDataSrc->filtersMerged; + tnsInfoDest->order[w][HIFILT] = tnsInfoSrc->order[w][HIFILT]; + tnsInfoDest->length[w][HIFILT] = tnsInfoSrc->length[w][HIFILT]; + tnsInfoDest->direction[w][HIFILT] = tnsInfoSrc->direction[w][HIFILT]; + tnsInfoDest->coefCompress[w][HIFILT] = + tnsInfoSrc->coefCompress[w][HIFILT]; + + for (i = 0; i < tC->maxOrder; i++) { + tnsInfoDest->coef[w][HIFILT][i] = tnsInfoSrc->coef[w][HIFILT][i]; + } + } else + pSbInfoDestW->tnsActive[HIFILT] = tnsInfoDest->numOfFilters[w] = 0; + } + } + } +} + +/***************************************************************************/ +/*! + \brief FDKaacEnc_TnsEncode + + perform TNS encoding + + \param pointer to TNS info structure + \param pointer to TNS data structure + \param number of sfbs + \param pointer to TNS config structure + \param low-pass line + \param pointer to spectrum + \param number of sub-block + \param block type + + \return ERROR STATUS +****************************************************************************/ +INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData, + const INT numOfSfb, const TNS_CONFIG *tC, + const INT lowPassLine, FIXP_DBL *spectrum, + const INT subBlockNumber, const INT blockType) { + INT i, startLine, stopLine; + + if (((blockType == SHORT_WINDOW) && + (!tnsData->dataRaw.Short.subBlockInfo[subBlockNumber] + .tnsActive[HIFILT])) || + ((blockType != SHORT_WINDOW) && + (!tnsData->dataRaw.Long.subBlockInfo.tnsActive[HIFILT]))) { + return 1; + } + + startLine = (tnsData->filtersMerged) ? tC->lpcStartLine[LOFILT] + : tC->lpcStartLine[HIFILT]; + stopLine = tC->lpcStopLine; + + for (i = 0; i < tnsInfo->numOfFilters[subBlockNumber]; i++) { + INT lpcGainFactor; + FIXP_LPC LpcCoeff[TNS_MAX_ORDER]; + FIXP_DBL workBuffer[TNS_MAX_ORDER]; + FIXP_LPC parcor_tmp[TNS_MAX_ORDER]; + + FDKaacEnc_Index2Parcor(tnsInfo->coef[subBlockNumber][i], parcor_tmp, + tnsInfo->order[subBlockNumber][i], tC->coefRes); + + lpcGainFactor = CLpc_ParcorToLpc( + parcor_tmp, LpcCoeff, tnsInfo->order[subBlockNumber][i], workBuffer); + + FDKmemclear(workBuffer, TNS_MAX_ORDER * sizeof(FIXP_DBL)); + CLpc_Analysis(&spectrum[startLine], stopLine - startLine, LpcCoeff, + lpcGainFactor, tnsInfo->order[subBlockNumber][i], workBuffer, + NULL); + + /* update for second filter */ + startLine = tC->lpcStartLine[LOFILT]; + stopLine = tC->lpcStartLine[HIFILT]; + } + + return (0); +} + +static void FDKaacEnc_CalcGaussWindow(FIXP_DBL *win, const int winSize, + const INT samplingRate, + const INT transformResolution, + const FIXP_DBL timeResolution, + const INT timeResolution_e) { +#define PI_E (2) +#define PI_M FL2FXCONST_DBL(3.1416f / (float)(1 << PI_E)) + +#define EULER_E (2) +#define EULER_M FL2FXCONST_DBL(2.7183 / (float)(1 << EULER_E)) + +#define COEFF_LOOP_SCALE (4) + + INT i, e1, e2, gaussExp_e; + FIXP_DBL gaussExp_m; + + /* calc. window exponent from time resolution: + * + * gaussExp = PI * samplingRate * 0.001f * timeResolution / + * transformResolution; gaussExp = -0.5f * gaussExp * gaussExp; + */ + gaussExp_m = fMultNorm( + timeResolution, + fMult(PI_M, + fDivNorm((FIXP_DBL)(samplingRate), + (FIXP_DBL)(LONG)(transformResolution * 1000.f), &e1)), + &e2); + gaussExp_m = -fPow2Div2(gaussExp_m); + gaussExp_e = 2 * (e1 + e2 + timeResolution_e + PI_E); + + FDK_ASSERT(winSize < (1 << COEFF_LOOP_SCALE)); + + /* calc. window coefficients + * win[i] = (float)exp( gaussExp * (i+0.5) * (i+0.5) ); + */ + for (i = 0; i < winSize; i++) { + win[i] = fPow( + EULER_M, EULER_E, + fMult(gaussExp_m, + fPow2((i * FL2FXCONST_DBL(1.f / (float)(1 << COEFF_LOOP_SCALE)) + + FL2FXCONST_DBL(.5f / (float)(1 << COEFF_LOOP_SCALE))))), + gaussExp_e + 2 * COEFF_LOOP_SCALE, &e1); + + win[i] = scaleValueSaturate(win[i], e1); + } +} + +static INT FDKaacEnc_Search3(FIXP_LPC parcor) { + INT i, index = 0; + + for (i = 0; i < 8; i++) { + if (parcor > FDKaacEnc_tnsCoeff3Borders[i]) index = i; + } + return (index - 4); +} + +static INT FDKaacEnc_Search4(FIXP_LPC parcor) { + INT i, index = 0; + + for (i = 0; i < 16; i++) { + if (parcor > FDKaacEnc_tnsCoeff4Borders[i]) index = i; + } + return (index - 8); +} + +/***************************************************************************** + + functionname: FDKaacEnc_Parcor2Index + +*****************************************************************************/ +static void FDKaacEnc_Parcor2Index(const FIXP_LPC *parcor, INT *RESTRICT index, + const INT order, const INT bitsPerCoeff) { + INT i; + for (i = 0; i < order; i++) { + if (bitsPerCoeff == 3) + index[i] = FDKaacEnc_Search3(parcor[i]); + else + index[i] = FDKaacEnc_Search4(parcor[i]); + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_Index2Parcor + description: inverse quantization for reflection coefficients + returns: - + input: quantized values, ptr. to reflection coefficients, + no. of coefficients, resolution + output: reflection coefficients + +*****************************************************************************/ +static void FDKaacEnc_Index2Parcor(const INT *index, FIXP_LPC *RESTRICT parcor, + const INT order, const INT bitsPerCoeff) { + INT i; + for (i = 0; i < order; i++) + parcor[i] = bitsPerCoeff == 4 ? FDKaacEnc_tnsEncCoeff4[index[i] + 8] + : FDKaacEnc_tnsEncCoeff3[index[i] + 4]; +} diff --git a/fdk-aac/libAACenc/src/aacenc_tns.h b/fdk-aac/libAACenc/src/aacenc_tns.h new file mode 100644 index 0000000..a37f978 --- /dev/null +++ b/fdk-aac/libAACenc/src/aacenc_tns.h @@ -0,0 +1,213 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Groeschel + + Description: Temporal noise shaping + +*******************************************************************************/ + +#ifndef AACENC_TNS_H +#define AACENC_TNS_H + +#include "common_fix.h" + +#include "psy_const.h" + +#ifndef PI +#define PI 3.1415926535897931f +#endif + +/** + * TNS_ENABLE_MASK + * This bitfield defines which TNS features are enabled + * The TNS mask is composed of 4 bits. + * tnsMask |= 0x1; activate TNS short blocks + * tnsMask |= 0x2; activate TNS for long blocks + * tnsMask |= 0x4; activate TNS PEAK tool for short blocks + * tnsMask |= 0x8; activate TNS PEAK tool for long blocks + */ +#define TNS_ENABLE_MASK 0xf + +/* TNS max filter order for Low Complexity MPEG4 profile */ +#define TNS_MAX_ORDER 12 + +#define MAX_NUM_OF_FILTERS 2 + +#define HIFILT 0 /* index of higher filter */ +#define LOFILT 1 /* index of lower filter */ + +typedef struct { /* stuff that is tabulated dependent on bitrate etc. */ + INT filterEnabled[MAX_NUM_OF_FILTERS]; + INT threshOn[MAX_NUM_OF_FILTERS]; /* min. prediction gain for using tns + TABUL*/ + INT filterStartFreq[MAX_NUM_OF_FILTERS]; /* lowest freq for lpc TABUL*/ + INT tnsLimitOrder[MAX_NUM_OF_FILTERS]; /* Limit for TNS order TABUL*/ + INT tnsFilterDirection[MAX_NUM_OF_FILTERS]; /* Filtering direction, 0=up, + 1=down TABUL */ + INT acfSplit[MAX_NUM_OF_FILTERS]; + FIXP_DBL tnsTimeResolution[MAX_NUM_OF_FILTERS]; /* TNS max. time resolution + TABUL. Should be fract but + MSVC won't compile then */ + INT seperateFiltersAllowed; +} TNS_PARAMETER_TABULATED; + +typedef struct { /*assigned at InitTime*/ + TNS_PARAMETER_TABULATED confTab; + INT isLowDelay; + INT tnsActive; + INT maxOrder; /* max. order of tns filter */ + INT coefRes; + FIXP_DBL acfWindow[MAX_NUM_OF_FILTERS][TNS_MAX_ORDER + 3 + 1]; + /* now some things that only probably can be done at Init time; + could be they have to be split up for each individual (short) window or + even filter. */ + INT lpcStartBand[MAX_NUM_OF_FILTERS]; + INT lpcStartLine[MAX_NUM_OF_FILTERS]; + INT lpcStopBand; + INT lpcStopLine; + +} TNS_CONFIG; + +typedef struct { + INT tnsActive[MAX_NUM_OF_FILTERS]; + INT predictionGain[MAX_NUM_OF_FILTERS]; +} TNS_SUBBLOCK_INFO; + +typedef struct { /*changed at runTime*/ + TNS_SUBBLOCK_INFO subBlockInfo[TRANS_FAC]; + FIXP_DBL ratioMultTable[TRANS_FAC][MAX_SFB_SHORT]; +} TNS_DATA_SHORT; + +typedef struct { /*changed at runTime*/ + TNS_SUBBLOCK_INFO subBlockInfo; + FIXP_DBL ratioMultTable[MAX_SFB_LONG]; +} TNS_DATA_LONG; + +/* can be implemented as union */ +typedef shouldBeUnion { + TNS_DATA_LONG Long; + TNS_DATA_SHORT Short; +} +TNS_DATA_RAW; + +typedef struct { + INT numOfSubblocks; + TNS_DATA_RAW dataRaw; + INT tnsMaxScaleSpec; + INT filtersMerged; +} TNS_DATA; + +typedef struct { + INT numOfFilters[TRANS_FAC]; + INT coefRes[TRANS_FAC]; + INT length[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT order[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT direction[TRANS_FAC][MAX_NUM_OF_FILTERS]; + INT coefCompress[TRANS_FAC][MAX_NUM_OF_FILTERS]; + /* for Long: length TNS_MAX_ORDER (12 for LC) is required -> 12 */ + /* for Short: length TRANS_FAC*TNS_MAX_ORDER (only 5 for short LC) is required + * -> 8*5=40 */ + /* Currently TRANS_FAC*TNS_MAX_ORDER = 8*12 = 96 (for LC) is used (per + * channel)! Memory could be saved here! */ + INT coef[TRANS_FAC][MAX_NUM_OF_FILTERS][TNS_MAX_ORDER]; +} TNS_INFO; + +INT FDKaacEnc_FreqToBandWidthRounding(const INT freq, const INT fs, + const INT numOfBands, + const INT *bandStartOffset); + +#endif /* AACENC_TNS_H */ diff --git a/fdk-aac/libAACenc/src/adj_thr.cpp b/fdk-aac/libAACenc/src/adj_thr.cpp new file mode 100644 index 0000000..6e19680 --- /dev/null +++ b/fdk-aac/libAACenc/src/adj_thr.cpp @@ -0,0 +1,2924 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Threshold compensation + +*******************************************************************************/ + +#include "adj_thr.h" +#include "sf_estim.h" +#include "aacEnc_ram.h" + +#define NUM_NRG_LEVS (8) +#define INV_INT_TAB_SIZE (8) +static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = { + 0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa, + 0x20000000, 0x19999999, 0x15555555, 0x12492492}; + +#define INV_SQRT4_TAB_SIZE (8) +static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = { + 0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5, + 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1}; + +/*static const INT invRedExp = 4;*/ +static const FIXP_DBL SnrLdMin1 = + (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin2 = + (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdFac = + (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8) + /FDKlog(2.0)/LD_DATA_SCALING);*/ + +static const FIXP_DBL SnrLdMin3 = + (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin4 = + (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0) + /FDKlog(2.0)/LD_DATA_SCALING);*/ +static const FIXP_DBL SnrLdMin5 = + (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) + /FDKlog(2.0)/LD_DATA_SCALING);*/ + +/* +The bits2Pe factors are choosen for the case that some times +the crash recovery strategy will be activated once. +*/ +#define AFTERBURNER_STATI 2 +#define MAX_ALLOWED_EL_CHANNELS 2 + +typedef struct { + INT bitrate; + FIXP_DBL bits2PeFactor[AFTERBURNER_STATI][MAX_ALLOWED_EL_CHANNELS]; +} BIT_PE_SFAC; + +typedef struct { + INT sampleRate; + const BIT_PE_SFAC *pPeTab; + INT nEntries; + +} BITS2PE_CFG_TAB; + +#define FL2B2PE(value) FL2FXCONST_DBL((value) / (1 << 2)) + +static const BIT_PE_SFAC S_Bits2PeTab16000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {10000, + {{FL2B2PE(1.60f), FL2B2PE(0.00f)}, {FL2B2PE(1.40f), FL2B2PE(0.00f)}}}, + {24000, + {{FL2B2PE(1.80f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {32000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {48000, + {{FL2B2PE(1.60f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {64000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.60f)}}}, + {96000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab22050[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}}, + {32000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.20f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.40f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {96000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.80f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab24000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}}, + {32000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {96000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {128000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.80f)}}}, + {148000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab32000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.20f), FL2B2PE(1.40f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}}, + {24000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.60f)}}}, + {32000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(1.20f)}}}, + {64000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {128000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {148000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {160000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}}, + {200000, + {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.80f)}, {FL2B2PE(3.20f), FL2B2PE(1.80f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab44100[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(0.80f), FL2B2PE(1.00f)}}}, + {24000, + {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {32000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(0.80f), FL2B2PE(0.60f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}}, + {64000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {128000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {148000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {160000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {200000, + {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}}; + +static const BIT_PE_SFAC S_Bits2PeTab48000[] = { + /* bitrate| afterburner off | afterburner on | | nCh=1 + | nCh=2 | nCh=1 | nCh=2 */ + {16000, + {{FL2B2PE(1.40f), FL2B2PE(0.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.00f)}}}, + {24000, + {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}}, + {32000, + {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(0.60f), FL2B2PE(0.80f)}}}, + {48000, + {{FL2B2PE(1.20f), FL2B2PE(1.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}}, + {64000, + {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}}, + {96000, + {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}}, + {128000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {148000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {160000, + {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {200000, + {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}}, + {320000, + {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}}; + +static const BITS2PE_CFG_TAB bits2PeConfigTab[] = { + {16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000) / sizeof(BIT_PE_SFAC)}, + {22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050) / sizeof(BIT_PE_SFAC)}, + {24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000) / sizeof(BIT_PE_SFAC)}, + {32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000) / sizeof(BIT_PE_SFAC)}, + {44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100) / sizeof(BIT_PE_SFAC)}, + {48000, S_Bits2PeTab48000, + sizeof(S_Bits2PeTab48000) / sizeof(BIT_PE_SFAC)}}; + +/* values for avoid hole flag */ +enum _avoid_hole_state { NO_AH = 0, AH_INACTIVE = 1, AH_ACTIVE = 2 }; + +/* Q format definitions */ +#define Q_BITFAC \ + (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */ +#define Q_AVGBITS (17) /* scale bit values */ + +/***************************************************************************** + functionname: FDKaacEnc_InitBits2PeFactor + description: retrieve bits2PeFactor from table +*****************************************************************************/ +static void FDKaacEnc_InitBits2PeFactor( + FIXP_DBL *bits2PeFactor_m, INT *bits2PeFactor_e, const INT bitRate, + const INT nChannels, const INT sampleRate, const INT advancedBitsToPe, + const INT dZoneQuantEnable, const INT invQuant) { + /**** 1) Set default bits2pe factor ****/ + FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f / (1 << (1))); + INT bit2PE_e = 1; + + /**** 2) For AAC-(E)LD, make use of advanced bits to pe factor table ****/ + if (advancedBitsToPe && nChannels <= (2)) { + int i; + const BIT_PE_SFAC *peTab = NULL; + INT size = 0; + + /*** 2.1) Get correct table entry ***/ + for (i = 0; i < (INT)(sizeof(bits2PeConfigTab) / sizeof(BITS2PE_CFG_TAB)); + i++) { + if (sampleRate >= bits2PeConfigTab[i].sampleRate) { + peTab = bits2PeConfigTab[i].pPeTab; + size = bits2PeConfigTab[i].nEntries; + } + } + + if ((peTab != NULL) && (size != 0)) { + INT startB = -1; /* bitrate entry in table that is the next-lower to + actual bitrate */ + INT stopB = -1; /* bitrate entry in table that is the next-higher to + actual bitrate */ + FIXP_DBL startPF = + FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table that is the + next-lower to actual bits2PE factor */ + FIXP_DBL stopPF = FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table + that is the next-higher to + actual bits2PE factor */ + FIXP_DBL slope = FL2FXCONST_DBL( + 0.0f); /* the slope from the start bits2Pe entry to the next one */ + const int qualityIdx = (invQuant == 0) ? 0 : 1; + + if (bitRate >= peTab[size - 1].bitrate) { + /* Chosen bitrate is higher than the highest bitrate in table. + The slope for extrapolating the bits2PE factor must be zero. + Values are set accordingly. */ + startB = peTab[size - 1].bitrate; + stopB = + bitRate + + 1; /* Can be an arbitrary value greater than startB and bitrate. */ + startPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1]; + stopPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1]; + } else { + for (i = 0; i < size - 1; i++) { + if ((peTab[i].bitrate <= bitRate) && + (peTab[i + 1].bitrate > bitRate)) { + startB = peTab[i].bitrate; + stopB = peTab[i + 1].bitrate; + startPF = peTab[i].bits2PeFactor[qualityIdx][nChannels - 1]; + stopPF = peTab[i + 1].bits2PeFactor[qualityIdx][nChannels - 1]; + break; + } + } + } + + /*** 2.2) Configuration available? ***/ + if (startB != -1) { + /** 2.2.1) linear interpolate to actual PEfactor **/ + FIXP_DBL bit2PE = 0; + + const FIXP_DBL maxBit2PE = FL2FXCONST_DBL(3.f / 4.f); + + /* bit2PE = ((stopPF-startPF)/(stopB-startB))*(bitRate-startB)+startPF; + */ + slope = fDivNorm(bitRate - startB, stopB - startB); + bit2PE = fMult(slope, stopPF - startPF) + startPF; + + bit2PE = fMin(maxBit2PE, bit2PE); + + /** 2.2.2) sanity check if bits2pe value is high enough **/ + if (bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2)) { + bit2PE_m = bit2PE; + bit2PE_e = 2; /* table is fixed scaled */ + } + } /* br */ + } /* sr */ + } /* advancedBitsToPe */ + + if (dZoneQuantEnable) { + if (bit2PE_m >= (FL2FXCONST_DBL(0.6f)) >> bit2PE_e) { + /* Additional headroom for addition */ + bit2PE_m >>= 1; + bit2PE_e += 1; + } + + /* the quantTendencyCompensator compensates a lower bit consumption due to + * increasing the tendency to quantize low spectral values to the lower + * quantizer border for bitrates below a certain bitrate threshold --> see + * also function calcSfbDistLD in quantize.c */ + if ((bitRate / nChannels > 32000) && (bitRate / nChannels <= 40000)) { + bit2PE_m += (FL2FXCONST_DBL(0.4f)) >> bit2PE_e; + } else if (bitRate / nChannels > 20000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e; + } else if (bitRate / nChannels >= 16000) { + bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e; + } else { + bit2PE_m += (FL2FXCONST_DBL(0.0f)) >> bit2PE_e; + } + } + + /***** 3.) Return bits2pe factor *****/ + *bits2PeFactor_m = bit2PE_m; + *bits2PeFactor_e = bit2PE_e; +} + +/***************************************************************************** +functionname: FDKaacEnc_bits2pe2 +description: convert from bits to pe +*****************************************************************************/ +FDK_INLINE INT FDKaacEnc_bits2pe2(const INT bits, const FIXP_DBL factor_m, + const INT factor_e) { + return (INT)(fMult(factor_m, (FIXP_DBL)(bits << Q_AVGBITS)) >> + (Q_AVGBITS - factor_e)); +} + +/***************************************************************************** +functionname: FDKaacEnc_calcThreshExp +description: loudness calculation (threshold to the power of redExp) +*****************************************************************************/ +static void FDKaacEnc_calcThreshExp( + FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) { + INT ch, sfb, sfbGrp; + FIXP_DBL thrExpLdData; + + for (ch = 0; ch < nChannels; ch++) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] >> 2; + thrExp[ch][sfbGrp + sfb] = CalcInvLdData(thrExpLdData); + } + } + } +} + +/***************************************************************************** + functionname: FDKaacEnc_adaptMinSnr + description: reduce minSnr requirements for bands with relative low +energies +*****************************************************************************/ +static void FDKaacEnc_adaptMinSnr( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const MINSNR_ADAPT_PARAM *const msaParam, const INT nChannels) { + INT ch, sfb, sfbGrp, nSfb; + FIXP_DBL avgEnLD64, dbRatio, minSnrRed; + FIXP_DBL minSnrLimitLD64 = + FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */ + FIXP_DBL nSfbLD64; + FIXP_DBL accu; + + FIXP_DBL msaParam_maxRed = msaParam->maxRed; + FIXP_DBL msaParam_startRatio = msaParam->startRatio; + FIXP_DBL msaParam_redRatioFac = + fMult(msaParam->redRatioFac, FL2FXCONST_DBL(0.3010299956f)); + FIXP_DBL msaParam_redOffs = msaParam->redOffs; + + for (ch = 0; ch < nChannels; ch++) { + /* calc average energy per scalefactor band */ + nSfb = 0; + accu = FL2FXCONST_DBL(0.0f); + + DWORD_ALIGNED(psyOutChannel[ch]->sfbEnergy); + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup; + nSfb += maxSfbPerGroup; + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + accu += psyOutChannel[ch]->sfbEnergy[sfbGrp + sfb] >> 6; + } + } + + if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) { + avgEnLD64 = FL2FXCONST_DBL(-1.0f); + } else { + nSfbLD64 = CalcLdInt(nSfb); + avgEnLD64 = CalcLdData(accu); + avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - + nSfbLD64; /* 0.09375f: compensate shift with 6 */ + } + + /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */ + int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup; + int sfbCnt = psyOutChannel[ch]->sfbCnt; + int sfbPerGroup = psyOutChannel[ch]->sfbPerGroup; + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + FIXP_DBL *RESTRICT psfbEnergyLdData = + &qcOutChannel[ch]->sfbEnergyLdData[sfbGrp]; + FIXP_DBL *RESTRICT psfbMinSnrLdData = + &qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp]; + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + FIXP_DBL sfbEnergyLdData = *psfbEnergyLdData++; + FIXP_DBL sfbMinSnrLdData = *psfbMinSnrLdData; + dbRatio = avgEnLD64 - sfbEnergyLdData; + int update = (msaParam_startRatio < dbRatio) ? 1 : 0; + minSnrRed = msaParam_redOffs + fMult(msaParam_redRatioFac, + dbRatio); /* scaled by 1.0f/64.0f*/ + minSnrRed = + fixMax(minSnrRed, msaParam_maxRed); /* scaled by 1.0f/64.0f*/ + minSnrRed = (fMult(sfbMinSnrLdData, minSnrRed)) << 6; + minSnrRed = fixMin(minSnrLimitLD64, minSnrRed); + *psfbMinSnrLdData++ = update ? minSnrRed : sfbMinSnrLdData; + } + } + } +} + +/***************************************************************************** +functionname: FDKaacEnc_initAvoidHoleFlag +description: determine bands where avoid hole is not necessary resp. possible +*****************************************************************************/ +static void FDKaacEnc_initAvoidHoleFlag( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const struct TOOLSINFO *const toolsInfo, + const INT nChannels, const AH_PARAM *const ahParam) { + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEn, sfbEnm1; + FIXP_DBL sfbEnLdData; + FIXP_DBL avgEnLdData; + + /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts + (avoid more holes in long blocks) */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch]; + + if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >>= 1; + } else { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) + qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + FL2FXCONST_DBL(0.63f), qcOutChan->sfbSpreadEnergy[sfbGrp + sfb]); + } + } + + /* increase minSnr for local peaks, decrease it for valleys */ + if (ahParam->modifyMinSnr) { + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + FIXP_DBL sfbEnp1, avgEn; + if (sfb > 0) + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb - 1]; + else + sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb]; + + if (sfb < psyOutChannel[ch]->maxSfbPerGroup - 1) + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb + 1]; + else + sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb]; + + avgEn = (sfbEnm1 >> 1) + (sfbEnp1 >> 1); + avgEnLdData = CalcLdData(avgEn); + sfbEn = qcOutChan->sfbEnergy[sfbGrp + sfb]; + sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp + sfb]; + /* peak ? */ + if (sfbEn > avgEn) { + FIXP_DBL tmpMinSnrLdData; + if (psyOutChannel[ch]->lastWindowSequence == LONG_WINDOW) + tmpMinSnrLdData = + fixMax(SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), + (FIXP_DBL)SnrLdMin1); + else + tmpMinSnrLdData = + fixMax(SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), + (FIXP_DBL)SnrLdMin3); + + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb], tmpMinSnrLdData); + } + /* valley ? */ + if (((sfbEnLdData + (FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) && + (sfbEn > FL2FXCONST_DBL(0.0))) { + FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData - + (FIXP_DBL)SnrLdMin4 + + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]; + tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData); + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = + fixMin(tmpMinSnrLdData, + (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + + SnrLdMin2)); + } + } + } + } + } + + /* stereo: adapt the minimum requirements sfbMinSnr of mid and + side channels to avoid spending unnoticable bits */ + if (nChannels == 2) { + QC_OUT_CHANNEL *qcOutChanM = qcOutChannel[0]; + QC_OUT_CHANNEL *qcOutChanS = qcOutChannel[1]; + const PSY_OUT_CHANNEL *const psyOutChanM = psyOutChannel[0]; + for (sfbGrp = 0; sfbGrp < psyOutChanM->sfbCnt; + sfbGrp += psyOutChanM->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChanM->maxSfbPerGroup; sfb++) { + if (toolsInfo->msMask[sfbGrp + sfb]) { + FIXP_DBL maxSfbEnLd = + fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp + sfb], + qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]); + FIXP_DBL maxThrLd, sfbMinSnrTmpLd; + + if (((SnrLdMin5 >> 1) + (maxSfbEnLd >> 1) + + (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) <= + FL2FXCONST_DBL(-0.5f)) + maxThrLd = FL2FXCONST_DBL(-1.0f); + else + maxThrLd = SnrLdMin5 + maxSfbEnLd + + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb]; + + if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = + maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp + sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = + fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd); + + if (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac); + + if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f)) + sfbMinSnrTmpLd = + maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]; + else + sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f); + + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = + fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd); + + if (qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f)) + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = fixMin( + qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac); + + if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > + qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb]) + qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + qcOutChanS->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f)); + + if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > + qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb]) + qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb] = fMult( + qcOutChanM->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f)); + + } /* if (toolsInfo->msMask[sfbGrp+sfb]) */ + } /* sfb */ + } /* sfbGrp */ + } /* nChannels==2 */ + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch]; + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if ((qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] > + qcOutChan->sfbEnergy[sfbGrp + sfb]) || + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))) { + ahFlag[ch][sfbGrp + sfb] = NO_AH; + } else { + ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE; + } + } + } + } +} + +/** + * \brief Calculate constants that do not change during successive pe + * calculations. + * + * \param peData Pointer to structure containing PE data of + * current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding + * nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding + * nChannels elements. + * \param nChannels Number of channels in element. + * \param peOffset Fixed PE offset defined while + * FDKaacEnc_AdjThrInit() depending on bitrate. + * + * \return void + */ +static void FDKaacEnc_preparePe(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + const INT nChannels, const INT peOffset) { + INT ch; + + for (ch = 0; ch < nChannels; ch++) { + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + FDKaacEnc_prepareSfbPe( + &peData->peChannelData[ch], psyOutChan->sfbEnergyLdData, + psyOutChan->sfbThresholdLdData, qcOutChannel[ch]->sfbFormFactorLdData, + psyOutChan->sfbOffsets, psyOutChan->sfbCnt, psyOutChan->sfbPerGroup, + psyOutChan->maxSfbPerGroup); + } + peData->offset = peOffset; +} + +/** + * \brief Calculate weighting factor for threshold adjustment. + * + * Calculate weighting factor to be applied at energies and thresholds in ld64 + * format. + * + * \param peData, Pointer to PE data in current element. + * \param psyOutChannel Pointer to PSY_OUT_CHANNEL struct holding + * nChannels elements. + * \param qcOutChannel Pointer to QC_OUT_CHANNEL struct holding + * nChannels elements. + * \param toolsInfo Pointer to tools info struct of current element. + * \param adjThrStateElement Pointer to ATS_ELEMENT holding enFacPatch + * states. + * \param nChannels Number of channels in element. + * \param usePatchTool Apply the weighting tool 0 (no) else (yes). + * + * \return void + */ +static void FDKaacEnc_calcWeighting( + const PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, const INT nChannels, + const INT usePatchTool) { + int ch, noShortWindowInFrame = TRUE; + INT exePatchM = 0; + + for (ch = 0; ch < nChannels; ch++) { + if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) { + noShortWindowInFrame = FALSE; + } + FDKmemclear(qcOutChannel[ch]->sfbEnFacLd, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + } + + if (usePatchTool == 0) { + return; /* tool is disabled */ + } + + for (ch = 0; ch < nChannels; ch++) { + const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch]; + + if (noShortWindowInFrame) { /* retain energy ratio between blocks of + different length */ + + FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal; + FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34; + INT usePatch, exePatch; + int sfb, sfbGrp, nLinesSum = 0; + + nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f); + + /* calculate flatness of audible spectrum, i.e. spectrum above masking + * threshold. */ + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + FIXP_DBL nrgFac12 = CalcInvLdData( + psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1); /* nrg^(1/2) */ + FIXP_DBL nrgFac14 = CalcInvLdData( + psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 2); /* nrg^(1/4) */ + + /* maximal number of bands is 64, results scaling factor 6 */ + nLinesSum += peData->peChannelData[ch] + .sfbNLines[sfbGrp + sfb]; /* relevant lines */ + nrgTotal += + (psyOutChan->sfbEnergy[sfbGrp + sfb] >> 6); /* sum up nrg */ + nrgSum12 += (nrgFac12 >> 6); /* sum up nrg^(2/4) */ + nrgSum14 += (nrgFac14 >> 6); /* sum up nrg^(1/4) */ + nrgSum34 += (fMult(nrgFac14, nrgFac12) >> 6); /* sum up nrg^(3/4) */ + } + } + + nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */ + + nrgFacLd_14 = + CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */ + nrgFacLd_12 = + CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */ + nrgFacLd_34 = + CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */ + + /* Note: nLinesSum cannot be larger than the number of total lines, thats + * taken care of in line_pe.cpp FDKaacEnc_prepareSfbPe() */ + adjThrStateElement->chaosMeasureEnFac[ch] = + fMax(FL2FXCONST_DBL(0.1875f), + fDivNorm(nLinesSum, psyOutChan->sfbOffsets[psyOutChan->sfbCnt])); + + usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.78125f)); + exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch])); + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + INT sfbExePatch; + /* for MS coupled SFBs, also execute patch in side channel if done in + * mid channel */ + if ((ch == 1) && (toolsInfo->msMask[sfbGrp + sfb])) { + sfbExePatch = exePatchM; + } else { + sfbExePatch = exePatch; + } + + if ((sfbExePatch) && + (psyOutChan->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.f))) { + /* execute patch based on spectral flatness calculated above */ + if (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.8125f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_14 + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1))) >> + 1); /* sfbEnergy^(3/4) */ + } else if (adjThrStateElement->chaosMeasureEnFac[ch] > + FL2FXCONST_DBL(0.796875f)) { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp + sfb]) >> + 1); /* sfbEnergy^(2/4) */ + } else { + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + ((nrgFacLd_34 + + (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1)) >> + 1); /* sfbEnergy^(1/4) */ + } + qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] = + fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb], (FIXP_DBL)0); + } + } + } /* sfb loop */ + + adjThrStateElement->lastEnFacPatch[ch] = usePatch; + exePatchM = exePatch; + } else { + /* !noShortWindowInFrame */ + adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f); + adjThrStateElement->lastEnFacPatch[ch] = + TRUE; /* allow use of sfbEnFac patch in upcoming frame */ + } + + } /* ch loop */ +} + +/***************************************************************************** +functionname: FDKaacEnc_calcPe +description: calculate pe for both channels +*****************************************************************************/ +static void FDKaacEnc_calcPe(const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + const QC_OUT_CHANNEL *const qcOutChannel[(2)], + PE_DATA *const peData, const INT nChannels) { + INT ch; + + peData->pe = peData->offset; + peData->constPart = 0; + peData->nActiveLines = 0; + for (ch = 0; ch < nChannels; ch++) { + PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch]; + + FDKaacEnc_calcSfbPe( + peChanData, qcOutChannel[ch]->sfbWeightedEnergyLdData, + qcOutChannel[ch]->sfbThresholdLdData, psyOutChannel[ch]->sfbCnt, + psyOutChannel[ch]->sfbPerGroup, psyOutChannel[ch]->maxSfbPerGroup, + psyOutChannel[ch]->isBook, psyOutChannel[ch]->isScale); + + peData->pe += peChanData->pe; + peData->constPart += peChanData->constPart; + peData->nActiveLines += peChanData->nActiveLines; + } +} + +void FDKaacEnc_peCalculation(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, + const INT nChannels) { + /* constants that will not change during successive pe calculations */ + FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels, + adjThrStateElement->peOffset); + + /* calculate weighting factor for threshold adjustment */ + FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo, + adjThrStateElement, nChannels, 1); + { + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + int ch; + for (ch = 0; ch < nChannels; ch++) { + int sfb, sfbGrp; + QC_OUT_CHANNEL *pQcOutCh = qcOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + pQcOutCh->sfbWeightedEnergyLdData[sfb + sfbGrp] = + pQcOutCh->sfbEnergyLdData[sfb + sfbGrp] - + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] -= + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + } + } + } + } + + /* pe without reduction */ + FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels); +} + +/***************************************************************************** +functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH +description: sum the pe data only for bands where avoid hole is inactive +*****************************************************************************/ +#define CONSTPART_HEADROOM 4 +static void FDKaacEnc_FDKaacEnc_calcPeNoAH( + INT *const pe, INT *const constPart, INT *const nActiveLines, + const PE_DATA *const peData, const UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) { + INT ch, sfb, sfbGrp; + + INT pe_tmp = peData->offset; + INT constPart_tmp = 0; + INT nActiveLines_tmp = 0; + for (ch = 0; ch < nChannels; ch++) { + const PE_CHANNEL_DATA *const peChanData = &peData->peChannelData[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + if (ahFlag[ch][sfbGrp + sfb] < AH_ACTIVE) { + pe_tmp += peChanData->sfbPe[sfbGrp + sfb]; + constPart_tmp += + peChanData->sfbConstPart[sfbGrp + sfb] >> CONSTPART_HEADROOM; + nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp + sfb]; + } + } + } + } + /* correct scaled pe and constPart values */ + *pe = pe_tmp >> PE_CONSTPART_SHIFT; + *constPart = constPart_tmp >> (PE_CONSTPART_SHIFT - CONSTPART_HEADROOM); + + *nActiveLines = nActiveLines_tmp; +} + +/***************************************************************************** +functionname: FDKaacEnc_reduceThresholdsCBR +description: apply reduction formula +*****************************************************************************/ +static const FIXP_DBL limitThrReducedLdData = + (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/ + +static void FDKaacEnc_reduceThresholdsCBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels, + const FIXP_DBL redVal_m, const SCHAR redVal_e) { + INT ch, sfb, sfbGrp; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL sfbThrExp; + + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]; + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb]; + sfbThrExp = thrExp[ch][sfbGrp + sfb]; + if ((sfbEnLdData > sfbThrLdData) && + (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) { + /* threshold reduction formula: + float tmp = thrExp[ch][sfb]+redVal; + tmp *= tmp; + sfbThrReduced = tmp*tmp; + */ + int minScale = fixMin(CountLeadingBits(sfbThrExp), + CountLeadingBits(redVal_m) - redVal_e) - + 1; + + /* 4*log( sfbThrExp + redVal ) */ + sfbThrReducedLdData = + CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) + + scaleValue(redVal_m, redVal_e + minScale))) - + (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + sfbThrReducedLdData <<= 2; + + /* avoid holes */ + if ((sfbThrReducedLdData > + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData)) && + (ahFlag[ch][sfbGrp + sfb] != NO_AH)) { + if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) { + sfbThrReducedLdData = fixMax( + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData), + sfbThrLdData); + } else + sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE; + } + + /* minimum of 29 dB Ratio for Thresholds */ + if ((sfbEnLdData + (FIXP_DBL)MAXVAL_DBL) > + FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) { + sfbThrReducedLdData = fixMax( + sfbThrReducedLdData, + (sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING))); + } + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/* similar to prepareSfbPe1() */ +static FIXP_DBL FDKaacEnc_calcChaosMeasure( + const PSY_OUT_CHANNEL *const psyOutChannel, + const FIXP_DBL *const sfbFormFactorLdData) { +#define SCALE_FORM_FAC \ + (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/ +#define SCALE_NRGS (8) +#define SCALE_NLINES (16) +#define SCALE_NRGS_SQRT4 (2) /* 0.25 * SCALE_NRGS */ +#define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */ + + INT sfbGrp, sfb; + FIXP_DBL chaosMeasure; + INT frameNLines = 0; + FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f); + FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f); + + for (sfbGrp = 0; sfbGrp < psyOutChannel->sfbCnt; + sfbGrp += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (psyOutChannel->sfbEnergyLdData[sfbGrp + sfb] > + psyOutChannel->sfbThresholdLdData[sfbGrp + sfb]) { + frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp + sfb]) >> + SCALE_FORM_FAC); + frameNLines += (psyOutChannel->sfbOffsets[sfbGrp + sfb + 1] - + psyOutChannel->sfbOffsets[sfbGrp + sfb]); + frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp + sfb] >> SCALE_NRGS); + } + } + } + + if (frameNLines > 0) { + /* frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy + *2^SCALE_NRGS)/frameNLines)^-0.25 chaosMeasure = frameNActiveLines / + frameNLines */ + chaosMeasure = CalcInvLdData( + (((CalcLdData(frameFormFactor) >> 1) - + (CalcLdData(frameEnergy) >> (2 + 1))) - + (fMultDiv2(FL2FXCONST_DBL(0.75f), + CalcLdData((FIXP_DBL)frameNLines + << (DFRACT_BITS - 1 - SCALE_NLINES))) - + (((FIXP_DBL)(-((-SCALE_FORM_FAC + SCALE_NRGS_SQRT4 - FORM_FAC_SHIFT + + SCALE_NLINES_P34) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)))) >> + 1))) + << 1); + } else { + /* assuming total chaos, if no sfb is above thresholds */ + chaosMeasure = FL2FXCONST_DBL(1.f); + } + + return chaosMeasure; +} + +/* apply reduction formula for VBR-mode */ +static void FDKaacEnc_reduceThresholdsVBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels, + const FIXP_DBL vbrQualFactor, FIXP_DBL *const chaosMeasureOld) { + INT ch, sfbGrp, sfb; + FIXP_DBL chGroupEnergy[TRANS_FAC][2]; /*energy for each group and channel*/ + FIXP_DBL chChaosMeasure[2]; + FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f); + FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f); + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp; + FIXP_DBL sfbThrReducedLdData; + FIXP_DBL chaosMeasureAvg; + INT groupCnt; /* loop counter */ + FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one + redVal for each group */ + QC_OUT_CHANNEL *qcOutChan = NULL; + const PSY_OUT_CHANNEL *psyOutChan = NULL; + +#define SCALE_GROUP_ENERGY (8) + +#define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f)) +#define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f - 0.25f)) + +#define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f)) + + for (ch = 0; ch < nChannels; ch++) { + psyOutChan = psyOutChannel[ch]; + + /* adding up energy for each channel and each group separately */ + FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f); + groupCnt = 0; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup, groupCnt++) { + chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f); + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + chGroupEnergy[groupCnt][ch] += + (psyOutChan->sfbEnergy[sfbGrp + sfb] >> SCALE_GROUP_ENERGY); + } + chEnergy += chGroupEnergy[groupCnt][ch]; + } + frameEnergy += chEnergy; + + /* chaosMeasure */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { + chChaosMeasure[ch] = FL2FXCONST_DBL( + 0.5f); /* assume a constant chaos measure of 0.5f for short blocks */ + } else { + chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure( + psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData); + } + chaosMeasure += fMult(chChaosMeasure[ch], chEnergy); + } + + if (frameEnergy > chaosMeasure) { + INT scale = CntLeadingZeros(frameEnergy) - 1; + FIXP_DBL num = chaosMeasure << scale; + FIXP_DBL denum = frameEnergy << scale; + chaosMeasure = schur_div(num, denum, 16); + } else { + chaosMeasure = FL2FXCONST_DBL(1.f); + } + + chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) + + fMult(CONST_CHAOS_MEAS_AVG_FAC_1, + *chaosMeasureOld); /* averaging chaos measure */ + *chaosMeasureOld = chaosMeasure = (fixMin( + chaosMeasure, chaosMeasureAvg)); /* use min-value, safe for next frame */ + + /* characteristic curve + chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f); + chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure)); + constants scaled by 4.f + */ + chaosMeasure = ((FL2FXCONST_DBL(0.2f) >> 2) + + fMult(FL2FXCONST_DBL(0.7f / (4.f * 0.3f)), + (chaosMeasure - FL2FXCONST_DBL(0.2f)))); + chaosMeasure = + (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f) >> 2), + fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f) >> 2), chaosMeasure))) + << 2; + + /* calculation of reduction value */ + if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { /* short-blocks */ + FDK_ASSERT(TRANS_FAC == 8); +#define WIN_TYPE_SCALE (3) + + groupCnt = 0; + for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt; + sfbGrp += psyOutChannel[0]->sfbPerGroup, groupCnt++) { + FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f); + + for (ch = 0; ch < nChannels; ch++) { + groupEnergy += + chGroupEnergy[groupCnt] + [ch]; /* adding up the channels groupEnergy */ + } + + FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt] <= INV_INT_TAB_SIZE); + groupEnergy = fMult( + groupEnergy, + invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of + group energy */ + groupEnergy = fixMin(groupEnergy, + frameEnergy >> WIN_TYPE_SCALE); /* do not allow an + higher redVal as + calculated + framewise */ + + groupEnergy >>= + 2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */ + + redVal[groupCnt] = + fMult(fMult(vbrQualFactor, chaosMeasure), + CalcInvLdData(CalcLdData(groupEnergy) >> 2)) + << (int)((2 + (2 * WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY) >> 2); + } + } else { /* long-block */ + + redVal[0] = fMult(fMult(vbrQualFactor, chaosMeasure), + CalcInvLdData(CalcLdData(frameEnergy) >> 2)) + << (int)(SCALE_GROUP_ENERGY >> 2); + } + + for (ch = 0; ch < nChannels; ch++) { + qcOutChan = qcOutChannel[ch]; + psyOutChan = psyOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]); + sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp + sfb]); + sfbThrExp = thrExp[ch][sfbGrp + sfb]; + + if ((sfbThrLdData >= MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) && + (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) { + /* Short-Window */ + if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) { + const int groupNumber = (int)sfb / psyOutChan->sfbPerGroup; + + FDK_ASSERT(INV_SQRT4_TAB_SIZE > psyOutChan->groupLen[groupNumber]); + + sfbThrExp = + fMult(sfbThrExp, + fMult(FL2FXCONST_DBL(2.82f / 4.f), + invSqrt4[psyOutChan->groupLen[groupNumber]])) + << 2; + + if (sfbThrExp <= (limitThrReducedLdData - redVal[groupNumber])) { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f); + } else { + if ((FIXP_DBL)redVal[groupNumber] >= + FL2FXCONST_DBL(1.0f) - sfbThrExp) + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + else { + /* threshold reduction formula */ + sfbThrReducedLdData = + CalcLdData(sfbThrExp + redVal[groupNumber]); + sfbThrReducedLdData <<= 2; + } + } + sfbThrReducedLdData += + (CalcLdInt(psyOutChan->groupLen[groupNumber]) - + ((FIXP_DBL)6 << (DFRACT_BITS - 1 - LD_DATA_SHIFT))); + } + + /* Long-Window */ + else { + if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f) - sfbThrExp) { + sfbThrReducedLdData = FL2FXCONST_DBL(0.0f); + } else { + /* threshold reduction formula */ + sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]); + sfbThrReducedLdData <<= 2; + } + } + + /* avoid holes */ + if (((sfbThrReducedLdData - sfbEnLdData) > + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) && + (ahFlag[ch][sfbGrp + sfb] != NO_AH)) { + if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) { + sfbThrReducedLdData = fixMax( + (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData), + sfbThrLdData); + } else + sfbThrReducedLdData = sfbThrLdData; + ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE; + } + + if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f)) + sfbThrReducedLdData = FL2FXCONST_DBL(-1.f); + + /* minimum of 29 dB Ratio for Thresholds */ + if ((sfbEnLdData + FL2FXCONST_DBL(1.0f)) > + FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) { + sfbThrReducedLdData = fixMax( + sfbThrReducedLdData, + sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)); + } + + sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData); + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } +} + +/***************************************************************************** +functionname: FDKaacEnc_correctThresh +description: if pe difference deltaPe between desired pe and real pe is small +enough, the difference can be distributed among the scale factor bands. New +thresholds can be derived from this pe-difference +*****************************************************************************/ +static void FDKaacEnc_correctThresh( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], + const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m, + const SCHAR redVal_e, const INT deltaPe, const INT processElements, + const INT elementOffset) { + INT ch, sfb, sfbGrp; + QC_OUT_CHANNEL *qcOutChan; + PSY_OUT_CHANNEL *psyOutChan; + PE_CHANNEL_DATA *peChanData; + FIXP_DBL thrFactorLdData; + FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData; + FIXP_DBL *sfbPeFactorsLdData[((8))][(2)]; + FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB]; + + INT normFactorInt; + FIXP_DBL normFactorLdData; + + INT nElements = elementOffset + processElements; + INT elementId; + + /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + /* The reinterpret_cast is used to suppress a compiler warning. We know + * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently + * aligned, so the cast is safe */ + sfbPeFactorsLdData[elementId][ch] = + reinterpret_cast(reinterpret_cast( + qcElement[elementId]->qcOutChannel[ch]->quantSpec)); + } + } + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the + * cast is safe */ + sfbNActiveLinesLdData = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_SfbNActiveLinesLdData)); + + /* for each sfb calc relative factors for pe changes */ + normFactorInt = 0; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) { + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(-1.0f); + } else { + /* Both CalcLdInt and CalcLdData can be used! + * No offset has to be subtracted, because sfbNActiveLinesLdData + * is shorted while thrFactor calculation */ + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] = + CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]); + } + if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) || + (deltaPe > 0)) && + peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) { + if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) { + /* sfbPeFactors[ch][sfbGrp+sfb] = + peChanData->sfbNActiveLines[sfbGrp+sfb] / + (thrExp[elementId][ch][sfbGrp+sfb] + + redVal[elementId]); */ + + int minScale = + fixMin( + CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]), + CountLeadingBits(redVal_m) - redVal_e) - + 1; + + /* sumld = ld64( sfbThrExp + redVal ) */ + FIXP_DBL sumLd = + CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb], + minScale) + + scaleValue(redVal_m, redVal_e + minScale)) - + (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + if (sumLd < FL2FXCONST_DBL(0.f)) { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + sumLd; + } else { + if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] > + (FL2FXCONST_DBL(-1.f) + sumLd)) { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + sumLd; + } else { + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb]; + } + } + + normFactorInt += (INT)CalcInvLdData( + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]); + } else + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(1.0f); + } else + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] = + FL2FXCONST_DBL(-1.0f); + } + } + } + } + } + + /* normFactorLdData = ld64(deltaPe/normFactorInt) */ + normFactorLdData = + CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) - + CalcLdData((FIXP_DBL)normFactorInt); + + /* distribute the pe difference to the scalefactors + and calculate the according thresholds */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + psyOutChan = psyOutElement[elementId]->psyOutChannel[ch]; + peChanData = &qcElement[elementId]->peData.peChannelData[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; + sfbGrp += psyOutChan->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) { + if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) { + /* pe difference for this sfb */ + if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] == + FL2FXCONST_DBL(-1.0f)) || + (deltaPe == 0)) { + thrFactorLdData = FL2FXCONST_DBL(0.f); + } else { + /* new threshold */ + FIXP_DBL tmp = CalcInvLdData( + sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] + + normFactorLdData - + sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] - + FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING)); + + /* limit thrFactor to 60dB */ + tmp = (deltaPe < 0) ? tmp : (-tmp); + thrFactorLdData = + fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING)); + } + + /* new threshold */ + sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb]; + sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]; + + if (thrFactorLdData < FL2FXCONST_DBL(0.f)) { + if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) { + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } else { + sfbThrReducedLdData = FL2FXCONST_DBL(-1.f); + } + } else { + sfbThrReducedLdData = sfbThrLdData + thrFactorLdData; + } + + /* avoid hole */ + if ((sfbThrReducedLdData - sfbEnLdData > + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) && + (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) { + /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, + * sfbThr); */ + if (sfbEnLdData > + (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) { + sfbThrReducedLdData = + qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData; + } else { + sfbThrReducedLdData = sfbThrLdData; + } + ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE; + } + + qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData; + } + } + } + } + } + } +} + +/***************************************************************************** + functionname: FDKaacEnc_reduceMinSnr + description: if the desired pe can not be reached, reduce pe by + reducing minSnr +*****************************************************************************/ +static void FDKaacEnc_reduceMinSnr( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe, + INT *const redPeGlobal, const INT processElements, const INT elementOffset) + +{ + INT ch, elementId, globalMaxSfb = 0; + const INT nElements = elementOffset + processElements; + INT newGlobalPe = *redPeGlobal; + + if (newGlobalPe <= desiredPe) { + goto bail; + } + + /* global maximum of maxSfbPerGroup */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + globalMaxSfb = + fMax(globalMaxSfb, + psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup); + } + } + } + + /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at + * highest SFB */ + while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) { + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + PE_DATA *peData = &qcElement[elementId]->peData; + + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch]; + PSY_OUT_CHANNEL *psyOutChan = + psyOutElement[elementId]->psyOutChannel[ch]; + + /* try to reduce SNR of channel's uppermost SFB(s) */ + if (globalMaxSfb < psyOutChan->maxSfbPerGroup) { + INT sfb, deltaPe = 0; + + for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt; + sfb += psyOutChan->sfbPerGroup) { + if (ahFlag[elementId][ch][sfb] != NO_AH && + qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac && + (qcOutChan->sfbWeightedEnergyLdData[sfb] > + qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) { + /* increase threshold to new minSnr of 1dB */ + qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac; + qcOutChan->sfbThresholdLdData[sfb] = + qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac; + + /* calc new pe */ + /* C2 + C3*ld(1/0.8) = 1.5 */ + deltaPe -= peData->peChannelData[ch].sfbPe[sfb]; + + /* sfbPe = 1.5 * sfbNLines */ + peData->peChannelData[ch].sfbPe[sfb] = + (3 * peData->peChannelData[ch].sfbNLines[sfb]) + << (PE_CONSTPART_SHIFT - 1); + deltaPe += peData->peChannelData[ch].sfbPe[sfb]; + } + + } /* sfb loop */ + + deltaPe >>= PE_CONSTPART_SHIFT; + peData->pe += deltaPe; + peData->peChannelData[ch].pe += deltaPe; + newGlobalPe += deltaPe; + + } /* if globalMaxSfb < maxSfbPerGroup */ + + /* stop if enough has been saved */ + if (newGlobalPe <= desiredPe) { + goto bail; + } + + } /* ch loop */ + } /* != ID_DSE */ + } /* elementId loop */ + } /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */ + +bail: + /* update global PE */ + *redPeGlobal = newGlobalPe; +} + +/***************************************************************************** + functionname: FDKaacEnc_allowMoreHoles + description: if the desired pe can not be reached, some more scalefactor + bands have to be quantized to zero +*****************************************************************************/ +static void FDKaacEnc_allowMoreHoles( + const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const ATS_ELEMENT *const AdjThrStateElement[((8))], + UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe, + const INT currentPe, const int processElements, const int elementOffset) { + INT elementId; + INT nElements = elementOffset + processElements; + INT actPe = currentPe; + + if (actPe <= desiredPe) { + return; /* nothing to do */ + } + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT ch, sfb, sfbGrp; + + PE_DATA *peData = &qcElement[elementId]->peData; + const INT nChannels = cm->elInfo[elementId].nChannelsInEl; + + QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL}; + PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL}; + + for (ch = 0; ch < nChannels; ch++) { + /* init pointers */ + qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch]; + psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch]; + + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = psyOutChannel[ch]->maxSfbPerGroup; + sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) { + peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0; + } + } + } + + /* for MS allow hole in the channel with less energy */ + if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence == + psyOutChannel[1]->lastWindowSequence) { + for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt; + sfbGrp += psyOutChannel[0]->sfbPerGroup) { + if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) { + FIXP_DBL EnergyLd_L = + qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb]; + FIXP_DBL EnergyLd_R = + qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb]; + + /* allow hole in side channel ? */ + if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f) >> 1) + + (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) > + ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) { + ahFlag[elementId][1][sfbGrp + sfb] = NO_AH; + qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + EnergyLd_R; + actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } + /* allow hole in mid channel ? */ + else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) && + (((FL2FXCONST_DBL(-0.02065512648f) >> 1) + + (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >> + 1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) { + ahFlag[elementId][0][sfbGrp + sfb] = NO_AH; + qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + EnergyLd_L; + actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } /* if (ahFlag) */ + } /* if MS */ + } /* sfbGrp */ + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfb */ + } /* MS possible ? */ + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + if (actPe > desiredPe) { + /* more holes necessary? subsequently erase bands starting with low energies + */ + INT ch, sfb, sfbGrp; + INT minSfb, maxSfb; + INT enIdx, ahCnt, done; + INT startSfb[(8)]; + INT sfbCnt[(8)]; + INT sfbPerGroup[(8)]; + INT maxSfbPerGroup[(8)]; + FIXP_DBL avgEn; + FIXP_DBL minEnLD64; + FIXP_DBL avgEnLD64; + FIXP_DBL enLD64[NUM_NRG_LEVS]; + INT avgEn_e; + + /* get the scaling factor over all audio elements and channels */ + maxSfb = 0; + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + for (sfbGrp = 0; + sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt; + sfbGrp += + psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) { + maxSfb += + psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup; + } + } + } + } + avgEn_e = + (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */ + + ahCnt = 0; + maxSfb = 0; + minSfb = MAX_SFB; + avgEn = FL2FXCONST_DBL(0.0f); + minEnLD64 = FL2FXCONST_DBL(0.0f); + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch]; + QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch]; + PSY_OUT_CHANNEL *psyOutChannel = + psyOutElement[elementId]->psyOutChannel[ch]; + + maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup; + sfbCnt[chIdx] = psyOutChannel->sfbCnt; + sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup; + + maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup); + + if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) { + startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL; + } else { + startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS; + } + + minSfb = fMin(minSfb, startSfb[chIdx]); + + sfbGrp = 0; + sfb = startSfb[chIdx]; + + do { + for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) && + (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] > + qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) { + minEnLD64 = fixMin(minEnLD64, + qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]); + avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e; + ahCnt++; + } + } + + sfbGrp += psyOutChannel->sfbPerGroup; + sfb = startSfb[chIdx]; + + } while (sfbGrp < psyOutChannel->sfbCnt); + } + } /* (cm->elInfo[elementId].elType != ID_DSE) */ + } /* (elementId = elementOffset;elementIdelInfo[elementId].elType != ID_DSE) { + PE_DATA *peData = &qcElement[elementId]->peData; + for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) { + const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch]; + QC_OUT_CHANNEL *qcOutChannel = + qcElement[elementId]->qcOutChannel[ch]; + if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) { + for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx]; + sfbGrp += sfbPerGroup[chIdx]) { + /* sfb energy below border ? */ + if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH && + qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] < + enLD64[enIdx]) { + /* allow hole */ + ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH; + qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] = + FL2FXCONST_DBL(0.015625f) + + qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb]; + actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >> + PE_CONSTPART_SHIFT; + } + if (actPe <= desiredPe) { + return; /* stop if enough has been saved */ + } + } /* sfbGrp */ + } /* sfb */ + } /* nChannelsInEl */ + } /* ID_DSE */ + } /* elementID */ + + sfb--; + if (sfb < minSfb) { + /* restart with next energy border */ + sfb = maxSfb; + enIdx++; + if (enIdx >= NUM_NRG_LEVS) { + done = 1; + } + } + } /* done */ + } /* (actPe <= desiredPe) */ +} + +/* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE */ +static void FDKaacEnc_resetAHFlags( + UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) { + int ch, sfb, sfbGrp; + + for (ch = 0; ch < nChannels; ch++) { + for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) { + if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) { + ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE; + } + } + } + } +} + +static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) { + FIXP_DBL value = FL2FXCONST_DBL(0.f); + + if (num >= FL2FXCONST_DBL(0.f)) { + value = fDivNorm(num, denum, scaling); + } else { + value = -fDivNorm(-num, denum, scaling); + } + value = f2Pow(value, *scaling, scaling); + + return value; +} + +/***************************************************************************** +functionname: FDKaacEnc_adaptThresholdsToPe +description: two guesses for the reduction value and one final correction of +the thresholds +*****************************************************************************/ +static void FDKaacEnc_adaptThresholdsToPe( + const CHANNEL_MAPPING *const cm, + ATS_ELEMENT *const AdjThrStateElement[((8))], + QC_OUT_ELEMENT *const qcElement[((8))], + const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe, + const INT maxIter2ndGuess, const INT processElements, + const INT elementOffset) { + FIXP_DBL reductionValue_m; + SCHAR reductionValue_e; + UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB]; + FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB]; + int iter; + + INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal; + constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0; + + int elementId; + + int nElements = elementOffset + processElements; + if (nElements > cm->nElements) { + nElements = cm->nElements; + } + + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe + */ + pAhFlag = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_Ah_Flag)); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe + */ + pThrExp = reinterpret_cast( + reinterpret_cast(qcElement[0]->dynMem_Thr_Exp)); + + /* ------------------------------------------------------- */ + /* Part I: Initialize data structures and variables... */ + /* ------------------------------------------------------- */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp( + pThrExp[elementId], qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, + &AdjThrStateElement[elementId]->minSnrAdaptParam, + nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + &psyOutElement[elementId]->toolsInfo, nChannels, + &AdjThrStateElement[elementId]->ahParam); + + /* sum up */ + constPartGlobal += peData->constPart; + noRedPeGlobal += peData->pe; + nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1); + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* + First guess of reduction value: + avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f * + nActiveLinesGlobal)); redVal = (float)pow(2.0f, (constPartGlobal - + desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal = max(0.f, + redVal); + */ + int redVal_e, avgThrExp_e, result_e; + FIXP_DBL redVal_m, avgThrExp_m; + + redVal_m = CalcRedValPower(constPartGlobal - desiredPe, + 4 * nActiveLinesGlobal, &redVal_e); + avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal, + 4 * nActiveLinesGlobal, &avgThrExp_e); + result_e = fMax(redVal_e, avgThrExp_e) + 1; + + reductionValue_m = fMax(FL2FXCONST_DBL(0.f), + scaleValue(redVal_m, redVal_e - result_e) - + scaleValue(avgThrExp_m, avgThrExp_e - result_e)); + reductionValue_e = result_e; + + /* ----------------------------------------------------------------------- */ + /* Part II: Calculate bit consumption of initial bit constraints setup */ + /* ----------------------------------------------------------------------- */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e); + + /* pe after first guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + + redPeGlobal += peData->pe; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* -------------------------------------------------- */ + /* Part III: Iterate until bit constraints are met */ + /* -------------------------------------------------- */ + iter = 0; + while ((fixp_abs(redPeGlobal - desiredPe) > + fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) && + (iter < maxIter2ndGuess)) { + INT desiredPeNoAHGlobal; + INT redPeNoAHGlobal = 0; + INT constPartNoAHGlobal = 0; + INT nActiveLinesNoAHGlobal = 0; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT redPeNoAH, constPartNoAH, nActiveLinesNoAH; + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe for bands where avoid hole is inactive */ + FDKaacEnc_FDKaacEnc_calcPeNoAH( + &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData, + pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel, + nChannels); + + redPeNoAHGlobal += redPeNoAH; + constPartNoAHGlobal += constPartNoAH; + nActiveLinesNoAHGlobal += nActiveLinesNoAH; + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + /* Calculate new redVal ... */ + if (desiredPe < redPeGlobal) { + /* new desired pe without bands where avoid hole is active */ + desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal); + + /* limit desiredPeNoAH to positive values, as the PE can not become + * negative */ + desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal); + + /* second guess (only if there are bands left where avoid hole is + * inactive)*/ + if (nActiveLinesNoAHGlobal > 0) { + /* + avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) / + (4.0f * nActiveLinesNoAHGlobal)); redVal += (float)pow(2.0f, + (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f * + nActiveLinesNoAHGlobal)) - avgThrExp; redVal = max(0.0f, redVal); + */ + + redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal, + 4 * nActiveLinesNoAHGlobal, &redVal_e); + avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal, + 4 * nActiveLinesNoAHGlobal, &avgThrExp_e); + result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1; + + reductionValue_m = + fMax(FL2FXCONST_DBL(0.f), + scaleValue(reductionValue_m, reductionValue_e - result_e) + + scaleValue(redVal_m, redVal_e - result_e) - + scaleValue(avgThrExp_m, avgThrExp_e - result_e)); + reductionValue_e = result_e; + + } /* nActiveLinesNoAHGlobal > 0 */ + } else { + /* redVal *= redPeGlobal/desiredPe; */ + int sc0, sc1; + reductionValue_m = fMultNorm( + reductionValue_m, + fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1); + reductionValue_e += sc0 + sc1; + + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + FDKaacEnc_resetAHFlags(pAhFlag[elementId], + cm->elInfo[elementId].nChannelsInEl, + psyOutElement[elementId]->psyOutChannel); + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + redPeGlobal = 0; + /* Calculate new redVal's PE... */ + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsCBR( + qcElement[elementId]->qcOutChannel, + psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], + pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e); + + /* pe after second guess */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + + iter++; + } /* EOF while */ + + /* ------------------------------------------------------- */ + /* Part IV: if still required, further reduce constraints */ + /* ------------------------------------------------------- */ + /* 1.0* 1.15* 1.20* + * desiredPe desiredPe desiredPe + * | | | + * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX| | + * | | |XXXXXXXXXXX... + * | |XXXXXXXXXXX| + * --- A --- | --- B --- | --- C --- + * + * (X): redPeGlobal + * (A): FDKaacEnc_correctThresh() + * (B): FDKaacEnc_allowMoreHoles() + * (C): FDKaacEnc_reduceMinSnr() + */ + + /* correct thresholds to get closer to the desired pe */ + if (redPeGlobal > desiredPe) { + FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp, + reductionValue_m, reductionValue_e, + desiredPe - redPeGlobal, processElements, + elementOffset); + + /* update PE */ + redPeGlobal = 0; + for (elementId = elementOffset; elementId < nElements; elementId++) { + if (cm->elInfo[elementId].elType != ID_DSE) { + INT nChannels = cm->elInfo[elementId].nChannelsInEl; + PE_DATA *peData = &qcElement[elementId]->peData; + + /* pe after correctThresh */ + FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, + qcElement[elementId]->qcOutChannel, peData, nChannels); + redPeGlobal += peData->pe; + + } /* EOF DSE-suppression */ + } /* EOF for all elements... */ + } + + if (redPeGlobal > desiredPe) { + /* reduce pe by reducing minSnr requirements */ + FDKaacEnc_reduceMinSnr( + cm, qcElement, psyOutElement, pAhFlag, + (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal, + processElements, elementOffset); + + /* reduce pe by allowing additional spectral holes */ + FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement, + pAhFlag, desiredPe, redPeGlobal, processElements, + elementOffset); + } +} + +/* similar to FDKaacEnc_adaptThresholdsToPe(), for VBR-mode */ +static void FDKaacEnc_AdaptThresholdsVBR( + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + ATS_ELEMENT *const AdjThrStateElement, + const struct TOOLSINFO *const toolsInfo, const INT nChannels) { + UCHAR(*pAhFlag)[MAX_GROUPED_SFB]; + FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB]; + + /* allocate scratch memory */ + C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB) + pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag; + pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp; + + /* thresholds to the power of redExp */ + FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels); + + /* lower the minSnr requirements for low energies compared to the average + energy in this frame */ + FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel, + &AdjThrStateElement->minSnrAdaptParam, nChannels); + + /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */ + FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo, + nChannels, &AdjThrStateElement->ahParam); + + /* reduce thresholds */ + FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp, + nChannels, AdjThrStateElement->vbrQualFactor, + &AdjThrStateElement->chaosMeasureOld); + + /* free scratch memory */ + C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB) + C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB) +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSave + description: Calculates percentage of bit save, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit save + +*****************************************************************************/ +/* + bitsave + maxBitSave(%)| clipLow + |---\ + | \ + | \ + | \ + | \ + |--------\--------------> bitres + | \ + minBitSave(%)| \------------ + clipHigh maxBitres +*/ +static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSave, + const FIXP_DBL maxBitSave, + const FIXP_DBL bitsave_slope) { + FIXP_DBL bitsave; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope); + + return (bitsave); +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcBitSpend + description: Calculates percentage of bit spend, see figure below + returns: + input: parameters and bitres-fullness + output: percentage of bit spend + +*****************************************************************************/ +/* + bitspend clipHigh + maxBitSpend(%)| /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> bitres + | / + minBitSpend(%)|--/ + clipLow +*/ +static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel, + const FIXP_DBL clipLow, + const FIXP_DBL clipHigh, + const FIXP_DBL minBitSpend, + const FIXP_DBL maxBitSpend, + const FIXP_DBL bitspend_slope) { + FIXP_DBL bitspend; + + fillLevel = fixMax(fillLevel, clipLow); + fillLevel = fixMin(fillLevel, clipHigh); + + bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope); + + return (bitspend); +} + +/***************************************************************************** + + functionname: FDKaacEnc_adjustPeMinMax() + description: adjusts peMin and peMax parameters over time + returns: + input: current pe, peMin, peMax, bitres size + output: adjusted peMin/peMax + +*****************************************************************************/ +static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) { + FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL, + minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f); + INT diff; + + INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe); + + if (currPe > *peMax) { + diff = (currPe - *peMax); + *peMin += fMultI(minFacHi, diff); + *peMax += fMultI(maxFacHi, diff); + } else if (currPe < *peMin) { + diff = (*peMin - currPe); + *peMin -= fMultI(minFacLo, diff); + *peMax -= fMultI(maxFacLo, diff); + } else { + *peMin += fMultI(minFacHi, (currPe - *peMin)); + *peMax -= fMultI(maxFacLo, (*peMax - currPe)); + } + + if ((*peMax - *peMin) < minDiff_fix) { + INT peMax_fix = *peMax, peMin_fix = *peMin; + FIXP_DBL partLo_fix, partHi_fix; + + partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix); + partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe); + + peMax_fix = + (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)), + minDiff_fix)); + peMin_fix = + (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)), + minDiff_fix)); + peMin_fix = fixMax(0, peMin_fix); + + *peMax = peMax_fix; + *peMin = peMin_fix; + } +} + +/***************************************************************************** + + functionname: BitresCalcBitFac + description: calculates factor of spending bits for one frame + 1.0 : take all frame dynpart bits + >1.0 : take all frame dynpart bits + bitres + <1.0 : put bits in bitreservoir + returns: BitFac + input: bitres-fullness, pe, blockType, parameter-settings + output: + +*****************************************************************************/ +/* + bitfac(%) pemax + bitspend(%) | /-----------maxBitres + | / + | / + | / + | / + | / + |----/-----------------> pe + | / + bitsave(%) |--/ + pemin +*/ + +void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits, + const INT pe, const INT lastWindowSequence, + const INT avgBits, const FIXP_DBL maxBitFac, + const ADJ_THR_STATE *const AdjThr, + ATS_ELEMENT *const adjThrChan, + FIXP_DBL *const pBitresFac, + INT *const pBitresFac_e) { + const BRES_PARAM *bresParam; + INT pex; + FIXP_DBL fillLevel; + INT fillLevel_e = 0; + + FIXP_DBL bitresFac; + INT bitresFac_e; + + FIXP_DBL bitSave, bitSpend; + FIXP_DBL bitsave_slope, bitspend_slope; + FIXP_DBL fillLevel_fix = MAXVAL_DBL; + + FIXP_DBL slope = MAXVAL_DBL; + + if (lastWindowSequence != SHORT_WINDOW) { + bresParam = &(AdjThr->bresParamLong); + bitsave_slope = FL2FXCONST_DBL(0.466666666); + bitspend_slope = FL2FXCONST_DBL(0.666666666); + } else { + bresParam = &(AdjThr->bresParamShort); + bitsave_slope = (FIXP_DBL)0x2E8BA2E9; + bitspend_slope = (FIXP_DBL)0x7fffffff; + } + + // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits); + if (bitresBits < maxBitresBits) { + fillLevel_fix = fDivNorm(bitresBits, maxBitresBits); + } + + pex = fMax(pe, adjThrChan->peMin); + pex = fMin(pex, adjThrChan->peMax); + + bitSave = FDKaacEnc_calcBitSave( + fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh, + bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope); + + bitSpend = FDKaacEnc_calcBitSpend( + fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh, + bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope); + + slope = schur_div((pex - adjThrChan->peMin), + (adjThrChan->peMax - adjThrChan->peMin), 31); + + /* scale down by 1 bit because the result of the following addition can be + * bigger than 1 (though smaller than 2) */ + bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1)); + bitresFac_e = 1; /* exp=1 */ + bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */ + + /*** limit bitresFac for small bitreservoir ***/ + fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e); + if (fillLevel_e < 0) { + fillLevel = scaleValue(fillLevel, fillLevel_e); + fillLevel_e = 0; + } + /* shift down value by 1 because of summation, ... */ + fillLevel >>= 1; + fillLevel_e += 1; + /* ..., this summation: */ + fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e); + /* set bitresfactor to same exponent as fillLevel */ + if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) { + bitresFac = fillLevel; + bitresFac_e = fillLevel_e; + } + + /* limit bitresFac for high bitrates */ + if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) { + bitresFac = maxBitFac; + bitresFac_e = (DFRACT_BITS - 1 - 24); + } + + FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax); + + /* output values */ + *pBitresFac = bitresFac; + *pBitresFac_e = bitresFac_e; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrNew +description: allocate ADJ_THR_STATE +*****************************************************************************/ +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) { + INT err = 0; + INT i; + ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold(); + if (hAdjThr == NULL) { + err = 1; + goto bail; + } + + for (i = 0; i < nElements; i++) { + hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i); + if (hAdjThr->adjThrStateElem[i] == NULL) { + err = 1; + goto bail; + } + } + +bail: + *phAdjThr = hAdjThr; + return err; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrInit +description: initialize ADJ_THR_STATE +*****************************************************************************/ +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant, + const CHANNEL_MAPPING *const channelMapping, const INT sampleRate, + const INT totalBitrate, const INT isLowDelay, + const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable, + const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) { + INT i; + + FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f); + FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f); + + if (bitDistributionMode == 1) { + hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT; + } else { + hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT; + } + + /* Max number of iterations in second guess is 3 for lowdelay aot and for + configurations with multiple audio elements in general, otherwise iteration + value is always 1. */ + hAdjThr->maxIter2ndGuess = + (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1; + + /* common for all elements: */ + /* parameters for bitres control */ + hAdjThr->bresParamLong.clipSaveLow = + (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSaveHigh = + (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSave = + (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamLong.maxBitSave = + (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */ + hAdjThr->bresParamLong.clipSpendLow = + (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamLong.clipSpendHigh = + (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */ + hAdjThr->bresParamLong.minBitSpend = + (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */ + hAdjThr->bresParamLong.maxBitSpend = + (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */ + + hAdjThr->bresParamShort.clipSaveLow = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSaveHigh = + (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSave = + (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */ + hAdjThr->bresParamShort.maxBitSave = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendLow = + (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */ + hAdjThr->bresParamShort.clipSpendHigh = + (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */ + hAdjThr->bresParamShort.minBitSpend = + (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */ + hAdjThr->bresParamShort.maxBitSpend = + (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */ + + /* specific for each element: */ + for (i = 0; i < channelMapping->nElements; i++) { + const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits; + const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl; + const INT bitrateInElement = + (relativeBits != (FIXP_DBL)MAXVAL_DBL) + ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate) + : totalBitrate; + const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1); + + ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i]; + MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam; + + /* parameters for bitres control */ + if (isLowDelay) { + atsElem->peMin = fMultI(POINT8, meanPe); + atsElem->peMax = fMultI(POINT6, meanPe) << 1; + } else { + atsElem->peMin = fMultI(POINT8, meanPe) >> 1; + atsElem->peMax = fMultI(POINT6, meanPe); + } + + /* for use in FDKaacEnc_reduceThresholdsVBR */ + atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f); + + /* additional pe offset to correct pe2bits for low bitrates */ + /* ---- no longer necessary, set by table ----- */ + atsElem->peOffset = 0; + + /* vbr initialisation */ + atsElem->vbrQualFactor = vbrQualFactor; + if (chBitrate < 32000) { + atsElem->peOffset = + fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate)); + } + + /* avoid hole parameters */ + if (chBitrate >= 20000) { + atsElem->ahParam.modifyMinSnr = TRUE; + atsElem->ahParam.startSfbL = 15; + atsElem->ahParam.startSfbS = 3; + } else { + atsElem->ahParam.modifyMinSnr = FALSE; + atsElem->ahParam.startSfbL = 0; + atsElem->ahParam.startSfbS = 0; + } + + /* minSnr adaptation */ + msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */ + /* start adaptation of minSnr for avgEn/sfbEn > startRatio */ + msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */ + /* maximum minSnr reduction to minSnr^maxRed is reached for + avgEn/sfbEn >= maxRatio */ + /* msaParam->maxRatio = 1000.0f; */ + /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / + * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/ + msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */ + /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * + * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/ + msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */ + + /* init pe correction */ + atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */ + atsElem->peCorrectionFactor_e = 1; + + atsElem->dynBitsLast = -1; + atsElem->peLast = 0; + + /* init bits to pe factor */ + + /* init bits2PeFactor */ + FDKaacEnc_InitBits2PeFactor( + &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement, + nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant); + + } /* for nElements */ +} + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection + description: calc desired pe +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_calcPeCorrection( + FIXP_DBL *const correctionFac_m, INT *const correctionFac_e, + const INT peAct, const INT peLast, const INT bitsLast, + const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) { + if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) && + (FDKaacEnc_bits2pe2(bitsLast, + fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m), + bits2PeFactor_e + 1) > peLast) && + (FDKaacEnc_bits2pe2(bitsLast, + fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m), + bits2PeFactor_e) < peLast)) { + FIXP_DBL corrFac = *correctionFac_m; + + int scaling = 0; + FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, + bits2PeFactor_e); + FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling); + + /* dead zone, newFac and corrFac are scaled by 0.5 */ + if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */ + newFac = fixMax( + scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac), + scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)), + scaling), + FL2FXCONST_DBL(0.85f / 2.f)); + } else { /* ratio < 1.f */ + newFac = fixMax( + fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling), + FL2FXCONST_DBL(1.15f / 2.f)), + FL2FXCONST_DBL(1.f / 2.f)); + } + + if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) && + (corrFac < FL2FXCONST_DBL(1.f / 2.f))) || + ((newFac < FL2FXCONST_DBL(1.f / 2.f)) && + (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) { + corrFac = FL2FXCONST_DBL(1.f / 2.f); + } + + /* faster adaptation towards 1.0, slower in the other direction */ + if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) || + (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) { + corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) + + fMult(FL2FXCONST_DBL(0.15f), newFac); + } else { + corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) + + fMult(FL2FXCONST_DBL(0.3f), newFac); + } + + corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)), + FL2FXCONST_DBL(0.85 / 2.f)); + + *correctionFac_m = corrFac; + *correctionFac_e = 1; + } else { + *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f); + *correctionFac_e = 1; + } +} + +static void FDKaacEnc_calcPeCorrectionLowBitRes( + FIXP_DBL *const correctionFac_m, INT *const correctionFac_e, + const INT peLast, const INT bitsLast, const INT bitresLevel, + const INT nChannels, const FIXP_DBL bits2PeFactor_m, + const INT bits2PeFactor_e) { + /* tuning params */ + const FIXP_DBL amp = FL2FXCONST_DBL(0.005); + const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f); + + if (bitsLast > 0) { + /* Estimate deviation of granted and used dynamic bits in previous frame, in + * PE units */ + const int bitsBalLast = + peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e); + + /* reserve n bits per channel */ + int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels); + + /* in PE units */ + headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e); + + /* + * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom) + * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2 + */ + FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2( + bitresLevel, bits2PeFactor_m, bits2PeFactor_e) + + (FIXP_DBL)headroom; + + int scaling = 0; + FIXP_DBL diff = + (bitsBalLast >= headroom) + ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom), + denominator, &scaling)) + : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom), + denominator, &scaling)); + + scaling -= 1; /* divide by 2 */ + + diff = (scaling <= 0) + ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1) + : fMax(fMin(diff, maxDiff >> (1 + scaling)), + -maxDiff >> (1 + scaling)) + << scaling; + + /* + * corrFac += diff + * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) ) + */ + *correctionFac_m = + fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)), + FL2FXCONST_DBL(0.75f / 2.f)); + *correctionFac_e = 1; + } else { + *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f); + *correctionFac_e = 1; + } +} + +void FDKaacEnc_DistributeBits( + ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe, + INT *grantedPeCorr, const INT nChannels, const INT commonWindow, + const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits, + const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) { + FIXP_DBL bitFactor; + INT bitFactor_e; + INT noRedPe = peData->pe; + + /* prefer short windows for calculation of bitFactor */ + INT curWindowSequence = LONG_WINDOW; + if (nChannels == 2) { + if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) || + (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) { + curWindowSequence = SHORT_WINDOW; + } + } else { + curWindowSequence = psyOutChannel[0]->lastWindowSequence; + } + + if (grantedDynBits >= 1) { + if (bitResMode != AACENC_BR_MODE_FULL) { + /* small or disabled bitreservoir */ + *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + } else { + /* factor dependend on current fill level and pe */ + FDKaacEnc_bitresCalcBitFac( + bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits, + maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e); + + /* desired pe for actual frame */ + /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */ + *grantedPe = FDKaacEnc_bits2pe2( + grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m), + AdjThrStateElement->bits2PeFactor_e + bitFactor_e); + } + } else { + *grantedPe = 0; /* prevent divsion by 0 */ + } + + /* correction of pe value */ + switch (bitResMode) { + case AACENC_BR_MODE_DISABLED: + case AACENC_BR_MODE_REDUCED: + /* correction of pe value for low bitres */ + FDKaacEnc_calcPeCorrectionLowBitRes( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, bitresBits, nChannels, + AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + break; + case AACENC_BR_MODE_FULL: + default: + /* correction of pe value for high bitres */ + FDKaacEnc_FDKaacEnc_calcPeCorrection( + &AdjThrStateElement->peCorrectionFactor_m, + &AdjThrStateElement->peCorrectionFactor_e, + fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast, + AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m, + AdjThrStateElement->bits2PeFactor_e); + break; + } + + *grantedPeCorr = + (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS), + AdjThrStateElement->peCorrectionFactor_m) >> + (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e)); + + /* update last pe */ + AdjThrStateElement->peLast = *grantedPe; + AdjThrStateElement->dynBitsLast = -1; +} + +/***************************************************************************** +functionname: FDKaacEnc_AdjustThresholds +description: adjust thresholds +*****************************************************************************/ +void FDKaacEnc_AdjustThresholds( + ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))], + QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) { + int i; + + if (CBRbitrateMode) { + /* In case, no bits must be shifted between different elements, */ + /* an element-wise execution of the pe-dependent threshold- */ + /* adaption becomes necessary... */ + if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging + */ + // if (totalGrantedPeCorr < totalNoRedPe) { + if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) { + /* calc threshold necessary for desired pe */ + FDKaacEnc_adaptThresholdsToPe( + cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement, + qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess, + 1, /* Process only 1 element */ + i /* Process exactly THIS element */ + ); + } + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + } /* -end- element loop */ + } /* AACENC_BD_MODE_INTRA_ELEMENT */ + else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) { + /* Use global Pe to obtain the thresholds? */ + if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) { + /* add equal loadness quantization noise to match the */ + /* desired pe calc threshold necessary for desired pe */ + /* Now carried out globally to cover all(!) channels. */ + FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement, + psyOutElement, qcOut->totalGrantedPeCorr, + hAdjThr->maxIter2ndGuess, + cm->nElements, /* Process all elements */ + 0); /* Process exactly THIS element */ + } else { + /* In case global pe doesn't need to be reduced check each element to + hold estimated bitrate below maximum element bitrate. */ + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + /* Element pe applies to dynamic bits of maximum element bitrate. */ + const int maxElementPe = FDKaacEnc_bits2pe2( + (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) - + qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed, + hAdjThr->adjThrStateElem[i]->bits2PeFactor_m, + hAdjThr->adjThrStateElem[i]->bits2PeFactor_e); + + if (maxElementPe < qcElement[i]->peData.pe) { + FDKaacEnc_adaptThresholdsToPe( + cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement, + maxElementPe, hAdjThr->maxIter2ndGuess, 1, i); + } + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + } /* -end- element loop */ + } /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */ + } /* AACENC_BD_MODE_INTER_ELEMENT */ + } else { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for VBR-mode */ + FDKaacEnc_AdaptThresholdsVBR( + qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel, + hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo, + cm->elInfo[i].nChannelsInEl); + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + } + for (i = 0; i < cm->nElements; i++) { + int ch, sfb, sfbGrp; + /* no weighting of threholds and energies for mlout */ + /* weight energies and thresholds */ + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch]; + for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; + sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) { + for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup; + sfb++) { + pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] += + pQcOutCh->sfbEnFacLd[sfb + sfbGrp]; + } + } + } + } +} + +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) { + INT i; + ADJ_THR_STATE *hAdjThr = *phAdjThr; + + if (hAdjThr != NULL) { + for (i = 0; i < ((8)); i++) { + if (hAdjThr->adjThrStateElem[i] != NULL) { + FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]); + } + } + FreeRam_aacEnc_AdjustThreshold(phAdjThr); + } +} diff --git a/fdk-aac/libAACenc/src/adj_thr.h b/fdk-aac/libAACenc/src/adj_thr.h new file mode 100644 index 0000000..1f5f998 --- /dev/null +++ b/fdk-aac/libAACenc/src/adj_thr.h @@ -0,0 +1,166 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Threshold compensation + +*******************************************************************************/ + +#ifndef ADJ_THR_H +#define ADJ_THR_H + +#include "common_fix.h" +#include "adj_thr_data.h" +#include "qc_data.h" +#include "line_pe.h" +#include "interface.h" + +/***************************************************************************** + functionname: FDKaacEnc_peCalculation + description: +*****************************************************************************/ +void FDKaacEnc_peCalculation(PE_DATA *const peData, + const PSY_OUT_CHANNEL *const psyOutChannel[(2)], + QC_OUT_CHANNEL *const qcOutChannel[(2)], + const struct TOOLSINFO *const toolsInfo, + ATS_ELEMENT *const adjThrStateElement, + const INT nChannels); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrNew +description: allocate ADJ_THR_STATE +*****************************************************************************/ +INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrInit +description: initialize ADJ_THR_STATE +*****************************************************************************/ +void FDKaacEnc_AdjThrInit( + ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant, + const CHANNEL_MAPPING *const channelMapping, const INT sampleRate, + const INT totalBitrate, const INT isLowDelay, + const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable, + const INT bitDistributionMode, const FIXP_DBL vbrQualFactor); + +/***************************************************************************** +functionname: FDKaacEnc_DistributeBits +description: +*****************************************************************************/ +void FDKaacEnc_DistributeBits( + ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe, + INT *grantedPeCorr, const INT nChannels, const INT commonWindow, + const INT avgBits, const INT bitresBits, const INT maxBitresBits, + const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode); + +/***************************************************************************** +functionname: FDKaacEnc_AdjustThresholds +description: adjust thresholds +*****************************************************************************/ +void FDKaacEnc_AdjustThresholds( + ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))], + QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))], + const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm); + +/***************************************************************************** +functionname: FDKaacEnc_AdjThrClose +description: +*****************************************************************************/ +void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **hAdjThr); + +#endif diff --git a/fdk-aac/libAACenc/src/adj_thr_data.h b/fdk-aac/libAACenc/src/adj_thr_data.h new file mode 100644 index 0000000..4cd1299 --- /dev/null +++ b/fdk-aac/libAACenc/src/adj_thr_data.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: threshold calculations + +*******************************************************************************/ + +#ifndef ADJ_THR_DATA_H +#define ADJ_THR_DATA_H + +#include "psy_const.h" + +typedef enum { + AACENC_BD_MODE_INTER_ELEMENT = 0, + AACENC_BD_MODE_INTRA_ELEMENT = 1 +} AACENC_BIT_DISTRIBUTION_MODE; + +typedef enum { + AACENC_BR_MODE_FULL = 0, + AACENC_BR_MODE_REDUCED = 1, + AACENC_BR_MODE_DISABLED = 2 +} AACENC_BITRES_MODE; + +typedef struct { + FIXP_DBL clipSaveLow, clipSaveHigh; + FIXP_DBL minBitSave, maxBitSave; + FIXP_DBL clipSpendLow, clipSpendHigh; + FIXP_DBL minBitSpend, maxBitSpend; +} BRES_PARAM; + +typedef struct { + INT modifyMinSnr; + INT startSfbL, startSfbS; +} AH_PARAM; + +typedef struct { + FIXP_DBL maxRed; + FIXP_DBL startRatio; + FIXP_DBL maxRatio; + FIXP_DBL redRatioFac; + FIXP_DBL redOffs; +} MINSNR_ADAPT_PARAM; + +typedef struct { + /* parameters for bitreservoir control */ + INT peMin, peMax; + /* constant offset to pe */ + INT peOffset; + /* constant PeFactor */ + FIXP_DBL bits2PeFactor_m; + INT bits2PeFactor_e; + /* avoid hole parameters */ + AH_PARAM ahParam; + /* parameters for adaptation of minSnr */ + MINSNR_ADAPT_PARAM minSnrAdaptParam; + + /* values for correction of pe */ + INT peLast; + INT dynBitsLast; + FIXP_DBL peCorrectionFactor_m; + INT peCorrectionFactor_e; + + /* vbr encoding */ + FIXP_DBL vbrQualFactor; + FIXP_DBL chaosMeasureOld; + + /* threshold weighting */ + FIXP_DBL chaosMeasureEnFac[(2)]; + INT lastEnFacPatch[(2)]; + +} ATS_ELEMENT; + +typedef struct { + BRES_PARAM bresParamLong, bresParamShort; + ATS_ELEMENT* adjThrStateElem[((8))]; + AACENC_BIT_DISTRIBUTION_MODE bitDistributionMode; + INT maxIter2ndGuess; +} ADJ_THR_STATE; + +#endif diff --git a/fdk-aac/libAACenc/src/band_nrg.cpp b/fdk-aac/libAACenc/src/band_nrg.cpp new file mode 100644 index 0000000..fb22dbb --- /dev/null +++ b/fdk-aac/libAACenc/src/band_nrg.cpp @@ -0,0 +1,361 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Band/Line energy calculations + +*******************************************************************************/ + +#include "band_nrg.h" + +/***************************************************************************** + functionname: FDKaacEnc_CalcSfbMaxScaleSpec + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *RESTRICT mdctSpectrum, + const INT *RESTRICT bandOffset, + INT *RESTRICT sfbMaxScaleSpec, + const INT numBands) { + INT i, j; + FIXP_DBL maxSpc, tmp; + + for (i = 0; i < numBands; i++) { + maxSpc = (FIXP_DBL)0; + + DWORD_ALIGNED(mdctSpectrum); + + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + tmp = fixp_abs(mdctSpectrum[j]); + maxSpc = fixMax(maxSpc, tmp); + } + j = CntLeadingZeros(maxSpc) - 1; + sfbMaxScaleSpec[i] = fixMin((DFRACT_BITS - 2), j); + /* CountLeadingBits() is not necessary here since test value is always > 0 + */ + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CheckBandEnergyOptim + description: + input: + output: +*****************************************************************************/ +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *const RESTRICT mdctSpectrum, + const INT *const RESTRICT sfbMaxScaleSpec, + const INT *const RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData, + const INT minSpecShift) { + INT i, j, scale, nr = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(-1.0f); + FIXP_DBL maxNrg = 0; + FIXP_DBL spec; + + for (i = 0; i < numBands; i++) { + scale = fixMax(0, sfbMaxScaleSpec[i] - 4); + FIXP_DBL tmp = 0; + + DWORD_ALIGNED(mdctSpectrum); + + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] << scale; + tmp = fPow2AddDiv2(tmp, spec); + } + bandEnergy[i] = tmp << 1; + + /* calculate ld of bandNrg, subtract scaling */ + bandEnergyLdData[i] = CalcLdData(bandEnergy[i]); + if (bandEnergyLdData[i] != FL2FXCONST_DBL(-1.0f)) { + bandEnergyLdData[i] -= scale * FL2FXCONST_DBL(2.0 / 64); + } + /* find index of maxNrg */ + if (bandEnergyLdData[i] > maxNrgLd) { + maxNrgLd = bandEnergyLdData[i]; + nr = i; + } + } + + /* return unscaled maxNrg*/ + scale = fixMax(0, sfbMaxScaleSpec[nr] - 4); + scale = fixMax(2 * (minSpecShift - scale), -(DFRACT_BITS - 1)); + + maxNrg = scaleValue(bandEnergy[nr], scale); + + return maxNrg; +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimLong + description: + input: + output: +*****************************************************************************/ +INT FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData) { + INT i, j, shiftBits = 0; + FIXP_DBL maxNrgLd = FL2FXCONST_DBL(0.0f); + + FIXP_DBL spec; + + for (i = 0; i < numBands; i++) { + INT leadingBits = sfbMaxScaleSpec[i] - + 4; /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + /* don't use scaleValue() here, it increases workload quite sufficiently... + */ + if (leadingBits >= 0) { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] << leadingBits; + tmp = fPow2AddDiv2(tmp, spec); + } + } else { + INT shift = -leadingBits; + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + spec = mdctSpectrum[j] >> shift; + tmp = fPow2AddDiv2(tmp, spec); + } + } + bandEnergy[i] = tmp << 1; + } + + /* calculate ld of bandNrg, subtract scaling */ + LdDataVector(bandEnergy, bandEnergyLdData, numBands); + for (i = numBands; i-- != 0;) { + FIXP_DBL scaleDiff = (sfbMaxScaleSpec[i] - 4) * FL2FXCONST_DBL(2.0 / 64); + + bandEnergyLdData[i] = (bandEnergyLdData[i] >= + ((FL2FXCONST_DBL(-1.f) >> 1) + (scaleDiff >> 1))) + ? bandEnergyLdData[i] - scaleDiff + : FL2FXCONST_DBL(-1.f); + /* find maxNrgLd */ + maxNrgLd = fixMax(maxNrgLd, bandEnergyLdData[i]); + } + + if (maxNrgLd <= (FIXP_DBL)0) { + for (i = numBands; i-- != 0;) { + INT scale = fixMin((sfbMaxScaleSpec[i] - 4) << 1, (DFRACT_BITS - 1)); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return 0; + } else { /* scale down NRGs */ + while (maxNrgLd > FL2FXCONST_DBL(0.0f)) { + maxNrgLd -= FL2FXCONST_DBL(2.0 / 64); + shiftBits++; + } + for (i = numBands; i-- != 0;) { + INT scale = fixMin(((sfbMaxScaleSpec[i] - 4) + shiftBits) << 1, + (DFRACT_BITS - 1)); + bandEnergyLdData[i] -= shiftBits * FL2FXCONST_DBL(2.0 / 64); + bandEnergy[i] = scaleValue(bandEnergy[i], -scale); + } + return shiftBits; + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandEnergyOptimShort + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, + const INT *RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy) { + INT i, j; + + for (i = 0; i < numBands; i++) { + int leadingBits = sfbMaxScaleSpec[i] - + 3; /* max sfbWidth = 36 ; 2^6=64 => 6/2 = 3 (spc*spc) */ + FIXP_DBL tmp = FL2FXCONST_DBL(0.0); + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL spec = scaleValue(mdctSpectrum[j], leadingBits); + tmp = fPow2AddDiv2(tmp, spec); + } + bandEnergy[i] = tmp; + } + + for (i = 0; i < numBands; i++) { + INT scale = (2 * (sfbMaxScaleSpec[i] - 3)) - + 1; /* max sfbWidth = 36 ; 2^6=64 => 6/2 = 3 (spc*spc) */ + scale = fixMax(fixMin(scale, (DFRACT_BITS - 1)), -(DFRACT_BITS - 1)); + bandEnergy[i] = scaleValueSaturate(bandEnergy[i], -scale); + } +} + +/***************************************************************************** + functionname: FDKaacEnc_CalcBandNrgMSOpt + description: + input: + output: +*****************************************************************************/ +void FDKaacEnc_CalcBandNrgMSOpt( + const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData) { + INT i, j, minScale; + FIXP_DBL NrgMid, NrgSide, specm, specs; + + for (i = 0; i < numBands; i++) { + NrgMid = NrgSide = FL2FXCONST_DBL(0.0); + minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i]) - 4; + minScale = fixMax(0, minScale); + + if (minScale > 0) { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL specL = mdctSpectrumLeft[j] << (minScale - 1); + FIXP_DBL specR = mdctSpectrumRight[j] << (minScale - 1); + specm = specL + specR; + specs = specL - specR; + NrgMid = fPow2AddDiv2(NrgMid, specm); + NrgSide = fPow2AddDiv2(NrgSide, specs); + } + } else { + for (j = bandOffset[i]; j < bandOffset[i + 1]; j++) { + FIXP_DBL specL = mdctSpectrumLeft[j] >> 1; + FIXP_DBL specR = mdctSpectrumRight[j] >> 1; + specm = specL + specR; + specs = specL - specR; + NrgMid = fPow2AddDiv2(NrgMid, specm); + NrgSide = fPow2AddDiv2(NrgSide, specs); + } + } + bandEnergyMid[i] = fMin(NrgMid, (FIXP_DBL)MAXVAL_DBL >> 1) << 1; + bandEnergySide[i] = fMin(NrgSide, (FIXP_DBL)MAXVAL_DBL >> 1) << 1; + } + + if (calcLdData) { + LdDataVector(bandEnergyMid, bandEnergyMidLdData, numBands); + LdDataVector(bandEnergySide, bandEnergySideLdData, numBands); + } + + for (i = 0; i < numBands; i++) { + minScale = fixMin(sfbMaxScaleSpecLeft[i], sfbMaxScaleSpecRight[i]); + INT scale = fixMax(0, 2 * (minScale - 4)); + + if (calcLdData) { + /* using the minimal scaling of left and right channel can cause very + small energies; check ldNrg before subtract scaling multiplication: + fract*INT we don't need fMult */ + + int minus = scale * FL2FXCONST_DBL(1.0 / 64); + + if (bandEnergyMidLdData[i] != FL2FXCONST_DBL(-1.0f)) + bandEnergyMidLdData[i] -= minus; + + if (bandEnergySideLdData[i] != FL2FXCONST_DBL(-1.0f)) + bandEnergySideLdData[i] -= minus; + } + scale = fixMin(scale, (DFRACT_BITS - 1)); + bandEnergyMid[i] >>= scale; + bandEnergySide[i] >>= scale; + } +} diff --git a/fdk-aac/libAACenc/src/band_nrg.h b/fdk-aac/libAACenc/src/band_nrg.h new file mode 100644 index 0000000..4137565 --- /dev/null +++ b/fdk-aac/libAACenc/src/band_nrg.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Band/Line energy calculation + +*******************************************************************************/ + +#ifndef BAND_NRG_H +#define BAND_NRG_H + +#include "common_fix.h" + +void FDKaacEnc_CalcSfbMaxScaleSpec(const FIXP_DBL *mdctSpectrum, + const INT *bandOffset, INT *sfbMaxScaleSpec, + const INT numBands); + +FIXP_DBL +FDKaacEnc_CheckBandEnergyOptim(const FIXP_DBL *const RESTRICT mdctSpectrum, + const INT *const RESTRICT sfbMaxScaleSpec, + const INT *const RESTRICT bandOffset, + const INT numBands, + FIXP_DBL *RESTRICT bandEnergy, + FIXP_DBL *RESTRICT bandEnergyLdData, + const INT minSpecShift); + +INT FDKaacEnc_CalcBandEnergyOptimLong(const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, const INT numBands, + FIXP_DBL *bandEnergy, + FIXP_DBL *bandEnergyLdData); + +void FDKaacEnc_CalcBandEnergyOptimShort(const FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, + const INT *bandOffset, + const INT numBands, + FIXP_DBL *bandEnergy); + +void FDKaacEnc_CalcBandNrgMSOpt( + const FIXP_DBL *RESTRICT mdctSpectrumLeft, + const FIXP_DBL *RESTRICT mdctSpectrumRight, + INT *RESTRICT sfbMaxScaleSpecLeft, INT *RESTRICT sfbMaxScaleSpecRight, + const INT *RESTRICT bandOffset, const INT numBands, + FIXP_DBL *RESTRICT bandEnergyMid, FIXP_DBL *RESTRICT bandEnergySide, + INT calcLdData, FIXP_DBL *RESTRICT bandEnergyMidLdData, + FIXP_DBL *RESTRICT bandEnergySideLdData); + +#endif diff --git a/fdk-aac/libAACenc/src/bandwidth.cpp b/fdk-aac/libAACenc/src/bandwidth.cpp new file mode 100644 index 0000000..36cd64d --- /dev/null +++ b/fdk-aac/libAACenc/src/bandwidth.cpp @@ -0,0 +1,360 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: bandwidth expert + +*******************************************************************************/ + +#include "channel_map.h" +#include "bandwidth.h" +#include "aacEnc_ram.h" + +typedef struct { + INT chanBitRate; + INT bandWidthMono; + INT bandWidth2AndMoreChan; + +} BANDWIDTH_TAB; + +static const BANDWIDTH_TAB bandWidthTable[] = { + {0, 3700, 5000}, {12000, 5000, 6400}, {20000, 6900, 9640}, + {28000, 9600, 13050}, {40000, 12060, 14260}, {56000, 13950, 15500}, + {72000, 14200, 16120}, {96000, 17000, 17000}, {576001, 17000, 17000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_22050[] = { + {8000, 2000, 2400}, {12000, 2500, 2700}, {16000, 3300, 3100}, + {24000, 6250, 7200}, {32000, 9200, 10500}, {40000, 16000, 16000}, + {48000, 16000, 16000}, {282241, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_24000[] = { + {8000, 2000, 2000}, {12000, 2000, 2300}, {16000, 2200, 2500}, + {24000, 5650, 7200}, {32000, 11600, 12000}, {40000, 12000, 16000}, + {48000, 16000, 16000}, {64000, 16000, 16000}, {307201, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_32000[] = { + {8000, 2000, 2000}, {12000, 2000, 2000}, {24000, 4250, 7200}, + {32000, 8400, 9000}, {40000, 9400, 11300}, {48000, 11900, 14700}, + {64000, 14800, 16000}, {76000, 16000, 16000}, {409601, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_44100[] = { + {8000, 2000, 2000}, {24000, 2000, 2000}, {32000, 4400, 5700}, + {40000, 7400, 8800}, {48000, 9000, 10700}, {56000, 11000, 12900}, + {64000, 14400, 15500}, {80000, 16000, 16200}, {96000, 16500, 16000}, + {128000, 16000, 16000}, {564481, 16000, 16000}}; + +static const BANDWIDTH_TAB bandWidthTable_LD_48000[] = { + {8000, 2000, 2000}, {24000, 2000, 2000}, {32000, 4400, 5700}, + {40000, 7400, 8800}, {48000, 9000, 10700}, {56000, 11000, 12800}, + {64000, 14300, 15400}, {80000, 16000, 16200}, {96000, 16500, 16000}, + {128000, 16000, 16000}, {614401, 16000, 16000}}; + +typedef struct { + AACENC_BITRATE_MODE bitrateMode; + int bandWidthMono; + int bandWidth2AndMoreChan; +} BANDWIDTH_TAB_VBR; + +static const BANDWIDTH_TAB_VBR bandWidthTableVBR[] = { + {AACENC_BR_MODE_CBR, 0, 0}, + {AACENC_BR_MODE_VBR_1, 13050, 13050}, + {AACENC_BR_MODE_VBR_2, 13050, 13050}, + {AACENC_BR_MODE_VBR_3, 14260, 14260}, + {AACENC_BR_MODE_VBR_4, 15500, 15500}, + {AACENC_BR_MODE_VBR_5, 48000, 48000}, + {AACENC_BR_MODE_SFR, 0, 0}, + {AACENC_BR_MODE_FF, 0, 0} + +}; + +static INT GetBandwidthEntry(const INT frameLength, const INT sampleRate, + const INT chanBitRate, const INT entryNo) { + INT bandwidth = -1; + const BANDWIDTH_TAB *pBwTab = NULL; + INT bwTabSize = 0; + + switch (frameLength) { + case 960: + case 1024: + pBwTab = bandWidthTable; + bwTabSize = sizeof(bandWidthTable) / sizeof(BANDWIDTH_TAB); + break; + case 120: + case 128: + case 240: + case 256: + case 480: + case 512: + switch (sampleRate) { + case 8000: + case 11025: + case 12000: + case 16000: + case 22050: + pBwTab = bandWidthTable_LD_22050; + bwTabSize = sizeof(bandWidthTable_LD_22050) / sizeof(BANDWIDTH_TAB); + break; + case 24000: + pBwTab = bandWidthTable_LD_24000; + bwTabSize = sizeof(bandWidthTable_LD_24000) / sizeof(BANDWIDTH_TAB); + break; + case 32000: + pBwTab = bandWidthTable_LD_32000; + bwTabSize = sizeof(bandWidthTable_LD_32000) / sizeof(BANDWIDTH_TAB); + break; + case 44100: + pBwTab = bandWidthTable_LD_44100; + bwTabSize = sizeof(bandWidthTable_LD_44100) / sizeof(BANDWIDTH_TAB); + break; + case 48000: + case 64000: + case 88200: + case 96000: + pBwTab = bandWidthTable_LD_48000; + bwTabSize = sizeof(bandWidthTable_LD_48000) / sizeof(BANDWIDTH_TAB); + break; + } + break; + default: + pBwTab = NULL; + bwTabSize = 0; + } + + if (pBwTab != NULL) { + int i; + for (i = 0; i < bwTabSize - 1; i++) { + if (chanBitRate >= pBwTab[i].chanBitRate && + chanBitRate < pBwTab[i + 1].chanBitRate) { + switch (frameLength) { + case 960: + case 1024: + bandwidth = (entryNo == 0) ? pBwTab[i].bandWidthMono + : pBwTab[i].bandWidth2AndMoreChan; + break; + case 120: + case 128: + case 240: + case 256: + case 480: + case 512: { + INT q_res = 0; + INT startBw = (entryNo == 0) ? pBwTab[i].bandWidthMono + : pBwTab[i].bandWidth2AndMoreChan; + INT endBw = (entryNo == 0) ? pBwTab[i + 1].bandWidthMono + : pBwTab[i + 1].bandWidth2AndMoreChan; + INT startBr = pBwTab[i].chanBitRate; + INT endBr = pBwTab[i + 1].chanBitRate; + + FIXP_DBL bwFac_fix = + fDivNorm(chanBitRate - startBr, endBr - startBr, &q_res); + bandwidth = + (INT)scaleValue(fMult(bwFac_fix, (FIXP_DBL)(endBw - startBw)), + q_res) + + startBw; + } break; + default: + bandwidth = -1; + } + break; + } /* within bitrate range */ + } + } /* pBwTab!=NULL */ + + return bandwidth; +} + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth( + const INT proposedBandWidth, const INT bitrate, + const AACENC_BITRATE_MODE bitrateMode, const INT sampleRate, + const INT frameLength, const CHANNEL_MAPPING *const cm, + const CHANNEL_MODE encoderMode, INT *const bandWidth) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT chanBitRate = bitrate / cm->nChannelsEff; + + switch (bitrateMode) { + case AACENC_BR_MODE_VBR_1: + case AACENC_BR_MODE_VBR_2: + case AACENC_BR_MODE_VBR_3: + case AACENC_BR_MODE_VBR_4: + case AACENC_BR_MODE_VBR_5: + if (proposedBandWidth != 0) { + /* use given bw */ + *bandWidth = proposedBandWidth; + } else { + /* take bw from table */ + switch (encoderMode) { + case MODE_1: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidthMono; + break; + case MODE_2: + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + *bandWidth = bandWidthTableVBR[bitrateMode].bandWidth2AndMoreChan; + break; + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + } + break; + case AACENC_BR_MODE_CBR: + case AACENC_BR_MODE_SFR: + case AACENC_BR_MODE_FF: + + /* bandwidth limiting */ + if (proposedBandWidth != 0) { + *bandWidth = fMin(proposedBandWidth, fMin(20000, sampleRate >> 1)); + } else { /* search reasonable bandwidth */ + + int entryNo = 0; + + switch (encoderMode) { + case MODE_1: /* mono */ + entryNo = 0; /* use mono bandwidth settings */ + break; + + case MODE_2: /* stereo */ + case MODE_1_2: /* sce + cpe */ + case MODE_1_2_1: /* sce + cpe + sce */ + case MODE_1_2_2: /* sce + cpe + cpe */ + case MODE_1_2_2_1: /* (5.1) sce + cpe + cpe + lfe */ + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + entryNo = 1; /* use stereo bandwidth settings */ + break; + + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + *bandWidth = + GetBandwidthEntry(frameLength, sampleRate, chanBitRate, entryNo); + + if (*bandWidth == -1) { + switch (frameLength) { + case 120: + case 128: + case 240: + case 256: + *bandWidth = 16000; + break; + default: + ErrorStatus = AAC_ENC_INVALID_CHANNEL_BITRATE; + } + } + } + break; + default: + *bandWidth = 0; + return AAC_ENC_UNSUPPORTED_BITRATE_MODE; + } + + *bandWidth = fMin(*bandWidth, sampleRate / 2); + + return ErrorStatus; +} diff --git a/fdk-aac/libAACenc/src/bandwidth.h b/fdk-aac/libAACenc/src/bandwidth.h new file mode 100644 index 0000000..088e829 --- /dev/null +++ b/fdk-aac/libAACenc/src/bandwidth.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Schug / A. Groeschel + + Description: bandwidth expert + +*******************************************************************************/ + +#ifndef BANDWIDTH_H +#define BANDWIDTH_H + +#include "qc_data.h" + +AAC_ENCODER_ERROR FDKaacEnc_DetermineBandWidth( + const INT proposedBandWidth, const INT bitrate, + const AACENC_BITRATE_MODE bitrateMode, const INT sampleRate, + const INT frameLength, const CHANNEL_MAPPING *const cm, + const CHANNEL_MODE encoderMode, INT *const bandWidth); + +#endif /* BANDWIDTH_H */ diff --git a/fdk-aac/libAACenc/src/bit_cnt.cpp b/fdk-aac/libAACenc/src/bit_cnt.cpp new file mode 100644 index 0000000..579df8c --- /dev/null +++ b/fdk-aac/libAACenc/src/bit_cnt.cpp @@ -0,0 +1,950 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Huffman Bitcounter & coder + +*******************************************************************************/ + +#include "bit_cnt.h" + +#include "aacEnc_ram.h" + +#define HI_LTAB(a) (a >> 16) +#define LO_LTAB(a) (a & 0xffff) + +/***************************************************************************** + + + functionname: FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11 + description: counts tables 1-11 + returns: + input: quantized spectrum + output: bitCount for tables 1-11 + +*****************************************************************************/ + +static void FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc1_2, bc3_4, bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + bc1_2 = 0; + bc3_4 = 0; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc1_2 += (INT)FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]; + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc3_4 += (INT)FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]; + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + bitCount[1] = HI_LTAB(bc1_2); + bitCount[2] = LO_LTAB(bc1_2); + bitCount[3] = HI_LTAB(bc3_4) + sc; + bitCount[4] = LO_LTAB(bc3_4) + sc; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count3_4_5_6_7_8_9_10_11 + description: counts tables 3-11 + returns: + input: quantized spectrum + output: bitCount for tables 3-11 + +*****************************************************************************/ + +static void FDKaacEnc_count3_4_5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc3_4, bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc3_4 = 0; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc3_4 += (INT)FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]; + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = HI_LTAB(bc3_4) + sc; + bitCount[4] = LO_LTAB(bc3_4) + sc; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count5_6_7_8_9_10_11 + description: counts tables 5-11 + returns: + input: quantized spectrum + output: bitCount for tables 5-11 + +*****************************************************************************/ + +static void FDKaacEnc_count5_6_7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc5_6, bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + bc5_6 = 0; + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + bc5_6 += (INT)FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4] + + (INT)FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = HI_LTAB(bc5_6); + bitCount[6] = LO_LTAB(bc5_6); + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count7_8_9_10_11 + description: counts tables 7-11 + returns: + input: quantized spectrum + output: bitCount for tables 7-11 + +*****************************************************************************/ + +static void FDKaacEnc_count7_8_9_10_11(const SHORT *const values, + const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc7_8, bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc7_8 = 0; + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc7_8 += (INT)FDKaacEnc_huff_ltab7_8[t0][t1] + + (INT)FDKaacEnc_huff_ltab7_8[t2][t3]; + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = HI_LTAB(bc7_8) + sc; + bitCount[8] = LO_LTAB(bc7_8) + sc; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count9_10_11 + description: counts tables 9-11 + returns: + input: quantized spectrum + output: bitCount for tables 9-11 + +*****************************************************************************/ + +static void FDKaacEnc_count9_10_11(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc9_10, bc11, sc; + INT t0, t1, t2, t3; + + bc9_10 = 0; + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc9_10 += (INT)FDKaacEnc_huff_ltab9_10[t0][t1] + + (INT)FDKaacEnc_huff_ltab9_10[t2][t3]; + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = INVALID_BITCOUNT; + bitCount[8] = INVALID_BITCOUNT; + bitCount[9] = HI_LTAB(bc9_10) + sc; + bitCount[10] = LO_LTAB(bc9_10) + sc; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_count11 + description: counts table 11 + returns: + input: quantized spectrum + output: bitCount for table 11 + +*****************************************************************************/ + +static void FDKaacEnc_count11(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc11, sc; + INT t0, t1, t2, t3; + + bc11 = 0; + sc = 0; + + DWORD_ALIGNED(values); + + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + + t0 = fixp_abs(t0); + sc += (t0 > 0); + t1 = fixp_abs(t1); + sc += (t1 > 0); + t2 = fixp_abs(t2); + sc += (t2 > 0); + t3 = fixp_abs(t3); + sc += (t3 > 0); + + bc11 += + (INT)FDKaacEnc_huff_ltab11[t0][t1] + (INT)FDKaacEnc_huff_ltab11[t2][t3]; + } + + bitCount[1] = INVALID_BITCOUNT; + bitCount[2] = INVALID_BITCOUNT; + bitCount[3] = INVALID_BITCOUNT; + bitCount[4] = INVALID_BITCOUNT; + bitCount[5] = INVALID_BITCOUNT; + bitCount[6] = INVALID_BITCOUNT; + bitCount[7] = INVALID_BITCOUNT; + bitCount[8] = INVALID_BITCOUNT; + bitCount[9] = INVALID_BITCOUNT; + bitCount[10] = INVALID_BITCOUNT; + bitCount[11] = bc11 + sc; +} + +/***************************************************************************** + + functionname: FDKaacEnc_countEsc + description: counts table 11 (with Esc) + returns: + input: quantized spectrum + output: bitCount for tables 11 (with Esc) + +*****************************************************************************/ + +static void FDKaacEnc_countEsc(const SHORT *const values, const INT width, + INT *RESTRICT bitCount) { + INT i; + INT bc11, ec, sc; + INT t0, t1, t00, t01; + + bc11 = 0; + sc = 0; + ec = 0; + for (i = 0; i < width; i += 2) { + t0 = fixp_abs(values[i + 0]); + t1 = fixp_abs(values[i + 1]); + + sc += (t0 > 0) + (t1 > 0); + + t00 = fixMin(t0, 16); + t01 = fixMin(t1, 16); + bc11 += (INT)FDKaacEnc_huff_ltab11[t00][t01]; + + if (t0 >= 16) { + ec += 5; + while ((t0 >>= 1) >= 16) ec += 2; + } + + if (t1 >= 16) { + ec += 5; + while ((t1 >>= 1) >= 16) ec += 2; + } + } + + for (i = 0; i < 11; i++) bitCount[i] = INVALID_BITCOUNT; + + bitCount[11] = bc11 + sc + ec; +} + +typedef void (*COUNT_FUNCTION)(const SHORT *const values, const INT width, + INT *RESTRICT bitCount); + +static const COUNT_FUNCTION countFuncTable[CODE_BOOK_ESC_LAV + 1] = { + + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 0 */ + FDKaacEnc_count1_2_3_4_5_6_7_8_9_10_11, /* 1 */ + FDKaacEnc_count3_4_5_6_7_8_9_10_11, /* 2 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 3 */ + FDKaacEnc_count5_6_7_8_9_10_11, /* 4 */ + FDKaacEnc_count7_8_9_10_11, /* 5 */ + FDKaacEnc_count7_8_9_10_11, /* 6 */ + FDKaacEnc_count7_8_9_10_11, /* 7 */ + FDKaacEnc_count9_10_11, /* 8 */ + FDKaacEnc_count9_10_11, /* 9 */ + FDKaacEnc_count9_10_11, /* 10 */ + FDKaacEnc_count9_10_11, /* 11 */ + FDKaacEnc_count9_10_11, /* 12 */ + FDKaacEnc_count11, /* 13 */ + FDKaacEnc_count11, /* 14 */ + FDKaacEnc_count11, /* 15 */ + FDKaacEnc_countEsc /* 16 */ +}; + +INT FDKaacEnc_bitCount(const SHORT *const values, const INT width, + const INT maxVal, INT *const RESTRICT bitCount) { + /* + check if we can use codebook 0 + */ + + bitCount[0] = (maxVal == 0) ? 0 : INVALID_BITCOUNT; + + countFuncTable[fixMin(maxVal, (INT)CODE_BOOK_ESC_LAV)](values, width, + bitCount); + + return (0); +} + +/* + count difference between actual and zeroed lines +*/ +INT FDKaacEnc_countValues(SHORT *RESTRICT values, INT width, INT codeBook) { + INT i, t0, t1, t2, t3; + INT bitCnt = 0; + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += + HI_LTAB(FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]); + } + break; + + case CODE_BOOK_2_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += + LO_LTAB(FDKaacEnc_huff_ltab1_2[t0 + 1][t1 + 1][t2 + 1][t3 + 1]); + } + break; + + case CODE_BOOK_3_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]); + } + break; + + case CODE_BOOK_4_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab3_4[t0][t1][t2][t3]); + } + break; + + case CODE_BOOK_5_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4]) + + HI_LTAB(FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]); + } + break; + + case CODE_BOOK_6_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0]; + t1 = values[i + 1]; + t2 = values[i + 2]; + t3 = values[i + 3]; + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab5_6[t0 + 4][t1 + 4]) + + LO_LTAB(FDKaacEnc_huff_ltab5_6[t2 + 4][t3 + 4]); + } + break; + + case CODE_BOOK_7_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]) + + HI_LTAB(FDKaacEnc_huff_ltab7_8[t2][t3]); + } + break; + + case CODE_BOOK_8_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]) + + LO_LTAB(FDKaacEnc_huff_ltab7_8[t2][t3]); + } + break; + + case CODE_BOOK_9_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += HI_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]) + + HI_LTAB(FDKaacEnc_huff_ltab9_10[t2][t3]); + } + break; + + case CODE_BOOK_10_NO: + for (i = 0; i < width; i += 4) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + t2 = fixp_abs(values[i + 2]); + bitCnt += (t2 > 0); + t3 = fixp_abs(values[i + 3]); + bitCnt += (t3 > 0); + bitCnt += LO_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]) + + LO_LTAB(FDKaacEnc_huff_ltab9_10[t2][t3]); + } + break; + + case CODE_BOOK_ESC_NO: + for (i = 0; i < width; i += 2) { + t0 = fixp_abs(values[i + 0]); + bitCnt += (t0 > 0); + t1 = fixp_abs(values[i + 1]); + bitCnt += (t1 > 0); + bitCnt += (INT)FDKaacEnc_huff_ltab11[fixMin(t0, 16)][fixMin(t1, 16)]; + if (t0 >= 16) { + bitCnt += 5; + while ((t0 >>= 1) >= 16) bitCnt += 2; + } + if (t1 >= 16) { + bitCnt += 5; + while ((t1 >>= 1) >= 16) bitCnt += 2; + } + } + break; + + default: + break; + } + + return (bitCnt); +} + +INT FDKaacEnc_codeValues(SHORT *RESTRICT values, INT width, INT codeBook, + HANDLE_FDK_BITSTREAM hBitstream) { + INT i, t0, t1, t2, t3, t00, t01; + INT codeWord, codeLength; + INT sign, signLength; + + DWORD_ALIGNED(values); + + switch (codeBook) { + case CODE_BOOK_ZERO_NO: + break; + + case CODE_BOOK_1_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0] + 1; + t1 = values[i + 1] + 1; + t2 = values[i + 2] + 1; + t3 = values[i + 3] + 1; + codeWord = FDKaacEnc_huff_ctab1[t0][t1][t2][t3]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab1_2[t0][t1][t2][t3]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_2_NO: + for (i = 0; i < width; i += 4) { + t0 = values[i + 0] + 1; + t1 = values[i + 1] + 1; + t2 = values[i + 2] + 1; + t3 = values[i + 3] + 1; + codeWord = FDKaacEnc_huff_ctab2[t0][t1][t2][t3]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab1_2[t0][t1][t2][t3]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_3_NO: + for (i = 0; i < (width >> 2); i++) { + sign = 0; + signLength = 0; + int index[4]; + for (int j = 0; j < 4; j++) { + int ti = *values++; + int zero = (ti == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)ti >> 31); + index[j] = fixp_abs(ti); + } + codeWord = FDKaacEnc_huff_ctab3[index[0]][index[1]][index[2]][index[3]]; + codeLength = HI_LTAB( + FDKaacEnc_huff_ltab3_4[index[0]][index[1]][index[2]][index[3]]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_4_NO: + for (i = 0; i < width; i += 4) { + sign = 0; + signLength = 0; + int index[4]; + for (int j = 0; j < 4; j++) { + int ti = *values++; + int zero = (ti == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)ti >> 31); + index[j] = fixp_abs(ti); + } + codeWord = FDKaacEnc_huff_ctab4[index[0]][index[1]][index[2]][index[3]]; + codeLength = LO_LTAB( + FDKaacEnc_huff_ltab3_4[index[0]][index[1]][index[2]][index[3]]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_5_NO: + for (i = 0; i < (width >> 2); i++) { + t0 = *values++ + 4; + t1 = *values++ + 4; + t2 = *values++ + 4; + t3 = *values++ + 4; + codeWord = FDKaacEnc_huff_ctab5[t0][t1]; + codeLength = + HI_LTAB(FDKaacEnc_huff_ltab5_6[t2][t3]); /* length of 2nd cw */ + codeWord = (codeWord << codeLength) + FDKaacEnc_huff_ctab5[t2][t3]; + codeLength += HI_LTAB(FDKaacEnc_huff_ltab5_6[t0][t1]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_6_NO: + for (i = 0; i < (width >> 2); i++) { + t0 = *values++ + 4; + t1 = *values++ + 4; + t2 = *values++ + 4; + t3 = *values++ + 4; + codeWord = FDKaacEnc_huff_ctab6[t0][t1]; + codeLength = + LO_LTAB(FDKaacEnc_huff_ltab5_6[t2][t3]); /* length of 2nd cw */ + codeWord = (codeWord << codeLength) + FDKaacEnc_huff_ctab6[t2][t3]; + codeLength += LO_LTAB(FDKaacEnc_huff_ltab5_6[t0][t1]); + FDKwriteBits(hBitstream, codeWord, codeLength); + } + break; + + case CODE_BOOK_7_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab7[t0][t1]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_8_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab8[t0][t1]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab7_8[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_9_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab9[t0][t1]; + codeLength = HI_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_10_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + codeWord = FDKaacEnc_huff_ctab10[t0][t1]; + codeLength = LO_LTAB(FDKaacEnc_huff_ltab9_10[t0][t1]); + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + } + break; + + case CODE_BOOK_ESC_NO: + for (i = 0; i < (width >> 1); i++) { + t0 = *values++; + sign = ((UINT)t0 >> 31); + t0 = fixp_abs(t0); + signLength = (t0 == 0) ? 0 : 1; + t1 = *values++; + INT zero = (t1 == 0) ? 0 : 1; + signLength += zero; + sign = (sign << zero) + ((UINT)t1 >> 31); + t1 = fixp_abs(t1); + + t00 = fixMin(t0, 16); + t01 = fixMin(t1, 16); + + codeWord = FDKaacEnc_huff_ctab11[t00][t01]; + codeLength = (INT)FDKaacEnc_huff_ltab11[t00][t01]; + FDKwriteBits(hBitstream, (codeWord << signLength) | sign, + codeLength + signLength); + for (int j = 0; j < 2; j++) { + if (t0 >= 16) { + INT n = 4, p = t0; + for (; (p >>= 1) >= 16;) n++; + FDKwriteBits(hBitstream, + (((1 << (n - 3)) - 2) << n) | (t0 - (1 << n)), + n + n - 3); + } + t0 = t1; + } + } + break; + + default: + break; + } + return (0); +} + +INT FDKaacEnc_codeScalefactorDelta(INT delta, HANDLE_FDK_BITSTREAM hBitstream) { + INT codeWord, codeLength; + + if (fixp_abs(delta) > CODE_BOOK_SCF_LAV) return (1); + + codeWord = FDKaacEnc_huff_ctabscf[delta + CODE_BOOK_SCF_LAV]; + codeLength = (INT)FDKaacEnc_huff_ltabscf[delta + CODE_BOOK_SCF_LAV]; + FDKwriteBits(hBitstream, codeWord, codeLength); + return (0); +} diff --git a/fdk-aac/libAACenc/src/bit_cnt.h b/fdk-aac/libAACenc/src/bit_cnt.h new file mode 100644 index 0000000..7f4c450 --- /dev/null +++ b/fdk-aac/libAACenc/src/bit_cnt.h @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Huffman Bitcounter & coder + +*******************************************************************************/ + +#ifndef BIT_CNT_H +#define BIT_CNT_H + +#include "common_fix.h" +#include "FDK_bitstream.h" +#include "aacEnc_rom.h" + +#define INVALID_BITCOUNT (FDK_INT_MAX / 4) + +/* + code book number table +*/ + +enum codeBookNo { + CODE_BOOK_ZERO_NO = 0, + CODE_BOOK_1_NO = 1, + CODE_BOOK_2_NO = 2, + CODE_BOOK_3_NO = 3, + CODE_BOOK_4_NO = 4, + CODE_BOOK_5_NO = 5, + CODE_BOOK_6_NO = 6, + CODE_BOOK_7_NO = 7, + CODE_BOOK_8_NO = 8, + CODE_BOOK_9_NO = 9, + CODE_BOOK_10_NO = 10, + CODE_BOOK_ESC_NO = 11, + CODE_BOOK_RES_NO = 12, + CODE_BOOK_PNS_NO = 13, + CODE_BOOK_IS_OUT_OF_PHASE_NO = 14, + CODE_BOOK_IS_IN_PHASE_NO = 15 + +}; + +/* + code book index table +*/ + +enum codeBookNdx { + CODE_BOOK_ZERO_NDX, + CODE_BOOK_1_NDX, + CODE_BOOK_2_NDX, + CODE_BOOK_3_NDX, + CODE_BOOK_4_NDX, + CODE_BOOK_5_NDX, + CODE_BOOK_6_NDX, + CODE_BOOK_7_NDX, + CODE_BOOK_8_NDX, + CODE_BOOK_9_NDX, + CODE_BOOK_10_NDX, + CODE_BOOK_ESC_NDX, + CODE_BOOK_RES_NDX, + CODE_BOOK_PNS_NDX, + CODE_BOOK_IS_OUT_OF_PHASE_NDX, + CODE_BOOK_IS_IN_PHASE_NDX, + NUMBER_OF_CODE_BOOKS +}; + +/* + code book lav table +*/ + +enum codeBookLav { + CODE_BOOK_ZERO_LAV = 0, + CODE_BOOK_1_LAV = 1, + CODE_BOOK_2_LAV = 1, + CODE_BOOK_3_LAV = 2, + CODE_BOOK_4_LAV = 2, + CODE_BOOK_5_LAV = 4, + CODE_BOOK_6_LAV = 4, + CODE_BOOK_7_LAV = 7, + CODE_BOOK_8_LAV = 7, + CODE_BOOK_9_LAV = 12, + CODE_BOOK_10_LAV = 12, + CODE_BOOK_ESC_LAV = 16, + CODE_BOOK_SCF_LAV = 60, + CODE_BOOK_PNS_LAV = 60 +}; + +INT FDKaacEnc_bitCount(const SHORT *aQuantSpectrum, const INT noOfSpecLines, + INT maxVal, INT *bitCountLut); + +INT FDKaacEnc_countValues(SHORT *values, INT width, INT codeBook); + +INT FDKaacEnc_codeValues(SHORT *values, INT width, INT codeBook, + HANDLE_FDK_BITSTREAM hBitstream); + +INT FDKaacEnc_codeScalefactorDelta(INT scalefactor, + HANDLE_FDK_BITSTREAM hBitstream); + +inline INT FDKaacEnc_bitCountScalefactorDelta(const INT delta) { + FDK_ASSERT((0 <= (delta + CODE_BOOK_SCF_LAV)) && + ((delta + CODE_BOOK_SCF_LAV) < + (int)(sizeof(FDKaacEnc_huff_ltabscf) / + sizeof((FDKaacEnc_huff_ltabscf[0]))))); + return ((INT)FDKaacEnc_huff_ltabscf[delta + CODE_BOOK_SCF_LAV]); +} + +#endif diff --git a/fdk-aac/libAACenc/src/bitenc.cpp b/fdk-aac/libAACenc/src/bitenc.cpp new file mode 100644 index 0000000..512d596 --- /dev/null +++ b/fdk-aac/libAACenc/src/bitenc.cpp @@ -0,0 +1,1362 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Bitstream encoder + +*******************************************************************************/ + +#include +#include "bitenc.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "qc_data.h" +#include "interface.h" +#include "aacEnc_ram.h" + +#include "tpenc_lib.h" + +#include "FDK_tools_rom.h" /* needed for the bitstream syntax tables */ + +static const int globalGainOffset = 100; +static const int icsReservedBit = 0; +static const int noiseOffset = 90; + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSpectralData + description: encode spectral data + returns: the number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSpectralData(INT *sfbOffset, + SECTION_DATA *sectionData, + SHORT *quantSpectrum, + HANDLE_FDK_BITSTREAM hBitStream) { + INT i, sfb; + INT dbgVal = FDKgetValidBits(hBitStream); + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO) { + /* huffencode spectral data for this huffsection */ + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (sfb = sectionData->huffsection[i].sfbStart; sfb < tmp; sfb++) { + FDKaacEnc_codeValues(quantSpectrum + sfbOffset[sfb], + sfbOffset[sfb + 1] - sfbOffset[sfb], + sectionData->huffsection[i].codeBook, hBitStream); + } + } + } + return (FDKgetValidBits(hBitStream) - dbgVal); +} + +/***************************************************************************** + + functionname:FDKaacEnc_encodeGlobalGain + description: encodes Global Gain (common scale factor) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGlobalGain(INT globalGain, INT scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT mdctScale) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, + globalGain - scalefac + globalGainOffset - + 4 * (LOG_NORM_PCM - mdctScale), + 8); + } + return (8); +} + +/***************************************************************************** + + functionname:FDKaacEnc_encodeIcsInfo + description: encodes Ics Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ + +static INT FDKaacEnc_encodeIcsInfo(INT blockType, INT windowShape, + INT groupingMask, INT maxSfbPerGroup, + HANDLE_FDK_BITSTREAM hBitStream, + UINT syntaxFlags) { + INT statBits; + + if (blockType == SHORT_WINDOW) { + statBits = 8 + TRANS_FAC - 1; + } else { + if (syntaxFlags & AC_ELD) { + statBits = 6; + } else { + statBits = (!(syntaxFlags & AC_SCALABLE)) ? 11 : 10; + } + } + + if (hBitStream != NULL) { + if (!(syntaxFlags & AC_ELD)) { + FDKwriteBits(hBitStream, icsReservedBit, 1); + FDKwriteBits(hBitStream, blockType, 2); + FDKwriteBits(hBitStream, + (windowShape == LOL_WINDOW) ? KBD_WINDOW : windowShape, 1); + } + + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + FDKwriteBits(hBitStream, maxSfbPerGroup, 6); + + if (!(syntaxFlags & + (AC_SCALABLE | AC_ELD))) { /* If not scalable syntax then ... */ + /* No predictor data present */ + FDKwriteBits(hBitStream, 0, 1); + } + break; + + case SHORT_WINDOW: + FDKwriteBits(hBitStream, maxSfbPerGroup, 4); + + /* Write grouping bits */ + FDKwriteBits(hBitStream, groupingMask, TRANS_FAC - 1); + break; + } + } + + return (statBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeSectionData + description: encode section data (common Huffman codebooks for adjacent + SFB's) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeSectionData(SECTION_DATA *sectionData, + HANDLE_FDK_BITSTREAM hBitStream, + UINT useVCB11) { + if (hBitStream != NULL) { + INT sectEscapeVal = 0, sectLenBits = 0; + INT sectLen; + INT i; + INT dbgVal = FDKgetValidBits(hBitStream); + INT sectCbBits = 4; + + switch (sectionData->blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sectEscapeVal = SECT_ESC_VAL_LONG; + sectLenBits = SECT_BITS_LONG; + break; + + case SHORT_WINDOW: + sectEscapeVal = SECT_ESC_VAL_SHORT; + sectLenBits = SECT_BITS_SHORT; + break; + } + + for (i = 0; i < sectionData->noOfSections; i++) { + INT codeBook = sectionData->huffsection[i].codeBook; + + FDKwriteBits(hBitStream, codeBook, sectCbBits); + + { + sectLen = sectionData->huffsection[i].sfbCnt; + + while (sectLen >= sectEscapeVal) { + FDKwriteBits(hBitStream, sectEscapeVal, sectLenBits); + sectLen -= sectEscapeVal; + } + FDKwriteBits(hBitStream, sectLen, sectLenBits); + } + } + return (FDKgetValidBits(hBitStream) - dbgVal); + } + return (0); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeScaleFactorData + description: encode DPCM coded scale factors + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeScaleFactorData(UINT *maxValueInSfb, + SECTION_DATA *sectionData, + INT *scalefac, + HANDLE_FDK_BITSTREAM hBitStream, + INT *RESTRICT noiseNrg, + const INT *isScale, INT globalGain) { + if (hBitStream != NULL) { + INT i, j, lastValScf, deltaScf; + INT deltaPns; + INT lastValPns = 0; + INT noisePCMFlag = TRUE; + INT lastValIs; + + INT dbgVal = FDKgetValidBits(hBitStream); + + lastValScf = scalefac[sectionData->firstScf]; + lastValPns = globalGain - scalefac[sectionData->firstScf] + + globalGainOffset - 4 * LOG_NORM_PCM - noiseOffset; + lastValIs = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { + if ((sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_IN_PHASE_NO)) { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < tmp; j++) { + INT deltaIs = isScale[j] - lastValIs; + lastValIs = isScale[j]; + if (FDKaacEnc_codeScalefactorDelta(deltaIs, hBitStream)) { + return (1); + } + } /* sfb */ + } else if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + INT sfbStart = sectionData->huffsection[i].sfbStart; + INT tmp = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < tmp; j++) { + deltaPns = noiseNrg[j] - lastValPns; + lastValPns = noiseNrg[j]; + + if (noisePCMFlag) { + FDKwriteBits(hBitStream, deltaPns + (1 << (PNS_PCM_BITS - 1)), + PNS_PCM_BITS); + noisePCMFlag = FALSE; + } else { + if (FDKaacEnc_codeScalefactorDelta(deltaPns, hBitStream)) { + return (1); + } + } + } /* sfb */ + } else { + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; j < tmp; j++) { + /* + check if we can repeat the last value to save bits + */ + if (maxValueInSfb[j] == 0) + deltaScf = 0; + else { + deltaScf = -(scalefac[j] - lastValScf); + lastValScf = scalefac[j]; + } + if (FDKaacEnc_codeScalefactorDelta(deltaScf, hBitStream)) { + return (1); + } + } /* sfb */ + } /* code scalefactor */ + } /* sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO */ + } /* section loop */ + + return (FDKgetValidBits(hBitStream) - dbgVal); + } /* if (hBitStream != NULL) */ + + return (0); +} + +/***************************************************************************** + + functionname:encodeMsInfo + description: encodes MS-Stereo Info + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeMSInfo(INT sfbCnt, INT grpSfb, INT maxSfb, + INT msDigest, INT *jsFlags, + HANDLE_FDK_BITSTREAM hBitStream) { + INT sfb, sfbOff, msBits = 0; + + if (hBitStream != NULL) { + switch (msDigest) { + case MS_NONE: + FDKwriteBits(hBitStream, SI_MS_MASK_NONE, 2); + msBits += 2; + break; + + case MS_ALL: + FDKwriteBits(hBitStream, SI_MS_MASK_ALL, 2); + msBits += 2; + break; + + case MS_SOME: + FDKwriteBits(hBitStream, SI_MS_MASK_SOME, 2); + msBits += 2; + for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) { + for (sfb = 0; sfb < maxSfb; sfb++) { + if (jsFlags[sfbOff + sfb] & MS_ON) { + FDKwriteBits(hBitStream, 1, 1); + } else { + FDKwriteBits(hBitStream, 0, 1); + } + msBits += 1; + } + } + break; + } + } else { + msBits += 2; + if (msDigest == MS_SOME) { + for (sfbOff = 0; sfbOff < sfbCnt; sfbOff += grpSfb) { + for (sfb = 0; sfb < maxSfb; sfb++) { + msBits += 1; + } + } + } + } + return (msBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeTnsDataPresent + description: encode TNS data (filter order, coeffs, ..) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeTnsDataPresent(TNS_INFO *tnsInfo, INT blockType, + HANDLE_FDK_BITSTREAM hBitStream) { + if ((hBitStream != NULL) && (tnsInfo != NULL)) { + INT i, tnsPresent = 0; + INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1); + + for (i = 0; i < numOfWindows; i++) { + if (tnsInfo->numOfFilters[i] != 0) { + tnsPresent = 1; + break; + } + } + + if (tnsPresent == 0) { + FDKwriteBits(hBitStream, 0, 1); + } else { + FDKwriteBits(hBitStream, 1, 1); + } + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeTnsData + description: encode TNS data (filter order, coeffs, ..) + returns: the number of static bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeTnsData(TNS_INFO *tnsInfo, INT blockType, + HANDLE_FDK_BITSTREAM hBitStream) { + INT tnsBits = 0; + + if (tnsInfo != NULL) { + INT i, j, k; + INT tnsPresent = 0; + INT coefBits; + INT numOfWindows = (blockType == SHORT_WINDOW ? TRANS_FAC : 1); + + for (i = 0; i < numOfWindows; i++) { + if (tnsInfo->numOfFilters[i] != 0) { + tnsPresent = 1; + } + } + + if (hBitStream != NULL) { + if (tnsPresent == 1) { /* there is data to be written*/ + for (i = 0; i < numOfWindows; i++) { + FDKwriteBits(hBitStream, tnsInfo->numOfFilters[i], + (blockType == SHORT_WINDOW ? 1 : 2)); + tnsBits += (blockType == SHORT_WINDOW ? 1 : 2); + if (tnsInfo->numOfFilters[i]) { + FDKwriteBits(hBitStream, (tnsInfo->coefRes[i] == 4 ? 1 : 0), 1); + tnsBits += 1; + } + for (j = 0; j < tnsInfo->numOfFilters[i]; j++) { + FDKwriteBits(hBitStream, tnsInfo->length[i][j], + (blockType == SHORT_WINDOW ? 4 : 6)); + tnsBits += (blockType == SHORT_WINDOW ? 4 : 6); + FDK_ASSERT(tnsInfo->order[i][j] <= 12); + FDKwriteBits(hBitStream, tnsInfo->order[i][j], + (blockType == SHORT_WINDOW ? 3 : 5)); + tnsBits += (blockType == SHORT_WINDOW ? 3 : 5); + if (tnsInfo->order[i][j]) { + FDKwriteBits(hBitStream, tnsInfo->direction[i][j], 1); + tnsBits += 1; /*direction*/ + if (tnsInfo->coefRes[i] == 4) { + coefBits = 3; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 3 || + tnsInfo->coef[i][j][k] < -4) { + coefBits = 4; + break; + } + } + } else { + coefBits = 2; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 1 || + tnsInfo->coef[i][j][k] < -2) { + coefBits = 3; + break; + } + } + } + FDKwriteBits(hBitStream, -(coefBits - tnsInfo->coefRes[i]), + 1); /*coef_compres*/ + tnsBits += 1; /*coef_compression */ + for (k = 0; k < tnsInfo->order[i][j]; k++) { + static const INT rmask[] = {0, 1, 3, 7, 15}; + FDKwriteBits(hBitStream, + tnsInfo->coef[i][j][k] & rmask[coefBits], + coefBits); + tnsBits += coefBits; + } + } + } + } + } + } else { + if (tnsPresent != 0) { + for (i = 0; i < numOfWindows; i++) { + tnsBits += (blockType == SHORT_WINDOW ? 1 : 2); + if (tnsInfo->numOfFilters[i]) { + tnsBits += 1; + for (j = 0; j < tnsInfo->numOfFilters[i]; j++) { + tnsBits += (blockType == SHORT_WINDOW ? 4 : 6); + tnsBits += (blockType == SHORT_WINDOW ? 3 : 5); + if (tnsInfo->order[i][j]) { + tnsBits += 1; /*direction*/ + tnsBits += 1; /*coef_compression */ + if (tnsInfo->coefRes[i] == 4) { + coefBits = 3; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 3 || + tnsInfo->coef[i][j][k] < -4) { + coefBits = 4; + break; + } + } + } else { + coefBits = 2; + for (k = 0; k < tnsInfo->order[i][j]; k++) { + if (tnsInfo->coef[i][j][k] > 1 || + tnsInfo->coef[i][j][k] < -2) { + coefBits = 3; + break; + } + } + } + for (k = 0; k < tnsInfo->order[i][j]; k++) { + tnsBits += coefBits; + } + } + } + } + } + } + } + } /* (tnsInfo!=NULL) */ + + return (tnsBits); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodeGainControlData + description: unsupported + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodeGainControlData(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_encodePulseData + description: not supported yet (dummy) + returns: none + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_encodePulseData(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + return (1); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeExtensionPayload + description: write extension payload to bitstream + returns: number of written bits + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_writeExtensionPayload(HANDLE_FDK_BITSTREAM hBitStream, + EXT_PAYLOAD_TYPE extPayloadType, + const UCHAR *extPayloadData, + INT extPayloadBits) { +#define EXT_TYPE_BITS (4) +#define DATA_EL_VERSION_BITS (4) +#define FILL_NIBBLE_BITS (4) + + INT extBitsUsed = 0; + + if (extPayloadBits >= EXT_TYPE_BITS) { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + /* case EXT_SAC_DATA: */ + case EXT_LDSAC_DATA: + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, *extPayloadData++, 4); /* nibble */ + } + extBitsUsed += 4; + FDK_FALLTHROUGH; + case EXT_DYNAMIC_RANGE: + case EXT_SBR_DATA: + case EXT_SBR_DATA_CRC: + if (hBitStream != NULL) { + int i, writeBits = extPayloadBits; + for (i = 0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, *extPayloadData++, 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, (*extPayloadData) >> (8 - writeBits), + writeBits); + } + } + extBitsUsed += extPayloadBits; + break; + + case EXT_DATA_ELEMENT: { + INT dataElementLength = (extPayloadBits + 7) >> 3; + INT cnt = dataElementLength; + int loopCounter = 1; + + while (dataElementLength >= 255) { + loopCounter++; + dataElementLength -= 255; + } + + if (hBitStream != NULL) { + int i; + FDKwriteBits( + hBitStream, 0x00, + DATA_EL_VERSION_BITS); /* data_element_version = ANC_DATA */ + + for (i = 1; i < loopCounter; i++) { + FDKwriteBits(hBitStream, 255, 8); + } + FDKwriteBits(hBitStream, dataElementLength, 8); + + for (i = 0; i < cnt; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + } + } + extBitsUsed += DATA_EL_VERSION_BITS + (loopCounter * 8) + (cnt * 8); + } break; + + case EXT_FILL_DATA: + fillByte = 0xA5; + FDK_FALLTHROUGH; + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = extPayloadBits; + FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS); + writeBits -= + 8; /* acount for the extension type and the fill nibble */ + while (writeBits >= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeDataStreamElement + description: write data stream elements like ancillary data ... + returns: the amount of used bits + input: + output: + +******************************************************************************/ +static INT FDKaacEnc_writeDataStreamElement(HANDLE_TRANSPORTENC hTpEnc, + INT elementInstanceTag, + INT dataPayloadBytes, + UCHAR *dataBuffer, + UINT alignAnchor) { +#define DATA_BYTE_ALIGN_FLAG (0) + +#define EL_INSTANCE_TAG_BITS (4) +#define DATA_BYTE_ALIGN_FLAG_BITS (1) +#define DATA_LEN_COUNT_BITS (8) +#define DATA_LEN_ESC_COUNT_BITS (8) + +#define MAX_DATA_ALIGN_BITS (7) +#define MAX_DSE_DATA_BYTES (510) + + INT dseBitsUsed = 0; + + while (dataPayloadBytes > 0) { + int esc_count = -1; + int cnt = 0; + INT crcReg = -1; + + dseBitsUsed += EL_ID_BITS + EL_INSTANCE_TAG_BITS + + DATA_BYTE_ALIGN_FLAG_BITS + DATA_LEN_COUNT_BITS; + + if (DATA_BYTE_ALIGN_FLAG) { + dseBitsUsed += MAX_DATA_ALIGN_BITS; + } + + cnt = fixMin(MAX_DSE_DATA_BYTES, dataPayloadBytes); + if (cnt >= 255) { + esc_count = cnt - 255; + dseBitsUsed += DATA_LEN_ESC_COUNT_BITS; + } + + dataPayloadBytes -= cnt; + dseBitsUsed += cnt * 8; + + if (hTpEnc != NULL) { + HANDLE_FDK_BITSTREAM hBitStream = transportEnc_GetBitstream(hTpEnc); + int i; + + FDKwriteBits(hBitStream, ID_DSE, EL_ID_BITS); + + crcReg = transportEnc_CrcStartReg(hTpEnc, 0); + + FDKwriteBits(hBitStream, elementInstanceTag, EL_INSTANCE_TAG_BITS); + FDKwriteBits(hBitStream, DATA_BYTE_ALIGN_FLAG, DATA_BYTE_ALIGN_FLAG_BITS); + + /* write length field(s) */ + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 255, DATA_LEN_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, DATA_LEN_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, DATA_LEN_COUNT_BITS); + } + + if (DATA_BYTE_ALIGN_FLAG) { + INT tmp = (INT)FDKgetValidBits(hBitStream); + FDKbyteAlign(hBitStream, alignAnchor); + /* count actual bits */ + dseBitsUsed += + (INT)FDKgetValidBits(hBitStream) - tmp - MAX_DATA_ALIGN_BITS; + } + + /* write payload */ + for (i = 0; i < cnt; i++) { + FDKwriteBits(hBitStream, dataBuffer[i], 8); + } + transportEnc_CrcEndReg(hTpEnc, crcReg); + } + } + + return (dseBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_writeExtensionData + description: write extension payload to bitstream + returns: number of written bits + input: + output: + +*****************************************************************************/ +INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc, + QC_OUT_EXTENSION *pExtension, + INT elInstanceTag, /* for DSE only */ + UINT alignAnchor, /* for DSE only */ + UINT syntaxFlags, AUDIO_OBJECT_TYPE aot, + SCHAR epConfig) { +#define FILL_EL_COUNT_BITS (4) +#define FILL_EL_ESC_COUNT_BITS (8) +#define MAX_FILL_DATA_BYTES (269) + + HANDLE_FDK_BITSTREAM hBitStream = NULL; + INT payloadBits = pExtension->nPayloadBits; + INT extBitsUsed = 0; + + if (hTpEnc != NULL) { + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + if (syntaxFlags & (AC_SCALABLE | AC_ER)) { + { + if ((syntaxFlags & AC_ELD) && ((pExtension->type == EXT_SBR_DATA) || + (pExtension->type == EXT_SBR_DATA_CRC))) { + if (hBitStream != NULL) { + int i, writeBits = payloadBits; + UCHAR *extPayloadData = pExtension->pPayload; + + for (i = 0; writeBits >= 8; i++) { + FDKwriteBits(hBitStream, extPayloadData[i], 8); + writeBits -= 8; + } + if (writeBits > 0) { + FDKwriteBits(hBitStream, extPayloadData[i] >> (8 - writeBits), + writeBits); + } + } + extBitsUsed += payloadBits; + } else { + /* ER or scalable syntax -> write extension en bloc */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( + hBitStream, pExtension->type, pExtension->pPayload, payloadBits); + } + } + } else { + /* We have normal GA bitstream payload (AOT 2,5,29) so pack + the data into a fill elements or DSEs */ + + if (pExtension->type == EXT_DATA_ELEMENT) { + extBitsUsed += FDKaacEnc_writeDataStreamElement( + hTpEnc, elInstanceTag, pExtension->nPayloadBits >> 3, + pExtension->pPayload, alignAnchor); + } else { + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count = -1, alignBits = 7; + + if ((pExtension->type == EXT_FILL_DATA) || + (pExtension->type == EXT_FIL)) { + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15 * 8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + } + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits + alignBits) >> 3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + + ((esc_count >= 0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt * 8, payloadBits); /* convert back to bits */ + extBitsUsed += FDKaacEnc_writeExtensionPayload( + hBitStream, pExtension->type, pExtension->pPayload, cnt); + payloadBits -= cnt; + } + } + } + + return (extBitsUsed); +} + +/***************************************************************************** + + functionname: FDKaacEnc_ByteAlignment + description: + returns: + input: + output: + +*****************************************************************************/ +static void FDKaacEnc_ByteAlignment(HANDLE_FDK_BITSTREAM hBitStream, + int alignBits) { + FDKwriteBits(hBitStream, 0, alignBits); +} + +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( + HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt) { + AAC_ENCODER_ERROR error = AAC_ENC_OK; + HANDLE_FDK_BITSTREAM hBitStream = NULL; + INT bitDemand = 0; + const element_list_t *list; + int i, ch, decision_bit; + INT crcReg1 = -1, crcReg2 = -1; + UCHAR numberOfChannels; + + if (hTpEnc != NULL) { + /* Get bitstream handle */ + hBitStream = transportEnc_GetBitstream(hTpEnc); + } + + if ((pElInfo->elType == ID_SCE) || (pElInfo->elType == ID_LFE)) { + numberOfChannels = 1; + } else { + numberOfChannels = 2; + } + + /* Get channel element sequence table */ + list = getBitstreamElementList(aot, epConfig, numberOfChannels, 0, 0); + if (list == NULL) { + error = AAC_ENC_UNSUPPORTED_AOT; + goto bail; + } + + if (!(syntaxFlags & (AC_SCALABLE | AC_ER))) { + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->elType, EL_ID_BITS); + } + bitDemand += EL_ID_BITS; + } + + /* Iterate through sequence table */ + i = 0; + ch = 0; + decision_bit = 0; + do { + /* some tmp values */ + SECTION_DATA *pChSectionData = NULL; + INT *pChScf = NULL; + UINT *pChMaxValueInSfb = NULL; + TNS_INFO *pTnsInfo = NULL; + INT chGlobalGain = 0; + INT chBlockType = 0; + INT chMaxSfbPerGrp = 0; + INT chSfbPerGrp = 0; + INT chSfbCnt = 0; + INT chFirstScf = 0; + + if (minCnt == 0) { + if (qcOutChannel != NULL) { + pChSectionData = &(qcOutChannel[ch]->sectionData); + pChScf = qcOutChannel[ch]->scf; + chGlobalGain = qcOutChannel[ch]->globalGain; + pChMaxValueInSfb = qcOutChannel[ch]->maxValueInSfb; + chBlockType = pChSectionData->blockType; + chMaxSfbPerGrp = pChSectionData->maxSfbPerGroup; + chSfbPerGrp = pChSectionData->sfbPerGroup; + chSfbCnt = pChSectionData->sfbCnt; + chFirstScf = pChScf[pChSectionData->firstScf]; + } else { + /* get values from PSY */ + chSfbCnt = psyOutChannel[ch]->sfbCnt; + chSfbPerGrp = psyOutChannel[ch]->sfbPerGroup; + chMaxSfbPerGrp = psyOutChannel[ch]->maxSfbPerGroup; + } + pTnsInfo = &psyOutChannel[ch]->tnsInfo; + } /* minCnt==0 */ + + if (qcOutChannel == NULL) { + chBlockType = psyOutChannel[ch]->lastWindowSequence; + } + + switch (list->id[i]) { + case element_instance_tag: + /* Write element instance tag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, pElInfo->instanceTag, 4); + } + bitDemand += 4; + break; + + case common_window: + /* Write common window flag */ + decision_bit = psyOutElement->commonWindow; + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, psyOutElement->commonWindow, 1); + } + bitDemand += 1; + break; + + case ics_info: + /* Write individual channel info */ + bitDemand += + FDKaacEnc_encodeIcsInfo(chBlockType, psyOutChannel[ch]->windowShape, + psyOutChannel[ch]->groupingMask, + chMaxSfbPerGrp, hBitStream, syntaxFlags); + break; + + case ltp_data_present: + /* Write LTP data present flag */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, 0, 1); + } + bitDemand += 1; + break; + + case ltp_data: + /* Predictor data not supported. + Nothing to do here. */ + break; + + case ms: + /* Write MS info */ + bitDemand += FDKaacEnc_encodeMSInfo( + chSfbCnt, chSfbPerGrp, chMaxSfbPerGrp, + (minCnt == 0) ? psyOutElement->toolsInfo.msDigest : MS_NONE, + psyOutElement->toolsInfo.msMask, hBitStream); + break; + + case global_gain: + bitDemand += FDKaacEnc_encodeGlobalGain( + chGlobalGain, chFirstScf, hBitStream, psyOutChannel[ch]->mdctScale); + break; + + case section_data: { + INT siBits = FDKaacEnc_encodeSectionData( + pChSectionData, hBitStream, (syntaxFlags & AC_ER_VCB11) ? 1 : 0); + if (hBitStream != NULL) { + if (siBits != qcOutChannel[ch]->sectionData.sideInfoBits) { + error = AAC_ENC_WRITE_SEC_ERROR; + } + } + bitDemand += siBits; + } break; + + case scale_factor_data: { + INT sfDataBits = FDKaacEnc_encodeScaleFactorData( + pChMaxValueInSfb, pChSectionData, pChScf, hBitStream, + psyOutChannel[ch]->noiseNrg, psyOutChannel[ch]->isScale, + chGlobalGain); + if ((hBitStream != NULL) && + (sfDataBits != (qcOutChannel[ch]->sectionData.scalefacBits + + qcOutChannel[ch]->sectionData.noiseNrgBits))) { + error = AAC_ENC_WRITE_SCAL_ERROR; + } + bitDemand += sfDataBits; + } break; + + case esc2_rvlc: + if (syntaxFlags & AC_ER_RVLC) { + /* write RVLC data into bitstream (error sens. cat. 2) */ + error = AAC_ENC_UNSUPPORTED_AOT; + } + break; + + case pulse: + /* Write pulse data */ + bitDemand += FDKaacEnc_encodePulseData(hBitStream); + break; + + case tns_data_present: + /* Write TNS data present flag */ + bitDemand += + FDKaacEnc_encodeTnsDataPresent(pTnsInfo, chBlockType, hBitStream); + break; + case tns_data: + /* Write TNS data */ + bitDemand += FDKaacEnc_encodeTnsData(pTnsInfo, chBlockType, hBitStream); + break; + + case gain_control_data: + /* Nothing to do here */ + break; + + case gain_control_data_present: + bitDemand += FDKaacEnc_encodeGainControlData(hBitStream); + break; + + case esc1_hcr: + if (syntaxFlags & AC_ER_HCR) { + error = AAC_ENC_UNKNOWN; + } + break; + + case spectral_data: + if (hBitStream != NULL) { + INT spectralBits = 0; + + spectralBits = FDKaacEnc_encodeSpectralData( + psyOutChannel[ch]->sfbOffsets, pChSectionData, + qcOutChannel[ch]->quantSpec, hBitStream); + + if (spectralBits != qcOutChannel[ch]->sectionData.huffmanBits) { + return AAC_ENC_WRITE_SPEC_ERROR; + } + bitDemand += spectralBits; + } + break; + + /* Non data cases */ + case adtscrc_start_reg1: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 192); + } + break; + case adtscrc_start_reg2: + if (hTpEnc != NULL) { + crcReg2 = transportEnc_CrcStartReg(hTpEnc, 128); + } + break; + case adtscrc_end_reg1: + case drmcrc_end_reg: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg1); + } + break; + case adtscrc_end_reg2: + if (hTpEnc != NULL) { + transportEnc_CrcEndReg(hTpEnc, crcReg2); + } + break; + case drmcrc_start_reg: + if (hTpEnc != NULL) { + crcReg1 = transportEnc_CrcStartReg(hTpEnc, 0); + } + break; + case next_channel: + ch = (ch + 1) % numberOfChannels; + break; + case link_sequence: + list = list->next[decision_bit]; + i = -1; + break; + + default: + error = AAC_ENC_UNKNOWN; + break; + } + + if (error != AAC_ENC_OK) { + return error; + } + + i++; + + } while (list->id[i] != end_of_sequence); + +bail: + if (pBitDemand != NULL) { + *pBitDemand = bitDemand; + } + + return error; +} + +//----------------------------------------------------------------------------------------------- + +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT *qcOut, PSY_OUT *psyOut, + QC_STATE *qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + HANDLE_FDK_BITSTREAM hBs = transportEnc_GetBitstream(hTpEnc); + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, n, doByteAlign = 1; + INT bitMarkUp; + INT frameBits; + /* Get first bit of raw data block. + In case of ADTS+PCE, AU would start at PCE. + This is okay because PCE assures alignment. */ + UINT alignAnchor = FDKgetValidBits(hBs); + + frameBits = bitMarkUp = alignAnchor; + + + /* Write DSEs first in case of DAB */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) { + if ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type == EXT_DATA_ELEMENT) ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here */ + } + + /* Channel element loop */ + for (i = 0; i < channelMapping->nElements; i++) { + ELEMENT_INFO elInfo = channelMapping->elInfo[i]; + INT elementUsedBits = 0; + + switch (elInfo.elType) { + case ID_SCE: /* single channel */ + case ID_CPE: /* channel pair */ + case ID_LFE: /* low freq effects channel */ + { + if (AAC_ENC_OK != + (ErrorStatus = FDKaacEnc_ChannelElementWrite( + hTpEnc, &elInfo, qcOut->qcElement[i]->qcOutChannel, + psyOut->psyOutElement[i], + psyOut->psyOutElement[i]->psyOutChannel, + syntaxFlags, /* syntaxFlags (ER tools ...) */ + aot, /* aot: AOT_AAC_LC, AOT_SBR, AOT_PS */ + epConfig, /* epConfig -1, 0, 1 */ + NULL, 0))) { + return ErrorStatus; + } + + if (!(syntaxFlags & AC_ER)) { + /* Write associated extension payload */ + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + FDKaacEnc_writeExtensionData( + hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor, + syntaxFlags, aot, epConfig); + } + } + } break; + + /* In FDK, DSE signalling explicit done in elDSE. See channel_map.cpp */ + default: + return AAC_ENC_INVALID_ELEMENTINFO_TYPE; + + } /* switch */ + + if (elInfo.elType != ID_DSE) { + elementUsedBits -= bitMarkUp; + bitMarkUp = FDKgetValidBits(hBs); + elementUsedBits += bitMarkUp; + frameBits += elementUsedBits; + } + + } /* for (i=0; inElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + if ((qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA) || + (qcOut->qcElement[i]->extension[n].type == EXT_SBR_DATA_CRC)) { + /* Write sbr extension payload */ + FDKaacEnc_writeExtensionData( + hTpEnc, &qcOut->qcElement[i]->extension[n], 0, alignAnchor, + syntaxFlags, aot, epConfig); + + channelElementExtensionWritten[i][n] = 1; + } /* SBR */ + } /* n */ + } /* i */ + } /* AC_ELD */ + + for (i = 0; i < channelMapping->nElements; i++) { + for (n = 0; n < qcOut->qcElement[i]->nExtensions; n++) { + if (channelElementExtensionWritten[i][n] == 0) { + /* Write all ramaining extension payloads in element */ + FDKaacEnc_writeExtensionData(hTpEnc, + &qcOut->qcElement[i]->extension[n], 0, + alignAnchor, syntaxFlags, aot, epConfig); + } + } /* n */ + } /* i */ + } /* if AC_ER */ + + /* Extend global extension payload table with fill bits */ + n = qcOut->nExtensions; + + /* Add fill data / stuffing bits */ + n = qcOut->nExtensions; + +// if (!(syntaxFlags & AC_DAB)) { + qcOut->extension[n].type = EXT_FILL_DATA; + qcOut->extension[n].nPayloadBits = qcOut->totFillBits; + qcOut->nExtensions++; +// } else { +// doByteAlign = 0; +// } + if (syntaxFlags & AC_DAB) + doByteAlign = 0; + + /* Write global extension payload and fill data */ + for (n = 0; (n < qcOut->nExtensions) && (n < (2+2)); n++) + { + if ( !(syntaxFlags & AC_DAB) || + ( (syntaxFlags & AC_DAB) && + (qcOut->extension[n].type != EXT_DATA_ELEMENT) + ) + ) { + FDKaacEnc_writeExtensionData( hTpEnc, + &qcOut->extension[n], + 0, + alignAnchor, + syntaxFlags, + aot, + epConfig ); + } + + /* For EXT_FIL or EXT_FILL_DATA we could do an additional sanity check here + */ + } + + if (!(syntaxFlags & (AC_SCALABLE | AC_ER | AC_DAB))) { + FDKwriteBits(hBs, ID_END, EL_ID_BITS); + } + + if (doByteAlign) { + /* Assure byte alignment*/ + if (((FDKgetValidBits(hBs) - alignAnchor + qcOut->alignBits) & 0x7) != 0) { + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + FDKaacEnc_ByteAlignment(hBs, qcOut->alignBits); + } + + frameBits -= bitMarkUp; + frameBits += FDKgetValidBits(hBs); + + transportEnc_EndAccessUnit(hTpEnc, &frameBits); + + if (frameBits != qcOut->totalBits + qcKernel->globHdrBits){ + fprintf(stderr, "frameBits != qcOut->totalBits + qcKernel->globHdrBits: %d != %d + %d", frameBits, qcOut->totalBits, qcKernel->globHdrBits); + return AAC_ENC_WRITTEN_BITS_ERROR; + } + + //fprintf(stderr, "ErrorStatus=%d", ErrorStatus); + return ErrorStatus; +} diff --git a/fdk-aac/libAACenc/src/bitenc.h b/fdk-aac/libAACenc/src/bitenc.h new file mode 100644 index 0000000..75dc068 --- /dev/null +++ b/fdk-aac/libAACenc/src/bitenc.h @@ -0,0 +1,184 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Bitstream encoder + +*******************************************************************************/ + +#ifndef BITENC_H +#define BITENC_H + +#include "qc_data.h" +#include "aacenc_tns.h" +#include "channel_map.h" +#include "interface.h" /* obsolete, when PSY_OUT is thrown out of the WritBS-call! */ +#include "FDK_audio.h" +#include "aacenc.h" + +#include "tpenc_lib.h" + +typedef enum { + MAX_ENCODER_CHANNELS = 9, + MAX_BLOCK_TYPES = 4, + MAX_AAC_LAYERS = 9, + MAX_LAYERS = MAX_AAC_LAYERS, /* only one core layer if present */ + FIRST_LAY = 1 /* default layer number for AAC nonscalable */ +} _MAX_CONST; + +#define BUFFER_MX_HUFFCB_SIZE \ + (32 * sizeof(INT)) /* our FDK_bitbuffer needs size of power 2 */ + +#define EL_ID_BITS (3) + +/** + * \brief Arbitrary order bitstream writer. This function can either assemble a + * bit stream and write into the bit buffer of hTpEnc or calculate the number of + * static bits (signal independent) TpEnc handle must be NULL in this + * case. Or also Calculate the minimum possible number of static bits + * which by disabling all tools e.g. MS, TNS and sbfCnt=0. The minCnt + * parameter has to be 1 in this latter case. + * \param hTpEnc Transport encoder handle. If NULL, the number of static bits + * will be returned into *pBitDemand. + * \param pElInfo + * \param qcOutChannel + * \param hReorderInfo + * \param psyOutElement + * \param psyOutChannel + * \param syntaxFlags Bit stream syntax flags as defined in FDK_audio.h (Audio + * Codec flags). + * \param aot + * \param epConfig + * \param pBitDemand Pointer to an int where the amount of bits is returned + * into. The returned value depends on if hTpEnc is NULL and minCnt. + * \param minCnt If non-zero the value returned into *pBitDemand is the absolute + * minimum required amount of static bits in order to write a valid bit stream. + * \return AAC_ENCODER_ERROR error code + */ +AAC_ENCODER_ERROR FDKaacEnc_ChannelElementWrite( + HANDLE_TRANSPORTENC hTpEnc, ELEMENT_INFO *pElInfo, + QC_OUT_CHANNEL *qcOutChannel[(2)], PSY_OUT_ELEMENT *psyOutElement, + PSY_OUT_CHANNEL *psyOutChannel[(2)], UINT syntaxFlags, + AUDIO_OBJECT_TYPE aot, SCHAR epConfig, INT *pBitDemand, UCHAR minCnt); +/** + * \brief Write bit stream or account static bits + * \param hTpEnc transport encoder handle. If NULL, the function will + * not write any bit stream data but only count the amount + * of static (signal independent) bits + * \param channelMapping Channel mapping info + * \param qcOut + * \param psyOut + * \param qcKernel + * \param hBSE + * \param aot Audio Object Type being encoded + * \param syntaxFlags Flags indicating format specific detail + * \param epConfig Error protection config + */ +AAC_ENCODER_ERROR FDKaacEnc_WriteBitstream(HANDLE_TRANSPORTENC hTpEnc, + CHANNEL_MAPPING *channelMapping, + QC_OUT *qcOut, PSY_OUT *psyOut, + QC_STATE *qcKernel, + AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +INT FDKaacEnc_writeExtensionData(HANDLE_TRANSPORTENC hTpEnc, + QC_OUT_EXTENSION *pExtension, + INT elInstanceTag, UINT alignAnchor, + UINT syntaxFlags, AUDIO_OBJECT_TYPE aot, + SCHAR epConfig); + +#endif /* BITENC_H */ diff --git a/fdk-aac/libAACenc/src/block_switch.cpp b/fdk-aac/libAACenc/src/block_switch.cpp new file mode 100644 index 0000000..c132253 --- /dev/null +++ b/fdk-aac/libAACenc/src/block_switch.cpp @@ -0,0 +1,582 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner, Tobias Chalupka + + Description: Block switching + +*******************************************************************************/ + +/****************** Includes *****************************/ + +#include "block_switch.h" +#include "genericStds.h" + +#define LOWOV_WINDOW _LOWOV_WINDOW + +/**************** internal function prototypes ***********/ + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx); + +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal); + +/****************** Constants *****************************/ +/* LONG START + * SHORT STOP LOWOV */ +static const INT blockType2windowShape[2][5] = { + {SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW, SINE_WINDOW, KBD_WINDOW}, /* LD */ + {KBD_WINDOW, SINE_WINDOW, SINE_WINDOW, KBD_WINDOW, WRONG_WINDOW}}; /* LC */ + +/* IIR high pass coeffs */ + +#ifndef SINETABLE_16BIT + +static const FIXP_DBL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_DBL(-0.5095), FL2FXCONST_DBL(0.7548)}; + +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_DBL oneMinusAccWindowNrgFac = FL2FXCONST_DBL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_DBL invAttackRatio = + FL2FXCONST_DBL(0.1f); /* inverted lower ratio limit for attacks */ + +/* The next constants are scaled, because they are used for comparison with + * scaled values*/ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#else + +static const FIXP_SGL hiPassCoeff[BLOCK_SWITCHING_IIR_LEN] = { + FL2FXCONST_SGL(-0.5095), FL2FXCONST_SGL(0.7548)}; + +static const FIXP_DBL accWindowNrgFac = + FL2FXCONST_DBL(0.3f); /* factor for accumulating filtered window energies */ +static const FIXP_SGL oneMinusAccWindowNrgFac = FL2FXCONST_SGL(0.7f); +/* static const float attackRatio = 10.0; */ /* lower ratio limit for attacks */ +static const FIXP_SGL invAttackRatio = + FL2FXCONST_SGL(0.1f); /* inverted lower ratio limit for attacks */ +/* minimum energy for attacks */ +static const FIXP_DBL minAttackNrg = + (FL2FXCONST_DBL(1e+6f * NORM_PCM_ENERGY) >> + BLOCK_SWITCH_ENERGY_SHIFT); /* minimum energy for attacks */ + +#endif + +/**************** internal function prototypes ***********/ + +/****************** Routines ****************************/ +void FDKaacEnc_InitBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay) { + FDKmemclear(blockSwitchingControl, sizeof(BLOCK_SWITCHING_CONTROL)); + + if (isLowDelay) { + blockSwitchingControl->nBlockSwitchWindows = 4; + blockSwitchingControl->allowShortFrames = 0; + blockSwitchingControl->allowLookAhead = 0; + } else { + blockSwitchingControl->nBlockSwitchWindows = 8; + blockSwitchingControl->allowShortFrames = 1; + blockSwitchingControl->allowLookAhead = 1; + } + + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + /* Initialize startvalue for blocktype */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; +} + +static const INT suggestedGroupingTable[TRANS_FAC][MAX_NO_OF_GROUPS] = { + /* Attack in Window 0 */ {1, 3, 3, 1}, + /* Attack in Window 1 */ {1, 1, 3, 3}, + /* Attack in Window 2 */ {2, 1, 3, 2}, + /* Attack in Window 3 */ {3, 1, 3, 1}, + /* Attack in Window 4 */ {3, 1, 1, 3}, + /* Attack in Window 5 */ {3, 2, 1, 2}, + /* Attack in Window 6 */ {3, 3, 1, 1}, + /* Attack in Window 7 */ {3, 3, 1, 1}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ +/* assume no look-ahead */ +static const INT chgWndSq[2][N_BLOCKTYPES] = { + /* LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW */ + /*no attack*/ {LONG_WINDOW, STOP_WINDOW, WRONG_WINDOW, LONG_WINDOW, + STOP_WINDOW, WRONG_WINDOW}, + /*attack */ {START_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, START_WINDOW, + LOWOV_WINDOW, WRONG_WINDOW}}; + +/* change block type depending on current blocktype and whether there's an + * attack */ +/* assume look-ahead */ +static const INT chgWndSqLkAhd[2][2][N_BLOCKTYPES] = { + /*attack LONG WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW LOWOV_WINDOW, WRONG_WINDOW */ /* last attack */ + /*no attack*/ { + {LONG_WINDOW, SHORT_WINDOW, STOP_WINDOW, LONG_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}, /* no attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, START_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}}, /* no attack */ + /*no attack*/ {{LONG_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LONG_WINDOW, + WRONG_WINDOW, WRONG_WINDOW}, /* attack */ + /*attack */ {START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, + START_WINDOW, WRONG_WINDOW, + WRONG_WINDOW}} /* attack */ +}; + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const INT granuleLength, const int isLFE, + const INT_PCM *pTimeSignal) { + UINT i; + FIXP_DBL enM1, enMax; + + UINT nBlockSwitchWindows = blockSwitchingControl->nBlockSwitchWindows; + + /* for LFE : only LONG window allowed */ + if (isLFE) { + /* case LFE: */ + /* only long blocks, always use sine windows (MPEG2 AAC, MPEG4 AAC) */ + blockSwitchingControl->lastWindowSequence = LONG_WINDOW; + blockSwitchingControl->windowShape = SINE_WINDOW; + blockSwitchingControl->noOfGroups = 1; + blockSwitchingControl->groupLen[0] = 1; + + return (0); + }; + + /* Save current attack index as last attack index */ + blockSwitchingControl->lastattack = blockSwitchingControl->attack; + blockSwitchingControl->lastAttackIndex = blockSwitchingControl->attackIndex; + + /* Save current window energy as last window energy */ + FDKmemcpy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->windowNrg[1], + sizeof(blockSwitchingControl->windowNrg[0])); + FDKmemcpy(blockSwitchingControl->windowNrgF[0], + blockSwitchingControl->windowNrgF[1], + sizeof(blockSwitchingControl->windowNrgF[0])); + + if (blockSwitchingControl->allowShortFrames) { + /* Calculate suggested grouping info for the last frame */ + + /* Reset grouping info */ + FDKmemclear(blockSwitchingControl->groupLen, + sizeof(blockSwitchingControl->groupLen)); + + /* Set grouping info */ + blockSwitchingControl->noOfGroups = MAX_NO_OF_GROUPS; + + FDKmemcpy(blockSwitchingControl->groupLen, + suggestedGroupingTable[blockSwitchingControl->lastAttackIndex], + sizeof(blockSwitchingControl->groupLen)); + + if (blockSwitchingControl->attack == TRUE) + blockSwitchingControl->maxWindowNrg = + FDKaacEnc_GetWindowEnergy(blockSwitchingControl->windowNrg[0], + blockSwitchingControl->lastAttackIndex); + else + blockSwitchingControl->maxWindowNrg = FL2FXCONST_DBL(0.0); + } + + /* Calculate unfiltered and filtered energies in subwindows and combine to + * segments */ + FDKaacEnc_CalcWindowEnergy( + blockSwitchingControl, + granuleLength >> (nBlockSwitchWindows == 4 ? 2 : 3), pTimeSignal); + + /* now calculate if there is an attack */ + + /* reset attack */ + blockSwitchingControl->attack = FALSE; + + /* look for attack */ + enMax = FL2FXCONST_DBL(0.0f); + enM1 = blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1]; + + for (i = 0; i < nBlockSwitchWindows; i++) { + FIXP_DBL tmp = + fMultDiv2(oneMinusAccWindowNrgFac, blockSwitchingControl->accWindowNrg); + blockSwitchingControl->accWindowNrg = fMultAdd(tmp, accWindowNrgFac, enM1); + + if (fMult(blockSwitchingControl->windowNrgF[1][i], invAttackRatio) > + blockSwitchingControl->accWindowNrg) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = i; + } + enM1 = blockSwitchingControl->windowNrgF[1][i]; + enMax = fixMax(enMax, enM1); + } + + if (enMax < minAttackNrg) blockSwitchingControl->attack = FALSE; + + /* Check if attack spreads over frame border */ + if ((blockSwitchingControl->attack == FALSE) && + (blockSwitchingControl->lastattack == TRUE)) { + /* if attack is in last window repeat SHORT_WINDOW */ + if (((blockSwitchingControl->windowNrgF[0][nBlockSwitchWindows - 1] >> 4) > + fMult((FIXP_DBL)(10 << (DFRACT_BITS - 1 - 4)), + blockSwitchingControl->windowNrgF[1][1])) && + (blockSwitchingControl->lastAttackIndex == + (INT)nBlockSwitchWindows - 1)) { + blockSwitchingControl->attack = TRUE; + blockSwitchingControl->attackIndex = 0; + } + } + + if (blockSwitchingControl->allowLookAhead) { + blockSwitchingControl->lastWindowSequence = + chgWndSqLkAhd[blockSwitchingControl->lastattack] + [blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } else { + /* Low Delay */ + blockSwitchingControl->lastWindowSequence = + chgWndSq[blockSwitchingControl->attack] + [blockSwitchingControl->lastWindowSequence]; + } + + /* update window shape */ + blockSwitchingControl->windowShape = + blockType2windowShape[blockSwitchingControl->allowShortFrames] + [blockSwitchingControl->lastWindowSequence]; + + return (0); +} + +static FIXP_DBL FDKaacEnc_GetWindowEnergy(const FIXP_DBL in[], + const INT blSwWndIdx) { + /* For coherency, change FDKaacEnc_GetWindowEnergy() to calcluate the energy + for a block switching analysis windows, not for a short block. The same is + done FDKaacEnc_CalcWindowEnergy(). The result of + FDKaacEnc_GetWindowEnergy() is used for a comparision of the max energy of + left/right channel. */ + + return in[blSwWndIdx]; +} + +static void FDKaacEnc_CalcWindowEnergy( + BLOCK_SWITCHING_CONTROL *RESTRICT blockSwitchingControl, INT windowLen, + const INT_PCM *pTimeSignal) { + INT i; + UINT w; + +#ifndef SINETABLE_16BIT + const FIXP_DBL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_DBL hiPassCoeff1 = hiPassCoeff[1]; +#else + const FIXP_SGL hiPassCoeff0 = hiPassCoeff[0]; + const FIXP_SGL hiPassCoeff1 = hiPassCoeff[1]; +#endif + + FIXP_DBL temp_iirState0 = blockSwitchingControl->iirStates[0]; + FIXP_DBL temp_iirState1 = blockSwitchingControl->iirStates[1]; + + /* sum up scalarproduct of timesignal as windowed Energies */ + for (w = 0; w < blockSwitchingControl->nBlockSwitchWindows; w++) { + ULONG temp_windowNrg = 0x0; + ULONG temp_windowNrgF = 0x0; + + /* windowNrg = sum(timesample^2) */ + for (i = 0; i < windowLen; i++) { + FIXP_DBL tempUnfiltered, t1, t2; + /* tempUnfiltered is scaled with 1 to prevent overflows during calculation + * of tempFiltred */ +#if SAMPLE_BITS == DFRACT_BITS + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ >> 1; +#else + tempUnfiltered = (FIXP_DBL)*pTimeSignal++ + << (DFRACT_BITS - SAMPLE_BITS - 1); +#endif + t1 = fMultDiv2(hiPassCoeff1, tempUnfiltered - temp_iirState0); + t2 = fMultDiv2(hiPassCoeff0, temp_iirState1); + temp_iirState0 = tempUnfiltered; + temp_iirState1 = (t1 - t2) << 1; + + temp_windowNrg += (LONG)fPow2Div2(temp_iirState0) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + temp_windowNrgF += (LONG)fPow2Div2(temp_iirState1) >> + (BLOCK_SWITCH_ENERGY_SHIFT - 1 - 2); + } + blockSwitchingControl->windowNrg[1][w] = + (LONG)fMin(temp_windowNrg, (UINT)MAXVAL_DBL); + blockSwitchingControl->windowNrgF[1][w] = + (LONG)fMin(temp_windowNrgF, (UINT)MAXVAL_DBL); + } + blockSwitchingControl->iirStates[0] = temp_iirState0; + blockSwitchingControl->iirStates[1] = temp_iirState1; +} + +static const UCHAR synchronizedBlockTypeTable[5][5] = { + /* LONG_WINDOW START_WINDOW SHORT_WINDOW STOP_WINDOW + LOWOV_WINDOW*/ + /* LONG_WINDOW */ {LONG_WINDOW, START_WINDOW, SHORT_WINDOW, STOP_WINDOW, + LOWOV_WINDOW}, + /* START_WINDOW */ + {START_WINDOW, START_WINDOW, SHORT_WINDOW, SHORT_WINDOW, LOWOV_WINDOW}, + /* SHORT_WINDOW */ + {SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, SHORT_WINDOW, WRONG_WINDOW}, + /* STOP_WINDOW */ + {STOP_WINDOW, SHORT_WINDOW, SHORT_WINDOW, STOP_WINDOW, LOWOV_WINDOW}, + /* LOWOV_WINDOW */ + {LOWOV_WINDOW, LOWOV_WINDOW, WRONG_WINDOW, LOWOV_WINDOW, LOWOV_WINDOW}, +}; + +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT nChannels, + const INT commonWindow) { + UCHAR patchType = LONG_WINDOW; + + if (nChannels == 2 && commonWindow == TRUE) { + /* could be better with a channel loop (need a handle to psy_data) */ + /* get suggested Block Types and synchronize */ + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlLeft + ->lastWindowSequence]; + patchType = synchronizedBlockTypeTable[patchType][blockSwitchingControlRight + ->lastWindowSequence]; + + /* sanity check (no change from low overlap window to short winow and vice + * versa) */ + if (patchType == WRONG_WINDOW) return -1; /* mixed up AAC-LC and AAC-LD */ + + /* Set synchronized Blocktype */ + blockSwitchingControlLeft->lastWindowSequence = patchType; + blockSwitchingControlRight->lastWindowSequence = patchType; + + /* update window shape */ + blockSwitchingControlLeft->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlLeft->lastWindowSequence]; + blockSwitchingControlRight->windowShape = + blockType2windowShape[blockSwitchingControlLeft->allowShortFrames] + [blockSwitchingControlRight->lastWindowSequence]; + } + + if (blockSwitchingControlLeft->allowShortFrames) { + int i; + + if (nChannels == 2) { + if (commonWindow == TRUE) { + /* Synchronize grouping info */ + int windowSequenceLeftOld = + blockSwitchingControlLeft->lastWindowSequence; + int windowSequenceRightOld = + blockSwitchingControlRight->lastWindowSequence; + + /* Long Blocks */ + if (patchType != SHORT_WINDOW) { + /* Set grouping info */ + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + blockSwitchingControlRight->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + blockSwitchingControlRight->groupLen[i] = 0; + } + } + + /* Short Blocks */ + else { + /* in case all two channels were detected as short-blocks before + * syncing, use the grouping of channel with higher maxWindowNrg */ + if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld == SHORT_WINDOW)) { + if (blockSwitchingControlLeft->maxWindowNrg > + blockSwitchingControlRight->maxWindowNrg) { + /* Left Channel wins */ + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; + } + } else { + /* Right Channel wins */ + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; + } + } + } else if ((windowSequenceLeftOld == SHORT_WINDOW) && + (windowSequenceRightOld != SHORT_WINDOW)) { + /* else use grouping of short-block channel */ + blockSwitchingControlRight->noOfGroups = + blockSwitchingControlLeft->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = + blockSwitchingControlLeft->groupLen[i]; + } + } else if ((windowSequenceRightOld == SHORT_WINDOW) && + (windowSequenceLeftOld != SHORT_WINDOW)) { + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups; + for (i = 0; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = + blockSwitchingControlRight->groupLen[i]; + } + } else { + /* syncing a start and stop window ... */ + blockSwitchingControlLeft->noOfGroups = + blockSwitchingControlRight->noOfGroups = 2; + blockSwitchingControlLeft->groupLen[0] = + blockSwitchingControlRight->groupLen[0] = 4; + blockSwitchingControlLeft->groupLen[1] = + blockSwitchingControlRight->groupLen[1] = 4; + } + } /* Short Blocks */ + } else { + /* stereo, no common window */ + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + if (blockSwitchingControlRight->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlRight->noOfGroups = 1; + blockSwitchingControlRight->groupLen[0] = 1; + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlRight->groupLen[i] = 0; + } + } + } /* common window */ + } else { + /* Mono */ + if (blockSwitchingControlLeft->lastWindowSequence != SHORT_WINDOW) { + blockSwitchingControlLeft->noOfGroups = 1; + blockSwitchingControlLeft->groupLen[0] = 1; + + for (i = 1; i < MAX_NO_OF_GROUPS; i++) { + blockSwitchingControlLeft->groupLen[i] = 0; + } + } + } + } /* allowShortFrames */ + + /* Translate LOWOV_WINDOW block type to a meaningful window shape. */ + if (!blockSwitchingControlLeft->allowShortFrames) { + if (blockSwitchingControlLeft->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlLeft->lastWindowSequence != STOP_WINDOW) { + blockSwitchingControlLeft->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlLeft->windowShape = LOL_WINDOW; + } + } + if (nChannels == 2) { + if (!blockSwitchingControlRight->allowShortFrames) { + if (blockSwitchingControlRight->lastWindowSequence != LONG_WINDOW && + blockSwitchingControlRight->lastWindowSequence != STOP_WINDOW) { + blockSwitchingControlRight->lastWindowSequence = LONG_WINDOW; + blockSwitchingControlRight->windowShape = LOL_WINDOW; + } + } + } + + return 0; +} diff --git a/fdk-aac/libAACenc/src/block_switch.h b/fdk-aac/libAACenc/src/block_switch.h new file mode 100644 index 0000000..ff20f84 --- /dev/null +++ b/fdk-aac/libAACenc/src/block_switch.h @@ -0,0 +1,162 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Block switching + +*******************************************************************************/ + +#ifndef BLOCK_SWITCH_H +#define BLOCK_SWITCH_H + +#include "common_fix.h" + +#include "psy_const.h" + +/****************** Defines ******************************/ +#define BLOCK_SWITCH_WINDOWS 8 /* number of windows for energy calculation */ + +#define BLOCK_SWITCHING_IIR_LEN \ + 2 /* Length of HighPass-IIR-Filter for Attack-Detection */ +#define BLOCK_SWITCH_ENERGY_SHIFT \ + 7 /* should be logDualis(BLOCK_SWITCH_WINDOW_LEN) to avoid overflow in \ + windowNrgs. */ + +#define LAST_WINDOW 0 +#define THIS_WINDOW 1 + +/****************** Structures ***************************/ +typedef struct { + INT lastWindowSequence; + INT windowShape; + INT lastWindowShape; + UINT nBlockSwitchWindows; /* number of windows for energy calculation */ + INT attack; + INT lastattack; + INT attackIndex; + INT lastAttackIndex; + INT allowShortFrames; /* for Low Delay, don't allow short frames */ + INT allowLookAhead; /* for Low Delay, don't do look-ahead */ + INT noOfGroups; + INT groupLen[MAX_NO_OF_GROUPS]; + FIXP_DBL maxWindowNrg; /* max energy in subwindows */ + + FIXP_DBL + windowNrg[2][BLOCK_SWITCH_WINDOWS]; /* time signal energy in Subwindows + (last and current) */ + FIXP_DBL windowNrgF[2][BLOCK_SWITCH_WINDOWS]; /* filtered time signal energy + in segments (last and + current) */ + FIXP_DBL accWindowNrg; /* recursively accumulated windowNrgF */ + + FIXP_DBL iirStates[BLOCK_SWITCHING_IIR_LEN]; /* filter delay-line */ + +} BLOCK_SWITCHING_CONTROL; + +void FDKaacEnc_InitBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControl, INT isLowDelay); + +int FDKaacEnc_BlockSwitching(BLOCK_SWITCHING_CONTROL *blockSwitchingControl, + const INT granuleLength, const int isLFE, + const INT_PCM *pTimeSignal); + +int FDKaacEnc_SyncBlockSwitching( + BLOCK_SWITCHING_CONTROL *blockSwitchingControlLeft, + BLOCK_SWITCHING_CONTROL *blockSwitchingControlRight, const INT noOfChannels, + const INT commonWindow); + +#endif /* #ifndef BLOCK_SWITCH_H */ diff --git a/fdk-aac/libAACenc/src/channel_map.cpp b/fdk-aac/libAACenc/src/channel_map.cpp new file mode 100644 index 0000000..6ee91d5 --- /dev/null +++ b/fdk-aac/libAACenc/src/channel_map.cpp @@ -0,0 +1,664 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Groeschel + + Description: channel mapping functionality + +*******************************************************************************/ + +#include "channel_map.h" +#include "bitenc.h" +#include "psy_const.h" +#include "qc_data.h" +#include "aacEnc_ram.h" +#include "FDK_tools_rom.h" + +/* channel_assignment treats the relationship of Input file channels + to the encoder channels. + This is necessary because the usual order in RIFF files (.wav) + is different from the elements order in the coder given + by Table 8.1 (implicit speaker mapping) of the AAC standard. + + In mono and stereo case, this is trivial. + In mc case, it looks like this: + + Channel Input file coder chan +5ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 3 3 (1st of 2nd CPE) + right surround 4 4 (2nd of 2nd CPE) + +5.1ch: + front center 2 0 (SCE channel) + left center 0 1 (1st of 1st CPE) + right center 1 2 (2nd of 1st CPE) + left surround 4 3 (1st of 2nd CPE) + right surround 5 4 (2nd of 2nd CPE) + LFE 3 5 (LFE) +*/ + +/* Channel mode configuration tab provides, + corresponding number of channels and elements +*/ +static const CHANNEL_MODE_CONFIG_TAB channelModeConfig[] = { + {MODE_1, 1, 1, 1}, /* chCfg 1, SCE */ + {MODE_2, 2, 2, 1}, /* chCfg 2, CPE */ + {MODE_1_2, 3, 3, 2}, /* chCfg 3, SCE,CPE */ + {MODE_1_2_1, 4, 4, 3}, /* chCfg 4, SCE,CPE,SCE */ + {MODE_1_2_2, 5, 5, 3}, /* chCfg 5, SCE,CPE,CPE */ + {MODE_1_2_2_1, 6, 5, 4}, /* chCfg 6, SCE,CPE,CPE,LFE */ + {MODE_1_2_2_2_1, 8, 7, 5}, /* chCfg 7, SCE,CPE,CPE,CPE,LFE */ + {MODE_6_1, 7, 6, 5}, /* chCfg 11, SCE,CPE,CPE,SCE,LFE */ + {MODE_7_1_BACK, 8, 7, 5}, /* chCfg 12, SCE,CPE,CPE,CPE,LFE */ + {MODE_7_1_TOP_FRONT, 8, 7, 5}, /* chCfg 14, SCE,CPE,CPE,LFE,CPE */ + {MODE_7_1_REAR_SURROUND, 8, 7, + 5}, /* same as MODE_7_1_BACK, SCE,CPE,CPE,CPE,LFE */ + {MODE_7_1_FRONT_CENTER, 8, 7, + 5}, /* same as MODE_1_2_2_2_1, SCE,CPE,CPE,CPE,LFE */ + +}; + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, + INT nChannels) { + INT i; + CHANNEL_MODE encMode = MODE_INVALID; + + if (*mode == MODE_UNKNOWN) { + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].nChannels == nChannels) { + encMode = channelModeConfig[i].encMode; + break; + } + } + *mode = encMode; + } else { + /* check if valid channel configuration */ + if (FDKaacEnc_GetChannelModeConfiguration(*mode)->nChannels == nChannels) { + encMode = *mode; + } + } + + if (encMode == MODE_INVALID) { + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +static INT FDKaacEnc_initElement(ELEMENT_INFO* elInfo, MP4_ELEMENT_ID elType, + INT* cnt, FDK_channelMapDescr* mapDescr, + UINT mapIdx, INT* it_cnt, + const FIXP_DBL relBits) { + INT error = 0; + INT counter = *cnt; + + elInfo->elType = elType; + elInfo->relativeBits = relBits; + + switch (elInfo->elType) { + case ID_SCE: + case ID_LFE: + case ID_CCE: + elInfo->nChannelsInEl = 1; + elInfo->ChannelIndex[0] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->instanceTag = it_cnt[elType]++; + break; + case ID_CPE: + elInfo->nChannelsInEl = 2; + elInfo->ChannelIndex[0] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->ChannelIndex[1] = + FDK_chMapDescr_getMapValue(mapDescr, counter++, mapIdx); + elInfo->instanceTag = it_cnt[elType]++; + break; + case ID_DSE: + elInfo->nChannelsInEl = 0; + elInfo->ChannelIndex[0] = 0; + elInfo->ChannelIndex[1] = 0; + elInfo->instanceTag = it_cnt[elType]++; + break; + default: + error = 1; + }; + *cnt = counter; + return error; +} + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, + CHANNEL_ORDER co, + CHANNEL_MAPPING* cm) { + INT count = 0; /* count through coder channels */ + INT it_cnt[ID_END + 1]; + INT i; + UINT mapIdx; + FDK_channelMapDescr mapDescr; + + for (i = 0; i < ID_END; i++) it_cnt[i] = 0; + + FDKmemclear(cm, sizeof(CHANNEL_MAPPING)); + + /* init channel mapping*/ + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].encMode == mode) { + cm->encMode = channelModeConfig[i].encMode; + cm->nChannels = channelModeConfig[i].nChannels; + cm->nChannelsEff = channelModeConfig[i].nChannelsEff; + cm->nElements = channelModeConfig[i].nElements; + + break; + } + } + + /* init map descriptor */ + FDK_chMapDescr_init(&mapDescr, NULL, 0, (co == CH_ORDER_MPEG) ? 1 : 0); + switch (mode) { + case MODE_7_1_REAR_SURROUND: /* MODE_7_1_REAR_SURROUND is equivalent to + MODE_7_1_BACK */ + mapIdx = (INT)MODE_7_1_BACK; + break; + case MODE_7_1_FRONT_CENTER: /* MODE_7_1_FRONT_CENTER is equivalent to + MODE_1_2_2_2_1 */ + mapIdx = (INT)MODE_1_2_2_2_1; + break; + default: + mapIdx = + (INT)mode > 14 + ? 0 + : (INT) + mode; /* if channel config > 14 MPEG mapping will be used */ + } + + /* init element info struct */ + switch (mode) { + case MODE_1: + /* (mono) sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + case MODE_2: + /* (stereo) cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, (FIXP_DBL)MAXVAL_DBL); + break; + + case MODE_1_2: + /* sce + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.6f)); + break; + + case MODE_1_2_1: + /* sce + cpe + sce */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.3f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.4f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.3f)); + break; + + case MODE_1_2_2: + /* sce + cpe + cpe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.37f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.37f)); + break; + + case MODE_1_2_2_1: + /* (5.1) sce + cpe + cpe + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.24f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.35f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.06f)); + break; + + case MODE_6_1: + /* (6.1) sce + cpe + cpe + sce + lfe */ + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.2f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.275f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.275f)); + FDKaacEnc_initElement(&cm->elInfo[3], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.2f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.05f)); + break; + + case MODE_1_2_2_2_1: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: { + /* (7.1) sce + cpe + cpe + cpe + lfe */ + /* (7.1 top) sce + cpe + cpe + lfe + cpe */ + + FDKaacEnc_initElement(&cm->elInfo[0], ID_SCE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.18f)); + FDKaacEnc_initElement(&cm->elInfo[1], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[2], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + if (mode != MODE_7_1_TOP_FRONT) { + FDKaacEnc_initElement(&cm->elInfo[3], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.04f)); + } else { + FDKaacEnc_initElement(&cm->elInfo[3], ID_LFE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.04f)); + FDKaacEnc_initElement(&cm->elInfo[4], ID_CPE, &count, &mapDescr, mapIdx, + it_cnt, FL2FXCONST_DBL(0.26f)); + } + break; + } + + default: + //*chMap=0; + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + }; + + FDK_ASSERT(cm->nElements <= ((8))); + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE* hQC, CHANNEL_MAPPING* cm, + INT bitrateTot, INT averageBitsTot, + INT maxChannelBits) { + int sc_brTot = CountLeadingBits(bitrateTot); + + switch (cm->encMode) { + case MODE_1: + hQC->elementBits[0]->chBitrateEl = bitrateTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + + case MODE_2: + hQC->elementBits[0]->chBitrateEl = bitrateTot >> 1; + + hQC->elementBits[0]->maxBitsEl = 2 * maxChannelBits; + + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + break; + case MODE_1_2: { + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + break; + } + case MODE_1_2_1: { + /* sce + cpe + sce */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sce1Rate = cm->elInfo[0].relativeBits; + FIXP_DBL cpeRate = cm->elInfo[1].relativeBits; + FIXP_DBL sce2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sce1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(sce2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = maxChannelBits; + break; + } + case MODE_1_2_2: { + /* sce + cpe + cpe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + break; + } + case MODE_1_2_2_1: { + /* (5.1) sce + cpe + cpe + lfe */ + hQC->elementBits[0]->relativeBitsEl = cm->elInfo[0].relativeBits; + hQC->elementBits[1]->relativeBitsEl = cm->elInfo[1].relativeBits; + hQC->elementBits[2]->relativeBitsEl = cm->elInfo[2].relativeBits; + hQC->elementBits[3]->relativeBitsEl = cm->elInfo[3].relativeBits; + FIXP_DBL sceRate = cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = cm->elInfo[2].relativeBits; + FIXP_DBL lfeRate = cm->elInfo[3].relativeBits; + + int maxBitsTot = + maxChannelBits * 5; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits); + sc = CountLeadingBits(maxChannelBits); + + maxChannelBits = + fMult((FIXP_DBL)maxChannelBits << sc, GetInvInt(5)) >> sc; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[3]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[3]->maxBitsEl = maxLfeBits; + + break; + } + case MODE_6_1: { + /* (6.1) sce + cpe + cpe + sce + lfe */ + FIXP_DBL sceRate = hQC->elementBits[0]->relativeBitsEl = + cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = hQC->elementBits[1]->relativeBitsEl = + cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = hQC->elementBits[2]->relativeBitsEl = + cm->elInfo[2].relativeBits; + FIXP_DBL sce2Rate = hQC->elementBits[3]->relativeBitsEl = + cm->elInfo[3].relativeBits; + FIXP_DBL lfeRate = hQC->elementBits[4]->relativeBitsEl = + cm->elInfo[4].relativeBits; + + int maxBitsTot = + maxChannelBits * 6; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits) / 6; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[3]->chBitrateEl = + fMult(sce2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[4]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[3]->maxBitsEl = maxChannelBits; + hQC->elementBits[4]->maxBitsEl = maxLfeBits; + break; + } + case MODE_7_1_TOP_FRONT: + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_1_2_2_2_1: { + int cpe3Idx = (cm->encMode != MODE_7_1_TOP_FRONT) ? 3 : 4; + int lfeIdx = (cm->encMode != MODE_7_1_TOP_FRONT) ? 4 : 3; + + /* (7.1) sce + cpe + cpe + cpe + lfe */ + FIXP_DBL sceRate = hQC->elementBits[0]->relativeBitsEl = + cm->elInfo[0].relativeBits; + FIXP_DBL cpe1Rate = hQC->elementBits[1]->relativeBitsEl = + cm->elInfo[1].relativeBits; + FIXP_DBL cpe2Rate = hQC->elementBits[2]->relativeBitsEl = + cm->elInfo[2].relativeBits; + FIXP_DBL cpe3Rate = hQC->elementBits[cpe3Idx]->relativeBitsEl = + cm->elInfo[cpe3Idx].relativeBits; + FIXP_DBL lfeRate = hQC->elementBits[lfeIdx]->relativeBitsEl = + cm->elInfo[lfeIdx].relativeBits; + + int maxBitsTot = + maxChannelBits * 7; /* LFE does not add to bit reservoir */ + int sc = CountLeadingBits(fixMax(maxChannelBits, averageBitsTot)); + int maxLfeBits = (int)fMax( + (INT)((fMult(lfeRate, (FIXP_DBL)(maxChannelBits << sc)) >> sc) << 1), + (INT)((fMult(FL2FXCONST_DBL(1.1f / 2.f), + fMult(lfeRate, (FIXP_DBL)(averageBitsTot << sc))) + << 1) >> + sc)); + + maxChannelBits = (maxBitsTot - maxLfeBits) / 7; + + hQC->elementBits[0]->chBitrateEl = + fMult(sceRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + hQC->elementBits[1]->chBitrateEl = + fMult(cpe1Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[2]->chBitrateEl = + fMult(cpe2Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[cpe3Idx]->chBitrateEl = + fMult(cpe3Rate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> (sc_brTot + 1); + hQC->elementBits[lfeIdx]->chBitrateEl = + fMult(lfeRate, (FIXP_DBL)(bitrateTot << sc_brTot)) >> sc_brTot; + + hQC->elementBits[0]->maxBitsEl = maxChannelBits; + hQC->elementBits[1]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[2]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[cpe3Idx]->maxBitsEl = 2 * maxChannelBits; + hQC->elementBits[lfeIdx]->maxBitsEl = maxLfeBits; + break; + } + + default: + return AAC_ENC_UNSUPPORTED_CHANNELCONFIG; + } + + return AAC_ENC_OK; +} + +/********************************************************************************/ +/* */ +/* function: GetMonoStereoMODE(const CHANNEL_MODE mode) */ +/* */ +/* description: Determines encoder setting from channel mode. */ +/* Multichannel modes are mapped to mono or stereo modes */ +/* returns MODE_MONO in case of mono, */ +/* MODE_STEREO in case of stereo */ +/* MODE_INVALID in case of error */ +/* */ +/* input: CHANNEL_MODE mode: Encoder mode (see qc_data.h). */ +/* output: return: CM_STEREO_MODE monoStereoSetting */ +/* (MODE_INVALID: error, */ +/* MODE_MONO: mono */ +/* MODE_STEREO: stereo). */ +/* */ +/* misc: No memory is allocated. */ +/* */ +/********************************************************************************/ + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode) { + ELEMENT_MODE monoStereoSetting = EL_MODE_INVALID; + + switch (mode) { + case MODE_1: /* mono setups */ + monoStereoSetting = EL_MODE_MONO; + break; + + case MODE_2: /* stereo setups */ + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + case MODE_6_1: + case MODE_1_2_2_2_1: + case MODE_7_1_REAR_SURROUND: + case MODE_7_1_FRONT_CENTER: + case MODE_7_1_BACK: + case MODE_7_1_TOP_FRONT: + monoStereoSetting = EL_MODE_STEREO; + break; + + default: /* error */ + monoStereoSetting = EL_MODE_INVALID; + break; + } + + return monoStereoSetting; +} + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration( + const CHANNEL_MODE mode) { + INT i; + const CHANNEL_MODE_CONFIG_TAB* cm_config = NULL; + + /* get channel mode config */ + for (i = 0; i < (INT)sizeof(channelModeConfig) / + (INT)sizeof(CHANNEL_MODE_CONFIG_TAB); + i++) { + if (channelModeConfig[i].encMode == mode) { + cm_config = &channelModeConfig[i]; + break; + } + } + return cm_config; +} diff --git a/fdk-aac/libAACenc/src/channel_map.h b/fdk-aac/libAACenc/src/channel_map.h new file mode 100644 index 0000000..f9154cd --- /dev/null +++ b/fdk-aac/libAACenc/src/channel_map.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Groeschel + + Description: channel mapping functionality + +*******************************************************************************/ + +#ifndef CHANNEL_MAP_H +#define CHANNEL_MAP_H + +#include "aacenc.h" +#include "psy_const.h" +#include "qc_data.h" + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; +} CHANNEL_MODE_CONFIG_TAB; + +/* Element mode */ +typedef enum { EL_MODE_INVALID = 0, EL_MODE_MONO, EL_MODE_STEREO } ELEMENT_MODE; + +AAC_ENCODER_ERROR FDKaacEnc_DetermineEncoderMode(CHANNEL_MODE* mode, + INT nChannels); + +AAC_ENCODER_ERROR FDKaacEnc_InitChannelMapping(CHANNEL_MODE mode, + CHANNEL_ORDER co, + CHANNEL_MAPPING* chMap); + +AAC_ENCODER_ERROR FDKaacEnc_InitElementBits(QC_STATE* hQC, CHANNEL_MAPPING* cm, + INT bitrateTot, INT averageBitsTot, + INT maxChannelBits); + +ELEMENT_MODE FDKaacEnc_GetMonoStereoMode(const CHANNEL_MODE mode); + +const CHANNEL_MODE_CONFIG_TAB* FDKaacEnc_GetChannelModeConfiguration( + const CHANNEL_MODE mode); + +#endif /* CHANNEL_MAP_H */ diff --git a/fdk-aac/libAACenc/src/chaosmeasure.cpp b/fdk-aac/libAACenc/src/chaosmeasure.cpp new file mode 100644 index 0000000..664284b --- /dev/null +++ b/fdk-aac/libAACenc/src/chaosmeasure.cpp @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Chaos measure calculation + +*******************************************************************************/ + +#include "chaosmeasure.h" + +/***************************************************************************** + functionname: FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast + description: Eberlein method of chaos measure calculation by high-pass + filtering amplitude spectrum + A special case of FDKaacEnc_CalculateChaosMeasureTonalGeneric +-- highly optimized +*****************************************************************************/ +static void FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( + FIXP_DBL *RESTRICT paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *RESTRICT chaosMeasure) { + INT i, j; + + /* calculate chaos measure by "peak filter" */ + /* make even and odd pass through data */ + FIXP_DBL left_0_div2, + center_0; /* left, center tap of filter, even numbered */ + FIXP_DBL left_1_div2, center_1; /* left, center tap of filter, odd numbered */ + + left_0_div2 = (FIXP_DBL)(((LONG)paMDCTDataNM0[0] ^ + ((LONG)paMDCTDataNM0[0] >> (DFRACT_BITS - 1))) >> + 1); + left_1_div2 = (FIXP_DBL)(((LONG)paMDCTDataNM0[1] ^ + ((LONG)paMDCTDataNM0[1] >> (DFRACT_BITS - 1))) >> + 1); + center_0 = (FIXP_DBL)((LONG)paMDCTDataNM0[2] ^ + ((LONG)paMDCTDataNM0[2] >> (DFRACT_BITS - 1))); + center_1 = (FIXP_DBL)((LONG)paMDCTDataNM0[3] ^ + ((LONG)paMDCTDataNM0[3] >> (DFRACT_BITS - 1))); + + for (j = 2; j < numberOfLines - 2; j += 2) { + FIXP_DBL right_0 = + (FIXP_DBL)((LONG)paMDCTDataNM0[j + 2] ^ + ((LONG)paMDCTDataNM0[j + 2] >> (DFRACT_BITS - 1))); + FIXP_DBL tmp_0 = left_0_div2 + (right_0 >> 1); + FIXP_DBL right_1 = + (FIXP_DBL)((LONG)paMDCTDataNM0[j + 3] ^ + ((LONG)paMDCTDataNM0[j + 3] >> (DFRACT_BITS - 1))); + FIXP_DBL tmp_1 = left_1_div2 + (right_1 >> 1); + + if (tmp_0 < center_0) { + INT leadingBits = CntLeadingZeros(center_0) - 1; + tmp_0 = schur_div(tmp_0 << leadingBits, center_0 << leadingBits, 8); + tmp_0 = fMult(tmp_0, tmp_0); + } else { + tmp_0 = (FIXP_DBL)MAXVAL_DBL; + } + chaosMeasure[j + 0] = tmp_0; + left_0_div2 = center_0 >> 1; + center_0 = right_0; + + if (tmp_1 < center_1) { + INT leadingBits = CntLeadingZeros(center_1) - 1; + tmp_1 = schur_div(tmp_1 << leadingBits, center_1 << leadingBits, 8); + tmp_1 = fMult(tmp_1, tmp_1); + } else { + tmp_1 = (FIXP_DBL)MAXVAL_DBL; + } + + left_1_div2 = center_1 >> 1; + center_1 = right_1; + chaosMeasure[j + 1] = tmp_1; + } + + /* provide chaos measure for first few lines */ + chaosMeasure[0] = chaosMeasure[2]; + chaosMeasure[1] = chaosMeasure[2]; + + /* provide chaos measure for last few lines */ + for (i = (numberOfLines - 3); i < numberOfLines; i++) + chaosMeasure[i] = FL2FXCONST_DBL(0.5); +} + +/***************************************************************************** + functionname: FDKaacEnc_CalculateChaosMeasure + description: calculates a chaosmeasure for every line, different methods + are available. 0 means tonal, 1 means noiselike + returns: + input: MDCT data, number of lines + output: chaosMeasure +*****************************************************************************/ +void FDKaacEnc_CalculateChaosMeasure(FIXP_DBL *paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *chaosMeasure) + +{ + FDKaacEnc_FDKaacEnc_CalculateChaosMeasurePeakFast( + paMDCTDataNM0, numberOfLines, chaosMeasure); +} diff --git a/fdk-aac/libAACenc/src/chaosmeasure.h b/fdk-aac/libAACenc/src/chaosmeasure.h new file mode 100644 index 0000000..60d4137 --- /dev/null +++ b/fdk-aac/libAACenc/src/chaosmeasure.h @@ -0,0 +1,112 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Chaos measure calculation + +*******************************************************************************/ + +#ifndef CHAOSMEASURE_H +#define CHAOSMEASURE_H + +#include "common_fix.h" +#include "psy_const.h" + +void FDKaacEnc_CalculateChaosMeasure(FIXP_DBL *paMDCTDataNM0, INT numberOfLines, + FIXP_DBL *chaosMeasure); + +#endif /* CHAOSMEASURE_H */ diff --git a/fdk-aac/libAACenc/src/dyn_bits.cpp b/fdk-aac/libAACenc/src/dyn_bits.cpp new file mode 100644 index 0000000..b52dc2e --- /dev/null +++ b/fdk-aac/libAACenc/src/dyn_bits.cpp @@ -0,0 +1,665 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Noiseless coder module + +*******************************************************************************/ + +#include "dyn_bits.h" +#include "bit_cnt.h" +#include "psy_const.h" +#include "aacenc_pns.h" +#include "aacEnc_ram.h" +#include "aacEnc_rom.h" + +typedef INT (*lookUpTable)[CODE_BOOK_ESC_NDX + 1]; + +static INT FDKaacEnc_getSideInfoBits(const SECTION_INFO* const huffsection, + const SHORT* const sideInfoTab, + const INT useHCR) { + INT sideInfoBits; + + if (useHCR && + ((huffsection->codeBook == 11) || (huffsection->codeBook >= 16))) { + sideInfoBits = 5; + } else { + sideInfoBits = sideInfoTab[huffsection->sfbCnt]; + } + + return (sideInfoBits); +} + +/* count bits using all possible tables */ +static void FDKaacEnc_buildBitLookUp( + const SHORT* const quantSpectrum, const INT maxSfb, + const INT* const sfbOffset, const UINT* const sfbMax, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + SECTION_INFO* const huffsection) { + INT i, sfbWidth; + + for (i = 0; i < maxSfb; i++) { + huffsection[i].sfbCnt = 1; + huffsection[i].sfbStart = i; + huffsection[i].sectionBits = INVALID_BITCOUNT; + huffsection[i].codeBook = -1; + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + FDKaacEnc_bitCount(quantSpectrum + sfbOffset[i], sfbWidth, sfbMax[i], + bitLookUp[i]); + } +} + +/* essential helper functions */ +static inline INT FDKaacEnc_findBestBook(const INT* const bc, INT* const book, + const INT useVCB11) { + INT minBits = INVALID_BITCOUNT, j; + + int end = CODE_BOOK_ESC_NDX; + + for (j = 0; j <= end; j++) { + if (bc[j] < minBits) { + minBits = bc[j]; + *book = j; + } + } + return (minBits); +} + +static inline INT FDKaacEnc_findMinMergeBits(const INT* const bc1, + const INT* const bc2, + const INT useVCB11) { + INT minBits = INVALID_BITCOUNT, j; + + DWORD_ALIGNED(bc1); + DWORD_ALIGNED(bc2); + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) { + minBits = fixMin(minBits, bc1[j] + bc2[j]); + } + return (minBits); +} + +static inline void FDKaacEnc_mergeBitLookUp(INT* const RESTRICT bc1, + const INT* const RESTRICT bc2) { + int j; + + for (j = 0; j <= CODE_BOOK_ESC_NDX; j++) { + FDK_ASSERT(INVALID_BITCOUNT == 0x1FFFFFFF); + bc1[j] = fixMin(bc1[j] + bc2[j], INVALID_BITCOUNT); + } +} + +static inline INT FDKaacEnc_findMaxMerge(const INT* const mergeGainLookUp, + const SECTION_INFO* const huffsection, + const INT maxSfb, INT* const maxNdx) { + INT i, maxMergeGain = 0; + int lastMaxNdx = 0; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) { + if (mergeGainLookUp[i] > maxMergeGain) { + maxMergeGain = mergeGainLookUp[i]; + lastMaxNdx = i; + } + } + *maxNdx = lastMaxNdx; + return (maxMergeGain); +} + +static inline INT FDKaacEnc_CalcMergeGain( + const SECTION_INFO* const huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const sideInfoTab, const INT ndx1, const INT ndx2, + const INT useVCB11) { + INT MergeGain, MergeBits, SplitBits; + + MergeBits = + sideInfoTab[huffsection[ndx1].sfbCnt + huffsection[ndx2].sfbCnt] + + FDKaacEnc_findMinMergeBits(bitLookUp[ndx1], bitLookUp[ndx2], useVCB11); + SplitBits = + huffsection[ndx1].sectionBits + + huffsection[ndx2].sectionBits; /* Bit amount for splitted huffsections */ + MergeGain = SplitBits - MergeBits; + + if ((huffsection[ndx1].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[ndx1].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[ndx1].codeBook == CODE_BOOK_IS_IN_PHASE_NO) || + (huffsection[ndx2].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + MergeGain = -1; + } + + return (MergeGain); +} + +/* sectioning Stage 0:find minimum codbooks */ +static void FDKaacEnc_gmStage0( + SECTION_INFO* const RESTRICT huffsection, + const INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const INT* const noiseNrg, const INT* const isBook) { + INT i; + + for (i = 0; i < maxSfb; i++) { + /* Side-Info bits will be calculated in Stage 1! */ + if (huffsection[i].sectionBits == INVALID_BITCOUNT) { + /* intensity and pns codebooks are already allocated in bitcount.c */ + if (noiseNrg[i] != NO_NOISE_PNS) { + huffsection[i].codeBook = CODE_BOOK_PNS_NO; + huffsection[i].sectionBits = 0; + } else if (isBook[i]) { + huffsection[i].codeBook = isBook[i]; + huffsection[i].sectionBits = 0; + } else { + huffsection[i].sectionBits = + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), + 0); /* useVCB11 must be 0!!! */ + } + } + } +} + +/* + sectioning Stage 1:merge all connected regions with the same code book and + calculate side info + */ +static void FDKaacEnc_gmStage1( + SECTION_INFO* const RESTRICT huffsection, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const SHORT* const sideInfoTab, const INT useVCB11) { + INT mergeStart = 0, mergeEnd; + + do { + for (mergeEnd = mergeStart + 1; mergeEnd < maxSfb; mergeEnd++) { + if (huffsection[mergeStart].codeBook != huffsection[mergeEnd].codeBook) + break; + + /* we can merge. update tables, side info bits will be updated outside of + * this loop */ + huffsection[mergeStart].sfbCnt++; + huffsection[mergeStart].sectionBits += huffsection[mergeEnd].sectionBits; + + /* update bit look up for all code books */ + FDKaacEnc_mergeBitLookUp(bitLookUp[mergeStart], bitLookUp[mergeEnd]); + } + + /* add side info info bits */ + huffsection[mergeStart].sectionBits += FDKaacEnc_getSideInfoBits( + &huffsection[mergeStart], sideInfoTab, useVCB11); + huffsection[mergeEnd - 1].sfbStart = + huffsection[mergeStart].sfbStart; /* speed up prev search */ + + mergeStart = mergeEnd; + + } while (mergeStart < maxSfb); +} + +/* + sectioning Stage 2:greedy merge algorithm, merge connected sections with + maximum bit gain until no more gain is possible + */ +static inline void FDKaacEnc_gmStage2( + SECTION_INFO* const RESTRICT huffsection, + INT* const RESTRICT mergeGainLookUp, + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], const INT maxSfb, + const SHORT* const sideInfoTab, const INT useVCB11) { + INT i; + + for (i = 0; i + huffsection[i].sfbCnt < maxSfb; i += huffsection[i].sfbCnt) { + mergeGainLookUp[i] = + FDKaacEnc_CalcMergeGain(huffsection, bitLookUp, sideInfoTab, i, + i + huffsection[i].sfbCnt, useVCB11); + } + + while (TRUE) { + INT maxMergeGain, maxNdx, maxNdxNext, maxNdxLast; + + maxMergeGain = + FDKaacEnc_findMaxMerge(mergeGainLookUp, huffsection, maxSfb, &maxNdx); + + /* exit while loop if no more gain is possible */ + if (maxMergeGain <= 0) break; + + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + /* merge sections with maximum bit gain */ + huffsection[maxNdx].sfbCnt += huffsection[maxNdxNext].sfbCnt; + huffsection[maxNdx].sectionBits += + huffsection[maxNdxNext].sectionBits - maxMergeGain; + + /* update bit look up table for merged huffsection */ + FDKaacEnc_mergeBitLookUp(bitLookUp[maxNdx], bitLookUp[maxNdxNext]); + + /* update mergeLookUpTable */ + if (maxNdx != 0) { + maxNdxLast = huffsection[maxNdx - 1].sfbStart; + mergeGainLookUp[maxNdxLast] = FDKaacEnc_CalcMergeGain( + huffsection, bitLookUp, sideInfoTab, maxNdxLast, maxNdx, useVCB11); + } + maxNdxNext = maxNdx + huffsection[maxNdx].sfbCnt; + + huffsection[maxNdxNext - 1].sfbStart = huffsection[maxNdx].sfbStart; + + if (maxNdxNext < maxSfb) + mergeGainLookUp[maxNdx] = FDKaacEnc_CalcMergeGain( + huffsection, bitLookUp, sideInfoTab, maxNdx, maxNdxNext, useVCB11); + } +} + +/* count bits used by the noiseless coder */ +static void FDKaacEnc_noiselessCounter( + SECTION_DATA* const RESTRICT sectionData, INT mergeGainLookUp[MAX_SFB_LONG], + INT bitLookUp[MAX_SFB_LONG][CODE_BOOK_ESC_NDX + 1], + const SHORT* const quantSpectrum, const UINT* const maxValueInSfb, + const INT* const sfbOffset, const INT blockType, const INT* const noiseNrg, + const INT* const isBook, const INT useVCB11) { + INT grpNdx, i; + const SHORT* sideInfoTab = NULL; + SECTION_INFO* huffsection; + + /* use appropriate side info table */ + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + default: + sideInfoTab = FDKaacEnc_sideInfoTabLong; + break; + case SHORT_WINDOW: + sideInfoTab = FDKaacEnc_sideInfoTabShort; + break; + } + + FDK_ASSERT(sideInfoTab != NULL); + + sectionData->noOfSections = 0; + sectionData->huffmanBits = 0; + sectionData->sideInfoBits = 0; + + if (sectionData->maxSfbPerGroup == 0) return; + + /* loop trough groups */ + for (grpNdx = 0; grpNdx < sectionData->sfbCnt; + grpNdx += sectionData->sfbPerGroup) { + huffsection = sectionData->huffsection + sectionData->noOfSections; + + /* count bits in this group */ + FDKaacEnc_buildBitLookUp(quantSpectrum, sectionData->maxSfbPerGroup, + sfbOffset + grpNdx, maxValueInSfb + grpNdx, + bitLookUp, huffsection); + + /* 0.Stage :Find minimum Codebooks */ + FDKaacEnc_gmStage0(huffsection, bitLookUp, sectionData->maxSfbPerGroup, + noiseNrg + grpNdx, isBook + grpNdx); + + /* 1.Stage :Merge all connected regions with the same code book */ + FDKaacEnc_gmStage1(huffsection, bitLookUp, sectionData->maxSfbPerGroup, + sideInfoTab, useVCB11); + + /* + 2.Stage + greedy merge algorithm, merge connected huffsections with maximum bit + gain until no more gain is possible + */ + + FDKaacEnc_gmStage2(huffsection, mergeGainLookUp, bitLookUp, + sectionData->maxSfbPerGroup, sideInfoTab, useVCB11); + + /* + compress output, calculate total huff and side bits + since we did not update the actual codebook in stage 2 + to save time, we must set it here for later use in bitenc + */ + + for (i = 0; i < sectionData->maxSfbPerGroup; i += huffsection[i].sfbCnt) { + if ((huffsection[i].codeBook == CODE_BOOK_PNS_NO) || + (huffsection[i].codeBook == CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + huffsection[i].sectionBits = 0; + } else { + /* the sections in the sectionData are now marked with the optimal code + * book */ + + FDKaacEnc_findBestBook(bitLookUp[i], &(huffsection[i].codeBook), + useVCB11); + + sectionData->huffmanBits += + huffsection[i].sectionBits - + FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + } + + huffsection[i].sfbStart += grpNdx; + + /* sum up side info bits (section data bits) */ + sectionData->sideInfoBits += + FDKaacEnc_getSideInfoBits(&huffsection[i], sideInfoTab, useVCB11); + sectionData->huffsection[sectionData->noOfSections++] = huffsection[i]; + } + } +} + +/******************************************************************************* + + functionname: FDKaacEnc_scfCount + returns : --- + description : count bits used by scalefactors. + + not in all cases if maxValueInSfb[] == 0 we set deltaScf + to zero. only if the difference of the last and future + scalefacGain is not greater then CODE_BOOK_SCF_LAV (60). + + example: + ^ + scalefacGain | + | + | last 75 + | | + | | + | | + | | current 50 + | | | + | | | + | | | + | | | + | | | future 5 + | | | | + --- ... ---------------------------- ... ---------> + sfb + + + if maxValueInSfb[] of current is zero because of a + notfallstrategie, we do not save bits and transmit a + deltaScf of 25. otherwise the deltaScf between the last + scalfacGain (75) and the future scalefacGain (5) is 70. + +********************************************************************************/ +static void FDKaacEnc_scfCount(const INT* const scalefacGain, + const UINT* const maxValueInSfb, + SECTION_DATA* const RESTRICT sectionData, + const INT* const isScale) { + INT i, j, k, m, n; + + INT lastValScf = 0; + INT deltaScf = 0; + INT found = 0; + INT scfSkipCounter = 0; + INT lastValIs = 0; + + sectionData->scalefacBits = 0; + + if (scalefacGain == NULL) return; + + sectionData->firstScf = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) { + sectionData->firstScf = sectionData->huffsection[i].sfbStart; + lastValScf = scalefacGain[sectionData->firstScf]; + break; + } + } + + for (i = 0; i < sectionData->noOfSections; i++) { + if ((sectionData->huffsection[i].codeBook == + CODE_BOOK_IS_OUT_OF_PHASE_NO) || + (sectionData->huffsection[i].codeBook == CODE_BOOK_IS_IN_PHASE_NO)) { + for (j = sectionData->huffsection[i].sfbStart; + j < sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + j++) { + INT deltaIs = isScale[j] - lastValIs; + lastValIs = isScale[j]; + sectionData->scalefacBits += + FDKaacEnc_bitCountScalefactorDelta(deltaIs); + } + } /* Intensity */ + else if ((sectionData->huffsection[i].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[i].codeBook != CODE_BOOK_PNS_NO)) { + INT tmp = sectionData->huffsection[i].sfbStart + + sectionData->huffsection[i].sfbCnt; + for (j = sectionData->huffsection[i].sfbStart; j < tmp; j++) { + /* check if we can repeat the last value to save bits */ + if (maxValueInSfb[j] == 0) { + found = 0; + /* are scalefactors skipped? */ + if (scfSkipCounter == 0) { + /* end of section */ + if (j == (tmp - 1)) + found = 0; /* search in other sections for maxValueInSfb != 0 */ + else { + /* search in this section for the next maxValueInSfb[] != 0 */ + for (k = (j + 1); k < tmp; k++) { + if (maxValueInSfb[k] != 0) { + found = 1; + if ((fixp_abs(scalefacGain[k] - lastValScf)) <= + CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + + /* search for the next maxValueInSfb[] != 0 in all other sections */ + for (m = (i + 1); (m < sectionData->noOfSections) && (found == 0); + m++) { + if ((sectionData->huffsection[m].codeBook != CODE_BOOK_ZERO_NO) && + (sectionData->huffsection[m].codeBook != CODE_BOOK_PNS_NO)) { + INT end = sectionData->huffsection[m].sfbStart + + sectionData->huffsection[m].sfbCnt; + for (n = sectionData->huffsection[m].sfbStart; n < end; n++) { + if (maxValueInSfb[n] != 0) { + found = 1; + if (fixp_abs(scalefacGain[n] - lastValScf) <= + CODE_BOOK_SCF_LAV) + deltaScf = 0; /* save bits */ + else { + /* do not save bits */ + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + scfSkipCounter = 0; + } + break; + } + /* count scalefactor skip */ + scfSkipCounter++; + } + } + } + /* no maxValueInSfb[] != 0 found */ + if (found == 0) { + deltaScf = 0; + scfSkipCounter = 0; + } + } else { + /* consider skipped scalefactors */ + deltaScf = 0; + scfSkipCounter--; + } + } else { + deltaScf = lastValScf - scalefacGain[j]; + lastValScf = scalefacGain[j]; + } + sectionData->scalefacBits += + FDKaacEnc_bitCountScalefactorDelta(deltaScf); + } + } + } /* for (i=0; inoOfSections; i++) */ +} + +/* count bits used by pns */ +static void FDKaacEnc_noiseCount(SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg) { + INT noisePCMFlag = TRUE; + INT lastValPns = 0, deltaPns; + int i, j; + + sectionData->noiseNrgBits = 0; + + for (i = 0; i < sectionData->noOfSections; i++) { + if (sectionData->huffsection[i].codeBook == CODE_BOOK_PNS_NO) { + int sfbStart = sectionData->huffsection[i].sfbStart; + int sfbEnd = sfbStart + sectionData->huffsection[i].sfbCnt; + for (j = sfbStart; j < sfbEnd; j++) { + if (noisePCMFlag) { + sectionData->noiseNrgBits += PNS_PCM_BITS; + lastValPns = noiseNrg[j]; + noisePCMFlag = FALSE; + } else { + deltaPns = noiseNrg[j] - lastValPns; + lastValPns = noiseNrg[j]; + sectionData->noiseNrgBits += + FDKaacEnc_bitCountScalefactorDelta(deltaPns); + } + } + } + } +} + +INT FDKaacEnc_dynBitCount(BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, const INT blockType, + const INT sfbCnt, const INT maxSfbPerGroup, + const INT sfbPerGroup, const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, const INT* const isBook, + const INT* const isScale, const UINT syntaxFlags) { + sectionData->blockType = blockType; + sectionData->sfbCnt = sfbCnt; + sectionData->sfbPerGroup = sfbPerGroup; + sectionData->noOfGroups = sfbCnt / sfbPerGroup; + sectionData->maxSfbPerGroup = maxSfbPerGroup; + + FDKaacEnc_noiselessCounter(sectionData, hBC->mergeGainLookUp, + (lookUpTable)hBC->bitLookUp, quantSpectrum, + maxValueInSfb, sfbOffset, blockType, noiseNrg, + isBook, (syntaxFlags & AC_ER_VCB11) ? 1 : 0); + + FDKaacEnc_scfCount(scalefac, maxValueInSfb, sectionData, isScale); + + FDKaacEnc_noiseCount(sectionData, noiseNrg); + + return (sectionData->huffmanBits + sectionData->sideInfoBits + + sectionData->scalefacBits + sectionData->noiseNrgBits); +} + +INT FDKaacEnc_BCNew(BITCNTR_STATE** phBC, UCHAR* dynamic_RAM) { + BITCNTR_STATE* hBC = GetRam_aacEnc_BitCntrState(); + + if (hBC) { + *phBC = hBC; + hBC->bitLookUp = GetRam_aacEnc_BitLookUp(0, dynamic_RAM); + hBC->mergeGainLookUp = GetRam_aacEnc_MergeGainLookUp(0, dynamic_RAM); + if (hBC->bitLookUp == 0 || hBC->mergeGainLookUp == 0) { + return 1; + } + } + return (hBC == 0) ? 1 : 0; +} + +void FDKaacEnc_BCClose(BITCNTR_STATE** phBC) { + if (*phBC != NULL) { + FreeRam_aacEnc_BitCntrState(phBC); + } +} diff --git a/fdk-aac/libAACenc/src/dyn_bits.h b/fdk-aac/libAACenc/src/dyn_bits.h new file mode 100644 index 0000000..a727a30 --- /dev/null +++ b/fdk-aac/libAACenc/src/dyn_bits.h @@ -0,0 +1,160 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Noiseless coder module + +*******************************************************************************/ + +#ifndef DYN_BITS_H +#define DYN_BITS_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" + +#define MAX_SECTIONS MAX_GROUPED_SFB +#define SECT_ESC_VAL_LONG 31 +#define SECT_ESC_VAL_SHORT 7 +#define CODE_BOOK_BITS 4 +#define SECT_BITS_LONG 5 +#define SECT_BITS_SHORT 3 +#define PNS_PCM_BITS 9 + +typedef struct { + INT codeBook; + INT sfbStart; + INT sfbCnt; + INT sectionBits; /* huff + si ! */ +} SECTION_INFO; + +typedef struct { + INT blockType; + INT noOfGroups; + INT sfbCnt; + INT maxSfbPerGroup; + INT sfbPerGroup; + INT noOfSections; + SECTION_INFO huffsection[MAX_SECTIONS]; + INT sideInfoBits; /* sectioning bits */ + INT huffmanBits; /* huffman coded bits */ + INT scalefacBits; /* scalefac coded bits */ + INT noiseNrgBits; /* noiseEnergy coded bits */ + INT firstScf; /* first scf to be coded */ +} SECTION_DATA; + +struct BITCNTR_STATE { + INT* bitLookUp; + INT* mergeGainLookUp; +}; + +INT FDKaacEnc_BCNew(BITCNTR_STATE** phBC, UCHAR* dynamic_RAM); + +void FDKaacEnc_BCClose(BITCNTR_STATE** phBC); + +INT FDKaacEnc_dynBitCount(BITCNTR_STATE* const hBC, + const SHORT* const quantSpectrum, + const UINT* const maxValueInSfb, + const INT* const scalefac, const INT blockType, + const INT sfbCnt, const INT maxSfbPerGroup, + const INT sfbPerGroup, const INT* const sfbOffset, + SECTION_DATA* const RESTRICT sectionData, + const INT* const noiseNrg, const INT* const isBook, + const INT* const isScale, const UINT syntaxFlags); + +#endif diff --git a/fdk-aac/libAACenc/src/grp_data.cpp b/fdk-aac/libAACenc/src/grp_data.cpp new file mode 100644 index 0000000..bc9d85f --- /dev/null +++ b/fdk-aac/libAACenc/src/grp_data.cpp @@ -0,0 +1,264 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Short block grouping + +*******************************************************************************/ + +#include "psy_const.h" +#include "interface.h" + +/* + * this routine does not work in-place + */ + +/* + * Don't use fAddSaturate2() because it looses one bit accuracy which is + * usefull for quality. + */ +static inline FIXP_DBL nrgAddSaturate(const FIXP_DBL a, const FIXP_DBL b) { + return ((a >= (FIXP_DBL)MAXVAL_DBL - b) ? (FIXP_DBL)MAXVAL_DBL : (a + b)); +} + +void FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, const INT sfbCnt, + const INT sfbActive, const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, /* out */ + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, const INT *groupLen, + const INT granuleLength) { + INT i, j; + INT line; /* counts through lines */ + INT sfb; /* counts through scalefactor bands */ + INT grp; /* counts through groups */ + INT wnd; /* counts through windows in a group */ + INT offset; /* needed in sfbOffset grouping */ + INT highestSfb; + INT granuleLength_short = granuleLength / TRANS_FAC; + + C_ALLOC_SCRATCH_START(tmpSpectrum, FIXP_DBL, (1024)) + + /* for short blocks: regroup spectrum and */ + /* group energies and thresholds according to grouping */ + + /* calculate maxSfbPerGroup */ + highestSfb = 0; + for (wnd = 0; wnd < TRANS_FAC; wnd++) { + for (sfb = sfbActive - 1; sfb >= highestSfb; sfb--) { + for (line = sfbOffset[sfb + 1] - 1; line >= sfbOffset[sfb]; line--) { + if (mdctSpectrum[wnd * granuleLength_short + line] != + FL2FXCONST_SPC(0.0)) + break; /* this band is not completely zero */ + } + if (line >= sfbOffset[sfb]) break; /* this band was not completely zero */ + } + highestSfb = fixMax(highestSfb, sfb); + } + highestSfb = highestSfb > 0 ? highestSfb : 0; + *maxSfbPerGroup = highestSfb + 1; + + /* calculate groupedSfbOffset */ + i = 0; + offset = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive + 1; sfb++) { + groupedSfbOffset[i++] = offset + sfbOffset[sfb] * groupLen[grp]; + } + i += sfbCnt - sfb; + offset += groupLen[grp] * granuleLength_short; + } + groupedSfbOffset[i++] = granuleLength; + + /* calculate groupedSfbMinSnr */ + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + groupedSfbMinSnrLdData[i++] = sfbMinSnrLdData[sfb]; + } + i += sfbCnt - sfb; + } + + /* sum up sfbThresholds */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL thresh = sfbThreshold->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + thresh = nrgAddSaturate(thresh, sfbThreshold->Short[wnd + j][sfb]); + } + sfbThreshold->Long[i++] = thresh; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies left/right */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbEnergy->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbEnergy->Short[wnd + j][sfb]); + } + sfbEnergy->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbEnergies mid/side */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbEnergyMS->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbEnergyMS->Short[wnd + j][sfb]); + } + sfbEnergyMS->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* sum up sfbSpreadEnergies */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + FIXP_DBL energy = sfbSpreadEnergy->Short[wnd][sfb]; + for (j = 1; j < groupLen[grp]; j++) { + energy = nrgAddSaturate(energy, sfbSpreadEnergy->Short[wnd + j][sfb]); + } + sfbSpreadEnergy->Long[i++] = energy; + } + i += sfbCnt - sfb; + wnd += groupLen[grp]; + } + + /* re-group spectrum */ + wnd = 0; + i = 0; + for (grp = 0; grp < noOfGroups; grp++) { + for (sfb = 0; sfb < sfbActive; sfb++) { + int width = sfbOffset[sfb + 1] - sfbOffset[sfb]; + FIXP_DBL *pMdctSpectrum = + &mdctSpectrum[sfbOffset[sfb]] + wnd * granuleLength_short; + for (j = 0; j < groupLen[grp]; j++) { + FIXP_DBL *pTmp = pMdctSpectrum; + for (line = width; line > 0; line--) { + tmpSpectrum[i++] = *pTmp++; + } + pMdctSpectrum += granuleLength_short; + } + } + i += (groupLen[grp] * (sfbOffset[sfbCnt] - sfbOffset[sfb])); + wnd += groupLen[grp]; + } + + FDKmemcpy(mdctSpectrum, tmpSpectrum, granuleLength * sizeof(FIXP_DBL)); + + C_ALLOC_SCRATCH_END(tmpSpectrum, FIXP_DBL, (1024)) +} diff --git a/fdk-aac/libAACenc/src/grp_data.h b/fdk-aac/libAACenc/src/grp_data.h new file mode 100644 index 0000000..3e1a708 --- /dev/null +++ b/fdk-aac/libAACenc/src/grp_data.h @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Short block grouping + +*******************************************************************************/ + +#ifndef GRP_DATA_H +#define GRP_DATA_H + +#include "common_fix.h" + +#include "psy_data.h" + +void FDKaacEnc_groupShortData(FIXP_DBL *mdctSpectrum, /* in-out */ + SFB_THRESHOLD *sfbThreshold, /* in-out */ + SFB_ENERGY *sfbEnergy, /* in-out */ + SFB_ENERGY *sfbEnergyMS, /* in-out */ + SFB_ENERGY *sfbSpreadEnergy, const INT sfbCnt, + const INT sfbActive, const INT *sfbOffset, + const FIXP_DBL *sfbMinSnrLdData, + INT *groupedSfbOffset, /* out */ + INT *maxSfbPerGroup, + FIXP_DBL *groupedSfbMinSnrLdData, + const INT noOfGroups, const INT *groupLen, + const INT granuleLength); + +#endif /* _INTERFACE_H */ diff --git a/fdk-aac/libAACenc/src/intensity.cpp b/fdk-aac/libAACenc/src/intensity.cpp new file mode 100644 index 0000000..8cb1b45 --- /dev/null +++ b/fdk-aac/libAACenc/src/intensity.cpp @@ -0,0 +1,810 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK) + + Description: intensity stereo processing + +*******************************************************************************/ + +#include "intensity.h" + +#include "interface.h" +#include "psy_configuration.h" +#include "psy_const.h" +#include "qc_main.h" +#include "bit_cnt.h" + +/* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH + */ +#define IS_CORR_THRESH FL2FXCONST_DBL(0.95f) + +/* when expanding the IS region to more SFBs only accept an error that is + * not more than IS_TOTAL_ERROR_THRESH overall and + * not more than IS_LOCAL_ERROR_THRESH for the current SFB */ +#define IS_TOTAL_ERROR_THRESH FL2FXCONST_DBL(0.04f) +#define IS_LOCAL_ERROR_THRESH FL2FXCONST_DBL(0.01f) + +/* the maximum allowed change of the intensity direction (unit: IS scale) - + * scaled with factor 0.25 - */ +#define IS_DIRECTION_DEVIATION_THRESH_SF 2 +#define IS_DIRECTION_DEVIATION_THRESH \ + FL2FXCONST_DBL(2.0f / (1 << IS_DIRECTION_DEVIATION_THRESH_SF)) + +/* IS regions need to have a minimal percentage of the overall loudness, e.g. + * 0.06 == 6% */ +#define IS_REGION_MIN_LOUDNESS FL2FXCONST_DBL(0.1f) + +/* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */ +#define IS_MIN_SFBS 6 + +/* only do IS if + * if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / + * IS_LEFT_RIGHT_RATIO_THRESH + * -> no IS if the panning angle is not far from the middle, MS will do */ +/* this is equivalent to a scale of +/-1.02914634566 */ +#define IS_LEFT_RIGHT_RATIO_THRESH FL2FXCONST_DBL(0.7f) + +/* scalefactor of realScale */ +#define REAL_SCALE_SF 1 + +/* scalefactor overallLoudness */ +#define OVERALL_LOUDNESS_SF 6 + +/* scalefactor for sum over max samples per goup */ +#define MAX_SFB_PER_GROUP_SF 6 + +/* scalefactor for sum of mdct spectrum */ +#define MDCT_SPEC_SF 6 + +typedef struct { + FIXP_DBL corr_thresh; /*!< Only set an IS seed it left/right channel + correlation is above corr_thresh */ + + FIXP_DBL total_error_thresh; /*!< When expanding the IS region to more SFBs + only accept an error that is not more than + 'total_error_thresh' overall. */ + + FIXP_DBL local_error_thresh; /*!< When expanding the IS region to more SFBs + only accept an error that is not more than + 'local_error_thresh' for the current SFB. */ + + FIXP_DBL direction_deviation_thresh; /*!< The maximum allowed change of the + intensity direction (unit: IS scale) + */ + + FIXP_DBL is_region_min_loudness; /*!< IS regions need to have a minimal + percentage of the overall loudness, e.g. + 0.06 == 6% */ + + INT min_is_sfbs; /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be + processed */ + + FIXP_DBL left_right_ratio_threshold; /*!< No IS if the panning angle is not + far from the middle, MS will do */ + +} INTENSITY_PARAMETERS; + +/***************************************************************************** + + functionname: calcSfbMaxScale + + description: Calc max value in scalefactor band + + input: *mdctSpectrum + l1 + l2 + + output: none + + returns: scalefactor + +*****************************************************************************/ +static INT calcSfbMaxScale(const FIXP_DBL *mdctSpectrum, const INT l1, + const INT l2) { + INT i; + INT sfbMaxScale; + FIXP_DBL maxSpc; + + maxSpc = FL2FXCONST_DBL(0.0); + for (i = l1; i < l2; i++) { + FIXP_DBL tmp = fixp_abs((FIXP_DBL)mdctSpectrum[i]); + maxSpc = fixMax(maxSpc, tmp); + } + sfbMaxScale = (maxSpc == FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS - 2) + : CntLeadingZeros(maxSpc) - 1; + + return sfbMaxScale; +} + +/***************************************************************************** + + functionname: FDKaacEnc_initIsParams + + description: Initialization of intensity parameters + + input: isParams + + output: isParams + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_initIsParams(INTENSITY_PARAMETERS *isParams) { + isParams->corr_thresh = IS_CORR_THRESH; + isParams->total_error_thresh = IS_TOTAL_ERROR_THRESH; + isParams->local_error_thresh = IS_LOCAL_ERROR_THRESH; + isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH; + isParams->is_region_min_loudness = IS_REGION_MIN_LOUDNESS; + isParams->min_is_sfbs = IS_MIN_SFBS; + isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH; +} + +/***************************************************************************** + + functionname: FDKaacEnc_prepareIntensityDecision + + description: Prepares intensity decision + + input: sfbEnergyLeft + sfbEnergyRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + mdctSpectrumLeft + sfbEnergyLdDataRight + isParams + + output: hrrErr scale: none + isMask scale: none + realScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_prepareIntensityDecision( + const FIXP_DBL *sfbEnergyLeft, const FIXP_DBL *sfbEnergyRight, + const FIXP_DBL *sfbEnergyLdDataLeft, const FIXP_DBL *sfbEnergyLdDataRight, + const FIXP_DBL *mdctSpectrumLeft, const FIXP_DBL *mdctSpectrumRight, + const INTENSITY_PARAMETERS *isParams, FIXP_DBL *hrrErr, INT *isMask, + FIXP_DBL *realScale, FIXP_DBL *normSfbLoudness, const INT sfbCnt, + const INT sfbPerGroup, const INT maxSfbPerGroup, const INT *sfbOffset) { + INT j, sfb, sfboffs; + INT grpCounter; + + /* temporary variables to compute loudness */ + FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS]; + + /* temporary variables to compute correlation */ + FIXP_DBL channelCorr[MAX_GROUPED_SFB]; + FIXP_DBL ml, mr; + FIXP_DBL prod_lr; + FIXP_DBL square_l, square_r; + FIXP_DBL tmp_l, tmp_r; + FIXP_DBL inv_n; + + FDKmemclear(channelCorr, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS * sizeof(FIXP_DBL)); + FDKmemclear(realScale, MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; + sfboffs += sfbPerGroup, grpCounter++) { + overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f); + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT sL, sR, s; + FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb + sfboffs] - + sfbEnergyLdDataRight[sfb + sfboffs]; + + /* delimitate intensity scale value to representable range */ + realScale[sfb + sfboffs] = fixMin( + FL2FXCONST_DBL(60.f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT))), + fixMax(FL2FXCONST_DBL(-60.f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT))), + isValue)); + + sL = fixMax(0, (CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs]) - 1)); + sR = fixMax(0, (CntLeadingZeros(sfbEnergyRight[sfb + sfboffs]) - 1)); + s = (fixMin(sL, sR) >> 2) << 2; + normSfbLoudness[sfb + sfboffs] = + sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs] << s) >> 1) + + ((sfbEnergyRight[sfb + sfboffs] << s) >> 1))) >> + (s >> 2); + + overallLoudness[grpCounter] += + normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF; + /* don't do intensity if + * - panning angle is too close to the middle or + * - one channel is non-existent or + * - if it is dual mono */ + if ((sfbEnergyLeft[sfb + sfboffs] >= + fMult(isParams->left_right_ratio_threshold, + sfbEnergyRight[sfb + sfboffs])) && + (fMult(isParams->left_right_ratio_threshold, + sfbEnergyLeft[sfb + sfboffs]) <= + sfbEnergyRight[sfb + sfboffs])) { + /* this will prevent post processing from considering this SFB for + * merging */ + hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0 / 8.0); + } + } + } + + for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; + sfboffs += sfbPerGroup, grpCounter++) { + INT invOverallLoudnessSF; + FIXP_DBL invOverallLoudness; + + if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) { + invOverallLoudness = FL2FXCONST_DBL(0.0); + invOverallLoudnessSF = 0; + } else { + invOverallLoudness = + fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter], + &invOverallLoudnessSF); + invOverallLoudnessSF = + invOverallLoudnessSF - OVERALL_LOUDNESS_SF + + 1; /* +1: compensate fMultDiv2() in subsequent loop */ + } + invOverallLoudnessSF = fixMin( + fixMax(invOverallLoudnessSF, -(DFRACT_BITS - 1)), DFRACT_BITS - 1); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + FIXP_DBL tmp; + + tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF) + << OVERALL_LOUDNESS_SF, + invOverallLoudness); + + normSfbLoudness[sfb + sfboffs] = scaleValue(tmp, invOverallLoudnessSF); + + channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + + /* max width of scalefactorband is 96; width's are always even */ + /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent + * loops */ + inv_n = GetInvInt( + (sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs]) >> 1); + + if (inv_n > FL2FXCONST_DBL(0.0f)) { + INT s, sL, sR; + + /* correlation := Pearson's product-moment coefficient */ + /* compute correlation between channels and check if it is over + * threshold */ + ml = FL2FXCONST_DBL(0.0f); + mr = FL2FXCONST_DBL(0.0f); + prod_lr = FL2FXCONST_DBL(0.0f); + square_l = FL2FXCONST_DBL(0.0f); + square_r = FL2FXCONST_DBL(0.0f); + + sL = calcSfbMaxScale(mdctSpectrumLeft, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + sR = calcSfbMaxScale(mdctSpectrumRight, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + s = fixMin(sL, sR); + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + ml += fMultDiv2((mdctSpectrumLeft[j] << s), + inv_n); // scaled with mdctScale - s + inv_n + mr += fMultDiv2((mdctSpectrumRight[j] << s), + inv_n); // scaled with mdctScale - s + inv_n + } + ml = fMultDiv2(ml, inv_n); // scaled with mdctScale - s + inv_n + mr = fMultDiv2(mr, inv_n); // scaled with mdctScale - s + inv_n + + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + tmp_l = fMultDiv2((mdctSpectrumLeft[j] << s), inv_n) - + ml; // scaled with mdctScale - s + inv_n + tmp_r = fMultDiv2((mdctSpectrumRight[j] << s), inv_n) - + mr; // scaled with mdctScale - s + inv_n + + prod_lr += fMultDiv2( + tmp_l, tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_l += + fPow2Div2(tmp_l); // scaled with 2*(mdctScale - s + inv_n) + 1 + square_r += + fPow2Div2(tmp_r); // scaled with 2*(mdctScale - s + inv_n) + 1 + } + prod_lr = prod_lr << 1; // scaled with 2*(mdctScale - s + inv_n) + square_l = square_l << 1; // scaled with 2*(mdctScale - s + inv_n) + square_r = square_r << 1; // scaled with 2*(mdctScale - s + inv_n) + + if (square_l > FL2FXCONST_DBL(0.0f) && + square_r > FL2FXCONST_DBL(0.0f)) { + INT channelCorrSF = 0; + + /* local scaling of square_l and square_r is compensated after sqrt + * calculation */ + sL = fixMax(0, (CntLeadingZeros(square_l) - 1)); + sR = fixMax(0, (CntLeadingZeros(square_r) - 1)); + s = ((sL + sR) >> 1) << 1; + sL = fixMin(sL, s); + sR = s - sL; + tmp = fMult(square_l << sL, square_r << sR); + tmp = sqrtFixp(tmp); + + FDK_ASSERT(tmp > FL2FXCONST_DBL(0.0f)); + + /* numerator and denominator have the same scaling */ + if (prod_lr < FL2FXCONST_DBL(0.0f)) { + channelCorr[sfb + sfboffs] = + -(fDivNorm(-prod_lr, tmp, &channelCorrSF)); + + } else { + channelCorr[sfb + sfboffs] = + (fDivNorm(prod_lr, tmp, &channelCorrSF)); + } + channelCorrSF = fixMin( + fixMax((channelCorrSF + ((sL + sR) >> 1)), -(DFRACT_BITS - 1)), + DFRACT_BITS - 1); + + if (channelCorrSF < 0) { + channelCorr[sfb + sfboffs] = + channelCorr[sfb + sfboffs] >> (-channelCorrSF); + } else { + /* avoid overflows due to limited computational accuracy */ + if (fAbs(channelCorr[sfb + sfboffs]) > + (((FIXP_DBL)MAXVAL_DBL) >> channelCorrSF)) { + if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f)) + channelCorr[sfb + sfboffs] = -(FIXP_DBL)MAXVAL_DBL; + else + channelCorr[sfb + sfboffs] = (FIXP_DBL)MAXVAL_DBL; + } else { + channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] + << channelCorrSF; + } + } + } + } + + /* for post processing: hrrErr is the error in terms of (too little) + * correlation weighted with the loudness of the SFB; SFBs with small + * hrrErr can be merged */ + if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0 / 8.0)) { + continue; + } + + hrrErr[sfb + sfboffs] = + fMultDiv2((FL2FXCONST_DBL(0.25f) - (channelCorr[sfb + sfboffs] >> 2)), + normSfbLoudness[sfb + sfboffs]); + + /* set IS mask/vector to 1, if correlation is high enough */ + if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) { + isMask[sfb + sfboffs] = 1; + } + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_finalizeIntensityDecision + + description: Finalizes intensity decision + + input: isParams scale: none + hrrErr scale: none + realIsScale scale: LD_DATA_SHIFT + REAL_SCALE_SF + normSfbLoudness scale: none + + output: isMask scale: none + + returns: none + +*****************************************************************************/ +static void FDKaacEnc_finalizeIntensityDecision( + const FIXP_DBL *hrrErr, INT *isMask, const FIXP_DBL *realIsScale, + const FIXP_DBL *normSfbLoudness, const INTENSITY_PARAMETERS *isParams, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup) { + INT sfb, sfboffs, j; + FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f); + INT isStartValueFound = 0; + + for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) { + INT startIsSfb = 0; + INT inIsBlock = 0; + INT currentIsSfbCount = 0; + FIXP_DBL overallHrrError = FL2FXCONST_DBL(0.0f); + FIXP_DBL isRegionLoudness = FL2FXCONST_DBL(0.0f); + + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + if (isMask[sfboffs + sfb] == 1) { + if (currentIsSfbCount == 0) { + startIsSfb = sfboffs + sfb; + } + if (isStartValueFound == 0) { + isScaleLast = realIsScale[sfboffs + sfb]; + isStartValueFound = 1; + } + inIsBlock = 1; + currentIsSfbCount++; + overallHrrError += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF - 3); + isRegionLoudness += + normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + } else { + /* based on correlation, IS should not be used + * -> use it anyway, if overall error is below threshold + * and if local error does not exceed threshold + * otherwise: check if there are enough IS SFBs + */ + if (inIsBlock) { + overallHrrError += + hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF - 3); + isRegionLoudness += + normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF; + + if ((hrrErr[sfboffs + sfb] < (isParams->local_error_thresh >> 3)) && + (overallHrrError < + (isParams->total_error_thresh >> MAX_SFB_PER_GROUP_SF))) { + currentIsSfbCount++; + /* overwrite correlation based decision */ + isMask[sfboffs + sfb] = 1; + } else { + inIsBlock = 0; + } + } + } + /* check for large direction deviation */ + if (inIsBlock) { + if (fAbs(isScaleLast - realIsScale[sfboffs + sfb]) < + (isParams->direction_deviation_thresh >> + (REAL_SCALE_SF + LD_DATA_SHIFT - + IS_DIRECTION_DEVIATION_THRESH_SF))) { + isScaleLast = realIsScale[sfboffs + sfb]; + } else { + isMask[sfboffs + sfb] = 0; + inIsBlock = 0; + currentIsSfbCount--; + } + } + + if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) { + /* not enough SFBs -> do not use IS */ + if (currentIsSfbCount < isParams->min_is_sfbs || + (isRegionLoudnessis_region_min_loudness>> + MAX_SFB_PER_GROUP_SF)) { + for (j = startIsSfb; j <= sfboffs + sfb; j++) { + isMask[j] = 0; + } + isScaleLast = FL2FXCONST_DBL(0.0f); + isStartValueFound = 0; + for (j = 0; j < startIsSfb; j++) { + if (isMask[j] != 0) { + isScaleLast = realIsScale[j]; + isStartValueFound = 1; + } + } + } + currentIsSfbCount = 0; + overallHrrError = FL2FXCONST_DBL(0.0f); + isRegionLoudness = FL2FXCONST_DBL(0.0f); + } + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_IntensityStereoProcessing + + description: Intensity stereo processing tool + + input: sfbEnergyLeft + sfbEnergyRight + mdctSpectrumLeft + mdctSpectrumRight + sfbThresholdLeft + sfbThresholdRight + sfbSpreadEnLeft + sfbSpreadEnRight + sfbEnergyLdDataLeft + sfbEnergyLdDataRight + + output: isBook + isScale + pnsData->pnsFlag + msDigest zeroed from start to sfbCnt + msMask zeroed from start to sfbCnt + mdctSpectrumRight zeroed where isBook!=0 + sfbEnergyRight zeroed where isBook!=0 + sfbSpreadEnRight zeroed where isBook!=0 + sfbThresholdRight zeroed where isBook!=0 + sfbEnergyLdDataRight FL2FXCONST_DBL(-1.0) where isBook!=0 + sfbThresholdLdDataRight FL2FXCONST_DBL(-0.515625f) where +isBook!=0 + + returns: none + +*****************************************************************************/ +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, INT *msDigest, INT *msMask, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + const INT *sfbOffset, const INT allowIS, INT *isBook, INT *isScale, + PNS_DATA *RESTRICT pnsData[2]) { + INT sfb, sfboffs, j; + FIXP_DBL scale; + FIXP_DBL lr; + FIXP_DBL hrrErr[MAX_GROUPED_SFB]; + FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB]; + FIXP_DBL realIsScale[MAX_GROUPED_SFB]; + INTENSITY_PARAMETERS isParams; + INT isMask[MAX_GROUPED_SFB]; + + FDKmemclear((void *)isBook, sfbCnt * sizeof(INT)); + FDKmemclear((void *)isMask, sfbCnt * sizeof(INT)); + FDKmemclear((void *)realIsScale, sfbCnt * sizeof(FIXP_DBL)); + FDKmemclear((void *)isScale, sfbCnt * sizeof(INT)); + FDKmemclear((void *)hrrErr, sfbCnt * sizeof(FIXP_DBL)); + + if (!allowIS) return; + + FDKaacEnc_initIsParams(&isParams); + + /* compute / set the following values per SFB: + * - left/right ratio between channels + * - normalized loudness + * + loudness == average of energy in channels to 0.25 + * + normalization: division by sum of all SFB loudnesses + * - isMask (is set to 0 if channels are the same or one is 0) + */ + FDKaacEnc_prepareIntensityDecision( + sfbEnergyLeft, sfbEnergyRight, sfbEnergyLdDataLeft, sfbEnergyLdDataRight, + mdctSpectrumLeft, mdctSpectrumRight, &isParams, hrrErr, isMask, + realIsScale, normSfbLoudness, sfbCnt, sfbPerGroup, maxSfbPerGroup, + sfbOffset); + + FDKaacEnc_finalizeIntensityDecision(hrrErr, isMask, realIsScale, + normSfbLoudness, &isParams, sfbCnt, + sfbPerGroup, maxSfbPerGroup); + + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + INT sL, sR; + FIXP_DBL inv_n; + + msMask[sfb + sfboffs] = 0; + if (isMask[sfb + sfboffs] == 0) { + continue; + } + + if ((sfbEnergyLeft[sfb + sfboffs] < sfbThresholdLeft[sfb + sfboffs]) && + (fMult(FL2FXCONST_DBL(1.0f / 1.5f), sfbEnergyRight[sfb + sfboffs]) > + sfbThresholdRight[sfb + sfboffs])) { + continue; + } + /* NEW: if there is a big-enough IS region, switch off PNS */ + if (pnsData[0]) { + if (pnsData[0]->pnsFlag[sfb + sfboffs]) { + pnsData[0]->pnsFlag[sfb + sfboffs] = 0; + } + if (pnsData[1]->pnsFlag[sfb + sfboffs]) { + pnsData[1]->pnsFlag[sfb + sfboffs] = 0; + } + } + + inv_n = GetInvInt( + (sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs]) >> + 1); // scaled with 2 to compensate fMultDiv2() in subsequent loop + sL = calcSfbMaxScale(mdctSpectrumLeft, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + sR = calcSfbMaxScale(mdctSpectrumRight, sfbOffset[sfb + sfboffs], + sfbOffset[sfb + sfboffs + 1]); + + lr = FL2FXCONST_DBL(0.0f); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) + lr += fMultDiv2( + fMultDiv2(mdctSpectrumLeft[j] << sL, mdctSpectrumRight[j] << sR), + inv_n); + lr = lr << 1; + + if (lr < FL2FXCONST_DBL(0.0f)) { + /* This means OUT OF phase intensity stereo, cf. standard */ + INT s0, s1, s2; + FIXP_DBL tmp, d, ed = FL2FXCONST_DBL(0.0f); + + s0 = fixMin(sL, sR); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + d = ((mdctSpectrumLeft[j] << s0) >> 1) - + ((mdctSpectrumRight[j] << s0) >> 1); + ed += fMultDiv2(d, d) >> (MDCT_SPEC_SF - 1); + } + msMask[sfb + sfboffs] = 1; + tmp = fDivNorm(sfbEnergyLeft[sfb + sfboffs], ed, &s1); + s2 = (s1) + (2 * s0) - 2 - MDCT_SPEC_SF; + if (s2 & 1) { + tmp = tmp >> 1; + s2 = s2 + 1; + } + s2 = (s2 >> 1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2, -(DFRACT_BITS - 1)), (DFRACT_BITS - 1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) - + fMultDiv2(mdctSpectrumRight[j], scale)) >> + s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } else { + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) - + fMultDiv2(mdctSpectrumRight[j], scale)) + << s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + } else { + /* This means IN phase intensity stereo, cf. standard */ + INT s0, s1, s2; + FIXP_DBL tmp, s, es = FL2FXCONST_DBL(0.0f); + + s0 = fixMin(sL, sR); + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + s = ((mdctSpectrumLeft[j] << s0) >> 1) + + ((mdctSpectrumRight[j] << s0) >> 1); + es = fAddSaturate(es, fMultDiv2(s, s) >> + (MDCT_SPEC_SF - + 1)); // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF + } + msMask[sfb + sfboffs] = 0; + tmp = fDivNorm(sfbEnergyLeft[sfb + sfboffs], es, &s1); + s2 = (s1) + (2 * s0) - 2 - MDCT_SPEC_SF; + if (s2 & 1) { + tmp = tmp >> 1; + s2 = s2 + 1; + } + s2 = (s2 >> 1) + 1; // +1 compensate fMultDiv2() in subsequent loop + s2 = fixMin(fixMax(s2, -(DFRACT_BITS - 1)), (DFRACT_BITS - 1)); + scale = sqrtFixp(tmp); + if (s2 < 0) { + s2 = -s2; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) + + fMultDiv2(mdctSpectrumRight[j], scale)) >> + s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } else { + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j], scale) + + fMultDiv2(mdctSpectrumRight[j], scale)) + << s2; + mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f); + } + } + } + + isBook[sfb + sfboffs] = CODE_BOOK_IS_IN_PHASE_NO; + + if (realIsScale[sfb + sfboffs] < FL2FXCONST_DBL(0.0f)) { + isScale[sfb + sfboffs] = + (INT)(((realIsScale[sfb + sfboffs] >> 1) - + FL2FXCONST_DBL( + 0.5f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT + 1)))) >> + (DFRACT_BITS - 1 - REAL_SCALE_SF - LD_DATA_SHIFT - 1)) + + 1; + } else { + isScale[sfb + sfboffs] = + (INT)(((realIsScale[sfb + sfboffs] >> 1) + + FL2FXCONST_DBL( + 0.5f / (1 << (REAL_SCALE_SF + LD_DATA_SHIFT + 1)))) >> + (DFRACT_BITS - 1 - REAL_SCALE_SF - LD_DATA_SHIFT - 1)); + } + + sfbEnergyRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + sfbEnergyLdDataRight[sfb + sfboffs] = FL2FXCONST_DBL(-1.0f); + sfbThresholdRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + sfbThresholdLdDataRight[sfb + sfboffs] = FL2FXCONST_DBL(-0.515625f); + sfbSpreadEnRight[sfb + sfboffs] = FL2FXCONST_DBL(0.0f); + + *msDigest = MS_SOME; + } + } +} diff --git a/fdk-aac/libAACenc/src/intensity.h b/fdk-aac/libAACenc/src/intensity.h new file mode 100644 index 0000000..70f23d5 --- /dev/null +++ b/fdk-aac/libAACenc/src/intensity.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): A. Horndasch (code originally from lwr and rtb) / Josef Hoepfl +(FDK) + + Description: intensity stereo prototype + +*******************************************************************************/ + +#ifndef INTENSITY_H +#define INTENSITY_H + +#include "aacenc_pns.h" +#include "common_fix.h" + +void FDKaacEnc_IntensityStereoProcessing( + FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *mdctSpectrumLeft, FIXP_DBL *mdctSpectrumRight, + FIXP_DBL *sfbThresholdLeft, FIXP_DBL *sfbThresholdRight, + FIXP_DBL *sfbThresholdLdDataRight, FIXP_DBL *sfbSpreadEnLeft, + FIXP_DBL *sfbSpreadEnRight, FIXP_DBL *sfbEnergyLdDataLeft, + FIXP_DBL *sfbEnergyLdDataRight, INT *msDigest, INT *msMask, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + const INT *sfbOffset, const INT allowIS, INT *isBook, INT *isScale, + PNS_DATA *RESTRICT pnsData[2]); + +#endif /* INTENSITY_H */ diff --git a/fdk-aac/libAACenc/src/interface.h b/fdk-aac/libAACenc/src/interface.h new file mode 100644 index 0000000..b1a31ef --- /dev/null +++ b/fdk-aac/libAACenc/src/interface.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Interface psychoaccoustic/quantizer + +*******************************************************************************/ + +#ifndef INTERFACE_H +#define INTERFACE_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "psy_data.h" +#include "aacenc_tns.h" + +enum { MS_NONE = 0, MS_SOME = 1, MS_ALL = 2 }; + +enum { MS_ON = 1 }; + +struct TOOLSINFO { + INT msDigest; /* 0 = no MS; 1 = some MS, 2 = all MS */ + INT msMask[MAX_GROUPED_SFB]; +}; + +typedef struct { + INT sfbCnt; + INT sfbPerGroup; + INT maxSfbPerGroup; + INT lastWindowSequence; + INT windowShape; + INT groupingMask; + INT sfbOffsets[MAX_GROUPED_SFB + 1]; + + INT mdctScale; /* number of transform shifts */ + INT groupLen[MAX_NO_OF_GROUPS]; + + TNS_INFO tnsInfo; + INT noiseNrg[MAX_GROUPED_SFB]; + INT isBook[MAX_GROUPED_SFB]; + INT isScale[MAX_GROUPED_SFB]; + + /* memory located in QC_OUT_CHANNEL */ + FIXP_DBL *mdctSpectrum; + FIXP_DBL *sfbEnergy; + FIXP_DBL *sfbSpreadEnergy; + FIXP_DBL *sfbThresholdLdData; + FIXP_DBL *sfbMinSnrLdData; + FIXP_DBL *sfbEnergyLdData; + +} PSY_OUT_CHANNEL; + +typedef struct { + /* information specific to each channel */ + PSY_OUT_CHANNEL *psyOutChannel[(2)]; + + /* information shared by both channels */ + INT commonWindow; + struct TOOLSINFO toolsInfo; + +} PSY_OUT_ELEMENT; + +typedef struct { + PSY_OUT_ELEMENT *psyOutElement[((8))]; + PSY_OUT_CHANNEL *pPsyOutChannels[(8)]; + +} PSY_OUT; + +inline int isLowDelay(AUDIO_OBJECT_TYPE aot) { + return (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD); +} + +#endif /* INTERFACE_H */ diff --git a/fdk-aac/libAACenc/src/line_pe.cpp b/fdk-aac/libAACenc/src/line_pe.cpp new file mode 100644 index 0000000..47734e5 --- /dev/null +++ b/fdk-aac/libAACenc/src/line_pe.cpp @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Perceptual entropie module + +*******************************************************************************/ + +#include "line_pe.h" +#include "sf_estim.h" +#include "bit_cnt.h" + +#include "genericStds.h" + +static const FIXP_DBL C1LdData = + FL2FXCONST_DBL(3.0 / LD_DATA_SCALING); /* C1 = 3.0 = log(8.0)/log(2) */ +static const FIXP_DBL C2LdData = FL2FXCONST_DBL( + 1.3219281 / LD_DATA_SCALING); /* C2 = 1.3219281 = log(2.5)/log(2) */ +static const FIXP_DBL C3LdData = FL2FXCONST_DBL(0.5593573); /* 1-C2/C1 */ + +/* constants that do not change during successive pe calculations */ +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const FIXP_DBL *RESTRICT const sfbFormFactorLdData, + const INT *RESTRICT const sfbOffset, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup) { + INT sfbGrp, sfb; + INT sfbWidth; + FIXP_DBL avgFormFactorLdData; + const FIXP_DBL formFacScaling = + FL2FXCONST_DBL((float)FORM_FAC_SHIFT / LD_DATA_SCALING); + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + if ((FIXP_DBL)sfbEnergyLdData[sfbGrp + sfb] > + (FIXP_DBL)sfbThresholdLdData[sfbGrp + sfb]) { + sfbWidth = sfbOffset[sfbGrp + sfb + 1] - sfbOffset[sfbGrp + sfb]; + /* estimate number of active lines */ + avgFormFactorLdData = ((-sfbEnergyLdData[sfbGrp + sfb] >> 1) + + (CalcLdInt(sfbWidth) >> 1)) >> + 1; + peChanData->sfbNLines[sfbGrp + sfb] = (INT)CalcInvLdData( + (sfbFormFactorLdData[sfbGrp + sfb] + formFacScaling) + + avgFormFactorLdData); + /* Make sure sfbNLines is never greater than sfbWidth due to + * unaccuracies (e.g. sfbEnergyLdData[sfbGrp+sfb] = 0x80000000) */ + peChanData->sfbNLines[sfbGrp + sfb] = + fMin(sfbWidth, peChanData->sfbNLines[sfbGrp + sfb]); + } else { + peChanData->sfbNLines[sfbGrp + sfb] = 0; + } + } + } +} + +/* + formula for one sfb: + pe = n * ld(en/thr), if ld(en/thr) >= C1 + pe = n * (C2 + C3 * ld(en/thr)), if ld(en/thr) < C1 + n: estimated number of lines in sfb, + ld(x) = log(x)/log(2) + + constPart is sfbPe without the threshold part n*ld(thr) or n*C3*ld(thr) +*/ +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *RESTRICT const isBook, + const INT *RESTRICT const isScale) { + INT sfbGrp, sfb, thisSfb; + INT nLines; + FIXP_DBL logDataRatio; + FIXP_DBL scaleLd = (FIXP_DBL)0; + INT lastValIs = 0; + + FIXP_DBL pe = 0; + FIXP_DBL constPart = 0; + FIXP_DBL nActiveLines = 0; + + FIXP_DBL tmpPe, tmpConstPart, tmpNActiveLines; + + for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + tmpPe = (FIXP_DBL)0; + tmpConstPart = (FIXP_DBL)0; + tmpNActiveLines = (FIXP_DBL)0; + + thisSfb = sfbGrp + sfb; + + if (sfbEnergyLdData[thisSfb] > sfbThresholdLdData[thisSfb]) { + logDataRatio = sfbEnergyLdData[thisSfb] - sfbThresholdLdData[thisSfb]; + nLines = peChanData->sfbNLines[thisSfb]; + + FIXP_DBL factor = nLines << (LD_DATA_SHIFT + PE_CONSTPART_SHIFT + 1); + if (logDataRatio >= C1LdData) { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + tmpPe = fMultDiv2(logDataRatio, factor); + tmpConstPart = fMultDiv2(sfbEnergyLdData[thisSfb] + scaleLd, factor); + } else { + /* scale sfbPe and sfbConstPart with PE_CONSTPART_SHIFT */ + tmpPe = fMultDiv2( + ((FIXP_DBL)C2LdData + fMult(C3LdData, logDataRatio)), factor); + tmpConstPart = + fMultDiv2(((FIXP_DBL)C2LdData + + fMult(C3LdData, sfbEnergyLdData[thisSfb] + scaleLd)), + factor); + + nLines = fMultI(C3LdData, nLines); + } + tmpNActiveLines = (FIXP_DBL)nLines; + } else if (isBook[thisSfb]) { + /* provide for cost of scale factor for Intensity */ + INT delta = isScale[thisSfb] - lastValIs; + lastValIs = isScale[thisSfb]; + peChanData->sfbPe[thisSfb] = FDKaacEnc_bitCountScalefactorDelta(delta) + << PE_CONSTPART_SHIFT; + peChanData->sfbConstPart[thisSfb] = 0; + peChanData->sfbNActiveLines[thisSfb] = 0; + } + peChanData->sfbPe[thisSfb] = tmpPe; + peChanData->sfbConstPart[thisSfb] = tmpConstPart; + peChanData->sfbNActiveLines[thisSfb] = tmpNActiveLines; + + /* sum up peChanData values */ + pe += tmpPe; + constPart += tmpConstPart; + nActiveLines += tmpNActiveLines; + } + } + + /* correct scaled pe and constPart values */ + peChanData->pe = pe >> PE_CONSTPART_SHIFT; + peChanData->constPart = constPart >> PE_CONSTPART_SHIFT; + + peChanData->nActiveLines = nActiveLines; +} diff --git a/fdk-aac/libAACenc/src/line_pe.h b/fdk-aac/libAACenc/src/line_pe.h new file mode 100644 index 0000000..ecc2388 --- /dev/null +++ b/fdk-aac/libAACenc/src/line_pe.h @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Perceptual entropie module + +*******************************************************************************/ + +#ifndef LINE_PE_H +#define LINE_PE_H + +#include "common_fix.h" + +#include "psy_const.h" + +#define PE_CONSTPART_SHIFT FRACT_BITS + +typedef struct { + /* calculated by FDKaacEnc_prepareSfbPe */ + INT sfbNLines[MAX_GROUPED_SFB]; /* number of relevant lines in sfb */ + /* the rest is calculated by FDKaacEnc_calcSfbPe */ + INT sfbPe[MAX_GROUPED_SFB]; /* pe for each sfb */ + INT sfbConstPart[MAX_GROUPED_SFB]; /* constant part for each sfb */ + INT sfbNActiveLines[MAX_GROUPED_SFB]; /* number of active lines in sfb */ + INT pe; /* sum of sfbPe */ + INT constPart; /* sum of sfbConstPart */ + INT nActiveLines; /* sum of sfbNActiveLines */ +} PE_CHANNEL_DATA; + +typedef struct { + PE_CHANNEL_DATA peChannelData[(2)]; + INT pe; + INT constPart; + INT nActiveLines; + INT offset; +} PE_DATA; + +void FDKaacEnc_prepareSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const FIXP_DBL *RESTRICT const sfbFormFactorLdData, + const INT *RESTRICT const sfbOffset, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup); + +void FDKaacEnc_calcSfbPe(PE_CHANNEL_DATA *RESTRICT const peChanData, + const FIXP_DBL *RESTRICT const sfbEnergyLdData, + const FIXP_DBL *RESTRICT const sfbThresholdLdData, + const INT sfbCnt, const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *RESTRICT const isBook, + const INT *RESTRICT const isScale); + +#endif diff --git a/fdk-aac/libAACenc/src/metadata_compressor.cpp b/fdk-aac/libAACenc/src/metadata_compressor.cpp new file mode 100644 index 0000000..bdac80a --- /dev/null +++ b/fdk-aac/libAACenc/src/metadata_compressor.cpp @@ -0,0 +1,1579 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Neusinger + + Description: Compressor for AAC Metadata Generator + +*******************************************************************************/ + +#include "metadata_compressor.h" +#include "channel_map.h" + +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define FIXP_ILOG2_DIV2 (FL2FXCONST_DBL(ILOG2 / 2)) + +/*----------------- defines ----------------------*/ + +#define MAX_DRC_CHANNELS (8) /*!< Max number of audio input channels. */ +#define DOWNMIX_SHIFT (3) /*!< Max 8 channel. */ +#define WEIGHTING_FILTER_SHIFT (2) /*!< Scaling used in weighting filter. */ + +#define METADATA_INT_BITS 10 +#define METADATA_LINT_BITS 20 +#define METADATA_INT_SCALE (INT64(1) << (METADATA_INT_BITS)) +#define METADATA_FRACT_BITS (DFRACT_BITS - 1 - METADATA_INT_BITS) +#define METADATA_FRACT_SCALE (INT64(1) << (METADATA_FRACT_BITS)) + +/** + * Enum for channel assignment. + */ +enum { L = 0, R = 1, C = 2, LFE = 3, LS = 4, RS = 5, S = 6, LS2 = 7, RS2 = 8 }; + +/*--------------- structure definitions --------------------*/ + +/** + * Structure holds weighting filter filter states. + */ +struct WEIGHTING_STATES { + FIXP_DBL x1; + FIXP_DBL x2; + FIXP_DBL y1; + FIXP_DBL y2; +}; + +/** + * Dynamic Range Control compressor structure. + */ +struct DRC_COMP { + FIXP_DBL maxBoostThr[2]; /*!< Max boost threshold. */ + FIXP_DBL boostThr[2]; /*!< Boost threshold. */ + FIXP_DBL earlyCutThr[2]; /*!< Early cut threshold. */ + FIXP_DBL cutThr[2]; /*!< Cut threshold. */ + FIXP_DBL maxCutThr[2]; /*!< Max cut threshold. */ + + FIXP_DBL boostFac[2]; /*!< Precalculated factor for boost compression. */ + FIXP_DBL + earlyCutFac[2]; /*!< Precalculated factor for early cut compression. */ + FIXP_DBL cutFac[2]; /*!< Precalculated factor for cut compression. */ + + FIXP_DBL maxBoost[2]; /*!< Maximum boost. */ + FIXP_DBL maxCut[2]; /*!< Maximum cut. */ + FIXP_DBL maxEarlyCut[2]; /*!< Maximum early cut. */ + + FIXP_DBL fastAttack[2]; /*!< Fast attack coefficient. */ + FIXP_DBL fastDecay[2]; /*!< Fast release coefficient. */ + FIXP_DBL slowAttack[2]; /*!< Slow attack coefficient. */ + FIXP_DBL slowDecay[2]; /*!< Slow release coefficient. */ + UINT holdOff[2]; /*!< Hold time in blocks. */ + + FIXP_DBL attackThr[2]; /*!< Slow/fast attack threshold. */ + FIXP_DBL decayThr[2]; /*!< Slow/fast release threshold. */ + + DRC_PROFILE profile[2]; /*!< DRC profile. */ + INT blockLength; /*!< Block length in samples. */ + UINT sampleRate; /*!< Sample rate. */ + CHANNEL_MODE chanConfig; /*!< Channel configuration. */ + + UCHAR useWeighting; /*!< Use weighting filter. */ + + UINT channels; /*!< Number of channels. */ + UINT fullChannels; /*!< Number of full range channels. */ + INT channelIdx[9]; /*!< Offsets of interleaved channel samples (L, R, C, LFE, + Ls, Rs, S, Ls2, Rs2). */ + + FIXP_DBL smoothLevel[2]; /*!< level smoothing states */ + FIXP_DBL smoothGain[2]; /*!< gain smoothing states */ + UINT holdCnt[2]; /*!< hold counter */ + + FIXP_DBL limGain[2]; /*!< limiter gain */ + FIXP_DBL limDecay; /*!< limiter decay (linear) */ + FIXP_DBL prevPeak[2]; /*!< max peak of previous block (stereo/mono)*/ + + WEIGHTING_STATES + filter[MAX_DRC_CHANNELS]; /*!< array holds weighting filter states */ +}; + +/*---------------- constants -----------------------*/ + +/** + * Profile tables. + */ +static const FIXP_DBL tabMaxBoostThr[] = { + (FIXP_DBL)(-(43 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(53 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(55 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(65 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(50 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(40 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabBoostThr[] = { + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(41 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(31 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabEarlyCutThr[] = { + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(26 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(20 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabCutThr[] = {(FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(11 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(21 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(16 << METADATA_FRACT_BITS)), + (FIXP_DBL)(-(10 << METADATA_FRACT_BITS))}; +static const FIXP_DBL tabMaxCutThr[] = { + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS), + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(9 << METADATA_FRACT_BITS), + (FIXP_DBL)(4 << METADATA_FRACT_BITS), (FIXP_DBL)(4 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabBoostRatio[] = { + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 5.f) - 1.f)), FL2FXCONST_DBL(((1.f / 5.f) - 1.f))}; +static const FIXP_DBL tabEarlyCutRatio[] = { + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 1.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f))}; +static const FIXP_DBL tabCutRatio[] = { + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 2.f) - 1.f)), + FL2FXCONST_DBL(((1.f / 20.f) - 1.f)), FL2FXCONST_DBL(((1.f / 20.f) - 1.f))}; +static const FIXP_DBL tabMaxBoost[] = {(FIXP_DBL)(6 << METADATA_FRACT_BITS), + (FIXP_DBL)(6 << METADATA_FRACT_BITS), + (FIXP_DBL)(12 << METADATA_FRACT_BITS), + (FIXP_DBL)(12 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabMaxCut[] = {(FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS), + (FIXP_DBL)(24 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabFastAttack[] = { + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabFastDecay[] = { + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((200.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabSlowAttack[] = { + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((100.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; +static const FIXP_DBL tabSlowDecay[] = { + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((10000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((3000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((1000.f / 1000.f) / METADATA_INT_SCALE), + FL2FXCONST_DBL((0.f / 1000.f) / METADATA_INT_SCALE)}; + +static const INT tabHoldOff[] = {10, 10, 10, 10, 10, 0}; + +static const FIXP_DBL tabAttackThr[] = {(FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(15 << METADATA_FRACT_BITS), + (FIXP_DBL)(10 << METADATA_FRACT_BITS), + (FIXP_DBL)(0 << METADATA_FRACT_BITS)}; +static const FIXP_DBL tabDecayThr[] = {(FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(20 << METADATA_FRACT_BITS), + (FIXP_DBL)(10 << METADATA_FRACT_BITS), + (FIXP_DBL)(0 << METADATA_FRACT_BITS)}; + +/** + * Weighting filter coefficients (biquad bandpass). + */ +static const FIXP_DBL b0 = FL2FXCONST_DBL(0.53050662f); /* b1 = 0, b2 = -b0 */ +static const FIXP_DBL a1 = FL2FXCONST_DBL(-0.95237983f), + a2 = FL2FXCONST_DBL(-0.02248836f); /* a0 = 1 */ + +/*------------- function definitions ----------------*/ + +/** + * \brief Calculate scaling factor for denoted processing block. + * + * \param blockLength Length of processing block. + * + * \return shiftFactor + */ +static UINT getShiftFactor(const UINT length) { + UINT ldN; + for (ldN = 1; (((UINT)1) << ldN) < length; ldN++) + ; + + return ldN; +} + +/** + * \brief Sum up fixpoint values with best possible accuracy. + * + * \param value1 First input value. + * \param q1 Scaling factor of first input value. + * \param pValue2 Pointer to second input value, will be modified on + * return. + * \param pQ2 Pointer to second scaling factor, will be modified on + * return. + * + * \return void + */ +static void fixpAdd(const FIXP_DBL value1, const int q1, + FIXP_DBL* const pValue2, int* const pQ2) { + const int headroom1 = fNormz(fixp_abs(value1)) - 1; + const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1; + int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2); + + if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) { + resultScale++; + } + + *pValue2 = scaleValue(value1, q1 - resultScale) + + scaleValue(*pValue2, (*pQ2) - resultScale); + *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1; +} + +/** + * \brief Function for converting time constant to filter coefficient. + * + * \param t Time constant. + * \param sampleRate Sampling rate in Hz. + * \param blockLength Length of processing block in samples per channel. + * + * \return result = 1.0 - exp(-1.0/((t) * (f))) + */ +static FIXP_DBL tc2Coeff(const FIXP_DBL t, const INT sampleRate, + const INT blockLength) { + FIXP_DBL sampleRateFract; + FIXP_DBL blockLengthFract; + FIXP_DBL f, product; + FIXP_DBL exponent, result; + INT e_res; + + /* f = sampleRate/blockLength */ + sampleRateFract = + (FIXP_DBL)(sampleRate << (DFRACT_BITS - 1 - METADATA_LINT_BITS)); + blockLengthFract = + (FIXP_DBL)(blockLength << (DFRACT_BITS - 1 - METADATA_LINT_BITS)); + f = fDivNorm(sampleRateFract, blockLengthFract, &e_res); + f = scaleValue(f, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* product = t*f */ + product = fMultNorm(t, f, &e_res); + product = scaleValue( + product, e_res + METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* exponent = (-1.0/((t) * (f))) */ + exponent = fDivNorm(METADATA_FRACT_SCALE, product, &e_res); + exponent = scaleValue( + exponent, e_res - METADATA_INT_BITS); /* convert to METADATA_FRACT */ + + /* exponent * ld(e) */ + exponent = fMult(exponent, FIXP_ILOG2_DIV2) << 1; /* e^(x) = 2^(x*ld(e)) */ + + /* exp(-1.0/((t) * (f))) */ + result = f2Pow(-exponent, DFRACT_BITS - 1 - METADATA_FRACT_BITS, &e_res); + + /* result = 1.0 - exp(-1.0/((t) * (f))) */ + result = (FIXP_DBL)MAXVAL_DBL - scaleValue(result, e_res); + + return result; +} + +static void findPeakLevels(HDRC_COMP drcComp, const INT_PCM* const inSamples, + const FIXP_DBL clev, const FIXP_DBL slev, + const FIXP_DBL ext_leva, const FIXP_DBL ext_levb, + const FIXP_DBL lfe_lev, const FIXP_DBL dmxGain5, + const FIXP_DBL dmxGain2, FIXP_DBL peak[2]) { + int i, c; + FIXP_DBL tmp = FL2FXCONST_DBL(0.f); + INT_PCM maxSample = 0; + + /* find peak level */ + peak[0] = peak[1] = FL2FXCONST_DBL(0.f); + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* single channels */ + for (c = 0; c < (int)drcComp->channels; c++) { + maxSample = fMax(maxSample, (INT_PCM)fAbs(pSamples[c])); + } + } + peak[0] = fixMax(peak[0], FX_PCM2FX_DBL(maxSample) >> DOWNMIX_SHIFT); + + /* 7.1/6.1 to 5.1 downmixes */ + if (drcComp->fullChannels > 5) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* channel 1 (L, Ls,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 2 (R, Rs,...) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* channel 3 (C) */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + DOWNMIX_SHIFT); /* C */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + break; + default: + break; + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + } /* for (blocklength) */ + + /* take downmix gain into accout */ + peak[0] = fMult(dmxGain5, peak[0]) + << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + + /* 7.1 / 5.1 to stereo downmixes */ + if (drcComp->fullChannels > 2) { + /* Lt/Rt downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp -= fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Rt */ + tmp = FL2FXCONST_DBL(0.f); + if (drcComp->channelIdx[LS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]]) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMultDiv2(FL2FXCONST_DBL(0.707f), + (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + + /* Lo/Ro downmix */ + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + /* Lo */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + break; + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + + /* Ro */ + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += + fMultDiv2(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += + fMultDiv2(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMultDiv2(lfe_lev, + (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[0] = fixMax(peak[0], fixp_abs(tmp)); + } + } + + peak[1] = fixMax(peak[0], peak[1]); + + /* Mono Downmix - for comp_val only */ + if (drcComp->fullChannels > 1) { + for (i = 0; i < drcComp->blockLength; i++) { + const INT_PCM* pSamples = &inSamples[i * drcComp->channels]; + + tmp = FL2FXCONST_DBL(0.f); + switch (drcComp->chanConfig) { + case MODE_6_1: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[6]]) >> + (DOWNMIX_SHIFT - 1); /* Cs */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(fMult(slev, ext_leva), + (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lrs / Lss*/ + tmp += fMultDiv2(fMult(slev, ext_levb), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rrs / Rss*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_1_2_2_2_1: + case MODE_7_1_FRONT_CENTER: + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + DOWNMIX_SHIFT); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc */ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lc - second path*/ + tmp += fMultDiv2(fMult(ext_leva, clev), + (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rc - second path*/ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + case MODE_7_1_TOP_FRONT: + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[0]]) >> + (DOWNMIX_SHIFT - 1); /* L */ + tmp += + fMultDiv2(ext_leva, (FIXP_PCM)pSamples[drcComp->channelIdx[1]]) >> + (DOWNMIX_SHIFT - 1); /* R */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[7]]) >> + (DOWNMIX_SHIFT - 1); /* Lvh */ + tmp += + fMultDiv2(ext_levb, (FIXP_PCM)pSamples[drcComp->channelIdx[8]]) >> + (DOWNMIX_SHIFT - 1); /* Rvh */ + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[2]]) >> + (DOWNMIX_SHIFT - 1); /* C */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[4]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + tmp += fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[5]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + break; + default: + if (drcComp->channelIdx[LS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS]]) >> + (DOWNMIX_SHIFT - 1); /* Ls */ + if (drcComp->channelIdx[LS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[LS2]]) >> + (DOWNMIX_SHIFT - 1); /* Ls2 */ + if (drcComp->channelIdx[RS] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS]]) >> + (DOWNMIX_SHIFT - 1); /* Rs */ + if (drcComp->channelIdx[RS2] >= 0) + tmp += + fMultDiv2(slev, (FIXP_PCM)pSamples[drcComp->channelIdx[RS2]]) >> + (DOWNMIX_SHIFT - 1); /* Rs2 */ + if ((drcComp->channelIdx[LS] >= 0) && (drcComp->channelIdx[LS2] >= 0)) + tmp = fMult(FL2FXCONST_DBL(0.707f), tmp); /* 7.1ch */ + /*if ((drcComp->channelIdx[RS] >= 0) && (drcComp->channelIdx[RS2] >= 0)) tmp *=0.707f;*/ /* 7.1ch */ + if (drcComp->channelIdx[S] >= 0) + tmp += + fMultDiv2(slev, + fMult(FL2FXCONST_DBL(0.7f), + (FIXP_PCM)pSamples[drcComp->channelIdx[S]])) >> + (DOWNMIX_SHIFT - 1); /* S */ + if (drcComp->channelIdx[C] >= 0) + tmp += fMult(clev, (FIXP_PCM)pSamples[drcComp->channelIdx[C]]) >> + (DOWNMIX_SHIFT - 1); /* C (2*clev) */ + if (drcComp->channelIdx[3] >= 0) + tmp += fMult(lfe_lev, (FIXP_PCM)pSamples[drcComp->channelIdx[3]]) >> + (DOWNMIX_SHIFT - 1 - LFE_LEV_SCALE); /* LFE */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[L]]) >> + DOWNMIX_SHIFT); /* L */ + tmp += (FX_PCM2FX_DBL((FIXP_PCM)pSamples[drcComp->channelIdx[R]]) >> + DOWNMIX_SHIFT); /* R */ + } + + /* apply scaling of downmix gains */ + /* only for positive values only, as legacy decoders might not know this + * parameter */ + if (dmxGain2 > FL2FXCONST_DBL(0.f)) { + if (drcComp->fullChannels > 5) { + tmp = fMult(dmxGain5, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + tmp = fMult(dmxGain2, tmp) << (DFRACT_BITS - 1 - METADATA_FRACT_BITS); + } + peak[1] = fixMax(peak[1], fixp_abs(tmp)); + } + } +} + +INT FDK_DRC_Generator_Open(HDRC_COMP* phDrcComp) { + INT err = 0; + HDRC_COMP hDcComp = NULL; + + if (phDrcComp == NULL) { + err = -1; + goto bail; + } + + /* allocate memory */ + hDcComp = (HDRC_COMP)FDKcalloc(1, sizeof(DRC_COMP)); + + if (hDcComp == NULL) { + err = -1; + goto bail; + } + + FDKmemclear(hDcComp, sizeof(DRC_COMP)); + + /* Return drc compressor instance */ + *phDrcComp = hDcComp; + return err; +bail: + FDK_DRC_Generator_Close(&hDcComp); + return err; +} + +INT FDK_DRC_Generator_Close(HDRC_COMP* phDrcComp) { + if (phDrcComp == NULL) { + return -1; + } + if (*phDrcComp != NULL) { + FDKfree(*phDrcComp); + *phDrcComp = NULL; + } + return 0; +} + +INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting) { + int i; + CHANNEL_MAPPING channelMapping; + + drcComp->limDecay = + FL2FXCONST_DBL(((0.006f / 256) * blockLength) / METADATA_INT_SCALE); + + /* Save parameters. */ + drcComp->blockLength = blockLength; + drcComp->sampleRate = sampleRate; + drcComp->chanConfig = channelMode; + drcComp->useWeighting = useWeighting; + + if (FDK_DRC_Generator_setDrcProfile(drcComp, profileLine, profileRF) != + 0) { /* expects initialized blockLength and sampleRate */ + return (-1); + } + + /* Set number of channels and channel offsets. */ + if (FDKaacEnc_InitChannelMapping(channelMode, channelOrder, + &channelMapping) != AAC_ENC_OK) { + return (-2); + } + + for (i = 0; i < 9; i++) drcComp->channelIdx[i] = -1; + + switch (channelMode) { + case MODE_1: /* mono */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_2: /* stereo */ + drcComp->channelIdx[L] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[0].ChannelIndex[1]; + break; + case MODE_1_2: /* 3ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + break; + case MODE_1_2_1: /* 4ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[S] = channelMapping.elInfo[2].ChannelIndex[0]; + break; + case MODE_1_2_2: /* 5ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_1: /* 5.1 ch */ + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; + drcComp->channelIdx[LFE] = channelMapping.elInfo[3].ChannelIndex[0]; + drcComp->channelIdx[LS] = channelMapping.elInfo[2].ChannelIndex[0]; + drcComp->channelIdx[RS] = channelMapping.elInfo[2].ChannelIndex[1]; + break; + case MODE_1_2_2_2_1: /* 7.1 ch */ + case MODE_7_1_FRONT_CENTER: + drcComp->channelIdx[L] = channelMapping.elInfo[2].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[2].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[1].ChannelIndex[0]; /* lc */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[1].ChannelIndex[1]; /* rc */ + break; + case MODE_7_1_BACK: + case MODE_7_1_REAR_SURROUND: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lrear */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[3].ChannelIndex[1]; /* rrear */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + break; + case MODE_6_1: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[S] = channelMapping.elInfo[3].ChannelIndex[0]; /* s */ + break; + case MODE_7_1_TOP_FRONT: + drcComp->channelIdx[L] = channelMapping.elInfo[1].ChannelIndex[0]; /* l */ + drcComp->channelIdx[R] = channelMapping.elInfo[1].ChannelIndex[1]; /* r */ + drcComp->channelIdx[C] = channelMapping.elInfo[0].ChannelIndex[0]; /* c */ + drcComp->channelIdx[LFE] = + channelMapping.elInfo[3].ChannelIndex[0]; /* lfe */ + drcComp->channelIdx[LS] = + channelMapping.elInfo[2].ChannelIndex[0]; /* ls */ + drcComp->channelIdx[RS] = + channelMapping.elInfo[2].ChannelIndex[1]; /* rs */ + drcComp->channelIdx[LS2] = + channelMapping.elInfo[4].ChannelIndex[0]; /* lvh2 */ + drcComp->channelIdx[RS2] = + channelMapping.elInfo[4].ChannelIndex[1]; /* rvh2 */ + break; + default: + return (-1); + } + + drcComp->fullChannels = channelMapping.nChannelsEff; + drcComp->channels = channelMapping.nChannels; + + /* Init states. */ + drcComp->smoothLevel[0] = drcComp->smoothLevel[1] = + (FIXP_DBL)(-(135 << METADATA_FRACT_BITS)); + + FDKmemclear(drcComp->smoothGain, sizeof(drcComp->smoothGain)); + FDKmemclear(drcComp->holdCnt, sizeof(drcComp->holdCnt)); + FDKmemclear(drcComp->limGain, sizeof(drcComp->limGain)); + FDKmemclear(drcComp->prevPeak, sizeof(drcComp->prevPeak)); + FDKmemclear(drcComp->filter, sizeof(drcComp->filter)); + + return (0); +} + +INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF) { + int profileIdx, i; + + drcComp->profile[0] = profileLine; + drcComp->profile[1] = profileRF; + + for (i = 0; i < 2; i++) { + /* get profile index */ + switch (drcComp->profile[i]) { + case DRC_NONE: + case DRC_NOT_PRESENT: + case DRC_FILMSTANDARD: + profileIdx = 0; + break; + case DRC_FILMLIGHT: + profileIdx = 1; + break; + case DRC_MUSICSTANDARD: + profileIdx = 2; + break; + case DRC_MUSICLIGHT: + profileIdx = 3; + break; + case DRC_SPEECH: + profileIdx = 4; + break; + case DRC_DELAY_TEST: + profileIdx = 5; + break; + default: + return (-1); + } + + /* get parameters for selected profile */ + if (profileIdx >= 0) { + drcComp->maxBoostThr[i] = tabMaxBoostThr[profileIdx]; + drcComp->boostThr[i] = tabBoostThr[profileIdx]; + drcComp->earlyCutThr[i] = tabEarlyCutThr[profileIdx]; + drcComp->cutThr[i] = tabCutThr[profileIdx]; + drcComp->maxCutThr[i] = tabMaxCutThr[profileIdx]; + + drcComp->boostFac[i] = tabBoostRatio[profileIdx]; + drcComp->earlyCutFac[i] = tabEarlyCutRatio[profileIdx]; + drcComp->cutFac[i] = tabCutRatio[profileIdx]; + + drcComp->maxBoost[i] = tabMaxBoost[profileIdx]; + drcComp->maxCut[i] = tabMaxCut[profileIdx]; + drcComp->maxEarlyCut[i] = + -fMult((drcComp->cutThr[i] - drcComp->earlyCutThr[i]), + drcComp->earlyCutFac[i]); /* no scaling after mult needed, + earlyCutFac is in FIXP_DBL */ + + drcComp->fastAttack[i] = tc2Coeff( + tabFastAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->fastDecay[i] = tc2Coeff( + tabFastDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowAttack[i] = tc2Coeff( + tabSlowAttack[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->slowDecay[i] = tc2Coeff( + tabSlowDecay[profileIdx], drcComp->sampleRate, drcComp->blockLength); + drcComp->holdOff[i] = tabHoldOff[profileIdx] * 256 / drcComp->blockLength; + + drcComp->attackThr[i] = tabAttackThr[profileIdx]; + drcComp->decayThr[i] = tabDecayThr[profileIdx]; + } + + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } + return (0); +} + +INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM* const inSamples, + const UINT inSamplesBufSize, const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, const FIXP_DBL clev, + const FIXP_DBL slev, const FIXP_DBL ext_leva, + const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev, + const INT dmxGain5, const INT dmxGain2, + INT* const pDynrng, INT* const pCompr) { + int i, c; + FIXP_DBL peak[2]; + + /************************************************************************** + * compressor + **************************************************************************/ + if ((drcComp->profile[0] != DRC_NONE) || (drcComp->profile[1] != DRC_NONE)) { + /* Calc loudness level */ + FIXP_DBL level_b = FL2FXCONST_DBL(0.f); + int level_e = DFRACT_BITS - 1; + + /* Increase energy time resolution with shorter processing blocks. 16 is an + * empiric value. */ + const int granuleLength = fixMin(16, drcComp->blockLength); + + if (drcComp->useWeighting) { + FIXP_DBL x1, x2, y, y1, y2; + /* sum of filter coefficients about 2.5 -> squared value is 6.25 + WEIGHTING_FILTER_SHIFT is 2 -> scaling about 16, therefore reduce + granuleShift by 1. + */ + const int granuleShift = getShiftFactor(granuleLength) - 1; + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if (c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + /* get filter states */ + x1 = drcComp->filter[c].x1; + x2 = drcComp->filter[c].x2; + y1 = drcComp->filter[c].y1; + y2 = drcComp->filter[c].y2; + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* apply weighting filter */ + FIXP_DBL x = + FX_PCM2FX_DBL((FIXP_PCM)pSamples[i]) >> WEIGHTING_FILTER_SHIFT; + + /* y = b0 * (x - x2) - a1 * y1 - a2 * y2; */ + y = fMult(b0, x - x2) - fMult(a1, y1) - fMult(a2, y2); + + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + + accu += fPow2Div2(y) >> (granuleShift - 1); /* partial energy */ + } /* i */ + + fixpAdd(accu, granuleShift + 2 * WEIGHTING_FILTER_SHIFT, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + + /* save filter states */ + drcComp->filter[c].x1 = x1; + drcComp->filter[c].x2 = x2; + drcComp->filter[c].y1 = y1; + drcComp->filter[c].y2 = y2; + } /* c */ + } /* weighting */ + else { + const int granuleShift = getShiftFactor(granuleLength); + + for (c = 0; c < (int)drcComp->channels; c++) { + const INT_PCM* pSamples = inSamples + c * inSamplesBufSize; + + if ((int)c == drcComp->channelIdx[LFE]) { + continue; /* skip LFE */ + } + + i = 0; + + do { + int offset = i; + FIXP_DBL accu = FL2FXCONST_DBL(0.f); + + for (i = offset; + i < fixMin(offset + granuleLength, drcComp->blockLength); i++) { + /* partial energy */ + accu += fPow2Div2((FIXP_PCM)pSamples[i]) >> (granuleShift - 1); + } /* i */ + + fixpAdd(accu, granuleShift, &level_b, + &level_e); /* sup up partial energies */ + + } while (i < drcComp->blockLength); + } + } /* weighting */ + + /* + * Convert to dBFS, apply dialnorm + */ + /* level scaling */ + + /* descaled level in ld64 representation */ + FIXP_DBL ldLevel = + CalcLdData(level_b) + + (FIXP_DBL)((level_e - 12) << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) - + CalcLdData((FIXP_DBL)(drcComp->blockLength << (DFRACT_BITS - 1 - 12))); + + /* if (level < 1e-10) level = 1e-10f; */ + ldLevel = + fMax(ldLevel, FL2FXCONST_DBL(-0.51905126482615036685473741085772f)); + + /* level = 10 * log(level)/log(10) + 3; + * = 10*log(2)/log(10) * ld(level) + 3; + * = 10 * 0.30102999566398119521373889472449 * ld(level) + 3 + * = 10 * (0.30102999566398119521373889472449 * ld(level) + 0.3) + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 + * + * additional scaling with METADATA_FRACT_BITS: + * = 10 * (0.30102999566398119521373889472449 * ld64(level) + 0.3/64) + * * 64 * 2^(METADATA_FRACT_BITS) = 10 * (0.30102999566398119521373889472449 + * * ld64(level) + 0.3/64) * 2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) = + * 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * ( + * 0.30102999566398119521373889472449 * ld64(level) + 0.3/64 ) + * */ + FIXP_DBL level = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FXCONST_DBL(0.30102999566398119521373889472449f), ldLevel) + + (FIXP_DBL)(FL2FXCONST_DBL(0.3f) >> LD_DATA_SHIFT)); + + /* level -= dialnorm + 31 */ /* this is fixed to Dolby-ReferenceLevel as + compressor profiles are defined relative to + this */ + level -= ((FIXP_DBL)(dialnorm << (METADATA_FRACT_BITS - 16)) + + (FIXP_DBL)(31 << METADATA_FRACT_BITS)); + + for (i = 0; i < 2; i++) { + if (drcComp->profile[i] == DRC_NONE) { + /* no compression */ + drcComp->smoothGain[i] = FL2FXCONST_DBL(0.f); + } else { + FIXP_DBL gain, alpha, lvl2smthlvl; + + /* calc static gain */ + if (level <= drcComp->maxBoostThr[i]) { + /* max boost */ + gain = drcComp->maxBoost[i]; + } else if (level < drcComp->boostThr[i]) { + /* boost range */ + gain = fMult((level - drcComp->boostThr[i]), drcComp->boostFac[i]); + } else if (level <= drcComp->earlyCutThr[i]) { + /* null band */ + gain = FL2FXCONST_DBL(0.f); + } else if (level <= drcComp->cutThr[i]) { + /* early cut range */ + gain = + fMult((level - drcComp->earlyCutThr[i]), drcComp->earlyCutFac[i]); + } else if (level < drcComp->maxCutThr[i]) { + /* cut range */ + gain = fMult((level - drcComp->cutThr[i]), drcComp->cutFac[i]) - + drcComp->maxEarlyCut[i]; + } else { + /* max cut */ + gain = -drcComp->maxCut[i]; + } + + /* choose time constant */ + lvl2smthlvl = level - drcComp->smoothLevel[i]; + if (gain < drcComp->smoothGain[i]) { + /* attack */ + if (lvl2smthlvl > drcComp->attackThr[i]) { + /* fast attack */ + alpha = drcComp->fastAttack[i]; + } else { + /* slow attack */ + alpha = drcComp->slowAttack[i]; + } + } else { + /* release */ + if (lvl2smthlvl < -drcComp->decayThr[i]) { + /* fast release */ + alpha = drcComp->fastDecay[i]; + } else { + /* slow release */ + alpha = drcComp->slowDecay[i]; + } + } + + /* smooth gain & level */ + if ((gain < drcComp->smoothGain[i]) || + (drcComp->holdCnt[i] == + 0)) { /* hold gain unless we have an attack or hold + period is over */ + FIXP_DBL accu; + + /* drcComp->smoothLevel[i] = (1-alpha) * drcComp->smoothLevel[i] + + * alpha * level; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothLevel[i]); + accu += fMult(alpha, level); + drcComp->smoothLevel[i] = accu; + + /* drcComp->smoothGain[i] = (1-alpha) * drcComp->smoothGain[i] + + * alpha * gain; */ + accu = fMult(((FIXP_DBL)MAXVAL_DBL - alpha), drcComp->smoothGain[i]); + accu += fMult(alpha, gain); + drcComp->smoothGain[i] = accu; + } + + /* hold counter */ + if (drcComp->holdCnt[i]) { + drcComp->holdCnt[i]--; + } + if (gain < drcComp->smoothGain[i]) { + drcComp->holdCnt[i] = drcComp->holdOff[i]; + } + } /* profile != DRC_NONE */ + } /* for i=1..2 */ + } else { + /* no compression */ + drcComp->smoothGain[0] = FL2FXCONST_DBL(0.f); + drcComp->smoothGain[1] = FL2FXCONST_DBL(0.f); + } + + /************************************************************************** + * limiter + **************************************************************************/ + + findPeakLevels(drcComp, inSamples, clev, slev, ext_leva, ext_levb, lfe_lev, + (FIXP_DBL)((LONG)(dmxGain5) << (METADATA_FRACT_BITS - 16)), + (FIXP_DBL)((LONG)(dmxGain2) << (METADATA_FRACT_BITS - 16)), + peak); + + for (i = 0; i < 2; i++) { + FIXP_DBL tmp = drcComp->prevPeak[i]; + drcComp->prevPeak[i] = peak[i]; + peak[i] = fixMax(peak[i], tmp); + + /* + * Convert to dBFS, apply dialnorm + */ + /* descaled peak in ld64 representation */ + FIXP_DBL ld_peak = + CalcLdData(peak[i]) + + (FIXP_DBL)((LONG)DOWNMIX_SHIFT << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + /* if (peak < 1e-6) level = 1e-6f; */ + ld_peak = + fMax(ld_peak, FL2FXCONST_DBL(-0.31143075889569022011284244651463f)); + + /* peak[i] = 20 * log(peak[i])/log(10) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 20 * + * log(2)/log(10) * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) peak[i] = 10 * + * 2*0.30102999566398119521373889472449 * ld(peak[i]) + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS) + * + * additional scaling with METADATA_FRACT_BITS: + * peak[i] = (10 * 2*0.30102999566398119521373889472449 * ld64(peak[i]) * 64 + * + 0.2f + + * (drcComp->smoothGain[i]*2^METADATA_FRACT_BITS))*2^(-METADATA_FRACT_BITS) + * peak[i] = 10*2^(METADATA_FRACT_BITS+LD_DATA_SHIFT) * + * 2*0.30102999566398119521373889472449 * ld64(peak[i]) + * + 0.2f*2^(-METADATA_FRACT_BITS) + drcComp->smoothGain[i] + */ + peak[i] = fMult( + (FIXP_DBL)(10 << (METADATA_FRACT_BITS + LD_DATA_SHIFT)), + fMult(FL2FX_DBL(2 * 0.30102999566398119521373889472449f), ld_peak)); + peak[i] += + (FL2FX_DBL(0.5f) >> METADATA_INT_BITS); /* add a little bit headroom */ + peak[i] += drcComp->smoothGain[i]; + } + + /* peak -= dialnorm + 31; */ /* this is Dolby style only */ + peak[0] -= (FIXP_DBL)((dialnorm - drc_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[0] -= dialnorm - drc_TargetRefLevel */ + + /* peak += 11; */ + /* this is Dolby style only */ /* RF mode output is 11dB higher */ + /*peak += comp_TargetRefLevel - drc_TargetRefLevel;*/ + peak[1] -= + (FIXP_DBL)((dialnorm - comp_TargetRefLevel) + << (METADATA_FRACT_BITS - + 16)); /* peak[1] -= dialnorm - comp_TargetRefLevel */ + + /* limiter gain */ + drcComp->limGain[0] += drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[0] = fixMin(drcComp->limGain[0], -peak[0]); + + drcComp->limGain[1] += 2 * drcComp->limDecay; /* linear limiter release */ + drcComp->limGain[1] = fixMin(drcComp->limGain[1], -peak[1]); + + /*************************************************************************/ + + /* apply limiting, return DRC gains*/ + { + FIXP_DBL tmp; + + tmp = drcComp->smoothGain[0]; + if (drcComp->limGain[0] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[0]; + } + *pDynrng = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); + + tmp = drcComp->smoothGain[1]; + if (drcComp->limGain[1] < FL2FXCONST_DBL(0.f)) { + tmp += drcComp->limGain[1]; + } + *pCompr = (LONG)scaleValue(tmp, -(METADATA_FRACT_BITS - 16)); + } + + return 0; +} + +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp) { + return drcComp->profile[0]; +} + +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp) { + return drcComp->profile[1]; +} diff --git a/fdk-aac/libAACenc/src/metadata_compressor.h b/fdk-aac/libAACenc/src/metadata_compressor.h new file mode 100644 index 0000000..1d0aa42 --- /dev/null +++ b/fdk-aac/libAACenc/src/metadata_compressor.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Neusinger + + Description: Compressor for AAC Metadata Generator + +*******************************************************************************/ + +#ifndef METADATA_COMPRESSOR_H +#define METADATA_COMPRESSOR_H + +#include "FDK_audio.h" +#include "common_fix.h" + +#include "aacenc.h" + +#define LFE_LEV_SCALE 2 + +/** + * DRC compression profiles. + */ +typedef enum DRC_PROFILE { + DRC_NONE = 0, + DRC_FILMSTANDARD = 1, + DRC_FILMLIGHT = 2, + DRC_MUSICSTANDARD = 3, + DRC_MUSICLIGHT = 4, + DRC_SPEECH = 5, + DRC_DELAY_TEST = 6, + DRC_NOT_PRESENT = -2 + +} DRC_PROFILE; + +/** + * DRC Compressor handle. + */ +typedef struct DRC_COMP DRC_COMP, *HDRC_COMP; + +/** + * \brief Open a DRC Compressor instance. + * + * Allocate memory for a compressor instance. + * + * \param phDrcComp A pointer to a compressor handle. Initialized on + * return. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Open(HDRC_COMP *phDrcComp); + +/** + * \brief Close the DRC Compressor instance. + * + * Deallocate instance and free whole memory. + * + * \param phDrcComp Pointer to the compressor handle to be + * deallocated. + * + * \return + * - 0, on succes. + * - unequal 0, on failure. + */ +INT FDK_DRC_Generator_Close(HDRC_COMP *phDrcComp); + +/** + * \brief Configure DRC Compressor. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * \param blockLength Length of processing block in samples per + * channel. + * \param sampleRate Sampling rate in Hz. + * \param channelMode Channel configuration. + * \param channelOrder Channel order, MPEG or WAV. + * \param useWeighting Use weighting filter for loudness calculation + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Initialize(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF, + const INT blockLength, const UINT sampleRate, + const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder, + const UCHAR useWeighting); + +/** + * \brief Calculate DRC Compressor Gain. + * + * \param drcComp Compressor handle. + * \param inSamples Pointer to interleaved input audio samples. + * \param inSamplesBufSize Size of inSamples for one channel. + * \param dialnorm Dialog Level in dB (typically -31...-1). + * \param drc_TargetRefLevel + * \param comp_TargetRefLevel + * \param clev Downmix center mix factor (typically 0.707, + * 0.595 or 0.5) + * \param slev Downmix surround mix factor (typically 0.707, + * 0.5, or 0) + * \param ext_leva Downmix gain factor A + * \param ext_levb Downmix gain factor B + * \param lfe_lev LFE gain factor + * \param dmxGain5 Gain factor for downmix to 5 channels + * \param dmxGain2 Gain factor for downmix to 2 channels + * \param dynrng Pointer to variable receiving line mode DRC gain + * in dB + * \param compr Pointer to variable receiving RF mode DRC gain + * in dB + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_Calc(HDRC_COMP drcComp, const INT_PCM *const inSamples, + const UINT inSamplesBufSize, const INT dialnorm, + const INT drc_TargetRefLevel, + const INT comp_TargetRefLevel, const FIXP_DBL clev, + const FIXP_DBL slev, const FIXP_DBL ext_leva, + const FIXP_DBL ext_levb, const FIXP_DBL lfe_lev, + const INT dmxGain5, const INT dmxGain2, + INT *const dynrng, INT *const compr); + +/** + * \brief Configure DRC Compressor Profile. + * + * \param drcComp Compressor handle. + * \param profileLine DRC profile for line mode. + * \param profileRF DRC profile for RF mode. + * + * \return + * - 0, on success, + * - unequal 0, on failure + */ +INT FDK_DRC_Generator_setDrcProfile(HDRC_COMP drcComp, + const DRC_PROFILE profileLine, + const DRC_PROFILE profileRF); + +/** + * \brief Get DRC profile for line mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getDrcProfile(const HDRC_COMP drcComp); + +/** + * \brief Get DRC profile for RF mode. + * + * \param drcComp Compressor handle. + * + * \return Current Profile. + */ +DRC_PROFILE FDK_DRC_Generator_getCompProfile(const HDRC_COMP drcComp); + +#endif /* METADATA_COMPRESSOR_H */ diff --git a/fdk-aac/libAACenc/src/metadata_main.cpp b/fdk-aac/libAACenc/src/metadata_main.cpp new file mode 100644 index 0000000..ada4502 --- /dev/null +++ b/fdk-aac/libAACenc/src/metadata_main.cpp @@ -0,0 +1,1191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): V. Bacigalupo + + Description: Metadata Encoder library interface functions + +*******************************************************************************/ + +#include "metadata_main.h" +#include "metadata_compressor.h" +#include "FDK_bitstream.h" +#include "FDK_audio.h" +#include "genericStds.h" + +/*----------------- defines ----------------------*/ +#define MAX_DRC_BANDS (1 << 4) +#define MAX_DRC_FRAMELEN (2 * 1024) +#define MAX_DELAY_FRAMES (3) + +/*--------------- structure definitions --------------------*/ + +typedef struct AAC_METADATA { + /* MPEG: Dynamic Range Control */ + struct { + UCHAR prog_ref_level_present; + SCHAR prog_ref_level; + + UCHAR dyn_rng_sgn[MAX_DRC_BANDS]; + UCHAR dyn_rng_ctl[MAX_DRC_BANDS]; + + UCHAR drc_bands_present; + UCHAR drc_band_incr; + UCHAR drc_band_top[MAX_DRC_BANDS]; + UCHAR drc_interpolation_scheme; + AACENC_METADATA_DRC_PROFILE drc_profile; + INT drc_TargetRefLevel; /* used for Limiter */ + + /* excluded channels */ + UCHAR excluded_chns_present; + UCHAR exclude_mask[2]; /* MAX_NUMBER_CHANNELS/8 */ + } mpegDrc; + + /* ETSI: addtl ancillary data */ + struct { + /* Heavy Compression */ + UCHAR compression_on; /* flag, if compression value should be written */ + UCHAR compression_value; /* compression value */ + AACENC_METADATA_DRC_PROFILE comp_profile; + INT comp_TargetRefLevel; /* used for Limiter */ + INT timecode_coarse_status; + INT timecode_fine_status; + + UCHAR extAncDataStatus; + + struct { + UCHAR ext_downmix_lvl_status; + UCHAR ext_downmix_gain_status; + UCHAR ext_lfe_downmix_status; + UCHAR + ext_dmix_a_idx; /* extended downmix level (0..7, according to table) + */ + UCHAR + ext_dmix_b_idx; /* extended downmix level (0..7, according to table) + */ + UCHAR dmx_gain_5_sgn; + UCHAR dmx_gain_5_idx; + UCHAR dmx_gain_2_sgn; + UCHAR dmx_gain_2_idx; + UCHAR ext_dmix_lfe_idx; /* extended downmix level for lfe (0..15, + according to table) */ + + } extAncData; + + } etsiAncData; + + SCHAR centerMixLevel; /* center downmix level (0...7, according to table) */ + SCHAR + surroundMixLevel; /* surround downmix level (0...7, according to table) */ + UCHAR WritePCEMixDwnIdx; /* flag */ + UCHAR DmxLvl_On; /* flag */ + + UCHAR dolbySurroundMode; + UCHAR drcPresentationMode; + + UCHAR + metadataMode; /* indicate meta data mode in current frame (delay line) */ + +} AAC_METADATA; + +typedef struct FDK_METADATA_ENCODER { + INT metadataMode; + HDRC_COMP hDrcComp; + AACENC_MetaData submittedMetaData; + + INT nAudioDataDelay; /* Additional delay to round up to next frame border (in + samples) */ + INT nMetaDataDelay; /* Meta data delay (in frames) */ + INT nChannels; + CHANNEL_MODE channelMode; + + INT_PCM* pAudioDelayBuffer; + + AAC_METADATA metaDataBuffer[MAX_DELAY_FRAMES]; + INT metaDataDelayIdx; + + UCHAR drcInfoPayload[12]; + UCHAR drcDsePayload[8]; + + INT matrix_mixdown_idx; + + AACENC_EXT_PAYLOAD exPayload[2]; + INT nExtensions; + + UINT maxChannels; /* Maximum number of audio channels to be supported. */ + + INT finalizeMetaData; /* Delay switch off by one frame and write default + configuration to finalize the metadata setup. */ + INT initializeMetaData; /* Fill up delay line with first meta data info. This + is required to have meta data already in first + frame. */ +} FDK_METADATA_ENCODER; + +/*---------------- constants -----------------------*/ +static const AACENC_MetaData defaultMetaDataSetup = { + AACENC_METADATA_DRC_NONE, /* drc_profile */ + AACENC_METADATA_DRC_NOT_PRESENT, /* comp_profile */ + -(31 << 16), /* drc_TargetRefLevel */ + -(23 << 16), /* comp_TargetRefLevel */ + 0, /* prog_ref_level_present */ + -(23 << 16), /* prog_ref_level */ + 0, /* PCE_mixdown_idx_present */ + 0, /* ETSI_DmxLvl_present */ + 0, /* centerMixLevel */ + 0, /* surroundMixLevel */ + 0, /* dolbySurroundMode */ + 0, /* drcPresentationMode */ + {0, 0, 0, 0, 0, 0, 0, 0, 0} /* ExtMetaData */ +}; + +static const FIXP_DBL dmxTable[8] = { + ((FIXP_DBL)MAXVAL_DBL), FL2FXCONST_DBL(0.841f), FL2FXCONST_DBL(0.707f), + FL2FXCONST_DBL(0.596f), FL2FXCONST_DBL(0.500f), FL2FXCONST_DBL(0.422f), + FL2FXCONST_DBL(0.355f), FL2FXCONST_DBL(0.000f)}; + +#define FL2DMXLFE(a) FL2FXCONST_DBL((a) / (1 << LFE_LEV_SCALE)) +static const FIXP_DBL dmxLfeTable[16] = { + FL2DMXLFE(3.162f), FL2DMXLFE(2.000f), FL2DMXLFE(1.679f), FL2DMXLFE(1.413f), + FL2DMXLFE(1.189f), FL2DMXLFE(1.000f), FL2DMXLFE(0.841f), FL2DMXLFE(0.707f), + FL2DMXLFE(0.596f), FL2DMXLFE(0.500f), FL2DMXLFE(0.316f), FL2DMXLFE(0.178f), + FL2DMXLFE(0.100f), FL2DMXLFE(0.032f), FL2DMXLFE(0.010f), FL2DMXLFE(0.000f)}; + +static const UCHAR surmix2matrix_mixdown_idx[8] = {0, 0, 0, 1, 1, 2, 2, 3}; + +/*--------------- function declarations --------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA* const pMetadata); + +static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload); + +static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload); + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples); + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData* const hMetadata, const INT nChannels, + const INT metadataMode, AAC_METADATA* const pAacMetaData); + +static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM* const pSamples, + const UINT samplesBufSize, + const INT nSamples); + +/*------------- function definitions ----------------*/ + +static DRC_PROFILE convertProfile(AACENC_METADATA_DRC_PROFILE aacProfile) { + DRC_PROFILE drcProfile = DRC_NONE; + + switch (aacProfile) { + case AACENC_METADATA_DRC_NONE: + drcProfile = DRC_NONE; + break; + case AACENC_METADATA_DRC_FILMSTANDARD: + drcProfile = DRC_FILMSTANDARD; + break; + case AACENC_METADATA_DRC_FILMLIGHT: + drcProfile = DRC_FILMLIGHT; + break; + case AACENC_METADATA_DRC_MUSICSTANDARD: + drcProfile = DRC_MUSICSTANDARD; + break; + case AACENC_METADATA_DRC_MUSICLIGHT: + drcProfile = DRC_MUSICLIGHT; + break; + case AACENC_METADATA_DRC_SPEECH: + drcProfile = DRC_SPEECH; + break; + case AACENC_METADATA_DRC_NOT_PRESENT: + drcProfile = DRC_NOT_PRESENT; + break; + default: + drcProfile = DRC_NONE; + break; + } + return drcProfile; +} + +/* convert dialog normalization to program reference level */ +/* NOTE: this only is correct, if the decoder target level is set to -31dB for + * line mode / -20dB for RF mode */ +static UCHAR dialnorm2progreflvl(const INT d) { + return ((UCHAR)fMax(0, fMin((-d + (1 << 13)) >> 14, 127))); +} + +/* convert program reference level to dialog normalization */ +static INT progreflvl2dialnorm(const UCHAR p) { + return -((INT)(p << (16 - 2))); +} + +/* encode downmix levels to Downmixing_levels_MPEG4 */ +static SCHAR encodeDmxLvls(const SCHAR cmixlev, const SCHAR surmixlev) { + SCHAR dmxLvls = 0; + dmxLvls |= 0x80 | (cmixlev << 4); /* center_mix_level_on */ + dmxLvls |= 0x08 | surmixlev; /* surround_mix_level_on */ + + return dmxLvls; +} + +/* encode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static void encodeDynrng(INT gain, UCHAR* const dyn_rng_ctl, + UCHAR* const dyn_rng_sgn) { + if (gain < 0) { + *dyn_rng_sgn = 1; + gain = -gain; + } else { + *dyn_rng_sgn = 0; + } + gain = fMin(gain, (127 << 14)); + + *dyn_rng_ctl = (UCHAR)((gain + (1 << 13)) >> 14); +} + +/* decode AAC DRC gain (ISO/IEC 14496-3:2005 4.5.2.7) */ +static INT decodeDynrng(const UCHAR dyn_rng_ctl, const UCHAR dyn_rng_sgn) { + INT tmp = ((INT)dyn_rng_ctl << (16 - 2)); + if (dyn_rng_sgn) tmp = -tmp; + + return tmp; +} + +/* encode AAC compression value (ETSI TS 101 154 page 99) */ +static UCHAR encodeCompr(INT gain) { + UCHAR x, y; + INT tmp; + + /* tmp = (int)((48.164f - gain) / 6.0206f * 15 + 0.5f); */ + tmp = ((3156476 - gain) * 15 + 197283) / 394566; + + if (tmp >= 240) { + return 0xFF; + } else if (tmp < 0) { + return 0; + } else { + x = tmp / 15; + y = tmp % 15; + } + + return (x << 4) | y; +} + +/* decode AAC compression value (ETSI TS 101 154 page 99) */ +static INT decodeCompr(const UCHAR compr) { + INT gain; + SCHAR x = compr >> 4; /* 4 MSB of compr */ + UCHAR y = (compr & 0x0F); /* 4 LSB of compr */ + + /* gain = (INT)((48.164f - 6.0206f * x - 0.4014f * y) ); */ + gain = (INT)( + scaleValue((FIXP_DBL)(((LONG)FL2FXCONST_DBL(6.0206f / 128.f) * (8 - x) - + (LONG)FL2FXCONST_DBL(0.4014f / 128.f) * y)), + -(DFRACT_BITS - 1 - 7 - 16))); + + return gain; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Open(HANDLE_FDK_METADATA_ENCODER* phMetaData, + const UINT maxChannels) { + FDK_METADATA_ERROR err = METADATA_OK; + HANDLE_FDK_METADATA_ENCODER hMetaData = NULL; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* allocate memory */ + if (NULL == (hMetaData = (HANDLE_FDK_METADATA_ENCODER)FDKcalloc( + 1, sizeof(FDK_METADATA_ENCODER)))) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMetaData, sizeof(FDK_METADATA_ENCODER)); + + if (NULL == (hMetaData->pAudioDelayBuffer = (INT_PCM*)FDKcalloc( + maxChannels * MAX_DRC_FRAMELEN, sizeof(INT_PCM)))) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMetaData->pAudioDelayBuffer, + maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); + hMetaData->maxChannels = maxChannels; + + /* Allocate DRC Compressor. */ + if (FDK_DRC_Generator_Open(&hMetaData->hDrcComp) != 0) { + err = METADATA_MEMORY_ERROR; + goto bail; + } + hMetaData->channelMode = MODE_UNKNOWN; + + /* Return metadata instance */ + *phMetaData = hMetaData; + + return err; + +bail: + FDK_MetadataEnc_Close(&hMetaData); + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER* phMetaData) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (phMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + if (*phMetaData != NULL) { + FDK_DRC_Generator_Close(&(*phMetaData)->hDrcComp); + FDKfree((*phMetaData)->pAudioDelayBuffer); + FDKfree(*phMetaData); + *phMetaData = NULL; + } +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetaData, const INT resetStates, + const INT metadataMode, const INT audioDelay, const UINT frameLength, + const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder) { + FDK_METADATA_ERROR err = METADATA_OK; + int i, nFrames, delay; + + if (hMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + /* Determine values for delay compensation. */ + for (nFrames = 0, delay = audioDelay - (INT)frameLength; delay > 0; + delay -= (INT)frameLength, nFrames++) + ; + + if ((nChannels > (8)) || (nChannels > hMetaData->maxChannels) || + ((-delay) > MAX_DRC_FRAMELEN) || nFrames >= MAX_DELAY_FRAMES) { + err = METADATA_INIT_ERROR; + goto bail; + } + + /* Initialize with default setup. */ + FDKmemcpy(&hMetaData->submittedMetaData, &defaultMetaDataSetup, + sizeof(AACENC_MetaData)); + + hMetaData->finalizeMetaData = + 0; /* finalize meta data only while on/off switching, else disabled */ + hMetaData->initializeMetaData = + 0; /* fill up meta data delay line only at a reset otherwise disabled */ + + /* Reset delay lines. */ + if (resetStates || (hMetaData->nAudioDataDelay != -delay) || + (hMetaData->channelMode != channelMode)) { + if (resetStates || (hMetaData->channelMode == MODE_UNKNOWN)) { + /* clear delay buffer */ + FDKmemclear(hMetaData->pAudioDelayBuffer, + hMetaData->maxChannels * MAX_DRC_FRAMELEN * sizeof(INT_PCM)); + } else { + /* if possible, keep static audio channels for seamless channel + * reconfiguration */ + FDK_channelMapDescr mapDescrPrev, mapDescr; + int c, src[2] = {-1, -1}, dst[2] = {-1, -1}; + + if (channelOrder == CH_ORDER_WG4) { + FDK_chMapDescr_init(&mapDescrPrev, FDK_mapInfoTabWg4, + FDK_mapInfoTabLenWg4, 0); + FDK_chMapDescr_init(&mapDescr, FDK_mapInfoTabWg4, + FDK_mapInfoTabLenWg4, 0); + } else { + FDK_chMapDescr_init(&mapDescrPrev, NULL, 0, + (channelOrder == CH_ORDER_MPEG) ? 1 : 0); + FDK_chMapDescr_init(&mapDescr, NULL, 0, + (channelOrder == CH_ORDER_MPEG) ? 1 : 0); + } + + switch (channelMode) { + case MODE_1: + if ((INT)nChannels != 2) { + /* preserve center channel */ + src[0] = FDK_chMapDescr_getMapValue(&mapDescrPrev, 0, + hMetaData->channelMode); + dst[0] = FDK_chMapDescr_getMapValue(&mapDescr, 0, channelMode); + } + break; + case MODE_2: + case MODE_1_2: + case MODE_1_2_1: + case MODE_1_2_2: + case MODE_1_2_2_1: + if (hMetaData->nChannels >= 2) { + /* preserve left/right channel */ + src[0] = FDK_chMapDescr_getMapValue( + &mapDescrPrev, ((hMetaData->channelMode == 2) ? 0 : 1), + hMetaData->channelMode); + src[1] = FDK_chMapDescr_getMapValue( + &mapDescrPrev, ((hMetaData->channelMode == 2) ? 1 : 2), + hMetaData->channelMode); + dst[0] = FDK_chMapDescr_getMapValue( + &mapDescr, ((channelMode == 2) ? 0 : 1), channelMode); + dst[1] = FDK_chMapDescr_getMapValue( + &mapDescr, ((channelMode == 2) ? 1 : 2), channelMode); + } + break; + default:; + } + C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, (8)); + FDKmemclear(scratch_audioDelayBuffer, (8) * sizeof(INT_PCM)); + + i = (hMetaData->nChannels > (INT)nChannels) + ? 0 + : hMetaData->nAudioDataDelay - 1; + do { + for (c = 0; c < 2; c++) { + if (src[c] != -1 && dst[c] != -1) { + scratch_audioDelayBuffer[dst[c]] = + hMetaData->pAudioDelayBuffer[i * hMetaData->nChannels + src[c]]; + } + } + FDKmemcpy(&hMetaData->pAudioDelayBuffer[i * nChannels], + scratch_audioDelayBuffer, nChannels * sizeof(INT_PCM)); + i += (hMetaData->nChannels > (INT)nChannels) ? 1 : -1; + } while ((i < hMetaData->nAudioDataDelay) && (i >= 0)); + + C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, (8)); + } + FDKmemclear(hMetaData->metaDataBuffer, sizeof(hMetaData->metaDataBuffer)); + hMetaData->metaDataDelayIdx = 0; + hMetaData->initializeMetaData = + 1; /* fill up delay line with first meta data info */ + } else { + /* Enable meta data. */ + if ((hMetaData->metadataMode == 0) && (metadataMode != 0)) { + /* disable meta data in all delay lines */ + for (i = 0; + i < (int)(sizeof(hMetaData->metaDataBuffer) / sizeof(AAC_METADATA)); + i++) { + LoadSubmittedMetadata(&hMetaData->submittedMetaData, nChannels, 0, + &hMetaData->metaDataBuffer[i]); + } + } + + /* Disable meta data.*/ + if ((hMetaData->metadataMode != 0) && (metadataMode == 0)) { + hMetaData->finalizeMetaData = hMetaData->metadataMode; + } + } + + /* Initialize delay. */ + hMetaData->nAudioDataDelay = -delay; + hMetaData->nMetaDataDelay = nFrames; + hMetaData->nChannels = nChannels; + hMetaData->channelMode = channelMode; + hMetaData->metadataMode = metadataMode; + + /* Initialize compressor. */ + if ((metadataMode == 1) || (metadataMode == 2)) { + if (FDK_DRC_Generator_Initialize(hMetaData->hDrcComp, DRC_NONE, DRC_NONE, + frameLength, sampleRate, channelMode, + channelOrder, 1) != 0) { + err = METADATA_INIT_ERROR; + } + } +bail: + return err; +} + +static FDK_METADATA_ERROR ProcessCompressor(AAC_METADATA* pMetadata, + HDRC_COMP hDrcComp, + const INT_PCM* const pSamples, + const UINT samplesBufSize, + const INT nSamples) { + FDK_METADATA_ERROR err = METADATA_OK; + + INT dynrng, compr; + INT dmxGain5, dmxGain2; + DRC_PROFILE profileDrc; + DRC_PROFILE profileComp; + + if ((pMetadata == NULL) || (hDrcComp == NULL)) { + err = METADATA_INVALID_HANDLE; + return err; + } + + profileDrc = convertProfile(pMetadata->mpegDrc.drc_profile); + profileComp = convertProfile(pMetadata->etsiAncData.comp_profile); + + /* first, check if profile is same as last frame + * otherwise, update setup */ + if ((profileDrc != FDK_DRC_Generator_getDrcProfile(hDrcComp)) || + (profileComp != FDK_DRC_Generator_getCompProfile(hDrcComp))) { + FDK_DRC_Generator_setDrcProfile(hDrcComp, profileDrc, profileComp); + } + + /* Sanity check */ + if (profileComp == DRC_NONE) { + pMetadata->etsiAncData.compression_value = 0x80; /* to ensure no external + values will be written + if not configured */ + } + + /* in case of embedding external values, copy this now (limiter may overwrite + * them) */ + dynrng = decodeDynrng(pMetadata->mpegDrc.dyn_rng_ctl[0], + pMetadata->mpegDrc.dyn_rng_sgn[0]); + compr = decodeCompr(pMetadata->etsiAncData.compression_value); + + dmxGain5 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, + pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn); + dmxGain2 = decodeDynrng(pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, + pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn); + + /* Call compressor */ + if (FDK_DRC_Generator_Calc( + hDrcComp, pSamples, samplesBufSize, + progreflvl2dialnorm(pMetadata->mpegDrc.prog_ref_level), + pMetadata->mpegDrc.drc_TargetRefLevel, + pMetadata->etsiAncData.comp_TargetRefLevel, + dmxTable[pMetadata->centerMixLevel], + dmxTable[pMetadata->surroundMixLevel], + dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_a_idx], + dmxTable[pMetadata->etsiAncData.extAncData.ext_dmix_b_idx], + pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status + ? dmxLfeTable[pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx] + : (FIXP_DBL)0, + dmxGain5, dmxGain2, &dynrng, &compr) != 0) { + err = METADATA_ENCODE_ERROR; + goto bail; + } + + /* Write DRC values */ + pMetadata->mpegDrc.drc_band_incr = 0; + encodeDynrng(dynrng, pMetadata->mpegDrc.dyn_rng_ctl, + pMetadata->mpegDrc.dyn_rng_sgn); + pMetadata->etsiAncData.compression_value = encodeCompr(compr); + +bail: + return err; +} + +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples, + const AACENC_MetaData* const pMetadata, + AACENC_EXT_PAYLOAD** ppMetaDataExtPayload, UINT* nMetaDataExtensions, + INT* matrix_mixdown_idx) { + FDK_METADATA_ERROR err = METADATA_OK; + int metaDataDelayWriteIdx, metaDataDelayReadIdx, metadataMode; + + /* Where to write new meta data info */ + metaDataDelayWriteIdx = hMetaDataEnc->metaDataDelayIdx; + + /* How to write the data */ + metadataMode = hMetaDataEnc->metadataMode; + + /* Compensate meta data delay. */ + hMetaDataEnc->metaDataDelayIdx++; + if (hMetaDataEnc->metaDataDelayIdx > hMetaDataEnc->nMetaDataDelay) + hMetaDataEnc->metaDataDelayIdx = 0; + + /* Where to read pending meta data info from. */ + metaDataDelayReadIdx = hMetaDataEnc->metaDataDelayIdx; + + /* Submit new data if available. */ + if (pMetadata != NULL) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, pMetadata, + sizeof(AACENC_MetaData)); + } + + /* Write one additional frame with default configuration of meta data. Ensure + * defined behaviour on decoder side. */ + if ((hMetaDataEnc->finalizeMetaData != 0) && + (hMetaDataEnc->metadataMode == 0)) { + FDKmemcpy(&hMetaDataEnc->submittedMetaData, &defaultMetaDataSetup, + sizeof(AACENC_MetaData)); + metadataMode = hMetaDataEnc->finalizeMetaData; + hMetaDataEnc->finalizeMetaData = 0; + } + + /* Get last submitted data. */ + if ((err = LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, + metadataMode, + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])) != + METADATA_OK) { + goto bail; + } + + /* Calculate compressor if necessary and updata meta data info */ + if ((hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 1) || + (hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx].metadataMode == 2)) { + if ((err = ProcessCompressor( + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], + hMetaDataEnc->hDrcComp, pAudioSamples, audioSamplesBufSize, + nAudioSamples)) != METADATA_OK) { + /* Get last submitted data again. */ + LoadSubmittedMetadata( + &hMetaDataEnc->submittedMetaData, hMetaDataEnc->nChannels, + metadataMode, &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx]); + } + } + + /* Fill up delay line with initial meta data info.*/ + if ((hMetaDataEnc->initializeMetaData != 0) && + (hMetaDataEnc->metadataMode != 0)) { + int i; + for (i = 0; + i < (int)(sizeof(hMetaDataEnc->metaDataBuffer) / sizeof(AAC_METADATA)); + i++) { + if (i != metaDataDelayWriteIdx) { + FDKmemcpy(&hMetaDataEnc->metaDataBuffer[i], + &hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx], + sizeof(hMetaDataEnc->metaDataBuffer[metaDataDelayWriteIdx])); + } + } + hMetaDataEnc->initializeMetaData = 0; + } + + /* Convert Meta Data side info to bitstream data. */ + FDK_ASSERT(metaDataDelayReadIdx < MAX_DELAY_FRAMES); + if ((err = WriteMetadataPayload( + hMetaDataEnc, + &hMetaDataEnc->metaDataBuffer[metaDataDelayReadIdx])) != + METADATA_OK) { + goto bail; + } + + /* Assign meta data to output */ + *ppMetaDataExtPayload = hMetaDataEnc->exPayload; + *nMetaDataExtensions = hMetaDataEnc->nExtensions; + *matrix_mixdown_idx = hMetaDataEnc->matrix_mixdown_idx; + +bail: + /* Compensate audio delay, reset err status. */ + err = CompensateAudioDelay(hMetaDataEnc, pAudioSamples, audioSamplesBufSize, + nAudioSamples / hMetaDataEnc->nChannels); + + return err; +} + +static FDK_METADATA_ERROR CompensateAudioDelay( + HANDLE_FDK_METADATA_ENCODER hMetaDataEnc, INT_PCM* const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (hMetaDataEnc->nAudioDataDelay) { + C_ALLOC_SCRATCH_START(scratch_audioDelayBuffer, INT_PCM, 1024); + + for (int c = 0; c < hMetaDataEnc->nChannels; c++) { + int M = 1024; + INT_PCM* pAudioSamples2 = pAudioSamples + c * audioSamplesBufSize; + int delayIdx = hMetaDataEnc->nAudioDataDelay; + + do { + M = fMin(M, delayIdx); + delayIdx -= M; + + FDKmemcpy(&scratch_audioDelayBuffer[0], + &pAudioSamples2[(nAudioSamples - M)], sizeof(INT_PCM) * M); + FDKmemmove(&pAudioSamples2[M], &pAudioSamples2[0], + sizeof(INT_PCM) * (nAudioSamples - M)); + FDKmemcpy( + &pAudioSamples2[0], + &hMetaDataEnc->pAudioDelayBuffer[delayIdx + + c * hMetaDataEnc->nAudioDataDelay], + sizeof(INT_PCM) * M); + FDKmemcpy( + &hMetaDataEnc->pAudioDelayBuffer[delayIdx + + c * hMetaDataEnc->nAudioDataDelay], + &scratch_audioDelayBuffer[0], sizeof(INT_PCM) * M); + + } while (delayIdx > 0); + } + + C_ALLOC_SCRATCH_END(scratch_audioDelayBuffer, INT_PCM, 1024); + } + + return err; +} + +/*----------------------------------------------------------------------------- + + functionname: WriteMetadataPayload + description: fills anc data and extension payload + returns: Error status + + ------------------------------------------------------------------------------*/ +static FDK_METADATA_ERROR WriteMetadataPayload( + const HANDLE_FDK_METADATA_ENCODER hMetaData, + const AAC_METADATA* const pMetadata) { + FDK_METADATA_ERROR err = METADATA_OK; + + if ((hMetaData == NULL) || (pMetadata == NULL)) { + err = METADATA_INVALID_HANDLE; + goto bail; + } + + hMetaData->nExtensions = 0; + hMetaData->matrix_mixdown_idx = -1; + + if (pMetadata->metadataMode != 0) { + /* AAC-DRC */ + if ((pMetadata->metadataMode == 1) || (pMetadata->metadataMode == 2)) { + hMetaData->exPayload[hMetaData->nExtensions].pData = + hMetaData->drcInfoPayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DYNAMIC_RANGE; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteDynamicRangeInfoPayload( + pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + } /* pMetadata->metadataMode==1 || pMetadata->metadataMode==2 */ + + /* Matrix Mixdown Coefficient in PCE */ + if (pMetadata->WritePCEMixDwnIdx) { + hMetaData->matrix_mixdown_idx = + surmix2matrix_mixdown_idx[pMetadata->surroundMixLevel]; + } + + /* ETSI TS 101 154 (DVB) - MPEG4 ancillary_data() */ + if ((pMetadata->metadataMode == 2) || + (pMetadata->metadataMode == 3)) /* MP4_METADATA_MPEG_ETSI */ + { + hMetaData->exPayload[hMetaData->nExtensions].pData = + hMetaData->drcDsePayload; + hMetaData->exPayload[hMetaData->nExtensions].dataType = EXT_DATA_ELEMENT; + hMetaData->exPayload[hMetaData->nExtensions].associatedChElement = -1; + + hMetaData->exPayload[hMetaData->nExtensions].dataSize = + WriteEtsiAncillaryDataPayload( + pMetadata, hMetaData->exPayload[hMetaData->nExtensions].pData); + + hMetaData->nExtensions++; + } /* metadataMode==2 || metadataMode==3 */ + + } /* metadataMode != 0 */ + +bail: + return err; +} + +static INT WriteDynamicRangeInfoPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload) { + const INT pce_tag_present = 0; /* yet fixed setting! */ + const INT prog_ref_lev_res_bits = 0; + INT i, drc_num_bands = 1; + + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* dynamic_range_info() */ + FDKwriteBits(&bsWriter, pce_tag_present, 1); /* pce_tag_present */ + if (pce_tag_present) { + FDKwriteBits(&bsWriter, 0x0, 4); /* pce_instance_tag */ + FDKwriteBits(&bsWriter, 0x0, 4); /* drc_tag_reserved_bits */ + } + + /* Exclude channels */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.excluded_chns_present) ? 1 : 0, + 1); /* excluded_chns_present*/ + + /* Multiband DRC */ + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.drc_bands_present) ? 1 : 0, + 1); /* drc_bands_present */ + if (pMetadata->mpegDrc.drc_bands_present) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_incr, + 4); /* drc_band_incr */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_interpolation_scheme, + 4); /* drc_interpolation_scheme */ + drc_num_bands += pMetadata->mpegDrc.drc_band_incr; + for (i = 0; i < drc_num_bands; i++) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.drc_band_top[i], + 8); /* drc_band_top */ + } + } + + /* Program Reference Level */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level_present, + 1); /* prog_ref_level_present */ + if (pMetadata->mpegDrc.prog_ref_level_present) { + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.prog_ref_level, + 7); /* prog_ref_level */ + FDKwriteBits(&bsWriter, prog_ref_lev_res_bits, + 1); /* prog_ref_level_reserved_bits */ + } + + /* DRC Values */ + for (i = 0; i < drc_num_bands; i++) { + FDKwriteBits(&bsWriter, (pMetadata->mpegDrc.dyn_rng_sgn[i]) ? 1 : 0, + 1); /* dyn_rng_sgn[ */ + FDKwriteBits(&bsWriter, pMetadata->mpegDrc.dyn_rng_ctl[i], + 7); /* dyn_rng_ctl */ + } + + /* return number of valid bits in extension payload. */ + return FDKgetValidBits(&bsWriter); +} + +static INT WriteEtsiAncillaryDataPayload(const AAC_METADATA* const pMetadata, + UCHAR* const pExtensionPayload) { + FDK_BITSTREAM bsWriter; + FDKinitBitStream(&bsWriter, pExtensionPayload, 16, 0, BS_WRITER); + + /* ancillary_data_sync */ + FDKwriteBits(&bsWriter, 0xBC, 8); + + /* bs_info */ + FDKwriteBits(&bsWriter, 0x3, 2); /* mpeg_audio_type */ + FDKwriteBits(&bsWriter, pMetadata->dolbySurroundMode, + 2); /* dolby_surround_mode */ + FDKwriteBits(&bsWriter, pMetadata->drcPresentationMode, + 2); /* DRC presentation mode */ + FDKwriteBits(&bsWriter, 0x0, 1); /* stereo_downmix_mode */ + FDKwriteBits(&bsWriter, 0x0, 1); /* reserved */ + + /* ancillary_data_status */ + FDKwriteBits(&bsWriter, 0, 3); /* 3 bit Reserved, set to "0" */ + FDKwriteBits(&bsWriter, (pMetadata->DmxLvl_On) ? 1 : 0, + 1); /* downmixing_levels_MPEG4_status */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncDataStatus, + 1); /* ext_anc_data_status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.compression_on) ? 1 : 0, + 1); /* audio_coding_mode_and_compression status */ + FDKwriteBits(&bsWriter, + (pMetadata->etsiAncData.timecode_coarse_status) ? 1 : 0, + 1); /* coarse_grain_timecode_status */ + FDKwriteBits(&bsWriter, (pMetadata->etsiAncData.timecode_fine_status) ? 1 : 0, + 1); /* fine_grain_timecode_status */ + + /* downmixing_levels_MPEG4_status */ + if (pMetadata->DmxLvl_On) { + FDKwriteBits( + &bsWriter, + encodeDmxLvls(pMetadata->centerMixLevel, pMetadata->surroundMixLevel), + 8); + } + + /* audio_coding_mode_and_compression_status */ + if (pMetadata->etsiAncData.compression_on) { + FDKwriteBits(&bsWriter, 0x01, 8); /* audio coding mode */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.compression_value, + 8); /* compression value */ + } + + /* grain-timecode coarse/fine */ + if (pMetadata->etsiAncData.timecode_coarse_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + if (pMetadata->etsiAncData.timecode_fine_status) { + FDKwriteBits(&bsWriter, 0x0, 16); /* not yet supported */ + } + + /* extended ancillary data structure */ + if (pMetadata->etsiAncData.extAncDataStatus) { + /* ext_ancillary_data_status */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status, + 1); /* ext_downmixing_levels_status */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_downmix_gain_status, + 1); /* ext_downmixing_global_gains_status */ + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status, + 1); /* ext_downmixing_lfe_level_status" */ + FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ + + /* ext_downmixing_levels */ + if (pMetadata->etsiAncData.extAncData.ext_downmix_lvl_status) { + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_a_idx, + 3); /* dmix_a_idx */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.ext_dmix_b_idx, + 3); /* dmix_b_idx */ + FDKwriteBits(&bsWriter, 0, 2); /* Reserved, set to "0" */ + } + + /* ext_downmixing_gains */ + if (pMetadata->etsiAncData.extAncData.ext_downmix_gain_status) { + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_sgn, + 1); /* dmx_gain_5_sign */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_5_idx, + 6); /* dmx_gain_5_idx */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_sgn, + 1); /* dmx_gain_2_sign */ + FDKwriteBits(&bsWriter, pMetadata->etsiAncData.extAncData.dmx_gain_2_idx, + 6); /* dmx_gain_2_idx */ + FDKwriteBits(&bsWriter, 0, 1); /* Reserved, set to "0" */ + } + + if (pMetadata->etsiAncData.extAncData.ext_lfe_downmix_status) { + FDKwriteBits(&bsWriter, + pMetadata->etsiAncData.extAncData.ext_dmix_lfe_idx, + 4); /* dmix_lfe_idx */ + FDKwriteBits(&bsWriter, 0, 4); /* Reserved, set to "0" */ + } + } + + return FDKgetValidBits(&bsWriter); +} + +static FDK_METADATA_ERROR LoadSubmittedMetadata( + const AACENC_MetaData* const hMetadata, const INT nChannels, + const INT metadataMode, AAC_METADATA* const pAacMetaData) { + FDK_METADATA_ERROR err = METADATA_OK; + + if (pAacMetaData == NULL) { + err = METADATA_INVALID_HANDLE; + } else { + /* init struct */ + FDKmemclear(pAacMetaData, sizeof(AAC_METADATA)); + + if (hMetadata != NULL) { + /* convert data */ + pAacMetaData->mpegDrc.drc_profile = hMetadata->drc_profile; + pAacMetaData->etsiAncData.comp_profile = hMetadata->comp_profile; + pAacMetaData->mpegDrc.drc_TargetRefLevel = hMetadata->drc_TargetRefLevel; + pAacMetaData->etsiAncData.comp_TargetRefLevel = + hMetadata->comp_TargetRefLevel; + pAacMetaData->mpegDrc.prog_ref_level_present = + hMetadata->prog_ref_level_present; + pAacMetaData->mpegDrc.prog_ref_level = + dialnorm2progreflvl(hMetadata->prog_ref_level); + + pAacMetaData->centerMixLevel = hMetadata->centerMixLevel; + pAacMetaData->surroundMixLevel = hMetadata->surroundMixLevel; + pAacMetaData->WritePCEMixDwnIdx = hMetadata->PCE_mixdown_idx_present; + pAacMetaData->DmxLvl_On = hMetadata->ETSI_DmxLvl_present; + + pAacMetaData->etsiAncData.compression_on = + (hMetadata->comp_profile == AACENC_METADATA_DRC_NOT_PRESENT ? 0 : 1); + + if (pAacMetaData->mpegDrc.drc_profile == + AACENC_METADATA_DRC_NOT_PRESENT) { + pAacMetaData->mpegDrc.drc_profile = + AACENC_METADATA_DRC_NONE; /* MPEG DRC gains are + always present in BS + syntax */ + /* we should give a warning, but ErrorHandler does not support this */ + } + + if (nChannels == 2) { + pAacMetaData->dolbySurroundMode = + hMetadata->dolbySurroundMode; /* dolby_surround_mode */ + } else { + pAacMetaData->dolbySurroundMode = 0; + } + + pAacMetaData->drcPresentationMode = hMetadata->drcPresentationMode; + /* override external values if DVB DRC presentation mode is given */ + if (pAacMetaData->drcPresentationMode == 1) { + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(-(31 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); + pAacMetaData->etsiAncData.comp_TargetRefLevel = fMax( + -(20 << 16), + pAacMetaData->etsiAncData.comp_TargetRefLevel); /* implies -23dB */ + } + if (pAacMetaData->drcPresentationMode == 2) { + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(-(23 << 16), pAacMetaData->mpegDrc.drc_TargetRefLevel); + pAacMetaData->etsiAncData.comp_TargetRefLevel = + fMax(-(23 << 16), pAacMetaData->etsiAncData.comp_TargetRefLevel); + } + if (pAacMetaData->etsiAncData.comp_profile == + AACENC_METADATA_DRC_NOT_PRESENT) { + /* DVB defines to revert to Light DRC if heavy is not present */ + if (pAacMetaData->drcPresentationMode != 0) { + /* we exclude the "not indicated" mode as this requires the user to + * define desired levels anyway */ + pAacMetaData->mpegDrc.drc_TargetRefLevel = + fMax(pAacMetaData->etsiAncData.comp_TargetRefLevel, + pAacMetaData->mpegDrc.drc_TargetRefLevel); + } + } + + pAacMetaData->etsiAncData.timecode_coarse_status = + 0; /* not yet supported - attention: Update + GetEstMetadataBytesPerFrame() if enable this! */ + pAacMetaData->etsiAncData.timecode_fine_status = + 0; /* not yet supported - attention: Update + GetEstMetadataBytesPerFrame() if enable this! */ + + /* extended ancillary data */ + pAacMetaData->etsiAncData.extAncDataStatus = + ((hMetadata->ExtMetaData.extAncDataEnable == 1) ? 1 : 0); + + if (pAacMetaData->etsiAncData.extAncDataStatus) { + pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = + (hMetadata->ExtMetaData.extDownmixLevelEnable ? 1 : 0); + pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = + (hMetadata->ExtMetaData.dmxGainEnable ? 1 : 0); + pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = + (hMetadata->ExtMetaData.lfeDmxEnable ? 1 : 0); + + pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = + hMetadata->ExtMetaData.extDownmixLevel_A; + pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = + hMetadata->ExtMetaData.extDownmixLevel_B; + + if (pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status) { + encodeDynrng(hMetadata->ExtMetaData.dmxGain5, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(hMetadata->ExtMetaData.dmxGain2, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + } else { + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + } + + if (pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status) { + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + hMetadata->ExtMetaData.lfeDmxLevel; + } else { + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + 15; /* -inf dB */ + } + } else { + pAacMetaData->etsiAncData.extAncData.ext_downmix_lvl_status = 0; + pAacMetaData->etsiAncData.extAncData.ext_downmix_gain_status = 0; + pAacMetaData->etsiAncData.extAncData.ext_lfe_downmix_status = 0; + + pAacMetaData->etsiAncData.extAncData.ext_dmix_a_idx = 7; /* -inf dB */ + pAacMetaData->etsiAncData.extAncData.ext_dmix_b_idx = 7; /* -inf dB */ + + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_5_sgn)); + encodeDynrng(1 << 16, + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_idx), + &(pAacMetaData->etsiAncData.extAncData.dmx_gain_2_sgn)); + + pAacMetaData->etsiAncData.extAncData.ext_dmix_lfe_idx = + 15; /* -inf dB */ + } + + pAacMetaData->metadataMode = metadataMode; + } else { + pAacMetaData->metadataMode = 0; /* there is no configuration available */ + } + } + + return err; +} + +INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc) { + INT delay = 0; + + if (hMetadataEnc != NULL) { + delay = hMetadataEnc->nAudioDataDelay; + } + + return delay; +} diff --git a/fdk-aac/libAACenc/src/metadata_main.h b/fdk-aac/libAACenc/src/metadata_main.h new file mode 100644 index 0000000..d872c77 --- /dev/null +++ b/fdk-aac/libAACenc/src/metadata_main.h @@ -0,0 +1,226 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): V. Bacigalupo + + Description: Metadata Encoder library interface functions + +*******************************************************************************/ + +#ifndef METADATA_MAIN_H +#define METADATA_MAIN_H + +/* Includes ******************************************************************/ +#include "aacenc_lib.h" +#include "aacenc.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +typedef enum { + METADATA_OK = 0x0000, /*!< No error happened. All fine. */ + METADATA_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + METADATA_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + METADATA_INIT_ERROR = 0x0040, /*!< General initialization error. */ + METADATA_ENCODE_ERROR = + 0x0060 /*!< The encoding process was interrupted by an unexpected error. + */ + +} FDK_METADATA_ERROR; + +/** + * Meta Data handle. + */ +typedef struct FDK_METADATA_ENCODER *HANDLE_FDK_METADATA_ENCODER; + +/** + * \brief Open a Meta Data instance. + * + * \param phMetadataEnc A pointer to a Meta Data handle to be allocated. + * Initialized on return. + * \param maxChannels Maximum number of supported audio channels. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_MEMORY_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Open( + HANDLE_FDK_METADATA_ENCODER *phMetadataEnc, const UINT maxChannels); + +/** + * \brief Initialize a Meta Data instance. + * + * \param hMetadataEnc Meta Data handle. + * \param resetStates Indication for full reset of all states. + * \param metadataMode Configures meta data output format (0,1,2,3). + * \param audioDelay Delay cause by the audio encoder. + * \param frameLength Number of samples to be processes within one + * frame. + * \param sampleRate Sampling rat in Hz of audio input signal. + * \param nChannels Number of audio input channels. + * \param channelMode Channel configuration which is used by the + * encoder. + * \param channelOrder Channel order of the input data. (WAV, MPEG) + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_INIT_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Init( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, const INT resetStates, + const INT metadataMode, const INT audioDelay, const UINT frameLength, + const UINT sampleRate, const UINT nChannels, const CHANNEL_MODE channelMode, + const CHANNEL_ORDER channelOrder); + +/** + * \brief Calculate Meta Data processing. + * + * This function treats all step necessary for meta data processing. + * - Receive new meta data and make usable. + * - Calculate DRC compressor and extract meta data info. + * - Make meta data available for extern use. + * - Apply audio data and meta data delay compensation. + * + * \param hMetadataEnc Meta Data handle. + * \param pAudioSamples Pointer to audio input data. Existing function + * overwrites audio data with delayed audio samples. + * \param nAudioSamples Number of input audio samples to be prcessed. + * \param pMetadata Pointer to Metat Data input. + * \param ppMetaDataExtPayload Pointer to extension payload array. Filled on + * return. + * \param nMetaDataExtensions Pointer to variable to describe number of + * available extension payloads. Filled on return. + * \param matrix_mixdown_idx Pointer to variable for matrix mixdown + * coefficient. Filled on return. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, METADATA_ENCODE_ERROR, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Process( + HANDLE_FDK_METADATA_ENCODER hMetadataEnc, INT_PCM *const pAudioSamples, + const UINT audioSamplesBufSize, const INT nAudioSamples, + const AACENC_MetaData *const pMetadata, + AACENC_EXT_PAYLOAD **ppMetaDataExtPayload, UINT *nMetaDataExtensions, + INT *matrix_mixdown_idx); + +/** + * \brief Close the Meta Data instance. + * + * Deallocate instance and free whole memory. + * + * \param phMetaData Pointer to the Meta Data handle to be + * deallocated. + * + * \return + * - METADATA_OK, on succes. + * - METADATA_INVALID_HANDLE, on failure. + */ +FDK_METADATA_ERROR FDK_MetadataEnc_Close( + HANDLE_FDK_METADATA_ENCODER *phMetaData); + +/** + * \brief Get Meta Data Encoder delay. + * + * \param hMetadataEnc Meta Data Encoder handle. + * + * \return Delay caused by Meta Data module. + */ +INT FDK_MetadataEnc_GetDelay(HANDLE_FDK_METADATA_ENCODER hMetadataEnc); + +#endif /* METADATA_MAIN_H */ diff --git a/fdk-aac/libAACenc/src/mps_main.cpp b/fdk-aac/libAACenc/src/mps_main.cpp new file mode 100644 index 0000000..1048228 --- /dev/null +++ b/fdk-aac/libAACenc/src/mps_main.cpp @@ -0,0 +1,529 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Markus Lohwasser + + Description: Mpeg Surround library interface functions + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "mps_main.h" +#include "sacenc_lib.h" + +/* Data Types ****************************************************************/ +struct MPS_ENCODER { + HANDLE_MP4SPACE_ENCODER hSacEncoder; + + AUDIO_OBJECT_TYPE audioObjectType; + + FDK_bufDescr inBufDesc; + FDK_bufDescr outBufDesc; + SACENC_InArgs inargs; + SACENC_OutArgs outargs; + + void *pInBuffer[1]; + UINT pInBufferSize[1]; + UINT pInBufferElSize[1]; + UINT pInBufferType[1]; + + void *pOutBuffer[2]; + UINT pOutBufferSize[2]; + UINT pOutBufferElSize[2]; + UINT pOutBufferType[2]; + + UCHAR sacOutBuffer[1024]; /* Worst case memory consumption for ELDv2: 768 + bytes => 6144 bits (Core + SBR + MPS) */ +}; + +struct MPS_CONFIG_TAB { + AUDIO_OBJECT_TYPE audio_object_type; + CHANNEL_MODE channel_mode; + ULONG sbr_ratio; + ULONG sampling_rate; + ULONG bitrate_min; + ULONG bitrate_max; +}; + +/* Constants *****************************************************************/ +static const MPS_CONFIG_TAB mpsConfigTab[] = { + {AOT_ER_AAC_ELD, MODE_212, 0, 16000, 16000, 39999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 22050, 16000, 49999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 24000, 16000, 61999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 32000, 20000, 84999}, + {AOT_ER_AAC_ELD, MODE_212, 0, 44100, 50000, 192000}, + {AOT_ER_AAC_ELD, MODE_212, 0, 48000, 62000, 192000}, + + {AOT_ER_AAC_ELD, MODE_212, 1, 16000, 18000, 31999}, + {AOT_ER_AAC_ELD, MODE_212, 1, 22050, 18000, 31999}, + {AOT_ER_AAC_ELD, MODE_212, 1, 24000, 20000, 64000}, + + {AOT_ER_AAC_ELD, MODE_212, 2, 32000, 18000, 64000}, + {AOT_ER_AAC_ELD, MODE_212, 2, 44100, 21000, 64000}, + {AOT_ER_AAC_ELD, MODE_212, 2, 48000, 26000, 64000} + +}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, + UCHAR *const pOutputBuffer, + const int outputBufferSize); + +MPS_ENCODER_ERROR FDK_MpegsEnc_Open(HANDLE_MPS_ENCODER *phMpsEnc) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + HANDLE_MPS_ENCODER hMpsEnc = NULL; + + if (phMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + if (NULL == + (hMpsEnc = (HANDLE_MPS_ENCODER)FDKcalloc(1, sizeof(MPS_ENCODER)))) { + error = MPS_ENCODER_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hMpsEnc, sizeof(MPS_ENCODER)); + + if (SACENC_OK != FDK_sacenc_open(&hMpsEnc->hSacEncoder)) { + error = MPS_ENCODER_MEMORY_ERROR; + goto bail; + } + + /* Return mps encoder instance */ + *phMpsEnc = hMpsEnc; + +bail: + if (error != MPS_ENCODER_OK) { + FDK_MpegsEnc_Close(&hMpsEnc); + } + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Close(HANDLE_MPS_ENCODER *phMpsEnc) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (phMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + if (*phMpsEnc != NULL) { + FDK_sacenc_close(&(*phMpsEnc)->hSacEncoder); + FDKfree(*phMpsEnc); + *phMpsEnc = NULL; + } +bail: + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Init(HANDLE_MPS_ENCODER hMpsEnc, + const AUDIO_OBJECT_TYPE audioObjectType, + const UINT samplingrate, const UINT bitrate, + const UINT sbrRatio, const UINT framelength, + const UINT inputBufferSizePerChannel, + const UINT coreCoderDelay) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + const UINT fs_low = 27713; /* low MPS sampling frequencies */ + const UINT fs_high = 55426; /* high MPS sampling frequencies */ + UINT nTimeSlots = 0, nQmfBandsLd = 0; + + if (hMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + goto bail; + } + + /* Combine MPS with SBR only if the number of QMF band fits together.*/ + switch (sbrRatio) { + case 1: /* downsampled sbr - 32 QMF bands required */ + if (!(samplingrate < fs_low)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + case 2: /* dualrate - 64 QMF bands required */ + if (!((samplingrate >= fs_low) && (samplingrate < fs_high))) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + case 0: + default:; /* time interface - no samplingrate restriction */ + } + + /* 32 QMF-Bands ( fs < 27713 ) + * 64 QMF-Bands ( 27713 >= fs <= 55426 ) + * 128 QMF-Bands ( fs > 55426 ) + */ + nQmfBandsLd = + (samplingrate < fs_low) ? 5 : ((samplingrate > fs_high) ? 7 : 6); + nTimeSlots = framelength >> nQmfBandsLd; + + /* check if number of qmf bands is usable for given framelength */ + if (framelength != (nTimeSlots << nQmfBandsLd)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + /* is given bitrate intended to be supported */ + if ((INT)bitrate != FDK_MpegsEnc_GetClosestBitRate(audioObjectType, MODE_212, + samplingrate, sbrRatio, + bitrate)) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + /* init SAC library */ + switch (audioObjectType) { + case AOT_ER_AAC_ELD: { + const UINT noInterFrameCoding = 0; + + if ((SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_LOWDELAY, + (noInterFrameCoding == 1) ? 1 : 2)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_ENC_MODE, SACENC_212)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_SAMPLERATE, samplingrate)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_FRAME_TIME_SLOTS, + nTimeSlots)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_PARAM_BANDS, + SACENC_BANDS_15)) || + (SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_TIME_DOM_DMX, 2)) || + (SACENC_OK != + FDK_sacenc_setParam(hMpsEnc->hSacEncoder, SACENC_COARSE_QUANT, 0)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_QUANT_MODE, + SACENC_QUANTMODE_FINE)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_TIME_ALIGNMENT, 0)) || + (SACENC_OK != FDK_sacenc_setParam(hMpsEnc->hSacEncoder, + SACENC_INDEPENDENCY_FACTOR, 20))) { + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + break; + } + default: + error = MPS_ENCODER_INIT_ERROR; + goto bail; + } + + if (SACENC_OK != FDK_sacenc_init(hMpsEnc->hSacEncoder, coreCoderDelay)) { + error = MPS_ENCODER_INIT_ERROR; + } + + hMpsEnc->audioObjectType = audioObjectType; + + hMpsEnc->inBufDesc.ppBase = (void **)&hMpsEnc->pInBuffer; + hMpsEnc->inBufDesc.pBufSize = hMpsEnc->pInBufferSize; + hMpsEnc->inBufDesc.pEleSize = hMpsEnc->pInBufferElSize; + hMpsEnc->inBufDesc.pBufType = hMpsEnc->pInBufferType; + hMpsEnc->inBufDesc.numBufs = 1; + + hMpsEnc->outBufDesc.ppBase = (void **)&hMpsEnc->pOutBuffer; + hMpsEnc->outBufDesc.pBufSize = hMpsEnc->pOutBufferSize; + hMpsEnc->outBufDesc.pEleSize = hMpsEnc->pOutBufferElSize; + hMpsEnc->outBufDesc.pBufType = hMpsEnc->pOutBufferType; + hMpsEnc->outBufDesc.numBufs = 2; + + hMpsEnc->pInBuffer[0] = NULL; + hMpsEnc->pInBufferSize[0] = 0; + hMpsEnc->pInBufferElSize[0] = sizeof(INT_PCM); + hMpsEnc->pInBufferType[0] = (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA); + + hMpsEnc->pOutBuffer[0] = NULL; + hMpsEnc->pOutBufferSize[0] = 0; + hMpsEnc->pOutBufferElSize[0] = sizeof(INT_PCM); + hMpsEnc->pOutBufferType[0] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA); + + hMpsEnc->pOutBuffer[1] = NULL; + hMpsEnc->pOutBufferSize[1] = 0; + hMpsEnc->pOutBufferElSize[1] = sizeof(UCHAR); + hMpsEnc->pOutBufferType[1] = (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA); + + hMpsEnc->inargs.isInputInterleaved = 0; + hMpsEnc->inargs.inputBufferSizePerChannel = inputBufferSizePerChannel; + +bail: + return error; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_Process(HANDLE_MPS_ENCODER hMpsEnc, + INT_PCM *const pAudioSamples, + const INT nAudioSamples, + AACENC_EXT_PAYLOAD *pMpsExtPayload) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (hMpsEnc == NULL) { + error = MPS_ENCODER_INVALID_HANDLE; + } else { + int sacHeaderFlag = 1; + int sacOutBufferOffset = 0; + + /* In case of eld the ssc is explicit and doesn't need to be inband */ + if (hMpsEnc->audioObjectType == AOT_ER_AAC_ELD) { + sacHeaderFlag = 0; + } + + /* 4 bits nibble after extension type */ + hMpsEnc->sacOutBuffer[0] = (sacHeaderFlag == 0) ? 0x3 : 0x7; + sacOutBufferOffset += 1; + + if (sacHeaderFlag) { + sacOutBufferOffset += FDK_MpegsEnc_WriteFrameHeader( + hMpsEnc, &hMpsEnc->sacOutBuffer[sacOutBufferOffset], + sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset); + } + + /* Register input and output buffer. */ + hMpsEnc->pInBuffer[0] = (void *)pAudioSamples; + hMpsEnc->inargs.nInputSamples = nAudioSamples; + + hMpsEnc->pOutBuffer[0] = (void *)pAudioSamples; + hMpsEnc->pOutBufferSize[0] = sizeof(INT_PCM) * nAudioSamples / 2; + + hMpsEnc->pOutBuffer[1] = (void *)&hMpsEnc->sacOutBuffer[sacOutBufferOffset]; + hMpsEnc->pOutBufferSize[1] = + sizeof(hMpsEnc->sacOutBuffer) - sacOutBufferOffset; + + /* encode SAC frame */ + if (SACENC_OK != FDK_sacenc_encode(hMpsEnc->hSacEncoder, + &hMpsEnc->inBufDesc, + &hMpsEnc->outBufDesc, &hMpsEnc->inargs, + &hMpsEnc->outargs)) { + error = MPS_ENCODER_ENCODE_ERROR; + goto bail; + } + + /* export MPS payload */ + pMpsExtPayload->pData = (UCHAR *)hMpsEnc->sacOutBuffer; + pMpsExtPayload->dataSize = + hMpsEnc->outargs.nOutputBits + 8 * (sacOutBufferOffset - 1); + pMpsExtPayload->dataType = EXT_LDSAC_DATA; + pMpsExtPayload->associatedChElement = -1; + } + +bail: + return error; +} + +INT FDK_MpegsEnc_WriteSpatialSpecificConfig(HANDLE_MPS_ENCODER hMpsEnc, + HANDLE_FDK_BITSTREAM hBs) { + INT sscBits = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + + if (hBs != NULL) { + int i; + int writtenBits = 0; + for (i = 0; inSscSizeBits>> 3; i++) { + FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], 8); + writtenBits += 8; + } + FDKwriteBits(hBs, mp4SpaceEncoderInfo.pSscBuf->pSsc[i], + mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits - writtenBits); + } /* hBS */ + + sscBits = mp4SpaceEncoderInfo.pSscBuf->nSscSizeBits; + + } /* valid hMpsEnc */ + + return sscBits; +} + +static INT FDK_MpegsEnc_WriteFrameHeader(HANDLE_MPS_ENCODER hMpsEnc, + UCHAR *const pOutputBuffer, + const int outputBufferSize) { + const int sacTimeAlignFlag = 0; + + /* Initialize variables */ + int numBits = 0; + + if ((NULL != hMpsEnc) && (NULL != pOutputBuffer)) { + UINT alignAnchor, cnt; + FDK_BITSTREAM Bs; + FDKinitBitStream(&Bs, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + /* Calculate SSC length information */ + cnt = (FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, NULL) + 7) >> 3; + + /* Write SSC */ + FDKwriteBits(&Bs, sacTimeAlignFlag, 1); + + if (cnt < 127) { + FDKwriteBits(&Bs, cnt, 7); + } else { + FDKwriteBits(&Bs, 127, 7); + FDKwriteBits(&Bs, cnt - 127, 16); + } + + alignAnchor = FDKgetValidBits(&Bs); + FDK_MpegsEnc_WriteSpatialSpecificConfig(hMpsEnc, &Bs); + FDKbyteAlign(&Bs, alignAnchor); /* bsFillBits */ + + if (sacTimeAlignFlag) { + FDK_ASSERT(1); /* time alignment not supported */ + } + + numBits = FDKgetValidBits(&Bs); + } /* valid handle */ + + return ((numBits + 7) >> 3); +} + +INT FDK_MpegsEnc_GetClosestBitRate(const AUDIO_OBJECT_TYPE audioObjectType, + const CHANNEL_MODE channelMode, + const UINT samplingrate, const UINT sbrRatio, + const UINT bitrate) { + unsigned int i; + int targetBitrate = -1; + + for (i = 0; i < sizeof(mpsConfigTab) / sizeof(MPS_CONFIG_TAB); i++) { + if ((mpsConfigTab[i].audio_object_type == audioObjectType) && + (mpsConfigTab[i].channel_mode == channelMode) && + (mpsConfigTab[i].sbr_ratio == sbrRatio) && + (mpsConfigTab[i].sampling_rate == samplingrate)) { + targetBitrate = fMin(fMax(bitrate, mpsConfigTab[i].bitrate_min), + mpsConfigTab[i].bitrate_max); + } + } + + return targetBitrate; +} + +INT FDK_MpegsEnc_GetDelay(HANDLE_MPS_ENCODER hMpsEnc) { + INT delay = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + delay = mp4SpaceEncoderInfo.nCodecDelay; + } + + return delay; +} + +INT FDK_MpegsEnc_GetDecDelay(HANDLE_MPS_ENCODER hMpsEnc) { + INT delay = 0; + + if (NULL != hMpsEnc) { + MP4SPACEENC_INFO mp4SpaceEncoderInfo; + FDK_sacenc_getInfo(hMpsEnc->hSacEncoder, &mp4SpaceEncoderInfo); + delay = mp4SpaceEncoderInfo.nDecoderDelay; + } + + return delay; +} + +MPS_ENCODER_ERROR FDK_MpegsEnc_GetLibInfo(LIB_INFO *info) { + MPS_ENCODER_ERROR error = MPS_ENCODER_OK; + + if (NULL == info) { + error = MPS_ENCODER_INVALID_HANDLE; + } else if (SACENC_OK != FDK_sacenc_getLibInfo(info)) { + error = MPS_ENCODER_INIT_ERROR; + } + + return error; +} diff --git a/fdk-aac/libAACenc/src/mps_main.h b/fdk-aac/libAACenc/src/mps_main.h new file mode 100644 index 0000000..f56678a --- /dev/null +++ b/fdk-aac/libAACenc/src/mps_main.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Markus Lohwasser + + Description: Mpeg Surround library interface functions + +*******************************************************************************/ + +#ifndef MPS_MAIN_H +#define MPS_MAIN_H + +/* Includes ******************************************************************/ +#include "aacenc.h" +#include "FDK_audio.h" +#include "machine_type.h" + +/* Defines *******************************************************************/ +typedef enum { + MPS_ENCODER_OK = 0x0000, /*!< No error happened. All fine. */ + MPS_ENCODER_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + MPS_ENCODER_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + MPS_ENCODER_INIT_ERROR = 0x0040, /*!< General initialization error. */ + MPS_ENCODER_ENCODE_ERROR = + 0x0060 /*!< The encoding process was interrupted by an unexpected error. + */ + +} MPS_ENCODER_ERROR; + +/* Data Types ****************************************************************/ + +/** + * MPEG Surround Encoder interface handle. + */ +typedef struct MPS_ENCODER MPS_ENCODER, *HANDLE_MPS_ENCODER; + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Open a Mpeg Surround Encoder instance. + * + * \phMpsEnc A pointer to a MPS handle to be allocated. + * Initialized on return. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_MEMORY_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Open(HANDLE_MPS_ENCODER *phMpsEnc); + +/** + * \brief Close the Mpeg Surround Encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phMpsEnc Pointer to the MPS handle to be deallocated. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Close(HANDLE_MPS_ENCODER *phMpsEnc); + +/** + * \brief Initialize a Mpeg Surround Encoder instance. + * + * \param hMpsEnc MPS Encoder handle. + * \param audioObjectType Audio object type. + * \param samplingrate Sampling rate in Hz of audio input signal. + * \param bitrate Encder target bitrate. + * \param sbrRatio SBR sampling rate ratio. + * \param framelength Number of samples to be processes within one + * frame. + * \param inputBufferSizePerChannel Size of input buffer per channel. + * \param coreCoderDelay Core coder delay. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_ENCODE_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Init(HANDLE_MPS_ENCODER hMpsEnc, + const AUDIO_OBJECT_TYPE audioObjectType, + const UINT samplingrate, const UINT bitrate, + const UINT sbrRatio, const UINT framelength, + const UINT inputBufferSizePerChannel, + const UINT coreCoderDelay); + +/** + * \brief Calculate Mpeg Surround processing. + * + * This fuction applies the MPS processing. The MPS side info will be written to + * extension payload. The input audio data will be overwritten by the calculated + * downmix. + * + * \param hMpsEnc MPS Encoder handle. + * \param pAudioSamples Pointer to audio input/output data. + * \param nAudioSamples Number of input audio samples to be prcessed. + * \param pMpsExtPayload Pointer to extension payload to be filled on + * return. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_ENCODE_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_Process(HANDLE_MPS_ENCODER hMpsEnc, + INT_PCM *const pAudioSamples, + const INT nAudioSamples, + AACENC_EXT_PAYLOAD *pMpsExtPayload); + +/** + * \brief Write Spatial Specific Config. + * + * This function can be called via call back from the transport library to write + * the Spatial Specific Config to given bitstream buffer. + * + * \param hMpsEnc MPS Encoder handle. + * \param hBs Bitstream buffer handle. + * + * \return Number of written bits. + */ +INT FDK_MpegsEnc_WriteSpatialSpecificConfig(HANDLE_MPS_ENCODER hMpsEnc, + HANDLE_FDK_BITSTREAM hBs); + +/** + * \brief Get closest valid bitrate supported by given config. + * + * \param audioObjectType Audio object type. + * \param channelMode Encoder channel mode. + * \param samplingrate Sampling rate in Hz of audio input signal. + * \param sbrRatio SBR sampling rate ratio. + * \param bitrate The desired target bitrate. + * + * \return Closest valid bitrate to given bitrate.. + */ +INT FDK_MpegsEnc_GetClosestBitRate(const AUDIO_OBJECT_TYPE audioObjectType, + const CHANNEL_MODE channelMode, + const UINT samplingrate, const UINT sbrRatio, + const UINT bitrate); + +/** + * \brief Get codec delay. + * + * This function returns delay of the whole en-/decoded signal, including + * corecoder delay. + * + * \param hMpsEnc MPS Encoder handle. + * + * \return Codec delay in samples. + */ +INT FDK_MpegsEnc_GetDelay(HANDLE_MPS_ENCODER hMpsEnc); + +/** + * \brief Get Mpeg Surround Decoder delay. + * + * This function returns delay of the Mpeg Surround decoder. + * + * \param hMpsEnc MPS Encoder handle. + * + * \return Mpeg Surround Decoder delay in samples. + */ +INT FDK_MpegsEnc_GetDecDelay(HANDLE_MPS_ENCODER hMpsEnc); + +/** + * \brief Get information about encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - MPS_ENCODER_OK, on succes. + * - MPS_ENCODER_INVALID_HANDLE, MPS_ENCODER_INIT_ERROR, on failure. + */ +MPS_ENCODER_ERROR FDK_MpegsEnc_GetLibInfo(LIB_INFO *info); + +#endif /* MPS_MAIN_H */ diff --git a/fdk-aac/libAACenc/src/ms_stereo.cpp b/fdk-aac/libAACenc/src/ms_stereo.cpp new file mode 100644 index 0000000..6a121b2 --- /dev/null +++ b/fdk-aac/libAACenc/src/ms_stereo.cpp @@ -0,0 +1,295 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: MS stereo processing + +*******************************************************************************/ + +#include "ms_stereo.h" + +#include "psy_const.h" + +/* static const float scaleMinThres = 1.0f; */ /* 0.75f for 3db boost */ + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL *psyOutChannel[2], + const INT *isBook, INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT allowMS, const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset) { + FIXP_DBL *sfbEnergyLeft = + psyData[0]->sfbEnergy.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRight = + psyData[1]->sfbEnergy.Long; /* modified where msMask==1 */ + const FIXP_DBL *sfbEnergyMid = psyData[0]->sfbEnergyMS.Long; + const FIXP_DBL *sfbEnergySide = psyData[1]->sfbEnergyMS.Long; + FIXP_DBL *sfbThresholdLeft = + psyData[0]->sfbThreshold.Long; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRight = + psyData[1]->sfbThreshold.Long; /* modified where msMask==1 */ + + FIXP_DBL *sfbSpreadEnLeft = psyData[0]->sfbSpreadEnergy.Long; + FIXP_DBL *sfbSpreadEnRight = psyData[1]->sfbSpreadEnergy.Long; + + FIXP_DBL *sfbEnergyLeftLdData = + psyOutChannel[0]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyRightLdData = + psyOutChannel[1]->sfbEnergyLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbEnergyMidLdData = psyData[0]->sfbEnergyMSLdData; + FIXP_DBL *sfbEnergySideLdData = psyData[1]->sfbEnergyMSLdData; + FIXP_DBL *sfbThresholdLeftLdData = + psyOutChannel[0]->sfbThresholdLdData; /* modified where msMask==1 */ + FIXP_DBL *sfbThresholdRightLdData = + psyOutChannel[1]->sfbThresholdLdData; /* modified where msMask==1 */ + + FIXP_DBL *mdctSpectrumLeft = + psyData[0]->mdctSpectrum; /* modified where msMask==1 */ + FIXP_DBL *mdctSpectrumRight = + psyData[1]->mdctSpectrum; /* modified where msMask==1 */ + + INT sfb, sfboffs, j; /* loop counters */ + FIXP_DBL pnlrLdData, pnmsLdData; + FIXP_DBL minThresholdLdData; + FIXP_DBL minThreshold; + INT useMS; + + INT msMaskTrueSomewhere = 0; /* to determine msDigest */ + INT numMsMaskFalse = + 0; /* number of non-intensity bands where L/R coding is used */ + + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + if ((isBook == NULL) ? 1 : (isBook[sfb + sfboffs] == 0)) { + FIXP_DBL tmp; + + /* + minThreshold=min(sfbThresholdLeft[sfb+sfboffs], + sfbThresholdRight[sfb+sfboffs])*scaleMinThres; pnlr = + (sfbThresholdLeft[sfb+sfboffs]/ + max(sfbEnergyLeft[sfb+sfboffs],sfbThresholdLeft[sfb+sfboffs]))* + (sfbThresholdRight[sfb+sfboffs]/ + max(sfbEnergyRight[sfb+sfboffs],sfbThresholdRight[sfb+sfboffs])); + pnms = + (minThreshold/max(sfbEnergyMid[sfb+sfboffs],minThreshold))* + (minThreshold/max(sfbEnergySide[sfb+sfboffs],minThreshold)); + useMS = (pnms > pnlr); + */ + + /* we assume that scaleMinThres == 1.0f and we can drop it */ + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + + /* pnlrLdData = sfbThresholdLeftLdData[sfb+sfboffs] - + max(sfbEnergyLeftLdData[sfb+sfboffs], + sfbThresholdLeftLdData[sfb+sfboffs]) + + sfbThresholdRightLdData[sfb+sfboffs] - + max(sfbEnergyRightLdData[sfb+sfboffs], + sfbThresholdRightLdData[sfb+sfboffs]); */ + tmp = fixMax(sfbEnergyLeftLdData[sfb + sfboffs], + sfbThresholdLeftLdData[sfb + sfboffs]); + pnlrLdData = (sfbThresholdLeftLdData[sfb + sfboffs] >> 1) - (tmp >> 1); + pnlrLdData = pnlrLdData + (sfbThresholdRightLdData[sfb + sfboffs] >> 1); + tmp = fixMax(sfbEnergyRightLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + pnlrLdData = pnlrLdData - (tmp >> 1); + + /* pnmsLdData = minThresholdLdData - + max(sfbEnergyMidLdData[sfb+sfboffs], minThresholdLdData) + + minThresholdLdData - max(sfbEnergySideLdData[sfb+sfboffs], + minThresholdLdData); */ + tmp = fixMax(sfbEnergyMidLdData[sfb + sfboffs], minThresholdLdData); + pnmsLdData = minThresholdLdData - (tmp >> 1); + tmp = fixMax(sfbEnergySideLdData[sfb + sfboffs], minThresholdLdData); + pnmsLdData = pnmsLdData - (tmp >> 1); + useMS = ((allowMS != 0) && (pnmsLdData > pnlrLdData)) ? 1 : 0; + + if (useMS) { + msMask[sfb + sfboffs] = 1; + msMaskTrueSomewhere = 1; + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + FIXP_DBL specL, specR; + specL = mdctSpectrumLeft[j] >> 1; + specR = mdctSpectrumRight[j] >> 1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb + sfboffs], + sfbThresholdRight[sfb + sfboffs]); + sfbThresholdLeft[sfb + sfboffs] = sfbThresholdRight[sfb + sfboffs] = + minThreshold; + sfbThresholdLeftLdData[sfb + sfboffs] = + sfbThresholdRightLdData[sfb + sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb + sfboffs] = sfbEnergyMid[sfb + sfboffs]; + sfbEnergyRight[sfb + sfboffs] = sfbEnergySide[sfb + sfboffs]; + sfbEnergyLeftLdData[sfb + sfboffs] = + sfbEnergyMidLdData[sfb + sfboffs]; + sfbEnergyRightLdData[sfb + sfboffs] = + sfbEnergySideLdData[sfb + sfboffs]; + + sfbSpreadEnLeft[sfb + sfboffs] = sfbSpreadEnRight[sfb + sfboffs] = + fixMin(sfbSpreadEnLeft[sfb + sfboffs], + sfbSpreadEnRight[sfb + sfboffs]) >> + 1; + + } else { + msMask[sfb + sfboffs] = 0; + numMsMaskFalse++; + } /* useMS */ + } /* isBook */ + else { + /* keep mDigest from IS module */ + if (msMask[sfb + sfboffs]) { + msMaskTrueSomewhere = 1; + } + /* prohibit MS_MASK_ALL in combination with IS */ + numMsMaskFalse = 9; + } /* isBook */ + } /* sfboffs */ + } /* sfb */ + + if (msMaskTrueSomewhere == 1) { + if ((numMsMaskFalse == 0) || + ((numMsMaskFalse < maxSfbPerGroup) && (numMsMaskFalse < 9))) { + *msDigest = SI_MS_MASK_ALL; + /* loop through M/S bands; if msMask==0, set it to 1 and apply M/S */ + for (sfb = 0; sfb < sfbCnt; sfb += sfbPerGroup) { + for (sfboffs = 0; sfboffs < maxSfbPerGroup; sfboffs++) { + if (((isBook == NULL) ? 1 : (isBook[sfb + sfboffs] == 0)) && + (msMask[sfb + sfboffs] == 0)) { + msMask[sfb + sfboffs] = 1; + /* apply M/S coding */ + for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; + j++) { + FIXP_DBL specL, specR; + specL = mdctSpectrumLeft[j] >> 1; + specR = mdctSpectrumRight[j] >> 1; + mdctSpectrumLeft[j] = specL + specR; + mdctSpectrumRight[j] = specL - specR; + } + minThreshold = fixMin(sfbThresholdLeft[sfb + sfboffs], + sfbThresholdRight[sfb + sfboffs]); + sfbThresholdLeft[sfb + sfboffs] = sfbThresholdRight[sfb + sfboffs] = + minThreshold; + minThresholdLdData = fixMin(sfbThresholdLeftLdData[sfb + sfboffs], + sfbThresholdRightLdData[sfb + sfboffs]); + sfbThresholdLeftLdData[sfb + sfboffs] = + sfbThresholdRightLdData[sfb + sfboffs] = minThresholdLdData; + sfbEnergyLeft[sfb + sfboffs] = sfbEnergyMid[sfb + sfboffs]; + sfbEnergyRight[sfb + sfboffs] = sfbEnergySide[sfb + sfboffs]; + sfbEnergyLeftLdData[sfb + sfboffs] = + sfbEnergyMidLdData[sfb + sfboffs]; + sfbEnergyRightLdData[sfb + sfboffs] = + sfbEnergySideLdData[sfb + sfboffs]; + + sfbSpreadEnLeft[sfb + sfboffs] = sfbSpreadEnRight[sfb + sfboffs] = + fixMin(sfbSpreadEnLeft[sfb + sfboffs], + sfbSpreadEnRight[sfb + sfboffs]) >> + 1; + } + } + } + } else { + *msDigest = SI_MS_MASK_SOME; + } + } else { + *msDigest = SI_MS_MASK_NONE; + } +} diff --git a/fdk-aac/libAACenc/src/ms_stereo.h b/fdk-aac/libAACenc/src/ms_stereo.h new file mode 100644 index 0000000..a202307 --- /dev/null +++ b/fdk-aac/libAACenc/src/ms_stereo.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: MS stereo processing + +*******************************************************************************/ + +#ifndef MS_STEREO_H +#define MS_STEREO_H + +#include "interface.h" + +void FDKaacEnc_MsStereoProcessing(PSY_DATA *RESTRICT psyData[(2)], + PSY_OUT_CHANNEL *psyOutChannel[2], + const INT *isBook, INT *msDigest, /* output */ + INT *msMask, /* output */ + const INT allowMS, const INT sfbCnt, + const INT sfbPerGroup, + const INT maxSfbPerGroup, + const INT *sfbOffset); + +#endif /* MS_STEREO_H */ diff --git a/fdk-aac/libAACenc/src/noisedet.cpp b/fdk-aac/libAACenc/src/noisedet.cpp new file mode 100644 index 0000000..c984304 --- /dev/null +++ b/fdk-aac/libAACenc/src/noisedet.cpp @@ -0,0 +1,235 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: noisedet.c + Routines for Noise Detection + +*******************************************************************************/ + +#include "noisedet.h" + +#include "aacenc_pns.h" +#include "pnsparam.h" + +/***************************************************************************** + + functionname: FDKaacEnc_fuzzyIsSmaller + description: Fuzzy value calculation for "testVal is smaller than refVal" + returns: fuzzy value + input: test and ref Value, + low and high Lim + output: return fuzzy value + +*****************************************************************************/ +static FIXP_SGL FDKaacEnc_fuzzyIsSmaller(FIXP_DBL testVal, FIXP_DBL refVal, + FIXP_DBL loLim, FIXP_DBL hiLim) { + if (refVal <= FL2FXCONST_DBL(0.0)) + return (FL2FXCONST_SGL(0.0f)); + else if (testVal >= fMult((hiLim >> 1) + (loLim >> 1), refVal)) + return (FL2FXCONST_SGL(0.0f)); + else + return ((FIXP_SGL)MAXVAL_SGL); +} + +/***************************************************************************** + + functionname: FDKaacEnc_noiseDetect + description: detect tonal sfb's; two tests + Powerdistribution: + sfb splittet in four regions, + compare the energy in all sections + PsychTonality: + compare tonality from chaosmeasure with reftonality + returns: + input: spectrum of one large mdct + number of sfb's + pointer to offset of sfb's + pointer to noiseFuzzyMeasure (modified) + noiseparams struct + pointer to sfb energies + pointer to tonality calculated in chaosmeasure + output: noiseFuzzy Measure + +*****************************************************************************/ + +void FDKaacEnc_noiseDetect(FIXP_DBL *RESTRICT mdctSpectrum, + INT *RESTRICT sfbMaxScaleSpec, INT sfbActive, + const INT *RESTRICT sfbOffset, + FIXP_SGL *RESTRICT noiseFuzzyMeasure, + NOISEPARAMS *np, FIXP_SGL *RESTRICT sfbtonality) + +{ + int i, k, sfb, sfbWidth; + FIXP_SGL fuzzy, fuzzyTotal; + FIXP_DBL refVal, testVal; + + /***** Start detection phase *****/ + /* Start noise detection for each band based on a number of checks */ + for (sfb = 0; sfb < sfbActive; sfb++) { + fuzzyTotal = (FIXP_SGL)MAXVAL_SGL; + sfbWidth = sfbOffset[sfb + 1] - sfbOffset[sfb]; + + /* Reset output for lower bands or too small bands */ + if (sfb < np->startSfb || sfbWidth < np->minSfbWidth) { + noiseFuzzyMeasure[sfb] = FL2FXCONST_SGL(0.0f); + continue; + } + + if ((np->detectionAlgorithmFlags & USE_POWER_DISTRIBUTION) && + (fuzzyTotal > FL2FXCONST_SGL(0.5f))) { + FIXP_DBL fhelp1, fhelp2, fhelp3, fhelp4, maxVal, minVal; + INT leadingBits = fixMax( + 0, (sfbMaxScaleSpec[sfb] - + 3)); /* max sfbWidth = 96/4 ; 2^5=32 => 5/2 = 3 (spc*spc) */ + + /* check power distribution in four regions */ + fhelp1 = fhelp2 = fhelp3 = fhelp4 = FL2FXCONST_DBL(0.0f); + k = sfbWidth >> 2; /* Width of a quarter band */ + + for (i = sfbOffset[sfb]; i < sfbOffset[sfb] + k; i++) { + fhelp1 = fPow2AddDiv2(fhelp1, mdctSpectrum[i] << leadingBits); + fhelp2 = fPow2AddDiv2(fhelp2, mdctSpectrum[i + k] << leadingBits); + fhelp3 = fPow2AddDiv2(fhelp3, mdctSpectrum[i + 2 * k] << leadingBits); + fhelp4 = fPow2AddDiv2(fhelp4, mdctSpectrum[i + 3 * k] << leadingBits); + } + + /* get max into fhelp: */ + maxVal = fixMax(fhelp1, fhelp2); + maxVal = fixMax(maxVal, fhelp3); + maxVal = fixMax(maxVal, fhelp4); + + /* get min into fhelp1: */ + minVal = fixMin(fhelp1, fhelp2); + minVal = fixMin(minVal, fhelp3); + minVal = fixMin(minVal, fhelp4); + + /* Normalize min and max Val */ + leadingBits = CountLeadingBits(maxVal); + testVal = maxVal << leadingBits; + refVal = minVal << leadingBits; + + /* calculate fuzzy value for power distribution */ + testVal = fMultDiv2(testVal, np->powDistPSDcurve[sfb]); + + fuzzy = FDKaacEnc_fuzzyIsSmaller( + testVal, /* 1/2 * maxValue * PSDcurve */ + refVal, /* 1 * minValue */ + FL2FXCONST_DBL(0.495), /* 1/2 * loLim (0.99f/2) */ + FL2FXCONST_DBL(0.505)); /* 1/2 * hiLim (1.01f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + if ((np->detectionAlgorithmFlags & USE_PSYCH_TONALITY) && + (fuzzyTotal > FL2FXCONST_SGL(0.5f))) { + /* Detection with tonality-value of psych. acoustic (here: 1 is tonal!)*/ + + testVal = FX_SGL2FX_DBL(sfbtonality[sfb]) >> 1; /* 1/2 * sfbTonality */ + refVal = np->refTonality; + + fuzzy = FDKaacEnc_fuzzyIsSmaller( + testVal, refVal, FL2FXCONST_DBL(0.45f), /* 1/2 * loLim (0.9f/2) */ + FL2FXCONST_DBL(0.55f)); /* 1/2 * hiLim (1.1f/2) */ + + fuzzyTotal = fixMin(fuzzyTotal, fuzzy); + } + + /* Output of final result */ + noiseFuzzyMeasure[sfb] = fuzzyTotal; + } +} diff --git a/fdk-aac/libAACenc/src/noisedet.h b/fdk-aac/libAACenc/src/noisedet.h new file mode 100644 index 0000000..478701f --- /dev/null +++ b/fdk-aac/libAACenc/src/noisedet.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: noisedet.h + +*******************************************************************************/ + +#ifndef NOISEDET_H +#define NOISEDET_H + +#include "common_fix.h" + +#include "pnsparam.h" +#include "psy_data.h" + +void FDKaacEnc_noiseDetect(FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, + INT sfbActive, const INT *sfbOffset, + FIXP_SGL noiseFuzzyMeasure[], NOISEPARAMS *np, + FIXP_SGL *sfbtonality); + +#endif /* NOISEDET_H */ diff --git a/fdk-aac/libAACenc/src/pns_func.h b/fdk-aac/libAACenc/src/pns_func.h new file mode 100644 index 0000000..88f4586 --- /dev/null +++ b/fdk-aac/libAACenc/src/pns_func.h @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: pns_func.h + +*******************************************************************************/ + +#ifndef PNS_FUNC_H +#define PNS_FUNC_H + +#include "common_fix.h" +#include "aacenc_pns.h" +#include "psy_data.h" + +AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration( + PNS_CONFIG *pnsConf, INT bitRate, INT sampleRate, INT usePns, INT sfbCnt, + const INT *sfbOffset, const INT numChan, const INT isLC); + +void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, + const INT lastWindowSequence, const INT sfbActive, + const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, + const INT *sfbOffset, FIXP_DBL *mdctSpectrum, + INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, + int tnsOrder, INT tnsPredictionGain, INT tnsActive, + FIXP_DBL *sfbEnergyLdData, INT *noiseNrg); + +void FDKaacEnc_CodePnsChannel(const INT sfbActive, PNS_CONFIG *pnsConf, + INT *pnsFlag, FIXP_DBL *sfbEnergy, INT *noiseNrg, + FIXP_DBL *sfbThreshold); + +void FDKaacEnc_PreProcessPnsChannelPair( + const INT sfbActive, FIXP_DBL *sfbEnergyLeft, FIXP_DBL *sfbEnergyRight, + FIXP_DBL *sfbEnergyLeftLD, FIXP_DBL *sfbEnergyRightLD, + FIXP_DBL *sfbEnergyMid, PNS_CONFIG *pnsConfLeft, PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight); + +void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, + PNS_CONFIG *pnsConf, + PNS_DATA *pnsDataLeft, + PNS_DATA *pnsDataRight, INT *msMask, + INT *msDigest); + +#endif /* PNS_FUNC_H */ diff --git a/fdk-aac/libAACenc/src/pnsparam.cpp b/fdk-aac/libAACenc/src/pnsparam.cpp new file mode 100644 index 0000000..a6aab06 --- /dev/null +++ b/fdk-aac/libAACenc/src/pnsparam.cpp @@ -0,0 +1,574 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Lohwasser + + Description: PNS parameters depending on bitrate and bandwidth + +*******************************************************************************/ + +#include "pnsparam.h" + +#include "psy_configuration.h" + +typedef struct { + SHORT startFreq; + /* Parameters for detection */ + FIXP_SGL refPower; + FIXP_SGL refTonality; + SHORT tnsGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + SHORT tnsPNSGainThreshold; /* scaled by TNS_PREDGAIN_SCALE (=1000) */ + FIXP_SGL gapFillThr; + SHORT minSfbWidth; + USHORT detectionAlgorithmFlags; +} PNS_INFO_TAB; + +typedef struct { + ULONG brFrom; + ULONG brTo; + UCHAR S16000; + UCHAR S22050; + UCHAR S24000; + UCHAR S32000; + UCHAR S44100; + UCHAR S48000; +} AUTO_PNS_TAB; + +static const AUTO_PNS_TAB levelTable_mono[] = { + { + 0, + 11999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 12000, + 19999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 20000, + 28999, + 0, + 2, + 1, + 1, + 1, + 1, + }, + { + 29000, + 40999, + 0, + 4, + 4, + 4, + 2, + 2, + }, + { + 41000, + 55999, + 0, + 9, + 9, + 7, + 7, + 7, + }, + { + 56000, + 61999, + 0, + 0, + 0, + 0, + 9, + 9, + }, + { + 62000, + 75999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 76000, + 92999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 93000, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; + +static const AUTO_PNS_TAB levelTable_stereo[] = { + { + 0, + 11999, + 0, + 1, + 1, + 1, + 1, + 1, + }, + { + 12000, + 19999, + 0, + 3, + 1, + 1, + 1, + 1, + }, + { + 20000, + 28999, + 0, + 3, + 3, + 3, + 2, + 2, + }, + { + 29000, + 40999, + 0, + 7, + 6, + 6, + 5, + 5, + }, + { + 41000, + 55999, + 0, + 9, + 9, + 7, + 7, + 7, + }, + { + 56000, + 79999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 80000, + 99999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 100000, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; + +static const PNS_INFO_TAB pnsInfoTab[] = { + /*0 pns off */ + /*1*/ {4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.06), 1150, 1200, + FL2FXCONST_SGL(0.02), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*2*/ + {4000, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1130, 1300, + FL2FXCONST_SGL(0.05), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*3*/ + {4100, FL2FXCONST_SGL(0.04), FL2FXCONST_SGL(0.07), 1100, 1400, + FL2FXCONST_SGL(0.10), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*4*/ + {4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS /*| JUST_LONG_WINDOW*/}, + /*5*/ + {4300, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.15), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*6*/ + {5000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.25), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*7*/ + {5500, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1100, 1400, + FL2FXCONST_SGL(0.35), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*8*/ + {6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.12), 1080, 1400, + FL2FXCONST_SGL(0.40), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*9*/ + {6000, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.14), 1070, 1400, + FL2FXCONST_SGL(0.45), 8, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, +}; + +static const AUTO_PNS_TAB levelTable_lowComplexity[] = { + { + 0, + 27999, + 0, + 0, + 0, + 0, + 0, + 0, + }, + { + 28000, + 31999, + 0, + 2, + 2, + 2, + 2, + 2, + }, + { + 32000, + 47999, + 0, + 3, + 3, + 3, + 3, + 3, + }, + { + 48000, + 48000, + 0, + 4, + 4, + 4, + 4, + 4, + }, + { + 48001, + 999999, + 0, + 0, + 0, + 0, + 0, + 0, + }, +}; +/* conversion of old LC tuning tables to new (LD enc) structure (only entries + * which are actually used were converted) */ +static const PNS_INFO_TAB pnsInfoTab_lowComplexity[] = { + /*0 pns off */ + /* DEFAULT parameter set */ + /*1*/ {4100, FL2FXCONST_SGL(0.03), FL2FXCONST_SGL(0.16), 1100, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*2*/ + {4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1410, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /*3*/ + {4100, FL2FXCONST_SGL(0.05), FL2FXCONST_SGL(0.10), 1100, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, + /* LOWSUBST -> PNS is used less often than with DEFAULT parameter set (for + br: 48000 - 79999) */ + /*4*/ + {4100, FL2FXCONST_SGL(0.20), FL2FXCONST_SGL(0.10), 1410, 1400, + FL2FXCONST_SGL(0.5), 16, + USE_POWER_DISTRIBUTION | USE_PSYCH_TONALITY | USE_TNS_GAIN_THR | + USE_TNS_PNS | JUST_LONG_WINDOW}, +}; + +/**************************************************************************** + function to look up used pns level +****************************************************************************/ +int FDKaacEnc_lookUpPnsUse(int bitRate, int sampleRate, int numChan, + const int isLC) { + int hUsePns = 0, size, i; + const AUTO_PNS_TAB *levelTable; + + if (isLC) { + levelTable = &levelTable_lowComplexity[0]; + size = sizeof(levelTable_lowComplexity); + } else { /* (E)LD */ + levelTable = (numChan > 1) ? &levelTable_stereo[0] : &levelTable_mono[0]; + size = (numChan > 1) ? sizeof(levelTable_stereo) : sizeof(levelTable_mono); + } + + for (i = 0; i < (int)(size / sizeof(AUTO_PNS_TAB)); i++) { + if (((ULONG)bitRate >= levelTable[i].brFrom) && + ((ULONG)bitRate <= levelTable[i].brTo)) + break; + } + + /* sanity check */ + if ((int)(sizeof(pnsInfoTab) / sizeof(PNS_INFO_TAB)) < i) { + return (PNS_TABLE_ERROR); + } + + switch (sampleRate) { + case 16000: + hUsePns = levelTable[i].S16000; + break; + case 22050: + hUsePns = levelTable[i].S22050; + break; + case 24000: + hUsePns = levelTable[i].S24000; + break; + case 32000: + hUsePns = levelTable[i].S32000; + break; + case 44100: + hUsePns = levelTable[i].S44100; + break; + case 48000: + hUsePns = levelTable[i].S48000; + break; + default: + if (isLC) { + hUsePns = levelTable[i].S48000; + } + break; + } + + return (hUsePns); +} + +/***************************************************************************** + + functionname: FDKaacEnc_GetPnsParam + description: Gets PNS parameters depending on bitrate and bandwidth or + bitsPerLine + returns: error status + input: Noiseparams struct, bitrate, sampling rate, + number of sfb's, pointer to sfb offset + output: PNS parameters + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, INT bitRate, + INT sampleRate, INT sfbCnt, + const INT *sfbOffset, INT *usePns, + INT numChan, const INT isLC) { + int i, hUsePns; + const PNS_INFO_TAB *pnsInfo; + + if (*usePns <= 0) return AAC_ENC_OK; + + if (isLC) { + np->detectionAlgorithmFlags = IS_LOW_COMPLEXITY; + + pnsInfo = pnsInfoTab_lowComplexity; + + /* new pns params */ + hUsePns = FDKaacEnc_lookUpPnsUse(bitRate, sampleRate, numChan, isLC); + if (hUsePns == 0) { + *usePns = 0; + return AAC_ENC_OK; + } + + if (hUsePns == PNS_TABLE_ERROR) { + return AAC_ENC_PNS_TABLE_ERROR; + } + + /* select correct row of tuning table */ + pnsInfo += hUsePns - 1; + + } else { + np->detectionAlgorithmFlags = 0; + pnsInfo = pnsInfoTab; + + /* new pns params */ + hUsePns = FDKaacEnc_lookUpPnsUse(bitRate, sampleRate, numChan, isLC); + if (hUsePns == 0) { + *usePns = 0; + return AAC_ENC_OK; + } + if (hUsePns == PNS_TABLE_ERROR) return AAC_ENC_PNS_TABLE_ERROR; + + /* select correct row of tuning table */ + pnsInfo += hUsePns - 1; + } + + np->startSfb = FDKaacEnc_FreqToBandWidthRounding( + pnsInfo->startFreq, sampleRate, sfbCnt, sfbOffset); + + np->detectionAlgorithmFlags |= pnsInfo->detectionAlgorithmFlags; + + np->refPower = FX_SGL2FX_DBL(pnsInfo->refPower); + np->refTonality = FX_SGL2FX_DBL(pnsInfo->refTonality); + np->tnsGainThreshold = pnsInfo->tnsGainThreshold; + np->tnsPNSGainThreshold = pnsInfo->tnsPNSGainThreshold; + np->minSfbWidth = pnsInfo->minSfbWidth; + + np->gapFillThr = + pnsInfo->gapFillThr; /* for LC it is always FL2FXCONST_SGL(0.5) */ + + /* assuming a constant dB/Hz slope in the signal's PSD curve, + the detection threshold needs to be corrected for the width of the band */ + + for (i = 0; i < (sfbCnt - 1); i++) { + INT qtmp, sfbWidth; + FIXP_DBL tmp; + + sfbWidth = sfbOffset[i + 1] - sfbOffset[i]; + + tmp = fPow(np->refPower, 0, sfbWidth, DFRACT_BITS - 1 - 5, &qtmp); + np->powDistPSDcurve[i] = (FIXP_SGL)((LONG)(scaleValue(tmp, qtmp) >> 16)); + } + np->powDistPSDcurve[sfbCnt] = np->powDistPSDcurve[sfbCnt - 1]; + + return AAC_ENC_OK; +} diff --git a/fdk-aac/libAACenc/src/pnsparam.h b/fdk-aac/libAACenc/src/pnsparam.h new file mode 100644 index 0000000..c37738a --- /dev/null +++ b/fdk-aac/libAACenc/src/pnsparam.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: PNS parameters depending on bitrate and bandwidth + +*******************************************************************************/ + +#ifndef PNSPARAM_H +#define PNSPARAM_H + +#include "aacenc.h" +#include "common_fix.h" +#include "psy_const.h" + +#define NUM_PNSINFOTAB 4 +#define PNS_TABLE_ERROR -1 + +/* detection algorithm flags */ +#define USE_POWER_DISTRIBUTION (1 << 0) +#define USE_PSYCH_TONALITY (1 << 1) +#define USE_TNS_GAIN_THR (1 << 2) +#define USE_TNS_PNS (1 << 3) +#define JUST_LONG_WINDOW (1 << 4) +/* additional algorithm flags */ +#define IS_LOW_COMPLEXITY (1 << 5) + +typedef struct { + /* PNS start band */ + short startSfb; + + /* detection algorithm flags */ + USHORT detectionAlgorithmFlags; + + /* Parameters for detection */ + FIXP_DBL refPower; + FIXP_DBL refTonality; + INT tnsGainThreshold; + INT tnsPNSGainThreshold; + INT minSfbWidth; + FIXP_SGL powDistPSDcurve[MAX_GROUPED_SFB]; + FIXP_SGL gapFillThr; +} NOISEPARAMS; + +int FDKaacEnc_lookUpPnsUse(int bitRate, int sampleRate, int numChan, + const int isLC); + +/****** Definition of prototypes ******/ + +AAC_ENCODER_ERROR FDKaacEnc_GetPnsParam(NOISEPARAMS *np, INT bitRate, + INT sampleRate, INT sfbCnt, + const INT *sfbOffset, INT *usePns, + INT numChan, const INT isLC); + +#endif /* PNSPARAM_H */ diff --git a/fdk-aac/libAACenc/src/pre_echo_control.cpp b/fdk-aac/libAACenc/src/pre_echo_control.cpp new file mode 100644 index 0000000..3d5d153 --- /dev/null +++ b/fdk-aac/libAACenc/src/pre_echo_control.cpp @@ -0,0 +1,176 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Pre echo control + +*******************************************************************************/ + +#include "pre_echo_control.h" +#include "psy_configuration.h" + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT *calcPreEcho, INT numPb, + FIXP_DBL *RESTRICT sfbPcmQuantThreshold, + INT *mdctScalenm1) { + *mdctScalenm1 = PCM_QUANT_THR_SCALE >> 1; + + FDKmemcpy(pbThresholdNm1, sfbPcmQuantThreshold, numPb * sizeof(FIXP_DBL)); + + *calcPreEcho = 1; +} + +void FDKaacEnc_PreEchoControl(FIXP_DBL *RESTRICT pbThresholdNm1, + INT calcPreEcho, INT numPb, + INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *RESTRICT pbThreshold, INT mdctScale, + INT *mdctScalenm1) { + int i; + FIXP_DBL tmpThreshold1, tmpThreshold2; + int scaling; + + /* If lastWindowSequence in previous frame was start- or stop-window, + skip preechocontrol calculation */ + if (calcPreEcho == 0) { + /* copy thresholds to internal memory */ + FDKmemcpy(pbThresholdNm1, pbThreshold, numPb * sizeof(FIXP_DBL)); + *mdctScalenm1 = mdctScale; + return; + } + + if (mdctScale > *mdctScalenm1) { + /* if current thresholds are downscaled more than the ones from the last + * block */ + scaling = 2 * (mdctScale - *mdctScalenm1); + for (i = 0; i < numPb; i++) { + /* multiplication with return data type fract ist equivalent to int + * multiplication */ + FDK_ASSERT(scaling >= 0); + tmpThreshold1 = maxAllowedIncreaseFactor * (pbThresholdNm1[i] >> scaling); + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + FIXP_DBL tmp = pbThreshold[i]; + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = tmp; + + tmp = fixMin(tmp, tmpThreshold1); + pbThreshold[i] = fixMax(tmp, tmpThreshold2); + } + } else { + /* if thresholds of last block are more downscaled than the current ones */ + scaling = 2 * (*mdctScalenm1 - mdctScale); + for (i = 0; i < numPb; i++) { + /* multiplication with return data type fract ist equivalent to int + * multiplication */ + tmpThreshold1 = (maxAllowedIncreaseFactor >> 1) * pbThresholdNm1[i]; + tmpThreshold2 = fMult(minRemainingThresholdFactor, pbThreshold[i]); + + /* copy thresholds to internal memory */ + pbThresholdNm1[i] = pbThreshold[i]; + + FDK_ASSERT(scaling >= 0); + if ((pbThreshold[i] >> (scaling + 1)) > tmpThreshold1) { + pbThreshold[i] = tmpThreshold1 << (scaling + 1); + } + pbThreshold[i] = fixMax(pbThreshold[i], tmpThreshold2); + } + } + + *mdctScalenm1 = mdctScale; +} diff --git a/fdk-aac/libAACenc/src/pre_echo_control.h b/fdk-aac/libAACenc/src/pre_echo_control.h new file mode 100644 index 0000000..688efdb --- /dev/null +++ b/fdk-aac/libAACenc/src/pre_echo_control.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Pre echo control + +*******************************************************************************/ + +#ifndef PRE_ECHO_CONTROL_H +#define PRE_ECHO_CONTROL_H + +#include "common_fix.h" + +void FDKaacEnc_InitPreEchoControl(FIXP_DBL *pbThresholdnm1, INT *calcPreEcho, + INT numPb, FIXP_DBL *sfbPcmQuantThreshold, + INT *mdctScalenm1); + +void FDKaacEnc_PreEchoControl(FIXP_DBL *pbThresholdNm1, INT calcPreEcho, + INT numPb, INT maxAllowedIncreaseFactor, + FIXP_SGL minRemainingThresholdFactor, + FIXP_DBL *pbThreshold, INT mdctScale, + INT *mdctScalenm1); + +#endif diff --git a/fdk-aac/libAACenc/src/psy_configuration.cpp b/fdk-aac/libAACenc/src/psy_configuration.cpp new file mode 100644 index 0000000..b444b58 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_configuration.cpp @@ -0,0 +1,801 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic configuration + +*******************************************************************************/ + +#include "psy_configuration.h" +#include "adj_thr.h" +#include "aacEnc_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + +typedef struct { + LONG sampleRate; + const SFB_PARAM_LONG *paramLong; + const SFB_PARAM_SHORT *paramShort; +} SFB_INFO_TAB; + +static const SFB_INFO_TAB sfbInfoTab[] = { + {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128}, + {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128}, + {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128}, + {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128}, + {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128}, + {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128}, + {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128}, + {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128}, + {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128}, + {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128}, + {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128}, + {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128} + +}; + + + +const SFB_PARAM_LONG p_FDKaacEnc_8000_long_960 = { + 40, + { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 16, + 16, 16, 16, 16, 16, 16, 20, 20, 20, 20, 24, 24, 24, 28, + 28, 32, 36, 36, 40, 44, 48, 52, 56, 60, 64, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_8000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_11025_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_11025_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_12000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_12000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_16000_long_960 = { + 42, + { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 16, 16, 16, 16, 20, 20, 20, 24, + 24, 28, 28, 32, 36, 40, 40, 44, 48, 52, 56, 60, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_16000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 12, 12, 16, 20, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_22050_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_22050_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_24000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, 12, 16, 16, 16, + 20, 20, 24, 24, 28, 28, 32, 36, 36, 40, 44, 48, 52, 52, + 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_24000_short_120 = { + 15, + { 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 16, 16, 12 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_32000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 12, 12, 12, + 12, 16, 16, 20, 20, 24, 24, 28, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_32000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_44100_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; + +const SFB_PARAM_SHORT p_FDKaacEnc_44100_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_48000_long_960 = { + 49, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 12, 16, 16, 20, 20, 24, 24, 28, + 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_48000_short_120 = { + 14, + { 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, 12, 16, 16, 8 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_64000_long_960 = { + 46, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 12, 12, + 12, 16, 16, 16, 20, 24, 24, 28, 36, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 16 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_64000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_88200_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_88200_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + +const SFB_PARAM_LONG p_FDKaacEnc_96000_long_960 = { + 40, + { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, 12, + 12, 12, 12, 12, 16, 16, 24, 28, 36, 44, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 } +}; +const SFB_PARAM_SHORT p_FDKaacEnc_96000_short_120 = { + 12, + { 4, 4, 4, 4, 4, 4, 8, 8, 8, 16, 28, 28 } +}; + + +static const SFB_INFO_TAB sfbInfoTab960[] = { + { 8000, &p_FDKaacEnc_8000_long_960, &p_FDKaacEnc_8000_short_120}, + {11025, &p_FDKaacEnc_11025_long_960, &p_FDKaacEnc_11025_short_120}, + {12000, &p_FDKaacEnc_12000_long_960, &p_FDKaacEnc_12000_short_120}, + {16000, &p_FDKaacEnc_16000_long_960, &p_FDKaacEnc_16000_short_120}, + {22050, &p_FDKaacEnc_22050_long_960, &p_FDKaacEnc_22050_short_120}, + {24000, &p_FDKaacEnc_24000_long_960, &p_FDKaacEnc_24000_short_120}, + {32000, &p_FDKaacEnc_32000_long_960, &p_FDKaacEnc_32000_short_120}, + {44100, &p_FDKaacEnc_44100_long_960, &p_FDKaacEnc_44100_short_120}, + {48000, &p_FDKaacEnc_48000_long_960, &p_FDKaacEnc_48000_short_120}, + {64000, &p_FDKaacEnc_64000_long_960, &p_FDKaacEnc_64000_short_120}, + {88200, &p_FDKaacEnc_88200_long_960, &p_FDKaacEnc_88200_short_120}, + {96000, &p_FDKaacEnc_96000_long_960, &p_FDKaacEnc_96000_short_120}, +}; + + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_512 = { + 31, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, 12, + 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_512 = { + 37, + {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, 8, + 12, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 32, 32, 32, 32, 32, 32, 32}}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_512 = { + 36, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 52}}; + +static const SFB_INFO_TAB sfbInfoTabLD512[] = { + {8000, &p_22050_long_512, NULL}, {11025, &p_22050_long_512, NULL}, + {12000, &p_22050_long_512, NULL}, {16000, &p_22050_long_512, NULL}, + {22050, &p_22050_long_512, NULL}, {24000, &p_22050_long_512, NULL}, + {32000, &p_32000_long_512, NULL}, {44100, &p_44100_long_512, NULL}, + {48000, &p_44100_long_512, NULL}, {64000, &p_44100_long_512, NULL}, + {88200, &p_44100_long_512, NULL}, {96000, &p_44100_long_512, NULL}, + {128000, &p_44100_long_512, NULL}, {176400, &p_44100_long_512, NULL}, + {192000, &p_44100_long_512, NULL}, {256000, &p_44100_long_512, NULL}, + {352800, &p_44100_long_512, NULL}, {384000, &p_44100_long_512, NULL}, +}; + +/* 22050 and 24000 Hz */ +static const SFB_PARAM_LONG p_22050_long_480 = { + 30, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 12, + 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 32000 Hz */ +static const SFB_PARAM_LONG p_32000_long_480 = { + 37, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, + 8, 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, 32, 32, 32, 32, 32, 32, 32}}; + +/* 44100 Hz */ +static const SFB_PARAM_LONG p_44100_long_480 = { + 35, {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, 8, 8, 8, + 8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, 32, 32, 32, 32, 48}}; + +static const SFB_INFO_TAB sfbInfoTabLD480[] = { + {8000, &p_22050_long_480, NULL}, {11025, &p_22050_long_480, NULL}, + {12000, &p_22050_long_480, NULL}, {16000, &p_22050_long_480, NULL}, + {22050, &p_22050_long_480, NULL}, {24000, &p_22050_long_480, NULL}, + {32000, &p_32000_long_480, NULL}, {44100, &p_44100_long_480, NULL}, + {48000, &p_44100_long_480, NULL}, {64000, &p_44100_long_480, NULL}, + {88200, &p_44100_long_480, NULL}, {96000, &p_44100_long_480, NULL}, + {128000, &p_44100_long_480, NULL}, {176400, &p_44100_long_480, NULL}, + {192000, &p_44100_long_480, NULL}, {256000, &p_44100_long_480, NULL}, + {352800, &p_44100_long_480, NULL}, {384000, &p_44100_long_480, NULL}, +}; + +/* Fixed point precision definitions */ +#define Q_BARCVAL (25) + +AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate, + const INT blockType, + const INT granuleLength, + INT *const sfbOffset, + INT *const sfbCnt) { + INT i, specStartOffset = 0; + INT granuleLengthWindow = granuleLength; + const UCHAR *sfbWidth = NULL; + const SFB_INFO_TAB *sfbInfo = NULL; + int size; + + /* + select table + */ + switch (granuleLength) { + case 1024: + sfbInfo = sfbInfoTab; + size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB)); + break; + case 960: + sfbInfo = sfbInfoTab960; + size = (INT)(sizeof(sfbInfoTab960)/sizeof(SFB_INFO_TAB)); + break; + case 512: + sfbInfo = sfbInfoTabLD512; + size = sizeof(sfbInfoTabLD512); + break; + case 480: + sfbInfo = sfbInfoTabLD480; + size = sizeof(sfbInfoTabLD480); + break; + default: + return AAC_ENC_INVALID_FRAME_LENGTH; + } + + for (i = 0; i < size; i++) { + if (sfbInfo[i].sampleRate == sampleRate) { + switch (blockType) { + case LONG_WINDOW: + case START_WINDOW: + case STOP_WINDOW: + sfbWidth = sfbInfo[i].paramLong->sfbWidth; + *sfbCnt = sfbInfo[i].paramLong->sfbCnt; + break; + case SHORT_WINDOW: + sfbWidth = sfbInfo[i].paramShort->sfbWidth; + *sfbCnt = sfbInfo[i].paramShort->sfbCnt; + granuleLengthWindow /= TRANS_FAC; + break; + } + break; + } + } + if (i == size) { + return AAC_ENC_UNSUPPORTED_SAMPLINGRATE; + } + + /* + calc sfb offsets + */ + for (i = 0; i < *sfbCnt; i++) { + sfbOffset[i] = specStartOffset; + specStartOffset += sfbWidth[i]; + if (specStartOffset >= granuleLengthWindow) { + i++; + break; + } + } + *sfbCnt = fixMin(i, *sfbCnt); + sfbOffset[*sfbCnt] = fixMin(specStartOffset, granuleLengthWindow); + return AAC_ENC_OK; +} + +/***************************************************************************** + + functionname: FDKaacEnc_BarcLineValue + description: Calculates barc value for one frequency line + returns: barc value of line + input: number of lines in transform, index of line to check, Fs + output: + +*****************************************************************************/ +static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine, + LONG samplingFreq) { + FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */ + FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a; /* 0.00076 in q41 */ + FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333; /* 13.3 in q26 */ + FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000; /* 3.5 in q27 */ + FIXP_DBL INV480 = (FIXP_DBL)0x44444444; // 1/480 in q39 + + FIXP_DBL center_freq, x1, x2; + FIXP_DBL bvalFFTLine, atan1, atan2; + + /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000 + */ + /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in + * q28 */ + /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in + * q25 */ + + center_freq = fftLine * samplingFreq; /* q11 or q8 */ + + + switch (noOfLines) { + case 1024: + center_freq = center_freq << 2; /* q13 */ + break; + case 960: + center_freq = fMult(center_freq, INV480) << 3; + break; + case 128: + center_freq = center_freq << 5; /* q13 */ + break; + case 120: + center_freq = fMult(center_freq, INV480) << 6; + break; + case 512: + center_freq = (fftLine * samplingFreq) << 3; // q13 + break; + case 480: + center_freq = fMult(center_freq, INV480) << 4; // q13 + break; + default: + center_freq = (FIXP_DBL)0; + } + + + x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */ + x2 = fMult(center_freq, PZZZ76) + << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */ + + atan1 = fixp_atan(x1); + atan2 = fixp_atan(x2); + + /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */ + bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1)); + return (bvalFFTLine); +} + +/* + do not consider energies below a certain input signal level, + i.e. of -96dB or 1 bit at 16 bit PCM resolution, + might need to be configurable to e.g. 24 bit PCM Input or a lower + resolution for low bit rates +*/ +static void FDKaacEnc_InitMinPCMResolution(int numPb, int *pbOffset, + FIXP_DBL *sfbPCMquantThreshold) { +/* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY * + * FDKpow(2,PCM_QUANT_THR_SCALE) */ +#define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062) + + for (int i = 0; i < numPb; i++) { + sfbPCMquantThreshold[i] = (pbOffset[i + 1] - pbOffset[i]) * PCM_QUANT_NOISE; + } +} + +static FIXP_DBL getMaskFactor(const FIXP_DBL dbVal_fix, const INT dbVal_e, + const FIXP_DBL ten_fix, const INT ten_e) { + INT q_msk; + FIXP_DBL mask_factor; + + mask_factor = fPow(ten_fix, DFRACT_BITS - 1 - ten_e, -dbVal_fix, + DFRACT_BITS - 1 - dbVal_e, &q_msk); + q_msk = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), q_msk)); + + if ((q_msk > 0) && (mask_factor > (FIXP_DBL)MAXVAL_DBL >> q_msk)) { + mask_factor = (FIXP_DBL)MAXVAL_DBL; + } else { + mask_factor = scaleValue(mask_factor, q_msk); + } + + return (mask_factor); +} + +static void FDKaacEnc_initSpreading(INT numPb, FIXP_DBL *pbBarcValue, + FIXP_DBL *pbMaskLoFactor, + FIXP_DBL *pbMaskHiFactor, + FIXP_DBL *pbMaskLoFactorSprEn, + FIXP_DBL *pbMaskHiFactorSprEn, + const LONG bitrate, const INT blockType) + +{ + INT i; + FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN; + + FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000; /* 3.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000; /* 2.0 in q29 */ + FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000; /* 1.5 in q29 */ + FIXP_DBL TEN = (FIXP_DBL)0x50000000; /* 10.0 in q27 */ + + if (blockType != SHORT_WINDOW) { + MASKLOWSPREN = MASKLOWSPRENLONG; + MASKHIGHSPREN = + (bitrate > 20000) ? MASKHIGHSPRENLONG : MASKHIGHSPRENLONGLOWBR; + } else { + MASKLOWSPREN = MASKLOWSPRENSHORT; + MASKHIGHSPREN = MASKHIGHSPRENSHORT; + } + + for (i = 0; i < numPb; i++) { + if (i > 0) { + pbMaskHiFactor[i] = getMaskFactor( + fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); + + pbMaskLoFactor[i - 1] = getMaskFactor( + fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27); + + pbMaskHiFactorSprEn[i] = getMaskFactor( + fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, + 27); + + pbMaskLoFactorSprEn[i - 1] = getMaskFactor( + fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, + 27); + } else { + pbMaskHiFactor[i] = (FIXP_DBL)0; + pbMaskLoFactor[numPb - 1] = (FIXP_DBL)0; + pbMaskHiFactorSprEn[i] = (FIXP_DBL)0; + pbMaskLoFactorSprEn[numPb - 1] = (FIXP_DBL)0; + } + } +} + +static void FDKaacEnc_initBarcValues(INT numPb, INT *pbOffset, INT numLines, + INT samplingFrequency, FIXP_DBL *pbBval) { + INT i; + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + + for (i = 0; i < numPb; i++) { + FIXP_DBL v1, v2, cur_bark; + v1 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i], samplingFrequency); + v2 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i + 1], samplingFrequency); + cur_bark = (v1 >> 1) + (v2 >> 1); + pbBval[i] = fixMin(cur_bark, MAX_BARC); + } +} + +static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate, + const INT numLines, const INT *sfbOffset, + const INT sfbActive, const INT blockType, + FIXP_DBL *sfbMinSnrLdData) { + INT sfb; + + /* Fix conversion variables */ + INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt; + INT qtmp, qsnr, sfbWidth; + + FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */ + FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */ + FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */ + FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2; /* 0.024 in q36 */ + FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000; /* 1.5 in q30 */ + FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333; /* 0.8 in q30 */ + FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9; /* 0.003 in q30 */ + + FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth; + FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5; + + /* relative number of active barks */ + barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue( + numLines, sfbOffset[sfbActive], samplerate), + MAX_BARC), + MAX_BARCP1, &qbfac); + + qbfac = DFRACT_BITS - 1 - qbfac; + + pePerWindow = fDivNorm(bitrate, samplerate, &qperwin); + qperwin = DFRACT_BITS - 1 - qperwin; + pePerWindow = fMult(pePerWindow, BITS2PEFAC); + qperwin = qperwin + 30 - (DFRACT_BITS - 1); + pePerWindow = fMult(pePerWindow, PERS2P4); + qperwin = qperwin + 36 - (DFRACT_BITS - 1); + + switch (numLines) { + case 1024: + qperwin = qperwin - 10; + break; + case 128: + qperwin = qperwin - 7; + break; + case 512: + qperwin = qperwin - 9; + break; + case 480: + qperwin = qperwin - 9; + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f)); + break; + case 960: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(960.f/1024.f)); + qperwin = qperwin - 10; + break; + case 120: + pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(120.f/128.f)); + qperwin = qperwin - 7; + break; + } + + /* for short blocks it is assumed that more bits are available */ + if (blockType == SHORT_WINDOW) { + pePerWindow = fMult(pePerWindow, ONEP5); + qperwin = qperwin + 30 - (DFRACT_BITS - 1); + } + pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv); + qpeprt_const = qperwin - qbfac + DFRACT_BITS - 1 - qdiv; + + for (sfb = 0; sfb < sfbActive; sfb++) { + barcWidth = + FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb + 1], samplerate) - + FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate); + + /* adapt to sfb bands */ + pePart = fMult(pePart_const, barcWidth); + qpeprt = qpeprt_const + 25 - (DFRACT_BITS - 1); + + /* pe -> snr calculation */ + sfbWidth = (sfbOffset[sfb + 1] - sfbOffset[sfb]); + pePart = fDivNorm(pePart, sfbWidth, &qdiv); + qpeprt += DFRACT_BITS - 1 - qdiv; + + tmp = f2Pow(pePart, DFRACT_BITS - 1 - qpeprt, &qtmp); + qtmp = DFRACT_BITS - 1 - qtmp; + + /* Subtract 1.5 */ + qsnr = fixMin(qtmp, 30); + tmp = tmp >> (qtmp - qsnr); + + if ((30 + 1 - qsnr) > (DFRACT_BITS - 1)) + one_point5 = (FIXP_DBL)0; + else + one_point5 = (FIXP_DBL)(ONEP5 >> (30 + 1 - qsnr)); + + snr = (tmp >> 1) - (one_point5); + qsnr -= 1; + + /* max(snr, 1.0) */ + if (qsnr > 0) + one_qsnr = (FIXP_DBL)(1 << qsnr); + else + one_qsnr = (FIXP_DBL)0; + + snr = fixMax(one_qsnr, snr); + + /* 1/snr */ + snr = fDivNorm(one_qsnr, snr, &qsnr); + qsnr = DFRACT_BITS - 1 - qsnr; + snr = (qsnr > 30) ? (snr >> (qsnr - 30)) : snr; + + /* upper limit is -1 dB */ + snr = (snr > MAX_SNR) ? MAX_SNR : snr; + + /* lower limit is -25 dB */ + snr = (snr < MIN_SNR) ? MIN_SNR : snr; + snr = snr << 1; + + sfbMinSnrLdData[sfb] = CalcLdData(snr); + } +} + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate, + INT bandwidth, INT blocktype, + INT granuleLength, INT useIS, + INT useMS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank) { + AAC_ENCODER_ERROR ErrorStatus; + INT sfb; + FIXP_DBL sfbBarcVal[MAX_SFB]; + const INT frameLengthLong = granuleLength; + const INT frameLengthShort = granuleLength / TRANS_FAC; + INT downscaleFactor = 1; + + switch (granuleLength) { + case 256: + case 240: + downscaleFactor = 2; + break; + case 128: + case 120: + downscaleFactor = 4; + break; + default: + downscaleFactor = 1; + break; + } + + FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION)); + psyConf->granuleLength = granuleLength; + psyConf->filterbank = filterbank; + + psyConf->allowIS = (useIS) && ((bitrate / bandwidth) < 5); + psyConf->allowMS = useMS; + + /* init sfb table */ + ErrorStatus = FDKaacEnc_initSfbTable(samplerate * downscaleFactor, blocktype, + granuleLength * downscaleFactor, + psyConf->sfbOffset, &psyConf->sfbCnt); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + /* calculate barc values for each pb */ + FDKaacEnc_initBarcValues(psyConf->sfbCnt, psyConf->sfbOffset, + psyConf->sfbOffset[psyConf->sfbCnt], samplerate, + sfbBarcVal); + + FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, psyConf->sfbOffset, + psyConf->sfbPcmQuantThreshold); + + /* calculate spreading function */ + FDKaacEnc_initSpreading(psyConf->sfbCnt, sfbBarcVal, + psyConf->sfbMaskLowFactor, psyConf->sfbMaskHighFactor, + psyConf->sfbMaskLowFactorSprEn, + psyConf->sfbMaskHighFactorSprEn, bitrate, blocktype); + + /* init ratio */ + + psyConf->maxAllowedIncreaseFactor = 2; /* integer */ + psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148; + /* FL2FXCONST_SGL(0.01f); */ /* fract */ + + psyConf->clipEnergy = + (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */ + + if (blocktype != SHORT_WINDOW) { + psyConf->lowpassLine = + (INT)((2 * bandwidth * frameLengthLong) / samplerate); + psyConf->lowpassLineLFE = LFE_LOWPASS_LINE; + } else { + psyConf->lowpassLine = + (INT)((2 * bandwidth * frameLengthShort) / samplerate); + psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */ + /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */ + psyConf->clipEnergy >>= 6; + } + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break; + } + psyConf->sfbActive = fMax(sfb, 1); + + for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) { + if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break; + } + psyConf->sfbActiveLFE = sfb; + psyConf->sfbActive = fMax(psyConf->sfbActive, psyConf->sfbActiveLFE); + + /* calculate minSnr */ + FDKaacEnc_initMinSnr(bitrate, samplerate * downscaleFactor, + psyConf->sfbOffset[psyConf->sfbCnt], psyConf->sfbOffset, + psyConf->sfbActive, blocktype, psyConf->sfbMinSnrLdData); + + return AAC_ENC_OK; +} diff --git a/fdk-aac/libAACenc/src/psy_configuration.h b/fdk-aac/libAACenc/src/psy_configuration.h new file mode 100644 index 0000000..52b2887 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_configuration.h @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic configuration + +*******************************************************************************/ + +#ifndef PSY_CONFIGURATION_H +#define PSY_CONFIGURATION_H + +#include "aacenc.h" +#include "common_fix.h" + +#include "psy_const.h" +#include "aacenc_tns.h" +#include "aacenc_pns.h" + +#define THR_SHIFTBITS 4 +#define PCM_QUANT_THR_SCALE 16 +#define BITS_PER_LINE_SHIFT 3 + +#define C_RATIO \ + (FIXP_DBL)0x02940a10 /* FL2FXCONST_DBL(0.001258925f) << THR_SHIFTBITS; */ /* pow(10.0f, -(29.0f/10.0f)) */ + +typedef struct { + INT sfbCnt; /* number of existing sf bands */ + INT sfbActive; /* number of sf bands containing energy after lowpass */ + INT sfbActiveLFE; + INT sfbOffset[MAX_SFB + 1]; + + INT filterbank; /* LC, LD or ELD */ + + FIXP_DBL sfbPcmQuantThreshold[MAX_SFB]; + + INT maxAllowedIncreaseFactor; /* preecho control */ + FIXP_SGL minRemainingThresholdFactor; + + INT lowpassLine; + INT lowpassLineLFE; + FIXP_DBL clipEnergy; /* for level dependend tmn */ + + FIXP_DBL sfbMaskLowFactor[MAX_SFB]; + FIXP_DBL sfbMaskHighFactor[MAX_SFB]; + + FIXP_DBL sfbMaskLowFactorSprEn[MAX_SFB]; + FIXP_DBL sfbMaskHighFactorSprEn[MAX_SFB]; + + FIXP_DBL sfbMinSnrLdData[MAX_SFB]; /* minimum snr (formerly known as bmax) */ + + TNS_CONFIG tnsConf; + PNS_CONFIG pnsConf; + + INT granuleLength; + INT allowIS; + INT allowMS; +} PSY_CONFIGURATION; + +typedef struct { + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR sfbWidth[MAX_SFB_LONG]; /* Width of scalefactor bands for long blocks */ +} SFB_PARAM_LONG; + +typedef struct { + UCHAR sfbCnt; /* Number of scalefactor bands */ + UCHAR + sfbWidth[MAX_SFB_SHORT]; /* Width of scalefactor bands for short blocks */ +} SFB_PARAM_SHORT; + +AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate, + INT bandwidth, INT blocktype, + INT granuleLength, INT useIS, + INT useMS, + PSY_CONFIGURATION *psyConf, + FB_TYPE filterbank); + +#endif /* PSY_CONFIGURATION_H */ diff --git a/fdk-aac/libAACenc/src/psy_const.h b/fdk-aac/libAACenc/src/psy_const.h new file mode 100644 index 0000000..c3f3f64 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_const.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Global psychoaccoustic constants + +*******************************************************************************/ + +#ifndef PSY_CONST_H +#define PSY_CONST_H + +#define TRUE 1 +#define FALSE 0 + +#define TRANS_FAC 8 /* encoder short long ratio */ + +#define FRAME_LEN_LONG_960 (960) +#define FRAME_MAXLEN_SHORT ((1024) / TRANS_FAC) +#define FRAME_LEN_SHORT_128 ((1024) / TRANS_FAC) +#define FRAME_LEN_SHORT_120 (FRAME_LEN_LONG_960 / TRANS_FAC) + +/* Filterbank type*/ +enum FB_TYPE { FB_LC = 0, FB_LD = 1, FB_ELD = 2 }; + +/* Block types */ +#define N_BLOCKTYPES 6 +enum { + LONG_WINDOW = 0, + START_WINDOW, + SHORT_WINDOW, + STOP_WINDOW, + _LOWOV_WINDOW, /* Do not use this block type out side of block_switch.cpp */ + WRONG_WINDOW +}; + +/* Window shapes */ +enum { + SINE_WINDOW = 0, + KBD_WINDOW = 1, + LOL_WINDOW = 2 /* Low OverLap window shape for AAC-LD */ +}; + +/* + MS stuff +*/ +enum { SI_MS_MASK_NONE = 0, SI_MS_MASK_SOME = 1, SI_MS_MASK_ALL = 2 }; + +#define MAX_NO_OF_GROUPS 4 +#define MAX_SFB_LONG \ + 51 /* 51 for a memory optimized implementation, maybe 64 for convenient \ + debugging */ +#define MAX_SFB_SHORT \ + 15 /* 15 for a memory optimized implementation, maybe 16 for convenient \ + debugging */ + +#define MAX_SFB \ + (MAX_SFB_SHORT > MAX_SFB_LONG ? MAX_SFB_SHORT : MAX_SFB_LONG) /* = 51 */ +#define MAX_GROUPED_SFB \ + (MAX_NO_OF_GROUPS * MAX_SFB_SHORT > MAX_SFB_LONG \ + ? MAX_NO_OF_GROUPS * MAX_SFB_SHORT \ + : MAX_SFB_LONG) /* = 60 */ + +#define MAX_INPUT_BUFFER_SIZE (2 * (1024)) /* 2048 */ + +#define PCM_LEVEL 1.0f +#define NORM_PCM (PCM_LEVEL / 32768.0f) +#define NORM_PCM_ENERGY (NORM_PCM * NORM_PCM) +#define LOG_NORM_PCM -15 + +#define TNS_PREDGAIN_SCALE (1000) + +#define LFE_LOWPASS_LINE 12 +#define LFE_LOWPASS_LINE_MIN 4 + +#endif /* PSY_CONST_H */ diff --git a/fdk-aac/libAACenc/src/psy_data.h b/fdk-aac/libAACenc/src/psy_data.h new file mode 100644 index 0000000..fc04734 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_data.h @@ -0,0 +1,169 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic data + +*******************************************************************************/ + +#ifndef PSY_DATA_H +#define PSY_DATA_H + +#include "block_switch.h" +#include "mdct.h" + +/* Be careful with MAX_SFB_LONG as length of the .Long arrays. + * sfbEnergy.Long and sfbEnergyMS.Long and sfbThreshold.Long are used as a + * temporary storage for the regrouped short energies and thresholds between + * FDKaacEnc_groupShortData() and BuildInterface() in FDKaacEnc_psyMain(). The + * space required for this is MAX_GROUPED_SFB ( = MAX_NO_OF_GROUPS*MAX_SFB_SHORT + * ). However, this is not important if unions are used (which is not possible + * with pfloat). */ + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_THRESHOLD; + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_ENERGY; + +typedef shouldBeUnion { + FIXP_DBL Long[MAX_GROUPED_SFB]; + FIXP_DBL Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_LD_ENERGY; + +typedef shouldBeUnion { + INT Long[MAX_GROUPED_SFB]; + INT Short[TRANS_FAC][MAX_SFB_SHORT]; +} +SFB_MAX_SCALE; + +typedef struct { + INT_PCM* psyInputBuffer; + FIXP_DBL overlapAddBuffer[3 * 512 / 2]; + + mdct_t mdctPers; /* MDCT persistent data */ + BLOCK_SWITCHING_CONTROL blockSwitchingControl; /* block switching */ + FIXP_DBL sfbThresholdnm1[MAX_SFB]; /* FDKaacEnc_PreEchoControl */ + INT mdctScalenm1; /* scale of last block's mdct (FDKaacEnc_PreEchoControl) */ + INT calcPreEcho; + INT isLFE; +} PSY_STATIC; + +typedef struct { + FIXP_DBL* mdctSpectrum; + SFB_THRESHOLD sfbThreshold; /* adapt */ + SFB_ENERGY sfbEnergy; /* sfb energies */ + SFB_LD_ENERGY sfbEnergyLdData; /* sfb energies in ldData format */ + SFB_MAX_SCALE sfbMaxScaleSpec; + SFB_ENERGY sfbEnergyMS; /* mid/side sfb energies */ + FIXP_DBL sfbEnergyMSLdData[MAX_GROUPED_SFB]; /* mid/side sfb energies in + ldData format */ + SFB_ENERGY sfbSpreadEnergy; + INT mdctScale; /* exponent of data in mdctSpectrum */ + INT groupedSfbOffset[MAX_GROUPED_SFB + 1]; + INT sfbActive; + INT lowpassLine; +} PSY_DATA; + +#endif /* PSY_DATA_H */ diff --git a/fdk-aac/libAACenc/src/psy_main.cpp b/fdk-aac/libAACenc/src/psy_main.cpp new file mode 100644 index 0000000..f6345e4 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_main.cpp @@ -0,0 +1,1348 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic major function block + +*******************************************************************************/ + +#include "psy_const.h" + +#include "block_switch.h" +#include "transform.h" +#include "spreading.h" +#include "pre_echo_control.h" +#include "band_nrg.h" +#include "psy_configuration.h" +#include "psy_data.h" +#include "ms_stereo.h" +#include "interface.h" +#include "psy_main.h" +#include "grp_data.h" +#include "tns_func.h" +#include "pns_func.h" +#include "tonality.h" +#include "aacEnc_ram.h" +#include "intensity.h" + +/* blending to reduce gibbs artifacts */ +#define FADE_OUT_LEN 6 +static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = { + 1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016}; + +/* forward definitions */ + +/***************************************************************************** + + functionname: FDKaacEnc_PsyNew + description: allocates memory for psychoacoustic + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, const INT nElements, + const INT nChannels, UCHAR *dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + PSY_INTERNAL *hPsy; + INT i; + + hPsy = GetRam_aacEnc_PsyInternal(); + *phpsy = hPsy; + if (hPsy == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + + for (i = 0; i < nElements; i++) { + /* PSY_ELEMENT */ + hPsy->psyElement[i] = GetRam_aacEnc_PsyElement(i); + if (hPsy->psyElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + for (i = 0; i < nChannels; i++) { + /* PSY_STATIC */ + hPsy->pStaticChannels[i] = GetRam_aacEnc_PsyStatic(i); + if (hPsy->pStaticChannels[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + /* AUDIO INPUT BUFFER */ + hPsy->pStaticChannels[i]->psyInputBuffer = GetRam_aacEnc_PsyInputBuffer(i); + if (hPsy->pStaticChannels[i]->psyInputBuffer == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + /* reusable psych memory */ + hPsy->psyDynamic = GetRam_aacEnc_PsyDynamic(0, dynamic_RAM); + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(phpsy, NULL); + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_PsyOutNew + description: allocates memory for psyOut struc + returns: an error code + input: pointer to a psych handle + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n = 0; n < nSubFrames; n++) { + phpsyOut[n] = GetRam_aacEnc_PsyOut(n); + + if (phpsyOut[n] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + + for (i = 0; i < nChannels; i++) { + phpsyOut[n]->pPsyOutChannels[i] = GetRam_aacEnc_PsyOutChannel(chInc++); + if (NULL == phpsyOut[n]->pPsyOutChannels[i]) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + + for (i = 0; i < nElements; i++) { + phpsyOut[n]->psyOutElement[i] = GetRam_aacEnc_PsyOutElements(elInc++); + if (phpsyOut[n]->psyOutElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto bail; + } + } + } /* nSubFrames */ + + return AAC_ENC_OK; + +bail: + FDKaacEnc_PsyClose(NULL, phpsyOut); + return ErrorStatus; +} + +AAC_ENCODER_ERROR FDKaacEnc_psyInitStates(PSY_INTERNAL *hPsy, + PSY_STATIC *psyStatic, + AUDIO_OBJECT_TYPE audioObjectType) { + /* init input buffer */ + FDKmemclear(psyStatic->psyInputBuffer, + MAX_INPUT_BUFFER_SIZE * sizeof(INT_PCM)); + + FDKaacEnc_InitBlockSwitching(&psyStatic->blockSwitchingControl, + isLowDelay(audioObjectType)); + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + int i, ch, n, chInc = 0, resetChannels = 3; + + if ((nMaxChannels > 2) && (cm->nChannels == 2)) { + chInc = 1; + FDKaacEnc_psyInitStates(hPsy, hPsy->pStaticChannels[0], audioObjectType); + } + + if ((nMaxChannels == 2)) { + resetChannels = 0; + } + + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[chInc]; + if (cm->elInfo[i].elType != ID_LFE) { + if (chInc >= resetChannels) { + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], + audioObjectType); + } + mdct_init(&(hPsy->psyElement[i]->psyStatic[ch]->mdctPers), NULL, 0); + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 0; + } else { + hPsy->psyElement[i]->psyStatic[ch]->isLFE = 1; + } + chInc++; + } + } + + for (n = 0; n < nSubFrames; n++) { + chInc = 0; + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + phpsyOut[n]->psyOutElement[i]->psyOutChannel[ch] = + phpsyOut[n]->pPsyOutChannels[chInc++]; + } + } + } + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_psyMainInit + description: initializes psychoacoustic + returns: an error code + +*****************************************************************************/ + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit( + PSY_INTERNAL *hPsy, AUDIO_OBJECT_TYPE audioObjectType, CHANNEL_MAPPING *cm, + INT sampleRate, INT granuleLength, INT bitRate, INT tnsMask, INT bandwidth, + INT usePns, INT useIS, INT useMS, UINT syntaxFlags, ULONG initFlags) { + AAC_ENCODER_ERROR ErrorStatus; + int i, ch; + int channelsEff = cm->nChannelsEff; + int tnsChannels = 0; + FB_TYPE filterBank; + + switch (FDKaacEnc_GetMonoStereoMode(cm->encMode)) { + /* ... and map to tnsChannels */ + case EL_MODE_MONO: + tnsChannels = 1; + break; + case EL_MODE_STEREO: + tnsChannels = 2; + break; + default: + tnsChannels = 0; + } + + switch (audioObjectType) { + default: + filterBank = FB_LC; + break; + case AOT_ER_AAC_LD: + filterBank = FB_LD; + break; + case AOT_ER_AAC_ELD: + filterBank = FB_ELD; + break; + } + + hPsy->granuleLength = granuleLength; + + ErrorStatus = FDKaacEnc_InitPsyConfiguration( + bitRate / channelsEff, sampleRate, bandwidth, LONG_WINDOW, + hPsy->granuleLength, useIS, useMS, &(hPsy->psyConf[0]), filterBank); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels, + LONG_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType), + (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &(hPsy->psyConf[0].tnsConf), + &hPsy->psyConf[0], (INT)(tnsMask & 2), (INT)(tnsMask & 8)); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + if (granuleLength > 512) { + ErrorStatus = FDKaacEnc_InitPsyConfiguration( + bitRate / channelsEff, sampleRate, bandwidth, SHORT_WINDOW, + hPsy->granuleLength, useIS, useMS, &hPsy->psyConf[1], filterBank); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + ErrorStatus = FDKaacEnc_InitTnsConfiguration( + (bitRate * tnsChannels) / channelsEff, sampleRate, tnsChannels, + SHORT_WINDOW, hPsy->granuleLength, isLowDelay(audioObjectType), + (syntaxFlags & AC_SBR_PRESENT) ? 1 : 0, &hPsy->psyConf[1].tnsConf, + &hPsy->psyConf[1], (INT)(tnsMask & 1), (INT)(tnsMask & 4)); + + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + } + + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + if (initFlags) { + /* reset states */ + FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], + audioObjectType); + } + + FDKaacEnc_InitPreEchoControl( + hPsy->psyElement[i]->psyStatic[ch]->sfbThresholdnm1, + &hPsy->psyElement[i]->psyStatic[ch]->calcPreEcho, + hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbPcmQuantThreshold, + &hPsy->psyElement[i]->psyStatic[ch]->mdctScalenm1); + } + } + + ErrorStatus = FDKaacEnc_InitPnsConfiguration( + &hPsy->psyConf[0].pnsConf, bitRate / channelsEff, sampleRate, usePns, + hPsy->psyConf[0].sfbCnt, hPsy->psyConf[0].sfbOffset, + cm->elInfo[0].nChannelsInEl, (hPsy->psyConf[0].filterbank == FB_LC)); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + + if (granuleLength > 512) { + ErrorStatus = FDKaacEnc_InitPnsConfiguration( + &hPsy->psyConf[1].pnsConf, bitRate / channelsEff, sampleRate, usePns, + hPsy->psyConf[1].sfbCnt, hPsy->psyConf[1].sfbOffset, + cm->elInfo[1].nChannelsInEl, (hPsy->psyConf[1].filterbank == FB_LC)); + if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; + } + + return ErrorStatus; +} + +/***************************************************************************** + + functionname: FDKaacEnc_psyMain + description: psychoacoustic + returns: an error code + + This function assumes that enough input data is in the modulo buffer. + +*****************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, PSY_ELEMENT *psyElement, + PSY_DYNAMIC *psyDynamic, + PSY_CONFIGURATION *psyConf, + PSY_OUT_ELEMENT *RESTRICT psyOutElement, + INT_PCM *pInput, const UINT inputBufSize, + INT *chIdx, INT totalChannels) { + const INT commonWindow = 1; + INT maxSfbPerGroup[(2)]; + INT mdctSpectrum_e; + INT ch; /* counts through channels */ + INT w; /* counts through windows */ + INT sfb; /* counts through scalefactor bands */ + INT line; /* counts through lines */ + + PSY_CONFIGURATION *RESTRICT hPsyConfLong = &psyConf[0]; + PSY_CONFIGURATION *RESTRICT hPsyConfShort = &psyConf[1]; + PSY_OUT_CHANNEL **RESTRICT psyOutChannel = psyOutElement->psyOutChannel; + FIXP_SGL sfbTonality[(2)][MAX_SFB_LONG]; + + PSY_STATIC **RESTRICT psyStatic = psyElement->psyStatic; + + PSY_DATA *RESTRICT psyData[(2)]; + TNS_DATA *RESTRICT tnsData[(2)]; + PNS_DATA *RESTRICT pnsData[(2)]; + + INT zeroSpec = TRUE; /* means all spectral lines are zero */ + + INT blockSwitchingOffset; + + PSY_CONFIGURATION *RESTRICT hThisPsyConf[(2)]; + INT windowLength[(2)]; + INT nWindows[(2)]; + INT wOffset; + + INT maxSfb[(2)]; + INT *pSfbMaxScaleSpec[(2)]; + FIXP_DBL *pSfbEnergy[(2)]; + FIXP_DBL *pSfbSpreadEnergy[(2)]; + FIXP_DBL *pSfbEnergyLdData[(2)]; + FIXP_DBL *pSfbEnergyMS[(2)]; + FIXP_DBL *pSfbThreshold[(2)]; + + INT isShortWindow[(2)]; + + /* number of incoming time samples to be processed */ + const INT nTimeSamples = psyConf->granuleLength; + + switch (hPsyConfLong->filterbank) { + case FB_LC: + blockSwitchingOffset = + nTimeSamples + (9 * nTimeSamples / (2 * TRANS_FAC)); + break; + case FB_LD: + case FB_ELD: + blockSwitchingOffset = nTimeSamples; + break; + default: + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + + for (ch = 0; ch < channels; ch++) { + psyData[ch] = &psyDynamic->psyData[ch]; + tnsData[ch] = &psyDynamic->tnsData[ch]; + pnsData[ch] = &psyDynamic->pnsData[ch]; + + psyData[ch]->mdctSpectrum = psyOutChannel[ch]->mdctSpectrum; + } + + /* block switching */ + if (hPsyConfLong->filterbank != FB_ELD) { + int err; + + for (ch = 0; ch < channels; ch++) { + C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024)) + + /* copy input data and use for block switching */ + FDKmemcpy(pTimeSignal, pInput + chIdx[ch] * inputBufSize, + nTimeSamples * sizeof(INT_PCM)); + + FDKaacEnc_BlockSwitching(&psyStatic[ch]->blockSwitchingControl, + nTimeSamples, psyStatic[ch]->isLFE, pTimeSignal); + + /* fill up internal input buffer, to 2xframelength samples */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset, + pTimeSignal, + (2 * nTimeSamples - blockSwitchingOffset) * sizeof(INT_PCM)); + + C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024)) + } + + /* synch left and right block type */ + err = FDKaacEnc_SyncBlockSwitching( + &psyStatic[0]->blockSwitchingControl, + (channels > 1) ? &psyStatic[1]->blockSwitchingControl : NULL, channels, + commonWindow); + + if (err) { + return AAC_ENC_UNSUPPORTED_AOT; /* mixed up LC and LD */ + } + + } else { + for (ch = 0; ch < channels; ch++) { + /* copy input data and use for block switching */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + blockSwitchingOffset, + pInput + chIdx[ch] * inputBufSize, + nTimeSamples * sizeof(INT_PCM)); + } + } + + for (ch = 0; ch < channels; ch++) + isShortWindow[ch] = + (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + SHORT_WINDOW); + + /* set parameters according to window length */ + for (ch = 0; ch < channels; ch++) { + if (isShortWindow[ch]) { + hThisPsyConf[ch] = hPsyConfShort; + windowLength[ch] = psyConf->granuleLength / TRANS_FAC; + nWindows[ch] = TRANS_FAC; + maxSfb[ch] = MAX_SFB_SHORT; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Short[0]; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Short[0]; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Short[0]; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Short[0]; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Short[0]; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Short[0]; + + } else { + hThisPsyConf[ch] = hPsyConfLong; + windowLength[ch] = psyConf->granuleLength; + nWindows[ch] = 1; + maxSfb[ch] = MAX_GROUPED_SFB; + + pSfbMaxScaleSpec[ch] = psyData[ch]->sfbMaxScaleSpec.Long; + pSfbEnergy[ch] = psyData[ch]->sfbEnergy.Long; + pSfbSpreadEnergy[ch] = psyData[ch]->sfbSpreadEnergy.Long; + pSfbEnergyLdData[ch] = psyData[ch]->sfbEnergyLdData.Long; + pSfbEnergyMS[ch] = psyData[ch]->sfbEnergyMS.Long; + pSfbThreshold[ch] = psyData[ch]->sfbThreshold.Long; + } + } + + /* Transform and get mdctScaling for all channels and windows. */ + for (ch = 0; ch < channels; ch++) { + /* update number of active bands */ + if (psyStatic[ch]->isLFE) { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActiveLFE; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLineLFE; + } else { + psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActive; + psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLine; + } + + if (hThisPsyConf[ch]->filterbank == FB_ELD) { + if (FDKaacEnc_Transform_Real_Eld( + psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyStatic[ch]->blockSwitchingControl.windowShape, + &psyStatic[ch]->blockSwitchingControl.lastWindowShape, + nTimeSamples, &mdctSpectrum_e, hThisPsyConf[ch]->filterbank, + psyStatic[ch]->overlapAddBuffer) != 0) { + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + } else { + if (FDKaacEnc_Transform_Real( + psyStatic[ch]->psyInputBuffer, psyData[ch]->mdctSpectrum, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyStatic[ch]->blockSwitchingControl.windowShape, + &psyStatic[ch]->blockSwitchingControl.lastWindowShape, + &psyStatic[ch]->mdctPers, nTimeSamples, &mdctSpectrum_e, + hThisPsyConf[ch]->filterbank) != 0) { + return AAC_ENC_UNSUPPORTED_FILTERBANK; + } + } + + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + + /* Low pass / highest sfb */ + FDKmemclear( + &psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset], + (windowLength[ch] - psyData[ch]->lowpassLine) * sizeof(FIXP_DBL)); + + if ((hPsyConfLong->filterbank != FB_LC) && + (psyData[ch]->lowpassLine >= FADE_OUT_LEN)) { + /* Do blending to reduce gibbs artifacts */ + for (int i = 0; i < FADE_OUT_LEN; i++) { + psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + wOffset - + FADE_OUT_LEN + i] = + fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine + + wOffset - FADE_OUT_LEN + i], + fadeOutFactor[i]); + } + } + + /* Check for zero spectrum. These loops will usually terminate very, very + * early. */ + for (line = 0; (line < psyData[ch]->lowpassLine) && (zeroSpec == TRUE); + line++) { + if (psyData[ch]->mdctSpectrum[line + wOffset] != (FIXP_DBL)0) { + zeroSpec = FALSE; + break; + } + } + + } /* w loop */ + + psyData[ch]->mdctScale = mdctSpectrum_e; + + /* rotate internal time samples */ + FDKmemmove(psyStatic[ch]->psyInputBuffer, + psyStatic[ch]->psyInputBuffer + nTimeSamples, + nTimeSamples * sizeof(INT_PCM)); + + /* ... and get remaining samples from input buffer */ + FDKmemcpy(psyStatic[ch]->psyInputBuffer + nTimeSamples, + pInput + (2 * nTimeSamples - blockSwitchingOffset) + + chIdx[ch] * inputBufSize, + (blockSwitchingOffset - nTimeSamples) * sizeof(INT_PCM)); + + } /* ch */ + + /* Do some rescaling to get maximum possible accuracy for energies */ + if (zeroSpec == FALSE) { + /* Calc possible spectrum leftshift for each sfb (1 means: 1 bit left shift + * is possible without overflow) */ + INT minSpecShift = MAX_SHIFT_DBL; + INT nrgShift = MAX_SHIFT_DBL; + INT finalShift = MAX_SHIFT_DBL; + FIXP_DBL currNrg = 0; + FIXP_DBL maxNrg = 0; + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + FDKaacEnc_CalcSfbMaxScaleSpec( + psyData[ch]->mdctSpectrum + wOffset, hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], psyData[ch]->sfbActive); + + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) + minSpecShift = fixMin(minSpecShift, + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb]); + } + } + + /* Calc possible energy leftshift for each sfb (1 means: 1 bit left shift is + * possible without overflow) */ + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + currNrg = FDKaacEnc_CheckBandEnergyOptim( + psyData[ch]->mdctSpectrum + wOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], hThisPsyConf[ch]->sfbOffset, + psyData[ch]->sfbActive, pSfbEnergy[ch] + w * maxSfb[ch], + pSfbEnergyLdData[ch] + w * maxSfb[ch], minSpecShift - 4); + + maxNrg = fixMax(maxNrg, currNrg); + } + } + + if (maxNrg != (FIXP_DBL)0) { + nrgShift = (CountLeadingBits(maxNrg) >> 1) + (minSpecShift - 4); + } + + /* 2check: Hasn't this decision to be made for both channels? */ + /* For short windows 1 additional bit headroom is necessary to prevent + * overflows when summing up energies in FDKaacEnc_groupShortData() */ + if (isShortWindow[0]) nrgShift--; + + /* both spectrum and energies mustn't overflow */ + finalShift = fixMin(minSpecShift, nrgShift); + + /* do not shift more than 3 bits more to the left than signal without + * blockfloating point would be to avoid overflow of scaled PCM quantization + * thresholds */ + if (finalShift > psyData[0]->mdctScale + 3) + finalShift = psyData[0]->mdctScale + 3; + + FDK_ASSERT(finalShift >= 0); /* right shift is not allowed */ + + /* correct sfbEnergy and sfbEnergyLdData with new finalShift */ + FIXP_DBL ldShift = finalShift * FL2FXCONST_DBL(2.0 / 64); + for (ch = 0; ch < channels; ch++) { + INT maxSfb_ch = maxSfb[ch]; + INT w_maxSfb_ch = 0; + for (w = 0; w < nWindows[ch]; w++) { + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + INT scale = fixMax(0, (pSfbMaxScaleSpec[ch] + w_maxSfb_ch)[sfb] - 4); + scale = fixMin((scale - finalShift) << 1, DFRACT_BITS - 1); + if (scale >= 0) + (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] >>= (scale); + else + (pSfbEnergy[ch] + w_maxSfb_ch)[sfb] <<= (-scale); + (pSfbThreshold[ch] + w_maxSfb_ch)[sfb] = + fMult((pSfbEnergy[ch] + w_maxSfb_ch)[sfb], C_RATIO); + (pSfbEnergyLdData[ch] + w_maxSfb_ch)[sfb] += ldShift; + } + w_maxSfb_ch += maxSfb_ch; + } + } + + if (finalShift != 0) { + for (ch = 0; ch < channels; ch++) { + INT wLen = windowLength[ch]; + INT lowpassLine = psyData[ch]->lowpassLine; + wOffset = 0; + FIXP_DBL *mdctSpectrum = &psyData[ch]->mdctSpectrum[0]; + for (w = 0; w < nWindows[ch]; w++) { + FIXP_DBL *spectrum = &mdctSpectrum[wOffset]; + for (line = 0; line < lowpassLine; line++) { + spectrum[line] <<= finalShift; + } + wOffset += wLen; + + /* update sfbMaxScaleSpec */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] -= finalShift; + } + /* update mdctScale */ + psyData[ch]->mdctScale -= finalShift; + } + } + + } else { + /* all spectral lines are zero */ + for (ch = 0; ch < channels; ch++) { + psyData[ch]->mdctScale = + 0; /* otherwise mdctScale would be for example 7 and PCM quantization + * thresholds would be shifted 14 bits to the right causing some of + * them to become 0 (which causes problems later) */ + /* clear sfbMaxScaleSpec */ + for (w = 0; w < nWindows[ch]; w++) { + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + (pSfbMaxScaleSpec[ch] + w * maxSfb[ch])[sfb] = 0; + (pSfbEnergy[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0; + (pSfbEnergyLdData[ch] + w * maxSfb[ch])[sfb] = FL2FXCONST_DBL(-1.0f); + (pSfbThreshold[ch] + w * maxSfb[ch])[sfb] = (FIXP_DBL)0; + } + } + } + } + + /* Advance psychoacoustics: Tonality and TNS */ + if ((channels >= 1) && (psyStatic[0]->isLFE)) { + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0; + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0; + } else { + for (ch = 0; ch < channels; ch++) { + if (!isShortWindow[ch]) { + /* tonality */ + FDKaacEnc_CalculateFullTonality( + psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch], + pSfbEnergyLdData[ch], sfbTonality[ch], psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbOffset, hThisPsyConf[ch]->pnsConf.usePns); + } + } /* ch */ + + if (hPsyConfLong->tnsConf.tnsActive || hPsyConfShort->tnsConf.tnsActive) { + INT tnsActive[TRANS_FAC] = {0}; + INT nrgScaling[2] = {0, 0}; + INT tnsSpecShift = 0; + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + /* TNS */ + FDKaacEnc_TnsDetect( + tnsData[ch], &hThisPsyConf[ch]->tnsConf, + &psyOutChannel[ch]->tnsInfo, hThisPsyConf[ch]->sfbCnt, + psyData[ch]->mdctSpectrum + wOffset, w, + psyStatic[ch]->blockSwitchingControl.lastWindowSequence); + } + } + + if (channels == 2) { + FDKaacEnc_TnsSync( + tnsData[1], tnsData[0], &psyOutChannel[1]->tnsInfo, + &psyOutChannel[0]->tnsInfo, + + psyStatic[1]->blockSwitchingControl.lastWindowSequence, + psyStatic[0]->blockSwitchingControl.lastWindowSequence, + &hThisPsyConf[1]->tnsConf); + } + + if (channels >= 1) { + FDK_ASSERT(1 == commonWindow); /* all checks for TNS do only work for + common windows (which is always set)*/ + for (w = 0; w < nWindows[0]; w++) { + if (isShortWindow[0]) + tnsActive[w] = + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] || + tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] || + tnsData[channels - 1] + ->dataRaw.Short.subBlockInfo[w] + .tnsActive[HIFILT] || + tnsData[channels - 1] + ->dataRaw.Short.subBlockInfo[w] + .tnsActive[LOFILT]; + else + tnsActive[w] = + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] || + tnsData[channels - 1] + ->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] || + tnsData[channels - 1] + ->dataRaw.Long.subBlockInfo.tnsActive[LOFILT]; + } + } + + for (ch = 0; ch < channels; ch++) { + if (tnsActive[0] && !isShortWindow[ch]) { + /* Scale down spectrum if tns is active in one of the two channels + * with same lastWindowSequence */ + /* first part of threshold calculation; it's not necessary to update + * sfbMaxScaleSpec */ + INT shift = 1; + for (sfb = 0; sfb < hThisPsyConf[ch]->lowpassLine; sfb++) { + psyData[ch]->mdctSpectrum[sfb] = + psyData[ch]->mdctSpectrum[sfb] >> shift; + } + + /* update thresholds */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + pSfbThreshold[ch][sfb] >>= (2 * shift); + } + + psyData[ch]->mdctScale += shift; /* update mdctScale */ + + /* calc sfbEnergies after tnsEncode again ! */ + } + } + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + wOffset = w * windowLength[ch]; + FDKaacEnc_TnsEncode( + &psyOutChannel[ch]->tnsInfo, tnsData[ch], + hThisPsyConf[ch]->sfbCnt, &hThisPsyConf[ch]->tnsConf, + hThisPsyConf[ch]->sfbOffset[psyData[ch]->sfbActive], + /*hThisPsyConf[ch]->lowpassLine*/ /* filter stops + before that + line ! */ + psyData[ch]->mdctSpectrum + + wOffset, + w, psyStatic[ch]->blockSwitchingControl.lastWindowSequence); + + if (tnsActive[w]) { + /* Calc sfb-bandwise mdct-energies for left and right channel again, + */ + /* if tns active in current channel or in one channel with same + * lastWindowSequence left and right */ + FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum + wOffset, + hThisPsyConf[ch]->sfbOffset, + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], + psyData[ch]->sfbActive); + } + } + } + + for (ch = 0; ch < channels; ch++) { + for (w = 0; w < nWindows[ch]; w++) { + if (tnsActive[w]) { + if (isShortWindow[ch]) { + FDKaacEnc_CalcBandEnergyOptimShort( + psyData[ch]->mdctSpectrum + w * windowLength[ch], + pSfbMaxScaleSpec[ch] + w * maxSfb[ch], + hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive, + pSfbEnergy[ch] + w * maxSfb[ch]); + } else { + nrgScaling[ch] = /* with tns, energy calculation can overflow; -> + scaling */ + FDKaacEnc_CalcBandEnergyOptimLong( + psyData[ch]->mdctSpectrum, pSfbMaxScaleSpec[ch], + hThisPsyConf[ch]->sfbOffset, psyData[ch]->sfbActive, + pSfbEnergy[ch], pSfbEnergyLdData[ch]); + tnsSpecShift = + fixMax(tnsSpecShift, nrgScaling[ch]); /* nrgScaling is set + only if nrg would + have an overflow */ + } + } /* if tnsActive */ + } + } /* end channel loop */ + + /* adapt scaling to prevent nrg overflow, only for long blocks */ + for (ch = 0; ch < channels; ch++) { + if ((tnsSpecShift != 0) && !isShortWindow[ch]) { + /* scale down spectrum, nrg's and thresholds, if there was an overflow + * in sfbNrg calculation after tns */ + for (line = 0; line < hThisPsyConf[ch]->lowpassLine; line++) { + psyData[ch]->mdctSpectrum[line] >>= tnsSpecShift; + } + INT scale = (tnsSpecShift - nrgScaling[ch]) << 1; + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + pSfbEnergyLdData[ch][sfb] -= + scale * FL2FXCONST_DBL(1.0 / LD_DATA_SCALING); + pSfbEnergy[ch][sfb] >>= scale; + pSfbThreshold[ch][sfb] >>= (tnsSpecShift << 1); + } + psyData[ch]->mdctScale += tnsSpecShift; /* update mdctScale; not + necessary to update + sfbMaxScaleSpec */ + } + } /* end channel loop */ + + } /* TNS active */ + else { + /* In case of disable TNS, reset its dynamic data. Some of its elements is + * required in PNS detection below. */ + FDKmemclear(psyDynamic->tnsData, sizeof(psyDynamic->tnsData)); + } + } /* !isLFE */ + + /* Advance thresholds */ + for (ch = 0; ch < channels; ch++) { + INT headroom; + + FIXP_DBL clipEnergy; + INT energyShift = psyData[ch]->mdctScale * 2; + INT clipNrgShift = energyShift - THR_SHIFTBITS; + if (isShortWindow[ch]) + headroom = 6; + else + headroom = 0; + + if (clipNrgShift >= 0) + clipEnergy = hThisPsyConf[ch]->clipEnergy >> clipNrgShift; + else if (clipNrgShift >= -headroom) + clipEnergy = hThisPsyConf[ch]->clipEnergy << -clipNrgShift; + else + clipEnergy = (FIXP_DBL)MAXVAL_DBL; + + for (w = 0; w < nWindows[ch]; w++) { + INT i; + /* limit threshold to avoid clipping */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = + fixMin(*(pSfbThreshold[ch] + w * maxSfb[ch] + i), clipEnergy); + } + + /* spreading */ + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactor, + hThisPsyConf[ch]->sfbMaskHighFactor, + pSfbThreshold[ch] + w * maxSfb[ch]); + + /* PCM quantization threshold */ + energyShift += PCM_QUANT_THR_SCALE; + if (energyShift >= 0) { + energyShift = fixMin(DFRACT_BITS - 1, energyShift); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax( + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] >> energyShift)); + } + } else { + energyShift = fixMin(DFRACT_BITS - 1, -energyShift); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) = fixMax( + *(pSfbThreshold[ch] + w * maxSfb[ch] + i) >> THR_SHIFTBITS, + (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] << energyShift)); + } + } + + if (!psyStatic[ch]->isLFE) { + /* preecho control */ + if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + STOP_WINDOW) { + /* prevent FDKaacEnc_PreEchoControl from comparing stop + thresholds with short thresholds */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + + FDKaacEnc_PreEchoControl( + psyStatic[ch]->sfbThresholdnm1, psyStatic[ch]->calcPreEcho, + psyData[ch]->sfbActive, hThisPsyConf[ch]->maxAllowedIncreaseFactor, + hThisPsyConf[ch]->minRemainingThresholdFactor, + pSfbThreshold[ch] + w * maxSfb[ch], psyData[ch]->mdctScale, + &psyStatic[ch]->mdctScalenm1); + + psyStatic[ch]->calcPreEcho = 1; + + if (psyStatic[ch]->blockSwitchingControl.lastWindowSequence == + START_WINDOW) { + /* prevent FDKaacEnc_PreEchoControl in next frame to compare start + thresholds with short thresholds */ + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL; + } + + psyStatic[ch]->mdctScalenm1 = 0; + psyStatic[ch]->calcPreEcho = 0; + } + } + + /* spread energy to avoid hole detection */ + FDKmemcpy(pSfbSpreadEnergy[ch] + w * maxSfb[ch], + pSfbEnergy[ch] + w * maxSfb[ch], + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive, + hThisPsyConf[ch]->sfbMaskLowFactorSprEn, + hThisPsyConf[ch]->sfbMaskHighFactorSprEn, + pSfbSpreadEnergy[ch] + w * maxSfb[ch]); + } + } + + /* Calc bandwise energies for mid and side channel. Do it only if 2 channels + * exist */ + if (channels == 2) { + for (w = 0; w < nWindows[1]; w++) { + wOffset = w * windowLength[1]; + FDKaacEnc_CalcBandNrgMSOpt( + psyData[0]->mdctSpectrum + wOffset, + psyData[1]->mdctSpectrum + wOffset, + pSfbMaxScaleSpec[0] + w * maxSfb[0], + pSfbMaxScaleSpec[1] + w * maxSfb[1], hThisPsyConf[1]->sfbOffset, + psyData[0]->sfbActive, pSfbEnergyMS[0] + w * maxSfb[0], + pSfbEnergyMS[1] + w * maxSfb[1], + (psyStatic[1]->blockSwitchingControl.lastWindowSequence != + SHORT_WINDOW), + psyData[0]->sfbEnergyMSLdData, psyData[1]->sfbEnergyMSLdData); + } + } + + /* group short data (maxSfb[ch] for short blocks is determined here) */ + for (ch = 0; ch < channels; ch++) { + if (isShortWindow[ch]) { + int sfbGrp; + int noSfb = psyStatic[ch]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt; + /* At this point, energies and thresholds are copied/regrouped from the + * ".Short" to the ".Long" arrays */ + FDKaacEnc_groupShortData( + psyData[ch]->mdctSpectrum, &psyData[ch]->sfbThreshold, + &psyData[ch]->sfbEnergy, &psyData[ch]->sfbEnergyMS, + &psyData[ch]->sfbSpreadEnergy, hPsyConfShort->sfbCnt, + psyData[ch]->sfbActive, hPsyConfShort->sfbOffset, + hPsyConfShort->sfbMinSnrLdData, psyData[ch]->groupedSfbOffset, + &maxSfbPerGroup[ch], psyOutChannel[ch]->sfbMinSnrLdData, + psyStatic[ch]->blockSwitchingControl.noOfGroups, + psyStatic[ch]->blockSwitchingControl.groupLen, + psyConf[1].granuleLength); + + /* calculate ldData arrays (short values are in .Long-arrays after + * FDKaacEnc_groupShortData) */ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergy.Long[sfbGrp], + &psyOutChannel[ch]->sfbEnergyLdData[sfbGrp], + psyData[ch]->sfbActive); + } + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbThreshold.Long[sfbGrp], + &psyOutChannel[ch]->sfbThresholdLdData[sfbGrp], + psyData[ch]->sfbActive); + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb], + FL2FXCONST_DBL(-0.515625f)); + } + } + + if (channels == 2) { + for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) { + LdDataVector(&psyData[ch]->sfbEnergyMS.Long[sfbGrp], + &psyData[ch]->sfbEnergyMSLdData[sfbGrp], + psyData[ch]->sfbActive); + } + } + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, psyData[ch]->groupedSfbOffset, + (MAX_GROUPED_SFB + 1) * sizeof(INT)); + + } else { + int i; + /* maxSfb[ch] for long blocks */ + for (sfb = psyData[ch]->sfbActive - 1; sfb >= 0; sfb--) { + for (line = hPsyConfLong->sfbOffset[sfb + 1] - 1; + line >= hPsyConfLong->sfbOffset[sfb]; line--) { + if (psyData[ch]->mdctSpectrum[line] != FL2FXCONST_SGL(0.0f)) break; + } + if (line > hPsyConfLong->sfbOffset[sfb]) break; + } + maxSfbPerGroup[ch] = sfb + 1; + maxSfbPerGroup[ch] = + fixMax(fixMin(5, psyData[ch]->sfbActive), maxSfbPerGroup[ch]); + + /* sfbNrgLdData is calculated in FDKaacEnc_advancePsychLong, copy in + * psyOut structure */ + FDKmemcpy(psyOutChannel[ch]->sfbEnergyLdData, + psyData[ch]->sfbEnergyLdData.Long, + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + FDKmemcpy(psyOutChannel[ch]->sfbOffsets, hPsyConfLong->sfbOffset, + (MAX_GROUPED_SFB + 1) * sizeof(INT)); + + /* sfbMinSnrLdData modified in adjust threshold, copy necessary */ + FDKmemcpy(psyOutChannel[ch]->sfbMinSnrLdData, + hPsyConfLong->sfbMinSnrLdData, + psyData[ch]->sfbActive * sizeof(FIXP_DBL)); + + /* sfbEnergyMSLdData ist already calculated in FDKaacEnc_CalcBandNrgMSOpt; + * only in long case */ + + /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/ + LdDataVector(psyData[ch]->sfbThreshold.Long, + psyOutChannel[ch]->sfbThresholdLdData, + psyData[ch]->sfbActive); + for (i = 0; i < psyData[ch]->sfbActive; i++) { + psyOutChannel[ch]->sfbThresholdLdData[i] = + fixMax(psyOutChannel[ch]->sfbThresholdLdData[i], + FL2FXCONST_DBL(-0.515625f)); + } + } + } + + /* + Intensity parameter intialization. + */ + for (ch = 0; ch < channels; ch++) { + FDKmemclear(psyOutChannel[ch]->isBook, MAX_GROUPED_SFB * sizeof(INT)); + FDKmemclear(psyOutChannel[ch]->isScale, MAX_GROUPED_SFB * sizeof(INT)); + } + + for (ch = 0; ch < channels; ch++) { + INT win = (isShortWindow[ch] ? 1 : 0); + if (!psyStatic[ch]->isLFE) { + /* PNS Decision */ + FDKaacEnc_PnsDetect( + &(psyConf[0].pnsConf), pnsData[ch], + psyStatic[ch]->blockSwitchingControl.lastWindowSequence, + psyData[ch]->sfbActive, + maxSfbPerGroup[ch], /* count of Sfb which are not zero. */ + psyOutChannel[ch]->sfbThresholdLdData, psyConf[win].sfbOffset, + psyData[ch]->mdctSpectrum, psyData[ch]->sfbMaxScaleSpec.Long, + sfbTonality[ch], psyOutChannel[ch]->tnsInfo.order[0][0], + tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT], + tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT], + psyOutChannel[ch]->sfbEnergyLdData, psyOutChannel[ch]->noiseNrg); + } /* !isLFE */ + } /* ch */ + + /* + stereo Processing + */ + if (channels == 2) { + psyOutElement->toolsInfo.msDigest = MS_NONE; + psyOutElement->commonWindow = commonWindow; + if (psyOutElement->commonWindow) + maxSfbPerGroup[0] = maxSfbPerGroup[1] = + fixMax(maxSfbPerGroup[0], maxSfbPerGroup[1]); + if (psyStatic[0]->blockSwitchingControl.lastWindowSequence != + SHORT_WINDOW) { + /* PNS preprocessing depending on ms processing: PNS not in Short Window! + */ + FDKaacEnc_PreProcessPnsChannelPair( + psyData[0]->sfbActive, (&psyData[0]->sfbEnergy)->Long, + (&psyData[1]->sfbEnergy)->Long, psyOutChannel[0]->sfbEnergyLdData, + psyOutChannel[1]->sfbEnergyLdData, psyData[0]->sfbEnergyMS.Long, + &(psyConf[0].pnsConf), pnsData[0], pnsData[1]); + + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[0].sfbCnt, psyConf[0].sfbCnt, maxSfbPerGroup[0], + psyConf[0].sfbOffset, + psyConf[0].allowIS && psyOutElement->commonWindow, + psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData); + + FDKaacEnc_MsStereoProcessing( + psyData, psyOutChannel, psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[0].allowMS, psyData[0]->sfbActive, psyData[0]->sfbActive, + maxSfbPerGroup[0], psyOutChannel[0]->sfbOffsets); + + /* PNS postprocessing */ + FDKaacEnc_PostProcessPnsChannelPair( + psyData[0]->sfbActive, &(psyConf[0].pnsConf), pnsData[0], pnsData[1], + psyOutElement->toolsInfo.msMask, &psyOutElement->toolsInfo.msDigest); + + } else { + FDKaacEnc_IntensityStereoProcessing( + psyData[0]->sfbEnergy.Long, psyData[1]->sfbEnergy.Long, + psyData[0]->mdctSpectrum, psyData[1]->mdctSpectrum, + psyData[0]->sfbThreshold.Long, psyData[1]->sfbThreshold.Long, + psyOutChannel[1]->sfbThresholdLdData, + psyData[0]->sfbSpreadEnergy.Long, psyData[1]->sfbSpreadEnergy.Long, + psyOutChannel[0]->sfbEnergyLdData, psyOutChannel[1]->sfbEnergyLdData, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyStatic[0]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt, + psyConf[1].sfbCnt, maxSfbPerGroup[0], psyData[0]->groupedSfbOffset, + psyConf[0].allowIS && psyOutElement->commonWindow, + psyOutChannel[1]->isBook, psyOutChannel[1]->isScale, pnsData); + + /* it's OK to pass the ".Long" arrays here. They contain grouped short + * data since FDKaacEnc_groupShortData() */ + FDKaacEnc_MsStereoProcessing( + psyData, psyOutChannel, psyOutChannel[1]->isBook, + &psyOutElement->toolsInfo.msDigest, psyOutElement->toolsInfo.msMask, + psyConf[1].allowMS, + psyStatic[0]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt, + hPsyConfShort->sfbCnt, maxSfbPerGroup[0], + psyOutChannel[0]->sfbOffsets); + } + } /* (channels == 2) */ + + /* + PNS Coding + */ + for (ch = 0; ch < channels; ch++) { + if (psyStatic[ch]->isLFE) { + /* no PNS coding */ + for (sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) { + psyOutChannel[ch]->noiseNrg[sfb] = NO_NOISE_PNS; + } + } else { + FDKaacEnc_CodePnsChannel( + psyData[ch]->sfbActive, &(hThisPsyConf[ch]->pnsConf), + pnsData[ch]->pnsFlag, psyData[ch]->sfbEnergyLdData.Long, + psyOutChannel[ch]->noiseNrg, /* this is the energy that will be + written to the bitstream */ + psyOutChannel[ch]->sfbThresholdLdData); + } + } + + /* + build output + */ + for (ch = 0; ch < channels; ch++) { + INT mask; + int grp; + psyOutChannel[ch]->maxSfbPerGroup = maxSfbPerGroup[ch]; + psyOutChannel[ch]->mdctScale = psyData[ch]->mdctScale; + if (isShortWindow[ch] == 0) { + psyOutChannel[ch]->sfbCnt = hPsyConfLong->sfbActive; + psyOutChannel[ch]->sfbPerGroup = hPsyConfLong->sfbActive; + psyOutChannel[ch]->lastWindowSequence = + psyStatic[ch]->blockSwitchingControl.lastWindowSequence; + psyOutChannel[ch]->windowShape = + psyStatic[ch]->blockSwitchingControl.windowShape; + } else { + INT sfbCnt = psyStatic[ch]->blockSwitchingControl.noOfGroups * + hPsyConfShort->sfbCnt; + + psyOutChannel[ch]->sfbCnt = sfbCnt; + psyOutChannel[ch]->sfbPerGroup = hPsyConfShort->sfbCnt; + psyOutChannel[ch]->lastWindowSequence = SHORT_WINDOW; + psyOutChannel[ch]->windowShape = SINE_WINDOW; + } + /* generate grouping mask */ + mask = 0; + for (grp = 0; grp < psyStatic[ch]->blockSwitchingControl.noOfGroups; + grp++) { + int j; + mask <<= 1; + for (j = 1; j < psyStatic[ch]->blockSwitchingControl.groupLen[grp]; j++) { + mask = (mask << 1) | 1; + } + } + psyOutChannel[ch]->groupingMask = mask; + + /* build interface */ + FDKmemcpy(psyOutChannel[ch]->groupLen, + psyStatic[ch]->blockSwitchingControl.groupLen, + MAX_NO_OF_GROUPS * sizeof(INT)); + FDKmemcpy(psyOutChannel[ch]->sfbEnergy, (&psyData[ch]->sfbEnergy)->Long, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + FDKmemcpy(psyOutChannel[ch]->sfbSpreadEnergy, + (&psyData[ch]->sfbSpreadEnergy)->Long, + MAX_GROUPED_SFB * sizeof(FIXP_DBL)); + // FDKmemcpy(psyOutChannel[ch]->mdctSpectrum, + // psyData[ch]->mdctSpectrum, (1024)*sizeof(FIXP_DBL)); + } + + return AAC_ENC_OK; +} + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, PSY_OUT **phPsyOut) { + int n, i; + + if (phPsyInternal != NULL) { + PSY_INTERNAL *hPsyInternal = *phPsyInternal; + + if (hPsyInternal) { + for (i = 0; i < (8); i++) { + if (hPsyInternal->pStaticChannels[i]) { + if (hPsyInternal->pStaticChannels[i]->psyInputBuffer) + FreeRam_aacEnc_PsyInputBuffer( + &hPsyInternal->pStaticChannels[i] + ->psyInputBuffer); /* AUDIO INPUT BUFFER */ + + FreeRam_aacEnc_PsyStatic( + &hPsyInternal->pStaticChannels[i]); /* PSY_STATIC */ + } + } + + for (i = 0; i < ((8)); i++) { + if (hPsyInternal->psyElement[i]) + FreeRam_aacEnc_PsyElement( + &hPsyInternal->psyElement[i]); /* PSY_ELEMENT */ + } + + FreeRam_aacEnc_PsyInternal(phPsyInternal); + } + } + + if (phPsyOut != NULL) { + for (n = 0; n < (1); n++) { + if (phPsyOut[n]) { + for (i = 0; i < (8); i++) { + if (phPsyOut[n]->pPsyOutChannels[i]) + FreeRam_aacEnc_PsyOutChannel( + &phPsyOut[n]->pPsyOutChannels[i]); /* PSY_OUT_CHANNEL */ + } + + for (i = 0; i < ((8)); i++) { + if (phPsyOut[n]->psyOutElement[i]) + FreeRam_aacEnc_PsyOutElements( + &phPsyOut[n]->psyOutElement[i]); /* PSY_OUT_ELEMENTS */ + } + + FreeRam_aacEnc_PsyOut(&phPsyOut[n]); + } + } + } +} diff --git a/fdk-aac/libAACenc/src/psy_main.h b/fdk-aac/libAACenc/src/psy_main.h new file mode 100644 index 0000000..7cc01a3 --- /dev/null +++ b/fdk-aac/libAACenc/src/psy_main.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Psychoaccoustic major function block + +*******************************************************************************/ + +#ifndef PSY_MAIN_H +#define PSY_MAIN_H + +#include "psy_configuration.h" +#include "qc_data.h" +#include "aacenc_pns.h" + +/* + psych internal +*/ +typedef struct { + PSY_STATIC *psyStatic[(2)]; + +} PSY_ELEMENT; + +typedef struct { + PSY_DATA psyData[(2)]; + TNS_DATA tnsData[(2)]; + PNS_DATA pnsData[(2)]; + +} PSY_DYNAMIC; + +typedef struct { + PSY_CONFIGURATION psyConf[2]; /* LONG / SHORT */ + PSY_ELEMENT *psyElement[((8))]; + PSY_STATIC *pStaticChannels[(8)]; + PSY_DYNAMIC *psyDynamic; + INT granuleLength; + +} PSY_INTERNAL; + +AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL **phpsy, const INT nElements, + const INT nChannels, UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT **phpsyOut, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL *hPsy, PSY_OUT **phpsyOut, + const INT nSubFrames, + const INT nMaxChannels, + const AUDIO_OBJECT_TYPE audioObjectType, + CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_psyMainInit( + PSY_INTERNAL *hPsy, AUDIO_OBJECT_TYPE audioObjectType, CHANNEL_MAPPING *cm, + INT sampleRate, INT granuleLength, INT bitRate, INT tnsMask, INT bandwidth, + INT usePns, INT useIS, INT useMS, UINT syntaxFlags, ULONG initFlags); + +AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT channels, PSY_ELEMENT *psyElement, + PSY_DYNAMIC *psyDynamic, + PSY_CONFIGURATION *psyConf, + PSY_OUT_ELEMENT *psyOutElement, + INT_PCM *pInput, const UINT inputBufSize, + INT *chIdx, INT totalChannels); + +void FDKaacEnc_PsyClose(PSY_INTERNAL **phPsyInternal, PSY_OUT **phPsyOut); + +#endif /* PSY_MAIN_H */ diff --git a/fdk-aac/libAACenc/src/qc_data.h b/fdk-aac/libAACenc/src/qc_data.h new file mode 100644 index 0000000..6e671ed --- /dev/null +++ b/fdk-aac/libAACenc/src/qc_data.h @@ -0,0 +1,299 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding data + +*******************************************************************************/ + +#ifndef QC_DATA_H +#define QC_DATA_H + +#include "aacenc.h" +#include "psy_const.h" +#include "dyn_bits.h" +#include "adj_thr_data.h" +#include "line_pe.h" +#include "FDK_audio.h" +#include "interface.h" + +typedef enum { + QCDATA_BR_MODE_INVALID = -1, + QCDATA_BR_MODE_CBR = 0, /* Constant bit rate, given average bitrate */ + QCDATA_BR_MODE_VBR_1 = 1, /* Variable bit rate, very low */ + QCDATA_BR_MODE_VBR_2 = 2, /* Variable bit rate, low */ + QCDATA_BR_MODE_VBR_3 = 3, /* Variable bit rate, medium */ + QCDATA_BR_MODE_VBR_4 = 4, /* Variable bit rate, high */ + QCDATA_BR_MODE_VBR_5 = 5, /* Variable bit rate, very high */ + QCDATA_BR_MODE_FF = 6, /* Fixed frame mode. */ + QCDATA_BR_MODE_SFR = 7 /* Superframe mode. */ + +} QCDATA_BR_MODE; + +typedef struct { + MP4_ELEMENT_ID elType; + INT instanceTag; + INT nChannelsInEl; + INT ChannelIndex[2]; + FIXP_DBL relativeBits; +} ELEMENT_INFO; + +typedef struct { + CHANNEL_MODE encMode; + INT nChannels; + INT nChannelsEff; + INT nElements; + ELEMENT_INFO elInfo[((8))]; +} CHANNEL_MAPPING; + +typedef struct { + INT paddingRest; +} PADDING; + +/* Quantizing & coding stage */ + +struct QC_INIT { + CHANNEL_MAPPING *channelMapping; + INT sceCpe; /* not used yet */ + INT maxBits; /* maximum number of bits in reservoir */ + INT averageBits; /* average number of bits we should use */ + INT bitRes; + INT sampleRate; /* output sample rate */ + INT isLowDelay; /* if set, calc bits2PE factor depending on samplerate */ + INT staticBits; /* Bits per frame consumed by transport layers. */ + QCDATA_BR_MODE bitrateMode; + INT meanPe; + INT chBitrate; /* Bitrate/channel */ + INT invQuant; + INT maxIterations; /* Maximum number of allowed iterations before + FDKaacEnc_crashRecovery() is applied. */ + FIXP_DBL maxBitFac; + INT bitrate; + INT nSubFrames; /* helper variable */ + INT minBits; /* minimal number of bits in one frame*/ + AACENC_BITRES_MODE bitResMode; /* 0: full bitreservoir, 1: reduced + bitreservoir, 2: disabled bitreservoir */ + INT bitDistributionMode; /* Configure element-wise execution or execution over + all elements for the pe-dependent + threshold-adaption */ + + PADDING padding; +}; + +typedef struct { + FIXP_DBL mdctSpectrum[(1024)]; + + SHORT quantSpec[(1024)]; + + UINT maxValueInSfb[MAX_GROUPED_SFB]; + INT scf[MAX_GROUPED_SFB]; + INT globalGain; + SECTION_DATA sectionData; + + FIXP_DBL sfbFormFactorLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbThresholdLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbMinSnrLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergyLdData[MAX_GROUPED_SFB]; + FIXP_DBL sfbEnergy[MAX_GROUPED_SFB]; + FIXP_DBL sfbWeightedEnergyLdData[MAX_GROUPED_SFB]; + + FIXP_DBL sfbEnFacLd[MAX_GROUPED_SFB]; + + FIXP_DBL sfbSpreadEnergy[MAX_GROUPED_SFB]; + +} QC_OUT_CHANNEL; + +typedef struct { + EXT_PAYLOAD_TYPE type; /* type of the extension payload */ + INT nPayloadBits; /* size of the payload */ + UCHAR *pPayload; /* pointer to payload */ + +} QC_OUT_EXTENSION; + +typedef struct { + INT staticBitsUsed; /* for verification purposes */ + INT dynBitsUsed; /* for verification purposes */ + + INT extBitsUsed; /* bit consumption of extended fill elements */ + INT nExtensions; /* number of extension payloads for this element */ + QC_OUT_EXTENSION extension[(1)]; /* reffering extension payload */ + + INT grantedDynBits; + + INT grantedPe; + INT grantedPeCorr; + + PE_DATA peData; + + QC_OUT_CHANNEL *qcOutChannel[(2)]; + + UCHAR + *dynMem_Ah_Flag; /* pointer to dynamic buffer used by AhFlag in function + FDKaacEnc_adaptThresholdsToPe() */ + UCHAR + *dynMem_Thr_Exp; /* pointer to dynamic buffer used by ThrExp in function + FDKaacEnc_adaptThresholdsToPe() */ + UCHAR *dynMem_SfbNActiveLinesLdData; /* pointer to dynamic buffer used by + sfbNActiveLinesLdData in function + FDKaacEnc_correctThresh() */ + +} QC_OUT_ELEMENT; + +typedef struct { + QC_OUT_ELEMENT *qcElement[((8))]; + QC_OUT_CHANNEL *pQcOutChannels[(8)]; + QC_OUT_EXTENSION extension[(2 + 2)]; /* global extension payload */ + INT nExtensions; /* number of extension payloads for this AU */ + INT maxDynBits; /* maximal allowed dynamic bits in frame */ + INT grantedDynBits; /* granted dynamic bits in frame */ + INT totFillBits; /* fill bits */ + INT elementExtBits; /* element associated extension payload bits, e.g. sbr, + drc ... */ + INT globalExtBits; /* frame/au associated extension payload bits (anc data + ...) */ + INT staticBits; /* aac side info bits */ + + INT totalNoRedPe; + INT totalGrantedPeCorr; + + INT usedDynBits; /* number of dynamic bits in use */ + INT alignBits; /* AU alignment bits */ + INT totalBits; /* sum of static, dyn, sbr, fill, align and dse bits */ + +} QC_OUT; + +typedef struct { + INT chBitrateEl; /* channel bitrate in element + (totalbitrate*el_relativeBits/el_channels) */ + INT maxBitsEl; /* used in crash recovery */ + INT bitResLevelEl; /* update bitreservoir level in each call of + FDKaacEnc_QCMain */ + INT maxBitResBitsEl; /* nEffChannels*6144 - averageBitsInFrame */ + FIXP_DBL relativeBitsEl; /* Bits relative to total Bits*/ +} ELEMENT_BITS; + +typedef struct { + /* this is basically struct QC_INIT */ + + INT globHdrBits; + INT maxBitsPerFrame; /* maximal allowed bits per frame, 6144*nChannelsEff */ + INT minBitsPerFrame; /* minimal allowd bits per fram, superframing - DRM */ + INT nElements; + QCDATA_BR_MODE bitrateMode; + AACENC_BITRES_MODE bitResMode; /* 0: full bitreservoir, 1: reduced + bitreservoir, 2: disabled bitreservoir */ + INT bitResTot; + INT bitResTotMax; + INT maxIterations; /* Maximum number of allowed iterations before + FDKaacEnc_crashRecovery() is applied. */ + INT invQuant; + + FIXP_DBL vbrQualFactor; + FIXP_DBL maxBitFac; + + PADDING padding; + + ELEMENT_BITS *elementBits[((8))]; + BITCNTR_STATE *hBitCounter; + ADJ_THR_STATE *hAdjThr; + + INT dZoneQuantEnable; /* enable dead zone quantizer */ + +} QC_STATE; + +#endif /* QC_DATA_H */ diff --git a/fdk-aac/libAACenc/src/qc_main.cpp b/fdk-aac/libAACenc/src/qc_main.cpp new file mode 100644 index 0000000..0bf234c --- /dev/null +++ b/fdk-aac/libAACenc/src/qc_main.cpp @@ -0,0 +1,1555 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding + +*******************************************************************************/ + +#include "qc_main.h" +#include "quantize.h" +#include "interface.h" +#include "adj_thr.h" +#include "sf_estim.h" +#include "bit_cnt.h" +#include "dyn_bits.h" +#include "channel_map.h" +#include "aacEnc_ram.h" + +#include "genericStds.h" + +#define AACENC_DZQ_BR_THR 32000 /* Dead zone quantizer bitrate threshold */ + +typedef struct { + QCDATA_BR_MODE bitrateMode; + LONG vbrQualFactor; +} TAB_VBR_QUAL_FACTOR; + +static const TAB_VBR_QUAL_FACTOR tableVbrQualFactor[] = { + {QCDATA_BR_MODE_VBR_1, + FL2FXCONST_DBL(0.160f)}, /* Approx. 32 - 48 (AC-LC), 32 - 56 + (AAC-LD/ELD) kbps/channel */ + {QCDATA_BR_MODE_VBR_2, + FL2FXCONST_DBL(0.148f)}, /* Approx. 40 - 56 (AC-LC), 40 - 64 + (AAC-LD/ELD) kbps/channel */ + {QCDATA_BR_MODE_VBR_3, + FL2FXCONST_DBL(0.135f)}, /* Approx. 48 - 64 (AC-LC), 48 - 72 + (AAC-LD/ELD) kbps/channel */ + {QCDATA_BR_MODE_VBR_4, + FL2FXCONST_DBL(0.111f)}, /* Approx. 64 - 80 (AC-LC), 64 - 88 + (AAC-LD/ELD) kbps/channel */ + {QCDATA_BR_MODE_VBR_5, + FL2FXCONST_DBL(0.070f)} /* Approx. 96 - 120 (AC-LC), 112 - 144 + (AAC-LD/ELD) kbps/channel */ +}; + +static INT isConstantBitrateMode(const QCDATA_BR_MODE bitrateMode) { + return (((bitrateMode == QCDATA_BR_MODE_CBR) || + (bitrateMode == QCDATA_BR_MODE_SFR) || + (bitrateMode == QCDATA_BR_MODE_FF)) + ? 1 + : 0); +} + +typedef enum { + FRAME_LEN_BYTES_MODULO = 1, + FRAME_LEN_BYTES_INT = 2 +} FRAME_LEN_RESULT_MODE; + +/* forward declarations */ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, INT maxSfbPerGroup, + INT sfbPerGroup, INT* RESTRICT sfbOffset, + SHORT* RESTRICT quantSpectrum, + UINT* RESTRICT maxValue); + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, QC_OUT_ELEMENT* qcElement, + INT bitsToSave, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption( + int* iterations, const int maxIterations, int gainAdjustment, + int* chConstraintsFulfilled, int* calculateQuant, int nChannels, + PSY_OUT_ELEMENT* psyOutElement, QC_OUT* qcOut, QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, + SCHAR epConfig); + +void FDKaacEnc_QCClose(QC_STATE** phQCstate, QC_OUT** phQC); + +/***************************************************************************** + + functionname: FDKaacEnc_calcFrameLen + description: + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_calcFrameLen(INT bitRate, INT sampleRate, + INT granuleLength, + FRAME_LEN_RESULT_MODE mode) { + INT result; + + result = ((granuleLength) >> 3) * (bitRate); + + switch (mode) { + case FRAME_LEN_BYTES_MODULO: + result %= sampleRate; + break; + case FRAME_LEN_BYTES_INT: + result /= sampleRate; + break; + } + return (result); +} + +/***************************************************************************** + + functionname:FDKaacEnc_framePadding + description: Calculates if padding is needed for actual frame + returns: + input: + output: + +*****************************************************************************/ +static INT FDKaacEnc_framePadding(INT bitRate, INT sampleRate, + INT granuleLength, INT* paddingRest) { + INT paddingOn; + INT difference; + + paddingOn = 0; + + difference = FDKaacEnc_calcFrameLen(bitRate, sampleRate, granuleLength, + FRAME_LEN_BYTES_MODULO); + *paddingRest -= difference; + + if (*paddingRest <= 0) { + paddingOn = 1; + *paddingRest += sampleRate; + } + + return (paddingOn); +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT** phQC, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR* dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int n, i; + int elInc = 0, chInc = 0; + + for (n = 0; n < nSubFrames; n++) { + phQC[n] = GetRam_aacEnc_QCout(n); + if (phQC[n] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + + for (i = 0; i < nChannels; i++) { + phQC[n]->pQcOutChannels[i] = GetRam_aacEnc_QCchannel(chInc, dynamic_RAM); + if (phQC[n]->pQcOutChannels[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + + chInc++; + } /* nChannels */ + + for (i = 0; i < nElements; i++) { + phQC[n]->qcElement[i] = GetRam_aacEnc_QCelement(elInc); + if (phQC[n]->qcElement[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCOutNew_bail; + } + elInc++; + + /* initialize pointer to dynamic buffer which are used in adjust + * thresholds */ + phQC[n]->qcElement[i]->dynMem_Ah_Flag = dynamic_RAM + (P_BUF_1); + phQC[n]->qcElement[i]->dynMem_Thr_Exp = + dynamic_RAM + (P_BUF_1) + ADJ_THR_AH_FLAG_SIZE; + phQC[n]->qcElement[i]->dynMem_SfbNActiveLinesLdData = + dynamic_RAM + (P_BUF_1) + ADJ_THR_AH_FLAG_SIZE + ADJ_THR_THR_EXP_SIZE; + + } /* nElements */ + + } /* nSubFrames */ + + return AAC_ENC_OK; + +QCOutNew_bail: + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCOutInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT* phQC[(1)], const INT nSubFrames, + const CHANNEL_MAPPING* cm) { + INT n, i, ch; + + for (n = 0; n < nSubFrames; n++) { + INT chInc = 0; + for (i = 0; i < cm->nElements; i++) { + for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) { + phQC[n]->qcElement[i]->qcOutChannel[ch] = + phQC[n]->pQcOutChannels[chInc]; + chInc++; + } /* chInEl */ + } /* nElements */ + } /* nSubFrames */ + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCNew + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE** phQC, INT nElements, + UCHAR* dynamic_RAM) { + AAC_ENCODER_ERROR ErrorStatus; + int i; + + QC_STATE* hQC = GetRam_aacEnc_QCstate(); + *phQC = hQC; + if (hQC == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_AdjThrNew(&hQC->hAdjThr, nElements)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + if (FDKaacEnc_BCNew(&(hQC->hBitCounter), dynamic_RAM)) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + + for (i = 0; i < nElements; i++) { + hQC->elementBits[i] = GetRam_aacEnc_ElementBits(i); + if (hQC->elementBits[i] == NULL) { + ErrorStatus = AAC_ENC_NO_MEMORY; + goto QCNew_bail; + } + } + + return AAC_ENC_OK; + +QCNew_bail: + FDKaacEnc_QCClose(phQC, NULL); + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCInit + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE* hQC, struct QC_INIT* init, + const ULONG initFlags) { + AAC_ENCODER_ERROR err = AAC_ENC_OK; + + int i; + hQC->maxBitsPerFrame = init->maxBits; + hQC->minBitsPerFrame = init->minBits; + hQC->nElements = init->channelMapping->nElements; + if ((initFlags != 0) || ((init->bitrateMode != QCDATA_BR_MODE_FF) && + (hQC->bitResTotMax != init->bitRes))) { + hQC->bitResTot = init->bitRes; + } + hQC->bitResTotMax = init->bitRes; + hQC->maxBitFac = init->maxBitFac; + hQC->bitrateMode = init->bitrateMode; + hQC->invQuant = init->invQuant; + hQC->maxIterations = init->maxIterations; + + if (isConstantBitrateMode(hQC->bitrateMode)) { + /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir + */ + hQC->bitResMode = init->bitResMode; + } else { + hQC->bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */ + } + + hQC->padding.paddingRest = init->padding.paddingRest; + + hQC->globHdrBits = init->staticBits; /* Bit overhead due to transport */ + + err = FDKaacEnc_InitElementBits( + hQC, init->channelMapping, init->bitrate, + (init->averageBits / init->nSubFrames) - hQC->globHdrBits, + hQC->maxBitsPerFrame / init->channelMapping->nChannelsEff); + if (err != AAC_ENC_OK) goto bail; + + hQC->vbrQualFactor = FL2FXCONST_DBL(0.f); + for (i = 0; + i < (int)(sizeof(tableVbrQualFactor) / sizeof(TAB_VBR_QUAL_FACTOR)); + i++) { + if (hQC->bitrateMode == tableVbrQualFactor[i].bitrateMode) { + hQC->vbrQualFactor = (FIXP_DBL)tableVbrQualFactor[i].vbrQualFactor; + break; + } + } + + if (init->channelMapping->nChannelsEff == 1 && + (init->bitrate / init->channelMapping->nChannelsEff) < + AACENC_DZQ_BR_THR && + init->isLowDelay != + 0) /* watch out here: init->bitrate is the bitrate "minus" the + standard SBR bitrate (=2500kbps) --> for the FDK the OFFSTE + tuning should start somewhere below 32000kbps-2500kbps ... so + everything is fine here */ + { + hQC->dZoneQuantEnable = 1; + } else { + hQC->dZoneQuantEnable = 0; + } + + FDKaacEnc_AdjThrInit( + hQC->hAdjThr, init->meanPe, hQC->invQuant, init->channelMapping, + init->sampleRate, /* output sample rate */ + init->bitrate, /* total bitrate */ + init->isLowDelay, /* if set, calc bits2PE factor + depending on samplerate */ + init->bitResMode /* for a small bitreservoir, the pe + correction is calc'd differently */ + , + hQC->dZoneQuantEnable, init->bitDistributionMode, hQC->vbrQualFactor); + +bail: + return err; +} + +/********************************************************************************* + + functionname: FDKaacEnc_QCMainPrepare + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare( + ELEMENT_INFO* elInfo, ATS_ELEMENT* RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT* RESTRICT psyOutElement, + QC_OUT_ELEMENT* RESTRICT qcOutElement, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT nChannels = elInfo->nChannelsInEl; + + PSY_OUT_CHANNEL** RESTRICT psyOutChannel = + psyOutElement->psyOutChannel; /* may be modified in-place */ + + FDKaacEnc_CalcFormFactor(qcOutElement->qcOutChannel, psyOutChannel, + nChannels); + + /* prepare and calculate PE without reduction */ + FDKaacEnc_peCalculation(&qcOutElement->peData, psyOutChannel, + qcOutElement->qcOutChannel, &psyOutElement->toolsInfo, + adjThrStateElement, nChannels); + + ErrorStatus = FDKaacEnc_ChannelElementWrite( + NULL, elInfo, NULL, psyOutElement, psyOutElement->psyOutChannel, + syntaxFlags, aot, epConfig, &qcOutElement->staticBitsUsed, 0); + + return ErrorStatus; +} + +/********************************************************************************* + + functionname: FDKaacEnc_AdjustBitrate + description: adjusts framelength via padding on a frame to frame +basis, to achieve a bitrate that demands a non byte aligned framelength return: +errorcode + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate( + QC_STATE* RESTRICT hQC, CHANNEL_MAPPING* RESTRICT cm, INT* avgTotalBits, + INT bitRate, /* total bitrate */ + INT sampleRate, /* output sampling rate */ + INT granuleLength) /* frame length */ +{ + INT paddingOn; + INT frameLen; + //fprintf(stderr, "hQC->padding.paddingRest=%d bytes! (before)\n", hQC->padding.paddingRest); + + /* Do we need an extra padding byte? */ + paddingOn = FDKaacEnc_framePadding(bitRate, sampleRate, granuleLength, + &hQC->padding.paddingRest); + + frameLen = + paddingOn + FDKaacEnc_calcFrameLen(bitRate, sampleRate, granuleLength, + FRAME_LEN_BYTES_INT); + + *avgTotalBits = frameLen << 3; + + return AAC_ENC_OK; +} + +#define isAudioElement(elType) \ + ((elType == ID_SCE) || (elType == ID_CPE) || (elType == ID_LFE)) + +/********************************************************************************* + + functionname: FDKaacEnc_distributeElementDynBits + description: distributes all bits over all elements. The relative bit + distibution is described in the ELEMENT_INFO of the + appropriate element. The bit distribution table is + initialized in FDKaacEnc_InitChannelMapping(). + return: errorcode + +**********************************************************************************/ +static AAC_ENCODER_ERROR FDKaacEnc_distributeElementDynBits( + QC_STATE* hQC, QC_OUT_ELEMENT* qcElement[((8))], CHANNEL_MAPPING* cm, + INT codeBits) { + INT i; /* counter variable */ + INT totalBits = 0; /* sum of bits over all elements */ + + for (i = (cm->nElements - 1); i >= 0; i--) { + if (isAudioElement(cm->elInfo[i].elType)) { + qcElement[i]->grantedDynBits = + fMax(0, fMultI(hQC->elementBits[i]->relativeBitsEl, codeBits)); + totalBits += qcElement[i]->grantedDynBits; + } + } + + /* Due to inaccuracies with the multiplication, codeBits may differ from + totalBits. For that case, the difference must be added/substracted again + to/from one element, i.e: + Negative differences are substracted from the element with the most bits. + Positive differences are added to the element with the least bits. + */ + if (codeBits != totalBits) { + INT elMaxBits = cm->nElements - 1; /* element with the most bits */ + INT elMinBits = cm->nElements - 1; /* element with the least bits */ + + /* Search for biggest and smallest audio element */ + for (i = (cm->nElements - 1); i >= 0; i--) { + if (isAudioElement(cm->elInfo[i].elType)) { + if (qcElement[i]->grantedDynBits > + qcElement[elMaxBits]->grantedDynBits) { + elMaxBits = i; + } + if (qcElement[i]->grantedDynBits < + qcElement[elMinBits]->grantedDynBits) { + elMinBits = i; + } + } + } + /* Compensate for bit distibution difference */ + if (codeBits - totalBits > 0) { + qcElement[elMinBits]->grantedDynBits += codeBits - totalBits; + } else { + qcElement[elMaxBits]->grantedDynBits += codeBits - totalBits; + } + } + + return AAC_ENC_OK; +} + +/** + * \brief Verify whether minBitsPerFrame criterion can be satisfied. + * + * This function evaluates the bit consumption only if minBitsPerFrame parameter + * is not 0. In hyperframing mode the difference between grantedDynBits and + * usedDynBits of all sub frames results the number of fillbits to be written. + * This bits can be distrubitued in superframe to reach minBitsPerFrame bit + * consumption in single AU's. The return value denotes if enough desired fill + * bits are available to achieve minBitsPerFrame in all frames. This check can + * only be used within superframes. + * + * \param qcOut Pointer to coding data struct. + * \param minBitsPerFrame Minimal number of bits to be consumed in each frame. + * \param nSubFrames Number of frames in superframe + * + * \return + * - 1: all fine + * - 0: criterion not fulfilled + */ +static int checkMinFrameBitsDemand(QC_OUT** qcOut, const INT minBitsPerFrame, + const INT nSubFrames) { + int result = 1; /* all fine*/ + return result; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/********************************************************************************* + + functionname: FDKaacEnc_getMinimalStaticBitdemand + description: calculate minmal size of static bits by reduction , + to zero spectrum and deactivating tns and MS + return: number of static bits + +**********************************************************************************/ +static int FDKaacEnc_getMinimalStaticBitdemand(CHANNEL_MAPPING* cm, + PSY_OUT** psyOut) { + AUDIO_OBJECT_TYPE aot = AOT_AAC_LC; + UINT syntaxFlags = 0; + SCHAR epConfig = -1; + int i, bitcount = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + INT minElBits = 0; + + FDKaacEnc_ChannelElementWrite(NULL, &elInfo, NULL, + psyOut[0]->psyOutElement[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, + syntaxFlags, aot, epConfig, &minElBits, 1); + bitcount += minElBits; + } + } + + return bitcount; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +static AAC_ENCODER_ERROR FDKaacEnc_prepareBitDistribution( + QC_STATE* hQC, PSY_OUT** psyOut, QC_OUT** qcOut, CHANNEL_MAPPING* cm, + QC_OUT_ELEMENT* qcElement[(1)][((8))], INT avgTotalBits, + INT* totalAvailableBits, INT* avgTotalDynBits) { + int i; + /* get maximal allowed dynamic bits */ + qcOut[0]->grantedDynBits = + (fixMin(hQC->maxBitsPerFrame, avgTotalBits) - hQC->globHdrBits) & ~7; + qcOut[0]->grantedDynBits -= (qcOut[0]->globalExtBits + qcOut[0]->staticBits + + qcOut[0]->elementExtBits); + qcOut[0]->maxDynBits = ((hQC->maxBitsPerFrame) & ~7) - + (qcOut[0]->globalExtBits + qcOut[0]->staticBits + + qcOut[0]->elementExtBits); + /* assure that enough bits are available */ + if ((qcOut[0]->grantedDynBits + hQC->bitResTot) < 0) { + /* crash recovery allows to reduce static bits to a minimum */ + if ((qcOut[0]->grantedDynBits + hQC->bitResTot) < + (FDKaacEnc_getMinimalStaticBitdemand(cm, psyOut) - + qcOut[0]->staticBits)) + return AAC_ENC_BITRES_TOO_LOW; + } + + /* distribute dynamic bits to each element */ + FDKaacEnc_distributeElementDynBits(hQC, qcElement[0], cm, + qcOut[0]->grantedDynBits); + + *avgTotalDynBits = 0; /*frameDynBits;*/ + + *totalAvailableBits = avgTotalBits; + + /* sum up corrected granted PE */ + qcOut[0]->totalGrantedPeCorr = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + int nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for ( all sub frames ) ... */ + FDKaacEnc_DistributeBits( + hQC->hAdjThr, hQC->hAdjThr->adjThrStateElem[i], + psyOut[0]->psyOutElement[i]->psyOutChannel, &qcElement[0][i]->peData, + &qcElement[0][i]->grantedPe, &qcElement[0][i]->grantedPeCorr, + nChannels, psyOut[0]->psyOutElement[i]->commonWindow, + qcElement[0][i]->grantedDynBits, hQC->elementBits[i]->bitResLevelEl, + hQC->elementBits[i]->maxBitResBitsEl, hQC->maxBitFac, + hQC->bitResMode); + + *totalAvailableBits += hQC->elementBits[i]->bitResLevelEl; + /* get total corrected granted PE */ + qcOut[0]->totalGrantedPeCorr += qcElement[0][i]->grantedPeCorr; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + *totalAvailableBits = fMin(hQC->maxBitsPerFrame, (*totalAvailableBits)); + + return AAC_ENC_OK; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +static AAC_ENCODER_ERROR FDKaacEnc_updateUsedDynBits( + INT* sumDynBitsConsumed, QC_OUT_ELEMENT* qcElement[((8))], + CHANNEL_MAPPING* cm) { + INT i; + + *sumDynBitsConsumed = 0; + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* sum up bits consumed */ + *sumDynBitsConsumed += qcElement[i]->dynBitsUsed; + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + return AAC_ENC_OK; +} + +static INT FDKaacEnc_getTotalConsumedDynBits(QC_OUT** qcOut, INT nSubFrames) { + INT c, totalBits = 0; + + /* sum up bit consumption for all sub frames */ + for (c = 0; c < nSubFrames; c++) { + /* bit consumption not valid if dynamic bits + not available in one sub frame */ + if (qcOut[c]->usedDynBits == -1) return -1; + totalBits += qcOut[c]->usedDynBits; + } + + return totalBits; +} + +static INT FDKaacEnc_getTotalConsumedBits(QC_OUT** qcOut, + QC_OUT_ELEMENT* qcElement[(1)][((8))], + CHANNEL_MAPPING* cm, INT globHdrBits, + INT nSubFrames) { + int c, i; + int totalUsedBits = 0; + + for (c = 0; c < nSubFrames; c++) { + int dataBits = 0; + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + dataBits += qcElement[c][i]->dynBitsUsed + + qcElement[c][i]->staticBitsUsed + + qcElement[c][i]->extBitsUsed; + } + } + dataBits += qcOut[c]->globalExtBits; + + totalUsedBits += (8 - (dataBits) % 8) % 8; + totalUsedBits += dataBits + globHdrBits; /* header bits for every frame */ + } + return totalUsedBits; +} + +static AAC_ENCODER_ERROR FDKaacEnc_BitResRedistribution( + QC_STATE* const hQC, const CHANNEL_MAPPING* const cm, + const INT avgTotalBits) { + /* check bitreservoir fill level */ + if (hQC->bitResTot < 0) { + return AAC_ENC_BITRES_TOO_LOW; + } else if (hQC->bitResTot > hQC->bitResTotMax) { + return AAC_ENC_BITRES_TOO_HIGH; + } else { + INT i; + INT totalBits = 0, totalBits_max = 0; + + const int totalBitreservoir = + fMin(hQC->bitResTot, (hQC->maxBitsPerFrame - avgTotalBits)); + const int totalBitreservoirMax = + fMin(hQC->bitResTotMax, (hQC->maxBitsPerFrame - avgTotalBits)); + + for (i = (cm->nElements - 1); i >= 0; i--) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + hQC->elementBits[i]->bitResLevelEl = + fMultI(hQC->elementBits[i]->relativeBitsEl, totalBitreservoir); + totalBits += hQC->elementBits[i]->bitResLevelEl; + + hQC->elementBits[i]->maxBitResBitsEl = + fMultI(hQC->elementBits[i]->relativeBitsEl, totalBitreservoirMax); + totalBits_max += hQC->elementBits[i]->maxBitResBitsEl; + } + } + for (i = 0; i < cm->nElements; i++) { + if ((cm->elInfo[i].elType == ID_SCE) || + (cm->elInfo[i].elType == ID_CPE) || + (cm->elInfo[i].elType == ID_LFE)) { + int deltaBits = fMax(totalBitreservoir - totalBits, + -hQC->elementBits[i]->bitResLevelEl); + hQC->elementBits[i]->bitResLevelEl += deltaBits; + totalBits += deltaBits; + + deltaBits = fMax(totalBitreservoirMax - totalBits_max, + -hQC->elementBits[i]->maxBitResBitsEl); + hQC->elementBits[i]->maxBitResBitsEl += deltaBits; + totalBits_max += deltaBits; + } + } + } + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, PSY_OUT** psyOut, + QC_OUT** qcOut, INT avgTotalBits, + CHANNEL_MAPPING* cm, + const AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + int i, c; + AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK; + INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */ + INT totalAvailableBits = 0; + INT nSubFrames = 1; + + /*-------------------------------------------- */ + /* redistribute total bitreservoir to elements */ + ErrorStatus = FDKaacEnc_BitResRedistribution(hQC, cm, avgTotalBits); + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + + /*-------------------------------------------- */ + /* fastenc needs one time threshold simulation, + in case of multiple frames, one more guess has to be calculated */ + + /*-------------------------------------------- */ + /* helper pointer */ + QC_OUT_ELEMENT* qcElement[(1)][((8))]; + + /* work on a copy of qcChannel and qcElement */ + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + { qcElement[c][i] = qcOut[c]->qcElement[i]; } + } + } + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + if (isConstantBitrateMode(hQC->bitrateMode)) { + /* calc granted dynamic bits for sub frame and + distribute it to each element */ + ErrorStatus = FDKaacEnc_prepareBitDistribution( + hQC, psyOut, qcOut, cm, qcElement, avgTotalBits, &totalAvailableBits, + &avgTotalDynBits); + + if (ErrorStatus != AAC_ENC_OK) { + return ErrorStatus; + } + } else { + qcOut[0]->grantedDynBits = + ((hQC->maxBitsPerFrame - (hQC->globHdrBits)) & ~7) - + (qcOut[0]->globalExtBits + qcOut[0]->staticBits + + qcOut[0]->elementExtBits); + qcOut[0]->maxDynBits = qcOut[0]->grantedDynBits; + + totalAvailableBits = hQC->maxBitsPerFrame; + avgTotalDynBits = 0; + } + + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + /* for CBR and VBR mode */ + FDKaacEnc_AdjustThresholds(hQC->hAdjThr, qcElement[c], qcOut[c], + psyOut[c]->psyOutElement, + isConstantBitrateMode(hQC->bitrateMode), cm); + + } /* -end- sub frame counter */ + + /*-------------------------------------------- */ + INT iterations[(1)][((8))]; + INT chConstraintsFulfilled[(1)][((8))][(2)]; + INT calculateQuant[(1)][((8))][(2)]; + INT constraintsFulfilled[(1)][((8))]; + /*-------------------------------------------- */ + + /* for ( all sub frames ) ... */ + for (c = 0; c < nSubFrames; c++) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* Turn thresholds into scalefactors, optimize bit consumption and + * verify conformance */ + FDKaacEnc_EstimateScaleFactors( + psyOut[c]->psyOutElement[i]->psyOutChannel, + qcElement[c][i]->qcOutChannel, hQC->invQuant, hQC->dZoneQuantEnable, + cm->elInfo[i].nChannelsInEl); + + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1; + iterations[c][i] = 0; + + for (ch = 0; ch < nChannels; ch++) { + chConstraintsFulfilled[c][i][ch] = 1; + calculateQuant[c][i][ch] = 1; + } + + /*-------------------------------------------- */ + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + qcOut[c]->usedDynBits = -1; + + } /* -end- sub frame counter */ + + INT quantizationDone = 0; + INT sumDynBitsConsumedTotal = 0; + INT decreaseBitConsumption = -1; /* no direction yet! */ + + /*-------------------------------------------- */ + /* -start- Quantization loop ... */ + /*-------------------------------------------- */ + do /* until max allowed bits per frame and maxDynBits!=-1*/ + { + quantizationDone = 0; + + c = 0; /* get frame to process */ + + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + INT ch, nChannels = elInfo.nChannelsInEl; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + do /* until element bits < nChannels*MIN_BUFSIZE_PER_EFF_CHAN */ + { + do /* until spectral values < MAX_QUANT */ + { + /*-------------------------------------------- */ + if (!constraintsFulfilled[c][i]) { + if ((ErrorStatus = FDKaacEnc_reduceBitConsumption( + &iterations[c][i], hQC->maxIterations, + (decreaseBitConsumption) ? 1 : -1, + chConstraintsFulfilled[c][i], calculateQuant[c][i], + nChannels, psyOut[c]->psyOutElement[i], qcOut[c], + qcElement[c][i], hQC->elementBits[i], aot, syntaxFlags, + epConfig)) != AAC_ENC_OK) { + return ErrorStatus; + } + } + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + constraintsFulfilled[c][i] = 1; + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + for (ch = 0; ch < nChannels; ch++) { + /*-------------------------------------------- */ + chConstraintsFulfilled[c][i][ch] = 1; + + /*-------------------------------------------- */ + + if (calculateQuant[c][i][ch]) { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL* psyOutCh = + psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + calculateQuant[c][i][ch] = + 0; /* calculate quantization only if necessary */ + + /*-------------------------------------------- */ + FDKaacEnc_QuantizeSpectrum( + psyOutCh->sfbCnt, psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, psyOutCh->sfbOffsets, + qcOutCh->mdctSpectrum, qcOutCh->globalGain, qcOutCh->scf, + qcOutCh->quantSpec, hQC->dZoneQuantEnable); + + /*-------------------------------------------- */ + if (FDKaacEnc_calcMaxValueInSfb( + psyOutCh->sfbCnt, psyOutCh->maxSfbPerGroup, + psyOutCh->sfbPerGroup, psyOutCh->sfbOffsets, + qcOutCh->quantSpec, + qcOutCh->maxValueInSfb) > MAX_QUANT) { + chConstraintsFulfilled[c][i][ch] = 0; + constraintsFulfilled[c][i] = 0; + /* if quanizted value out of range; increase global gain! */ + decreaseBitConsumption = 1; + } + + /*-------------------------------------------- */ + + } /* if calculateQuant[c][i][ch] */ + + } /* channel loop */ + + /*-------------------------------------------- */ + /* quantize spectrum (per each channel) */ + + /*-------------------------------------------- */ + + } while (!constraintsFulfilled[c][i]); /* does not regard bit + consumption */ + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + qcElement[c][i]->dynBitsUsed = 0; /* reset dynamic bits */ + + /* quantization valid in current channel! */ + for (ch = 0; ch < nChannels; ch++) { + QC_OUT_CHANNEL* qcOutCh = qcElement[c][i]->qcOutChannel[ch]; + PSY_OUT_CHANNEL* psyOutCh = + psyOut[c]->psyOutElement[i]->psyOutChannel[ch]; + + /* count dynamic bits */ + INT chDynBits = FDKaacEnc_dynBitCount( + hQC->hBitCounter, qcOutCh->quantSpec, qcOutCh->maxValueInSfb, + qcOutCh->scf, psyOutCh->lastWindowSequence, psyOutCh->sfbCnt, + psyOutCh->maxSfbPerGroup, psyOutCh->sfbPerGroup, + psyOutCh->sfbOffsets, &qcOutCh->sectionData, psyOutCh->noiseNrg, + psyOutCh->isBook, psyOutCh->isScale, syntaxFlags); + + /* sum up dynamic channel bits */ + qcElement[c][i]->dynBitsUsed += chDynBits; + } + + /* save dynBitsUsed for correction of bits2pe relation */ + if (hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast == -1) { + hQC->hAdjThr->adjThrStateElem[i]->dynBitsLast = + qcElement[c][i]->dynBitsUsed; + } + + /* hold total bit consumption in present element below maximum allowed + */ + if (qcElement[c][i]->dynBitsUsed > + ((nChannels * MIN_BUFSIZE_PER_EFF_CHAN) - + qcElement[c][i]->staticBitsUsed - + qcElement[c][i]->extBitsUsed)) { + constraintsFulfilled[c][i] = 0; + } + + } while (!constraintsFulfilled[c][i]); + + } /* -end- if(ID_SCE || ID_CPE || ID_LFE) */ + + } /* -end- element loop */ + + /* update dynBits of current subFrame */ + FDKaacEnc_updateUsedDynBits(&qcOut[c]->usedDynBits, qcElement[c], cm); + + /* get total consumed bits, dyn bits in all sub frames have to be valid */ + sumDynBitsConsumedTotal = + FDKaacEnc_getTotalConsumedDynBits(qcOut, nSubFrames); + + if (sumDynBitsConsumedTotal == -1) { + quantizationDone = 0; /* bit consumption not valid in all sub frames */ + } else { + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits( + qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + /* in all frames are valid dynamic bits */ + if (((sumBitsConsumedTotal < totalAvailableBits) || + sumDynBitsConsumedTotal == 0) && + (decreaseBitConsumption == 1) && + checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames) + /*()*/) { + quantizationDone = 1; /* exit bit adjustment */ + } + if (sumBitsConsumedTotal > totalAvailableBits && + (decreaseBitConsumption == 0)) { + quantizationDone = 0; /* reset! */ + } + } + + /*-------------------------------------------- */ + + int emergencyIterations = 1; + int dynBitsOvershoot = 0; + + for (c = 0; c < nSubFrames; c++) { + for (i = 0; i < cm->nElements; i++) { + ELEMENT_INFO elInfo = cm->elInfo[i]; + + if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) || + (elInfo.elType == ID_LFE)) { + /* iteration limitation */ + emergencyIterations &= + ((iterations[c][i] < hQC->maxIterations) ? 0 : 1); + } + } + /* detection if used dyn bits exceeds the maximal allowed criterion */ + dynBitsOvershoot |= + ((qcOut[c]->usedDynBits > qcOut[c]->maxDynBits) ? 1 : 0); + } + + if (quantizationDone == 0 || dynBitsOvershoot) { + int sumBitsConsumedTotal = FDKaacEnc_getTotalConsumedBits( + qcOut, qcElement, cm, hQC->globHdrBits, nSubFrames); + + if ((sumDynBitsConsumedTotal >= avgTotalDynBits) || + (sumDynBitsConsumedTotal == 0)) { + quantizationDone = 1; + } + if (emergencyIterations && (sumBitsConsumedTotal < totalAvailableBits)) { + quantizationDone = 1; + } + if ((sumBitsConsumedTotal > totalAvailableBits) || + !checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames)) { + quantizationDone = 0; + } + if ((sumBitsConsumedTotal < totalAvailableBits) && + checkMinFrameBitsDemand(qcOut, hQC->minBitsPerFrame, nSubFrames)) { + decreaseBitConsumption = 0; + } else { + decreaseBitConsumption = 1; + } + + if (dynBitsOvershoot) { + quantizationDone = 0; + decreaseBitConsumption = 1; + } + + /* reset constraints fullfilled flags */ + FDKmemclear(constraintsFulfilled, sizeof(constraintsFulfilled)); + FDKmemclear(chConstraintsFulfilled, sizeof(chConstraintsFulfilled)); + + } /* quantizationDone */ + + } while (!quantizationDone); + + /*-------------------------------------------- */ + /* ... -end- Quantization loop */ + /*-------------------------------------------- */ + + /*-------------------------------------------- */ + /*-------------------------------------------- */ + + return AAC_ENC_OK; +} + +static AAC_ENCODER_ERROR FDKaacEnc_reduceBitConsumption( + int* iterations, const int maxIterations, int gainAdjustment, + int* chConstraintsFulfilled, int* calculateQuant, int nChannels, + PSY_OUT_ELEMENT* psyOutElement, QC_OUT* qcOut, QC_OUT_ELEMENT* qcOutElement, + ELEMENT_BITS* elBits, AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, + SCHAR epConfig) { + int ch; + + /** SOLVING PROBLEM **/ + if ((*iterations) < maxIterations) { + /* increase gain (+ next iteration) */ + for (ch = 0; ch < nChannels; ch++) { + if (!chConstraintsFulfilled[ch]) { + qcOutElement->qcOutChannel[ch]->globalGain += gainAdjustment; + calculateQuant[ch] = 1; /* global gain has changed, recalculate + quantization in next iteration! */ + } + } + } else if ((*iterations) == maxIterations) { + if (qcOutElement->dynBitsUsed == 0) { + return AAC_ENC_QUANT_ERROR; + } else { + /* crash recovery */ + INT bitsToSave = 0; + if ((bitsToSave = fixMax( + (qcOutElement->dynBitsUsed + 8) - + (elBits->bitResLevelEl + qcOutElement->grantedDynBits), + (qcOutElement->dynBitsUsed + qcOutElement->staticBitsUsed + 8) - + (elBits->maxBitsEl))) > 0) { + FDKaacEnc_crashRecovery(nChannels, psyOutElement, qcOut, qcOutElement, + bitsToSave, aot, syntaxFlags, epConfig); + } else { + for (ch = 0; ch < nChannels; ch++) { + qcOutElement->qcOutChannel[ch]->globalGain += 1; + } + } + for (ch = 0; ch < nChannels; ch++) { + calculateQuant[ch] = 1; + } + } + } else { + /* (*iterations) > maxIterations */ + return AAC_ENC_QUANT_ERROR; + } + (*iterations)++; + + return AAC_ENC_OK; +} + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING* cm, + QC_STATE* qcKernel, + ELEMENT_BITS* RESTRICT elBits[((8))], + QC_OUT** qcOut) { + switch (qcKernel->bitrateMode) { + case QCDATA_BR_MODE_SFR: + break; + + case QCDATA_BR_MODE_FF: + break; + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + qcOut[0]->totFillBits = + (qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits) & + 7; /* precalculate alignment bits */ + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += + (fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_INVALID: + default: + INT bitResSpace = qcKernel->bitResTotMax - qcKernel->bitResTot; + /* processing fill-bits */ + INT deltaBitRes = qcOut[0]->grantedDynBits - qcOut[0]->usedDynBits; + qcOut[0]->totFillBits = fixMax( + (deltaBitRes & 7), (deltaBitRes - (fixMax(0, bitResSpace - 7) & ~7))); + qcOut[0]->totalBits = qcOut[0]->staticBits + qcOut[0]->usedDynBits + + qcOut[0]->totFillBits + qcOut[0]->elementExtBits + + qcOut[0]->globalExtBits; + qcOut[0]->totFillBits += + (fixMax(0, qcKernel->minBitsPerFrame - qcOut[0]->totalBits) + 7) & ~7; + break; + } /* switch (qcKernel->bitrateMode) */ + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_calcMaxValueInSfb + description: + return: + +**********************************************************************************/ + +static INT FDKaacEnc_calcMaxValueInSfb(INT sfbCnt, INT maxSfbPerGroup, + INT sfbPerGroup, INT* RESTRICT sfbOffset, + SHORT* RESTRICT quantSpectrum, + UINT* RESTRICT maxValue) { + INT sfbOffs, sfb; + INT maxValueAll = 0; + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT line; + INT maxThisSfb = 0; + for (line = sfbOffset[sfbOffs + sfb]; line < sfbOffset[sfbOffs + sfb + 1]; + line++) { + INT tmp = fixp_abs(quantSpectrum[line]); + maxThisSfb = fixMax(tmp, maxThisSfb); + } + + maxValue[sfbOffs + sfb] = maxThisSfb; + maxValueAll = fixMax(maxThisSfb, maxValueAll); + } + return maxValueAll; +} + +/********************************************************************************* + + functionname: FDKaacEnc_updateBitres + description: + return: + +**********************************************************************************/ +void FDKaacEnc_updateBitres(CHANNEL_MAPPING* cm, QC_STATE* qcKernel, + QC_OUT** qcOut) { + switch (qcKernel->bitrateMode) { + case QCDATA_BR_MODE_VBR_1: + case QCDATA_BR_MODE_VBR_2: + case QCDATA_BR_MODE_VBR_3: + case QCDATA_BR_MODE_VBR_4: + case QCDATA_BR_MODE_VBR_5: + /* variable bitrate */ + qcKernel->bitResTot = + fMin(qcKernel->maxBitsPerFrame, qcKernel->bitResTotMax); + break; + case QCDATA_BR_MODE_CBR: + case QCDATA_BR_MODE_SFR: + case QCDATA_BR_MODE_INVALID: + default: + int c = 0; + /* constant bitrate */ + { + qcKernel->bitResTot += qcOut[c]->grantedDynBits - + (qcOut[c]->usedDynBits + qcOut[c]->totFillBits + + qcOut[c]->alignBits); + } + break; + } +} + +/********************************************************************************* + + functionname: FDKaacEnc_FinalizeBitConsumption + description: + return: + +**********************************************************************************/ +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( + CHANNEL_MAPPING* cm, QC_STATE* qcKernel, QC_OUT* qcOut, + QC_OUT_ELEMENT** qcElement, HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig) { + QC_OUT_EXTENSION fillExtPayload; + INT totFillBits, alignBits; + + /* Get total consumed bits in AU */ + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + + qcOut->totFillBits + qcOut->elementExtBits + + qcOut->globalExtBits; + + if (qcKernel->bitrateMode == QCDATA_BR_MODE_CBR) { + /* Now we can get the exact transport bit amount, and hopefully it is equal + * to the estimated value */ + INT exactTpBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (exactTpBits != qcKernel->globHdrBits) { + INT diffFillBits = 0; + + /* How many bits can be take by bitreservoir */ + const INT bitresSpace = + qcKernel->bitResTotMax - + (qcKernel->bitResTot + + (qcOut->grantedDynBits - (qcOut->usedDynBits + qcOut->totFillBits))); + + /* Number of bits which can be moved to bitreservoir. */ + const INT bitsToBitres = qcKernel->globHdrBits - exactTpBits; + FDK_ASSERT(bitsToBitres >= 0); /* is always positive */ + + /* If bitreservoir can not take all bits, move ramaining bits to fillbits + */ + diffFillBits = fMax(0, bitsToBitres - bitresSpace); + + /* Assure previous alignment */ + diffFillBits = (diffFillBits + 7) & ~7; + + /* Move as many bits as possible to bitreservoir */ + qcKernel->bitResTot += (bitsToBitres - diffFillBits); + + /* Write remaing bits as fill bits */ + qcOut->totFillBits += diffFillBits; + qcOut->totalBits += diffFillBits; + qcOut->grantedDynBits += diffFillBits; + + /* Get new header bits */ + qcKernel->globHdrBits = + transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + if (qcKernel->globHdrBits != exactTpBits) { + /* In previous step, fill bits and corresponding total bits were changed + when bitreservoir was completely filled. Now we can take the too much + taken bits caused by header overhead from bitreservoir. + */ + qcKernel->bitResTot -= (qcKernel->globHdrBits - exactTpBits); + } + } + + } /* MODE_CBR */ + + /* Update exact number of consumed header bits. */ + qcKernel->globHdrBits = transportEnc_GetStaticBits(hTpEnc, qcOut->totalBits); + + /* Save total fill bits and distribut to alignment and fill bits */ + totFillBits = qcOut->totFillBits; + + /* fake a fill extension payload */ + FDKmemclear(&fillExtPayload, sizeof(QC_OUT_EXTENSION)); + + fillExtPayload.type = EXT_FILL_DATA; + fillExtPayload.nPayloadBits = totFillBits; + + /* ask bitstream encoder how many of that bits can be written in a fill + * extension data entity */ + qcOut->totFillBits = FDKaacEnc_writeExtensionData(NULL, &fillExtPayload, 0, 0, + syntaxFlags, aot, epConfig); + + //fprintf(stderr, "FinalizeBitConsumption(): totFillBits=%d, qcOut->totFillBits=%d \n", totFillBits, qcOut->totFillBits); + + /* now distribute extra fillbits and alignbits */ + alignBits = + 7 - (qcOut->staticBits + qcOut->usedDynBits + qcOut->elementExtBits + + qcOut->totFillBits + qcOut->globalExtBits - 1) % + 8; + + /* Maybe we could remove this */ + if (((alignBits + qcOut->totFillBits - totFillBits) == 8) && + (qcOut->totFillBits > 8)) + qcOut->totFillBits -= 8; + + qcOut->totalBits = qcOut->staticBits + qcOut->usedDynBits + + qcOut->totFillBits + alignBits + qcOut->elementExtBits + + qcOut->globalExtBits; + + if ((qcOut->totalBits > qcKernel->maxBitsPerFrame) || + (qcOut->totalBits < qcKernel->minBitsPerFrame)) { + return AAC_ENC_QUANT_ERROR; + } + + qcOut->alignBits = alignBits; + + return AAC_ENC_OK; +} + +/********************************************************************************* + + functionname: FDKaacEnc_crashRecovery + description: fulfills constraints by means of brute force... + => bits are saved by cancelling out spectral lines!! + (beginning at the highest frequencies) + return: errorcode + +**********************************************************************************/ + +static void FDKaacEnc_crashRecovery(INT nChannels, + PSY_OUT_ELEMENT* psyOutElement, + QC_OUT* qcOut, QC_OUT_ELEMENT* qcElement, + INT bitsToSave, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig) { + INT ch; + INT savedBits = 0; + INT sfb, sfbGrp; + INT bitsPerScf[(2)][MAX_GROUPED_SFB]; + INT sectionToScf[(2)][MAX_GROUPED_SFB]; + INT* sfbOffset; + INT sect, statBitsNew; + QC_OUT_CHANNEL** qcChannel = qcElement->qcOutChannel; + PSY_OUT_CHANNEL** psyChannel = psyOutElement->psyOutChannel; + + /* create a table which converts frq-bins to bit-demand... [bitsPerScf] */ + /* ...and another one which holds the corresponding sections [sectionToScf] */ + for (ch = 0; ch < nChannels; ch++) { + sfbOffset = psyChannel[ch]->sfbOffsets; + + for (sect = 0; sect < qcChannel[ch]->sectionData.noOfSections; sect++) { + INT codeBook = qcChannel[ch]->sectionData.huffsection[sect].codeBook; + + for (sfb = qcChannel[ch]->sectionData.huffsection[sect].sfbStart; + sfb < qcChannel[ch]->sectionData.huffsection[sect].sfbStart + + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt; + sfb++) { + bitsPerScf[ch][sfb] = 0; + if ((codeBook != CODE_BOOK_PNS_NO) /*&& + (sfb < (qcChannel[ch]->sectionData.noOfGroups*qcChannel[ch]->sectionData.maxSfbPerGroup))*/) { + INT sfbStartLine = sfbOffset[sfb]; + INT noOfLines = sfbOffset[sfb + 1] - sfbStartLine; + bitsPerScf[ch][sfb] = FDKaacEnc_countValues( + &(qcChannel[ch]->quantSpec[sfbStartLine]), noOfLines, codeBook); + } + sectionToScf[ch][sfb] = sect; + } + } + } + + /* LOWER [maxSfb] IN BOTH CHANNELS!! */ + /* Attention: in case of stereo: maxSfbL == maxSfbR, GroupingL == GroupingR ; + */ + + for (sfb = qcChannel[0]->sectionData.maxSfbPerGroup - 1; sfb >= 0; sfb--) { + for (sfbGrp = 0; sfbGrp < psyChannel[0]->sfbCnt; + sfbGrp += psyChannel[0]->sfbPerGroup) { + for (ch = 0; ch < nChannels; ch++) { + sect = sectionToScf[ch][sfbGrp + sfb]; + qcChannel[ch]->sectionData.huffsection[sect].sfbCnt--; + savedBits += bitsPerScf[ch][sfbGrp + sfb]; + + if (qcChannel[ch]->sectionData.huffsection[sect].sfbCnt == 0) { + savedBits += (psyChannel[ch]->lastWindowSequence != SHORT_WINDOW) + ? FDKaacEnc_sideInfoTabLong[0] + : FDKaacEnc_sideInfoTabShort[0]; + } + } + } + + /* ...have enough bits been saved? */ + if (savedBits >= bitsToSave) break; + + } /* sfb loop */ + + /* if not enough bits saved, + clean whole spectrum and remove side info overhead */ + if (sfb == -1) { + sfb = 0; + } + + for (ch = 0; ch < nChannels; ch++) { + qcChannel[ch]->sectionData.maxSfbPerGroup = sfb; + psyChannel[ch]->maxSfbPerGroup = sfb; + /* when no spectrum is coded save tools info in bitstream */ + if (sfb == 0) { + FDKmemclear(&psyChannel[ch]->tnsInfo, sizeof(TNS_INFO)); + FDKmemclear(&psyOutElement->toolsInfo, sizeof(TOOLSINFO)); + } + } + /* dynamic bits will be updated in iteration loop */ + + { /* if stop sfb has changed save bits in side info, e.g. MS or TNS coding */ + ELEMENT_INFO elInfo; + + FDKmemclear(&elInfo, sizeof(ELEMENT_INFO)); + elInfo.nChannelsInEl = nChannels; + elInfo.elType = (nChannels == 2) ? ID_CPE : ID_SCE; + + FDKaacEnc_ChannelElementWrite(NULL, &elInfo, NULL, psyOutElement, + psyChannel, syntaxFlags, aot, epConfig, + &statBitsNew, 0); + } + + savedBits = qcElement->staticBitsUsed - statBitsNew; + + /* update static and dynamic bits */ + qcElement->staticBitsUsed -= savedBits; + qcElement->grantedDynBits += savedBits; + + qcOut->staticBits -= savedBits; + qcOut->grantedDynBits += savedBits; + qcOut->maxDynBits += savedBits; +} + +void FDKaacEnc_QCClose(QC_STATE** phQCstate, QC_OUT** phQC) { + int n, i; + + if (phQC != NULL) { + for (n = 0; n < (1); n++) { + if (phQC[n] != NULL) { + QC_OUT* hQC = phQC[n]; + for (i = 0; i < (8); i++) { + } + + for (i = 0; i < ((8)); i++) { + if (hQC->qcElement[i]) FreeRam_aacEnc_QCelement(&hQC->qcElement[i]); + } + + FreeRam_aacEnc_QCout(&phQC[n]); + } + } + } + + if (phQCstate != NULL) { + if (*phQCstate != NULL) { + QC_STATE* hQCstate = *phQCstate; + + if (hQCstate->hAdjThr != NULL) FDKaacEnc_AdjThrClose(&hQCstate->hAdjThr); + + if (hQCstate->hBitCounter != NULL) + FDKaacEnc_BCClose(&hQCstate->hBitCounter); + + for (i = 0; i < ((8)); i++) { + if (hQCstate->elementBits[i] != NULL) { + FreeRam_aacEnc_ElementBits(&hQCstate->elementBits[i]); + } + } + FreeRam_aacEnc_QCstate(phQCstate); + } + } +} diff --git a/fdk-aac/libAACenc/src/qc_main.h b/fdk-aac/libAACenc/src/qc_main.h new file mode 100644 index 0000000..b9e8e2d --- /dev/null +++ b/fdk-aac/libAACenc/src/qc_main.h @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Quantizing & coding + +*******************************************************************************/ + +#ifndef QC_MAIN_H +#define QC_MAIN_H + +#include "aacenc.h" +#include "qc_data.h" +#include "interface.h" +#include "psy_main.h" +#include "tpenc_lib.h" + +/* Quantizing & coding stage */ + +AAC_ENCODER_ERROR FDKaacEnc_QCOutNew(QC_OUT **phQC, const INT nElements, + const INT nChannels, const INT nSubFrames, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_QCOutInit(QC_OUT *phQC[(1)], const INT nSubFrames, + const CHANNEL_MAPPING *cm); + +AAC_ENCODER_ERROR FDKaacEnc_QCNew(QC_STATE **phQC, INT nElements, + UCHAR *dynamic_RAM); + +AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE *hQC, struct QC_INIT *init, + const ULONG initFlags); + +AAC_ENCODER_ERROR FDKaacEnc_QCMainPrepare( + ELEMENT_INFO *elInfo, ATS_ELEMENT *RESTRICT adjThrStateElement, + PSY_OUT_ELEMENT *RESTRICT psyOutElement, + QC_OUT_ELEMENT *RESTRICT qcOutElement, /* returns error code */ + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE *RESTRICT hQC, PSY_OUT **psyOut, + QC_OUT **qcOut, INT avgTotalBits, + CHANNEL_MAPPING *cm, AUDIO_OBJECT_TYPE aot, + UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_updateFillBits(CHANNEL_MAPPING *cm, + QC_STATE *qcKernel, + ELEMENT_BITS *RESTRICT elBits[((8))], + QC_OUT **qcOut); + +void FDKaacEnc_updateBitres(CHANNEL_MAPPING *cm, QC_STATE *qcKernel, + QC_OUT **qcOut); + +AAC_ENCODER_ERROR FDKaacEnc_FinalizeBitConsumption( + CHANNEL_MAPPING *cm, QC_STATE *hQC, QC_OUT *qcOut, + QC_OUT_ELEMENT **qcElement, HANDLE_TRANSPORTENC hTpEnc, + AUDIO_OBJECT_TYPE aot, UINT syntaxFlags, SCHAR epConfig); + +AAC_ENCODER_ERROR FDKaacEnc_AdjustBitrate(QC_STATE *RESTRICT hQC, + CHANNEL_MAPPING *RESTRICT cm, + INT *avgTotalBits, INT bitRate, + INT sampleRate, INT granuleLength); + +void FDKaacEnc_QCClose(QC_STATE **phQCstate, QC_OUT **phQC); + +#endif /* QC_MAIN_H */ diff --git a/fdk-aac/libAACenc/src/quantize.cpp b/fdk-aac/libAACenc/src/quantize.cpp new file mode 100644 index 0000000..4d25263 --- /dev/null +++ b/fdk-aac/libAACenc/src/quantize.cpp @@ -0,0 +1,401 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Quantization + +*******************************************************************************/ + +#include "quantize.h" + +#include "aacEnc_rom.h" + +/***************************************************************************** + + functionname: FDKaacEnc_quantizeLines + description: quantizes spectrum lines + returns: + input: global gain, number of lines to process, spectral data + output: quantized spectrum + +*****************************************************************************/ +static void FDKaacEnc_quantizeLines(INT gain, INT noOfLines, + const FIXP_DBL *mdctSpectrum, + SHORT *quaSpectrum, INT dZoneQuantEnable) { + int line; + FIXP_DBL k = FL2FXCONST_DBL(0.0f); + FIXP_QTD quantizer = FDKaacEnc_quantTableQ[(-gain) & 3]; + INT quantizershift = ((-gain) >> 2) + 1; + const INT kShift = 16; + + if (dZoneQuantEnable) + k = FL2FXCONST_DBL(0.23f) >> kShift; + else + k = FL2FXCONST_DBL(-0.0946f + 0.5f) >> kShift; + + for (line = 0; line < noOfLines; line++) { + FIXP_DBL accu = fMultDiv2(mdctSpectrum[line], quantizer); + + if (accu < FL2FXCONST_DBL(0.0f)) { + accu = -accu; + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not + necessary here since test + value is always > 0 */ + accu <<= accuShift; + INT tabIndex = + (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + INT totalShift = quantizershift - accuShift + 1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex], + FDKaacEnc_quantTableE[totalShift & 3]); + totalShift = (16 - 4) - (3 * (totalShift >> 2)); + FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift, DFRACT_BITS - 1); + quaSpectrum[line] = + (SHORT)(-((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16))); + } else if (accu > FL2FXCONST_DBL(0.0f)) { + /* normalize */ + INT accuShift = CntLeadingZeros(accu) - 1; /* CountLeadingBits() is not + necessary here since test + value is always > 0 */ + accu <<= accuShift; + INT tabIndex = + (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + INT totalShift = quantizershift - accuShift + 1; + accu = fMultDiv2(FDKaacEnc_mTab_3_4[tabIndex], + FDKaacEnc_quantTableE[totalShift & 3]); + totalShift = (16 - 4) - (3 * (totalShift >> 2)); + FDK_ASSERT(totalShift >= 0); /* MAX_QUANT_VIOLATION */ + accu >>= fixMin(totalShift, DFRACT_BITS - 1); + quaSpectrum[line] = (SHORT)((LONG)(k + accu) >> (DFRACT_BITS - 1 - 16)); + } else { + quaSpectrum[line] = 0; + } + } +} + +/***************************************************************************** + + functionname:iFDKaacEnc_quantizeLines + description: iquantizes spectrum lines + mdctSpectrum = iquaSpectrum^4/3 *2^(0.25*gain) + input: global gain, number of lines to process,quantized spectrum + output: spectral data + +*****************************************************************************/ +static void FDKaacEnc_invQuantizeLines(INT gain, INT noOfLines, + SHORT *quantSpectrum, + FIXP_DBL *mdctSpectrum) + +{ + INT iquantizermod; + INT iquantizershift; + INT line; + + iquantizermod = gain & 3; + iquantizershift = gain >> 2; + + for (line = 0; line < noOfLines; line++) { + if (quantSpectrum[line] < 0) { + FIXP_DBL accu; + INT ex, specExp, tabIndex; + FIXP_DBL s, t; + + accu = (FIXP_DBL)-quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS - 1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with + * scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s, t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] - + 1; /* -1 to avoid overflows in accu */ + + if ((-iquantizershift - specExp) < 0) + accu <<= -(-iquantizershift - specExp); + else + accu >>= -iquantizershift - specExp; + + mdctSpectrum[line] = -accu; + } else if (quantSpectrum[line] > 0) { + FIXP_DBL accu; + INT ex, specExp, tabIndex; + FIXP_DBL s, t; + + accu = (FIXP_DBL)(INT)quantSpectrum[line]; + + ex = CountLeadingBits(accu); + accu <<= ex; + specExp = (DFRACT_BITS - 1) - ex; + + FDK_ASSERT(specExp < 14); /* this fails if abs(value) > 8191 */ + + tabIndex = (INT)(accu >> (DFRACT_BITS - 2 - MANT_DIGITS)) & (~MANT_SIZE); + + /* calculate "mantissa" ^4/3 */ + s = FDKaacEnc_mTab_4_3Elc[tabIndex]; + + /* get approperiate exponent multiplier for specExp^3/4 combined with + * scfMod */ + t = FDKaacEnc_specExpMantTableCombElc[iquantizermod][specExp]; + + /* multiply "mantissa" ^4/3 with exponent multiplier */ + accu = fMult(s, t); + + /* get approperiate exponent shifter */ + specExp = FDKaacEnc_specExpTableComb[iquantizermod][specExp] - + 1; /* -1 to avoid overflows in accu */ + + if ((-iquantizershift - specExp) < 0) + accu <<= -(-iquantizershift - specExp); + else + accu >>= -iquantizershift - specExp; + + mdctSpectrum[line] = accu; + } else { + mdctSpectrum[line] = FL2FXCONST_DBL(0.0f); + } + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_QuantizeSpectrum + description: quantizes the entire spectrum + returns: + input: number of scalefactor bands to be quantized, ... + output: quantized spectrum + +*****************************************************************************/ +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT maxSfbPerGroup, INT sfbPerGroup, + const INT *sfbOffset, + const FIXP_DBL *mdctSpectrum, INT globalGain, + const INT *scalefactors, + SHORT *quantizedSpectrum, + INT dZoneQuantEnable) { + INT sfbOffs, sfb; + + /* in FDKaacEnc_quantizeLines quaSpectrum is calculated with: + spec^(3/4) * 2^(-3/16*QSS) * 2^(3/4*scale) + k + simplify scaling calculation and reduce QSS before: + spec^(3/4) * 2^(-3/16*(QSS - 4*scale)) */ + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + INT scalefactor = scalefactors[sfbOffs + sfb]; + + FDKaacEnc_quantizeLines( + globalGain - scalefactor, /* QSS */ + sfbOffset[sfbOffs + sfb + 1] - sfbOffset[sfbOffs + sfb], + mdctSpectrum + sfbOffset[sfbOffs + sfb], + quantizedSpectrum + sfbOffset[sfbOffs + sfb], dZoneQuantEnable); + } +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcSfbDist + description: calculates distortion of quantized values + returns: distortion + input: gain, number of lines to process, spectral data + output: + +*****************************************************************************/ +FIXP_DBL FDKaacEnc_calcSfbDist(const FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, INT gain, + INT dZoneQuantEnable) { + INT i, scale; + FIXP_DBL xfsf; + FIXP_DBL diff; + FIXP_DBL invQuantSpec; + + xfsf = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < noOfLines; i++) { + /* quantization */ + FDKaacEnc_quantizeLines(gain, 1, &mdctSpectrum[i], &quantSpectrum[i], + dZoneQuantEnable); + + if (fAbs(quantSpectrum[i]) > MAX_QUANT) { + return FL2FXCONST_DBL(0.0f); + } + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1); + + diff = scaleValue(diff, -scale); + + xfsf = xfsf + diff; + } + + xfsf = CalcLdData(xfsf); + + return xfsf; +} + +/***************************************************************************** + + functionname: FDKaacEnc_calcSfbQuantEnergyAndDist + description: calculates energy and distortion of quantized values + returns: + input: gain, number of lines to process, quantized spectral data, + spectral data + output: energy, distortion + +*****************************************************************************/ +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, + INT gain, FIXP_DBL *en, + FIXP_DBL *dist) { + INT i, scale; + FIXP_DBL invQuantSpec; + FIXP_DBL diff; + + FIXP_DBL energy = FL2FXCONST_DBL(0.0f); + FIXP_DBL distortion = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < noOfLines; i++) { + if (fAbs(quantSpectrum[i]) > MAX_QUANT) { + *en = FL2FXCONST_DBL(0.0f); + *dist = FL2FXCONST_DBL(0.0f); + return; + } + + /* inverse quantization */ + FDKaacEnc_invQuantizeLines(gain, 1, &quantSpectrum[i], &invQuantSpec); + + /* energy */ + energy += fPow2(invQuantSpec); + + /* dist */ + diff = fixp_abs(fixp_abs(invQuantSpec) - fixp_abs(mdctSpectrum[i] >> 1)); + + scale = CountLeadingBits(diff); + diff = scaleValue(diff, scale); + diff = fPow2(diff); + + scale = fixMin(2 * (scale - 1), DFRACT_BITS - 1); + + diff = scaleValue(diff, -scale); + + distortion += diff; + } + + *en = CalcLdData(energy) + FL2FXCONST_DBL(0.03125f); + *dist = CalcLdData(distortion); +} diff --git a/fdk-aac/libAACenc/src/quantize.h b/fdk-aac/libAACenc/src/quantize.h new file mode 100644 index 0000000..dfc2206 --- /dev/null +++ b/fdk-aac/libAACenc/src/quantize.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Quantization + +*******************************************************************************/ + +#ifndef QUANTIZE_H +#define QUANTIZE_H + +#include "common_fix.h" + +/* quantizing */ + +#define MAX_QUANT 8191 + +void FDKaacEnc_QuantizeSpectrum(INT sfbCnt, INT maxSfbPerGroup, INT sfbPerGroup, + const INT *sfbOffset, + const FIXP_DBL *mdctSpectrum, INT globalGain, + const INT *scalefactors, + SHORT *quantizedSpectrum, INT dZoneQuantEnable); + +FIXP_DBL FDKaacEnc_calcSfbDist(const FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, INT gain, + INT dZoneQuantEnable); + +void FDKaacEnc_calcSfbQuantEnergyAndDist(FIXP_DBL *mdctSpectrum, + SHORT *quantSpectrum, INT noOfLines, + INT gain, FIXP_DBL *en, + FIXP_DBL *dist); + +#endif /* QUANTIZE_H */ diff --git a/fdk-aac/libAACenc/src/sf_estim.cpp b/fdk-aac/libAACenc/src/sf_estim.cpp new file mode 100644 index 0000000..17a8ae2 --- /dev/null +++ b/fdk-aac/libAACenc/src/sf_estim.cpp @@ -0,0 +1,1292 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Scale factor estimation + +*******************************************************************************/ + +#include "sf_estim.h" +#include "aacEnc_rom.h" +#include "quantize.h" +#include "bit_cnt.h" + +#ifdef __arm__ +#endif + +#define UPCOUNT_LIMIT 1 +#define AS_PE_FAC_SHIFT 7 +#define DIST_FAC_SHIFT 3 +#define AS_PE_FAC_FLOAT (float)(1 << AS_PE_FAC_SHIFT) +static const INT MAX_SCF_DELTA = 60; + +static const FIXP_DBL PE_C1 = FL2FXCONST_DBL( + 3.0f / AS_PE_FAC_FLOAT); /* (log(8.0)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C2 = FL2FXCONST_DBL( + 1.3219281f / AS_PE_FAC_FLOAT); /* (log(2.5)/log(2)) >> AS_PE_FAC_SHIFT */ +static const FIXP_DBL PE_C3 = FL2FXCONST_DBL(0.5593573f); /* 1-C2/C1 */ + +/* + Function; FDKaacEnc_FDKaacEnc_CalcFormFactorChannel + + Description: Calculates the formfactor + + sf: scale factor of the mdct spectrum + sfbFormFactorLdData is scaled with the factor 1/(((2^sf)^0.5) * + (2^FORM_FAC_SHIFT)) +*/ +static void FDKaacEnc_FDKaacEnc_CalcFormFactorChannel( + FIXP_DBL *RESTRICT sfbFormFactorLdData, + PSY_OUT_CHANNEL *RESTRICT psyOutChan) { + INT j, sfb, sfbGrp; + FIXP_DBL formFactor; + + int tmp0 = psyOutChan->sfbCnt; + int tmp1 = psyOutChan->maxSfbPerGroup; + int step = psyOutChan->sfbPerGroup; + for (sfbGrp = 0; sfbGrp < tmp0; sfbGrp += step) { + for (sfb = 0; sfb < tmp1; sfb++) { + formFactor = FL2FXCONST_DBL(0.0f); + /* calc sum of sqrt(spec) */ + for (j = psyOutChan->sfbOffsets[sfbGrp + sfb]; + j < psyOutChan->sfbOffsets[sfbGrp + sfb + 1]; j++) { + formFactor += + sqrtFixp(fixp_abs(psyOutChan->mdctSpectrum[j])) >> FORM_FAC_SHIFT; + } + sfbFormFactorLdData[sfbGrp + sfb] = CalcLdData(formFactor); + } + /* set sfbFormFactor for sfbs with zero spec to zero. Just for debugging. */ + for (; sfb < psyOutChan->sfbPerGroup; sfb++) { + sfbFormFactorLdData[sfbGrp + sfb] = FL2FXCONST_DBL(-1.0f); + } + } +} + +/* + Function: FDKaacEnc_CalcFormFactor + + Description: Calls FDKaacEnc_FDKaacEnc_CalcFormFactorChannel() for each + channel +*/ + +void FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels) { + INT j; + for (j = 0; j < nChannels; j++) { + FDKaacEnc_FDKaacEnc_CalcFormFactorChannel( + qcOutChannel[j]->sfbFormFactorLdData, psyOutChannel[j]); + } +} + +/* + Function: FDKaacEnc_calcSfbRelevantLines + + Description: Calculates sfbNRelevantLines + + sfbNRelevantLines is scaled with the factor 1/((2^FORM_FAC_SHIFT) * 2.0) +*/ +static void FDKaacEnc_calcSfbRelevantLines( + const FIXP_DBL *const sfbFormFactorLdData, + const FIXP_DBL *const sfbEnergyLdData, + const FIXP_DBL *const sfbThresholdLdData, const INT *const sfbOffsets, + const INT sfbCnt, const INT sfbPerGroup, const INT maxSfbPerGroup, + FIXP_DBL *sfbNRelevantLines) { + INT sfbOffs, sfb; + FIXP_DBL sfbWidthLdData; + FIXP_DBL asPeFacLdData = + FL2FXCONST_DBL(0.109375); /* AS_PE_FAC_SHIFT*ld64(2) */ + FIXP_DBL accu; + + /* sfbNRelevantLines[i] = 2^( (sfbFormFactorLdData[i] - 0.25 * + * (sfbEnergyLdData[i] - ld64(sfbWidth[i]/(2^7)) - AS_PE_FAC_SHIFT*ld64(2)) * + * 64); */ + + FDKmemclear(sfbNRelevantLines, sfbCnt * sizeof(FIXP_DBL)); + + for (sfbOffs = 0; sfbOffs < sfbCnt; sfbOffs += sfbPerGroup) { + for (sfb = 0; sfb < maxSfbPerGroup; sfb++) { + /* calc sum of sqrt(spec) */ + if ((FIXP_DBL)sfbEnergyLdData[sfbOffs + sfb] > + (FIXP_DBL)sfbThresholdLdData[sfbOffs + sfb]) { + INT sfbWidth = + sfbOffsets[sfbOffs + sfb + 1] - sfbOffsets[sfbOffs + sfb]; + + /* avgFormFactorLdData = + * sqrtFixp(sqrtFixp(sfbEnergyLdData[sfbOffs+sfb]/sfbWidth)); */ + /* sfbNRelevantLines[sfbOffs+sfb] = sfbFormFactor[sfbOffs+sfb] / + * avgFormFactorLdData; */ + sfbWidthLdData = + (FIXP_DBL)(sfbWidth << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + sfbWidthLdData = CalcLdData(sfbWidthLdData); + + accu = sfbEnergyLdData[sfbOffs + sfb] - sfbWidthLdData - asPeFacLdData; + accu = sfbFormFactorLdData[sfbOffs + sfb] - (accu >> 2); + + sfbNRelevantLines[sfbOffs + sfb] = CalcInvLdData(accu) >> 1; + } + } + } +} + +/* + Function: FDKaacEnc_countSingleScfBits + + Description: + + scfBitsFract is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countSingleScfBits(INT scf, INT scfLeft, + INT scfRight) { + FIXP_DBL scfBitsFract; + + scfBitsFract = (FIXP_DBL)(FDKaacEnc_bitCountScalefactorDelta(scfLeft - scf) + + FDKaacEnc_bitCountScalefactorDelta(scf - scfRight)); + + scfBitsFract = scfBitsFract << (DFRACT_BITS - 1 - (2 * AS_PE_FAC_SHIFT)); + + return scfBitsFract; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_calcSingleSpecPe + + specPe is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_calcSingleSpecPe(INT scf, FIXP_DBL sfbConstPePart, + FIXP_DBL nLines) { + FIXP_DBL specPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL ldRatio; + FIXP_DBL scfFract; + + scfFract = (FIXP_DBL)(scf << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + + ldRatio = sfbConstPePart - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + if (ldRatio >= PE_C1) { + specPe = fMult(FL2FXCONST_DBL(0.7f), fMult(nLines, ldRatio)); + } else { + specPe = fMult(FL2FXCONST_DBL(0.7f), + fMult(nLines, (PE_C2 + fMult(PE_C3, ldRatio)))); + } + + return specPe; /* output scaled by 1/(2^(2*AS_PE_FAC)) */ +} + +/* + Function: FDKaacEnc_countScfBitsDiff + + scfBitsDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_countScfBitsDiff(INT *scfOld, INT *scfNew, INT sfbCnt, + INT startSfb, INT stopSfb) { + FIXP_DBL scfBitsFract; + INT scfBitsDiff = 0; + INT sfb = 0, sfbLast; + INT sfbPrev, sfbNext; + + /* search for first relevant sfb */ + sfbLast = startSfb; + while ((sfbLast < stopSfb) && (scfOld[sfbLast] == FDK_INT_MIN)) sfbLast++; + /* search for previous relevant sfb and count diff */ + sfbPrev = startSfb - 1; + while ((sfbPrev >= 0) && (scfOld[sfbPrev] == FDK_INT_MIN)) sfbPrev--; + if (sfbPrev >= 0) + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbPrev] - scfNew[sfbLast]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbPrev] - scfOld[sfbLast]); + /* now loop through all sfbs and count diffs of relevant sfbs */ + for (sfb = sfbLast + 1; sfb < stopSfb; sfb++) { + if (scfOld[sfb] != FDK_INT_MIN) { + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfb]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfb]); + sfbLast = sfb; + } + } + /* search for next relevant sfb and count diff */ + sfbNext = stopSfb; + while ((sfbNext < sfbCnt) && (scfOld[sfbNext] == FDK_INT_MIN)) sfbNext++; + if (sfbNext < sfbCnt) + scfBitsDiff += + FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast] - scfNew[sfbNext]) - + FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast] - scfOld[sfbNext]); + + scfBitsFract = + (FIXP_DBL)(scfBitsDiff << (DFRACT_BITS - 1 - (2 * AS_PE_FAC_SHIFT))); + + return scfBitsFract; +} + +/* + Function: FDKaacEnc_calcSpecPeDiff + + specPeDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT)) +*/ +static FIXP_DBL FDKaacEnc_calcSpecPeDiff( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, INT *scfOld, + INT *scfNew, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines, INT startSfb, INT stopSfb) { + FIXP_DBL specPeDiff = FL2FXCONST_DBL(0.0f); + FIXP_DBL scfFract = FL2FXCONST_DBL(0.0f); + INT sfb; + + /* loop through all sfbs and count pe difference */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfOld[sfb] != FDK_INT_MIN) { + FIXP_DBL ldRatioOld, ldRatioNew, pOld, pNew; + + /* sfbConstPePart[sfb] = (float)log(psyOutChan->sfbEnergy[sfb] * 6.75f / + * sfbFormFactor[sfb]) * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for + * log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfb] == (FIXP_DBL)FDK_INT_MIN) + sfbConstPePart[sfb] = + ((psyOutChan->sfbEnergyLdData[sfb] - sfbFormFactorLdData[sfb] - + FL2FXCONST_DBL(0.09375f)) >> + 1) + + FL2FXCONST_DBL(0.02152255861f); + + scfFract = (FIXP_DBL)(scfOld[sfb] << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + ldRatioOld = + sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + scfFract = (FIXP_DBL)(scfNew[sfb] << (DFRACT_BITS - 1 - AS_PE_FAC_SHIFT)); + ldRatioNew = + sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f), scfFract); + + if (ldRatioOld >= PE_C1) + pOld = ldRatioOld; + else + pOld = PE_C2 + fMult(PE_C3, ldRatioOld); + + if (ldRatioNew >= PE_C1) + pNew = ldRatioNew; + else + pNew = PE_C2 + fMult(PE_C3, ldRatioNew); + + specPeDiff += fMult(FL2FXCONST_DBL(0.7f), + fMult(sfbNRelevantLines[sfb], (pNew - pOld))); + } + } + + return specPeDiff; +} + +/* + Function: FDKaacEnc_improveScf + + Description: Calculate the distortion by quantization and inverse quantization + of the spectrum with various scalefactors. The scalefactor which provides the + best results will be used. +*/ +static INT FDKaacEnc_improveScf(const FIXP_DBL *spec, SHORT *quantSpec, + SHORT *quantSpecTmp, INT sfbWidth, + FIXP_DBL threshLdData, INT scf, INT minScf, + FIXP_DBL *distLdData, INT *minScfCalculated, + INT dZoneQuantEnable) { + FIXP_DBL sfbDistLdData; + INT scfBest = scf; + INT k; + FIXP_DBL distFactorLdData = FL2FXCONST_DBL(-0.0050301265); /* ld64(1/1.25) */ + + /* calc real distortion */ + sfbDistLdData = + FDKaacEnc_calcSfbDist(spec, quantSpec, sfbWidth, scf, dZoneQuantEnable); + *minScfCalculated = scf; + /* nmr > 1.25 -> try to improve nmr */ + if (sfbDistLdData > (threshLdData - distFactorLdData)) { + INT scfEstimated = scf; + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + INT cnt; + /* improve by bigger scf ? */ + cnt = 0; + + while ((sfbDistLdData > (threshLdData - distFactorLdData)) && + (cnt++ < UPCOUNT_LIMIT)) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + } + /* improve by smaller scf ? */ + cnt = 0; + scf = scfEstimated; + sfbDistLdData = sfbDistBestLdData; + while ((sfbDistLdData > (threshLdData - distFactorLdData)) && (cnt++ < 1) && + (scf > minScf)) { + scf--; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistBestLdData) { + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + *minScfCalculated = scf; + } + *distLdData = sfbDistBestLdData; + } else { /* nmr <= 1.25 -> try to find bigger scf to use less bits */ + FIXP_DBL sfbDistBestLdData = sfbDistLdData; + FIXP_DBL sfbDistAllowedLdData = + fixMin(sfbDistLdData - distFactorLdData, threshLdData); + int cnt; + for (cnt = 0; cnt < UPCOUNT_LIMIT; cnt++) { + scf++; + sfbDistLdData = FDKaacEnc_calcSfbDist(spec, quantSpecTmp, sfbWidth, scf, + dZoneQuantEnable); + + if (sfbDistLdData < sfbDistAllowedLdData) { + *minScfCalculated = scfBest + 1; + scfBest = scf; + sfbDistBestLdData = sfbDistLdData; + for (k = 0; k < sfbWidth; k++) quantSpec[k] = quantSpecTmp[k]; + } + } + *distLdData = sfbDistBestLdData; + } + + /* return best scalefactor */ + return scfBest; +} + +/* + Function: FDKaacEnc_assimilateSingleScf + +*/ +static void FDKaacEnc_assimilateSingleScf( + const PSY_OUT_CHANNEL *psyOutChan, const QC_OUT_CHANNEL *qcOutChannel, + SHORT *quantSpec, SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, + const INT *minScf, FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, + const FIXP_DBL *sfbFormFactorLdData, const FIXP_DBL *sfbNRelevantLines, + INT *minScfCalculated, INT restartOnSuccess) { + INT sfbLast, sfbAct, sfbNext; + INT scfAct, *scfLast, *scfNext, scfMin, scfMax; + INT sfbWidth, sfbOffs; + FIXP_DBL enLdData; + FIXP_DBL sfbPeOld, sfbPeNew; + FIXP_DBL sfbDistNew; + INT i, k; + INT success = 0; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew, deltaPeTmp; + INT prevScfLast[MAX_GROUPED_SFB], prevScfNext[MAX_GROUPED_SFB]; + FIXP_DBL deltaPeLast[MAX_GROUPED_SFB]; + INT updateMinScfCalculated; + + for (i = 0; i < psyOutChan->sfbCnt; i++) { + prevScfLast[i] = FDK_INT_MAX; + prevScfNext[i] = FDK_INT_MAX; + deltaPeLast[i] = (FIXP_DBL)FDK_INT_MAX; + } + + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + do { + /* search for new relevant sfb */ + sfbNext++; + while ((sfbNext < psyOutChan->sfbCnt) && (scf[sfbNext] == FDK_INT_MIN)) + sfbNext++; + if ((sfbLast >= 0) && (sfbAct >= 0) && (sfbNext < psyOutChan->sfbCnt)) { + /* relevant scfs to the left and to the right */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = scf + sfbNext; + scfMin = fixMin(*scfLast, *scfNext); + scfMax = fixMax(*scfLast, *scfNext); + } else if ((sfbLast == -1) && (sfbAct >= 0) && + (sfbNext < psyOutChan->sfbCnt)) { + /* first relevant scf */ + scfAct = scf[sfbAct]; + scfLast = &scfAct; + scfNext = scf + sfbNext; + scfMin = *scfNext; + scfMax = *scfNext; + } else if ((sfbLast >= 0) && (sfbAct >= 0) && + (sfbNext == psyOutChan->sfbCnt)) { + /* last relevant scf */ + scfAct = scf[sfbAct]; + scfLast = scf + sfbLast; + scfNext = &scfAct; + scfMin = *scfLast; + scfMax = *scfLast; + } + if (sfbAct >= 0) scfMin = fixMax(scfMin, minScf[sfbAct]); + + if ((sfbAct >= 0) && (sfbLast >= 0 || sfbNext < psyOutChan->sfbCnt) && + (scfAct > scfMin) && (scfAct <= scfMin + MAX_SCF_DELTA) && + (scfAct >= scfMax - MAX_SCF_DELTA) && + (scfAct <= + fixMin(scfMin, fixMin(*scfLast, *scfNext)) + MAX_SCF_DELTA) && + (*scfLast != prevScfLast[sfbAct] || *scfNext != prevScfNext[sfbAct] || + deltaPe < deltaPeLast[sfbAct])) { + /* bigger than neighbouring scf found, try to use smaller scf */ + success = 0; + + sfbWidth = + psyOutChan->sfbOffsets[sfbAct + 1] - psyOutChan->sfbOffsets[sfbAct]; + sfbOffs = psyOutChan->sfbOffsets[sfbAct]; + + /* estimate required bits for actual scf */ + enLdData = qcOutChannel->sfbEnergyLdData[sfbAct]; + + /* sfbConstPePart[sfbAct] = (float)log(6.75f*en/sfbFormFactor[sfbAct]) * + * LOG2_1; */ + /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for + * log2 */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + if (sfbConstPePart[sfbAct] == (FIXP_DBL)FDK_INT_MIN) { + sfbConstPePart[sfbAct] = ((enLdData - sfbFormFactorLdData[sfbAct] - + FL2FXCONST_DBL(0.09375f)) >> + 1) + + FL2FXCONST_DBL(0.02152255861f); + } + + sfbPeOld = FDKaacEnc_calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], + sfbNRelevantLines[sfbAct]) + + FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext); + + deltaPeNew = deltaPe; + updateMinScfCalculated = 1; + + do { + /* estimate required bits for smaller scf */ + scfAct--; + /* check only if the same check was not done before */ + if (scfAct < minScfCalculated[sfbAct] && + scfAct >= scfMax - MAX_SCF_DELTA) { + /* estimate required bits for new scf */ + sfbPeNew = FDKaacEnc_calcSingleSpecPe(scfAct, sfbConstPePart[sfbAct], + sfbNRelevantLines[sfbAct]) + + FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext); + + /* use new scf if no increase in pe and + quantization error is smaller */ + deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld; + /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */ + if (deltaPeTmp < FL2FXCONST_DBL(0.0006103515625f)) { + /* distortion of new scf */ + sfbDistNew = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs, quantSpecTmp + sfbOffs, + sfbWidth, scfAct, dZoneQuantEnable); + + if (sfbDistNew < sfbDist[sfbAct]) { + /* success, replace scf by new one */ + scf[sfbAct] = scfAct; + sfbDist[sfbAct] = sfbDistNew; + + for (k = 0; k < sfbWidth; k++) + quantSpec[sfbOffs + k] = quantSpecTmp[sfbOffs + k]; + + deltaPeNew = deltaPeTmp; + success = 1; + } + /* mark as already checked */ + if (updateMinScfCalculated) minScfCalculated[sfbAct] = scfAct; + } else { + /* from this scf value on not all new values have been checked */ + updateMinScfCalculated = 0; + } + } + } while (scfAct > scfMin); + + deltaPe = deltaPeNew; + + /* save parameters to avoid multiple computations of the same sfb */ + prevScfLast[sfbAct] = *scfLast; + prevScfNext[sfbAct] = *scfNext; + deltaPeLast[sfbAct] = deltaPe; + } + + if (success && restartOnSuccess) { + /* start again at first sfb */ + sfbLast = -1; + sfbAct = -1; + sfbNext = -1; + scfLast = 0; + scfNext = 0; + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MAX; + success = 0; + } else { + /* shift sfbs for next band */ + sfbLast = sfbAct; + sfbAct = sfbNext; + } + } while (sfbNext < psyOutChan->sfbCnt); +} + +/* + Function: FDKaacEnc_assimilateMultipleScf + +*/ +static void FDKaacEnc_assimilateMultipleScf( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, + SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, const INT *minScf, + FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) { + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfMin, scfMax, scfAct; + INT possibleRegionFound; + INT sfbWidth, sfbOffs, i, k; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew; + INT sfbCnt = psyOutChan->sfbCnt; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb = 0; sfb < sfbCnt; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scfMin = fixMin(scfMin, scf[sfb]); + scfMax = fixMax(scfMax, scf[sfb]); + } + } + + if (scfMax != FDK_INT_MIN && scfMax <= scfMin + MAX_SCF_DELTA) { + scfAct = scfMax; + + do { + /* try smaller scf */ + scfAct--; + for (i = 0; i < MAX_GROUPED_SFB; i++) scfTmp[i] = scf[i]; + stopSfb = 0; + do { + /* search for region where all scfs are bigger than scfAct */ + sfb = stopSfb; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN || scf[sfb] <= scfAct)) + sfb++; + startSfb = sfb; + sfb++; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN || scf[sfb] > scfAct)) + sfb++; + stopSfb = sfb; + + /* check if in all sfb of a valid region scfAct >= minScf[sfb] */ + possibleRegionFound = 0; + if (startSfb < sfbCnt) { + possibleRegionFound = 1; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) + if (scfAct < minScf[sfb]) { + possibleRegionFound = 0; + break; + } + } + } + + if (possibleRegionFound) { /* region found */ + + /* replace scfs in region by scfAct */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfAct; + } + + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + + /* new bit demand small enough ? */ + /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */ + if (deltaPeNew < FL2FXCONST_DBL(0.0006103515625f)) { + /* quantize and calc sum of new distortion */ + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + + sfbWidth = psyOutChan->sfbOffsets[sfb + 1] - + psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs, + quantSpecTmp + sfbOffs, sfbWidth, scfAct, dZoneQuantEnable); + + if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + sfbWidth = psyOutChan->sfbOffsets[sfb + 1] - + psyOutChan->sfbOffsets[sfb]; + sfbOffs = psyOutChan->sfbOffsets[sfb]; + scf[sfb] = scfAct; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbWidth; k++) + quantSpec[sfbOffs + k] = quantSpecTmp[sfbOffs + k]; + } + } + } + } + } + + } while (stopSfb <= sfbCnt); + + } while (scfAct > scfMin); + } +} + +/* + Function: FDKaacEnc_FDKaacEnc_assimilateMultipleScf2 + +*/ +static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2( + PSY_OUT_CHANNEL *psyOutChan, QC_OUT_CHANNEL *qcOutChannel, SHORT *quantSpec, + SHORT *quantSpecTmp, INT dZoneQuantEnable, INT *scf, const INT *minScf, + FIXP_DBL *sfbDist, FIXP_DBL *sfbConstPePart, FIXP_DBL *sfbFormFactorLdData, + FIXP_DBL *sfbNRelevantLines) { + INT sfb, startSfb, stopSfb; + INT scfTmp[MAX_GROUPED_SFB], scfAct, scfNew; + INT scfPrev, scfNext, scfPrevNextMin, scfPrevNextMax, scfLo, scfHi; + INT scfMin, scfMax; + INT *sfbOffs = psyOutChan->sfbOffsets; + FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], sfbDistMax[MAX_GROUPED_SFB]; + FIXP_DBL distOldSum, distNewSum; + INT deltaScfBits; + FIXP_DBL deltaSpecPe; + FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f); + FIXP_DBL deltaPeNew = FL2FXCONST_DBL(0.0f); + INT sfbCnt = psyOutChan->sfbCnt; + INT bSuccess, bCheckScf; + INT i, k; + + /* calc min and max scalfactors */ + scfMin = FDK_INT_MAX; + scfMax = FDK_INT_MIN; + for (sfb = 0; sfb < sfbCnt; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scfMin = fixMin(scfMin, scf[sfb]); + scfMax = fixMax(scfMax, scf[sfb]); + } + } + + stopSfb = 0; + scfAct = FDK_INT_MIN; + do { + /* search for region with same scf values scfAct */ + scfPrev = scfAct; + + sfb = stopSfb; + while (sfb < sfbCnt && (scf[sfb] == FDK_INT_MIN)) sfb++; + startSfb = sfb; + scfAct = scf[startSfb]; + sfb++; + while (sfb < sfbCnt && + ((scf[sfb] == FDK_INT_MIN) || (scf[sfb] == scf[startSfb]))) + sfb++; + stopSfb = sfb; + + if (stopSfb < sfbCnt) + scfNext = scf[stopSfb]; + else + scfNext = scfAct; + + if (scfPrev == FDK_INT_MIN) scfPrev = scfAct; + + scfPrevNextMax = fixMax(scfPrev, scfNext); + scfPrevNextMin = fixMin(scfPrev, scfNext); + + /* try to reduce bits by checking scf values in the range + scf[startSfb]...scfHi */ + scfHi = fixMax(scfPrevNextMax, scfAct); + /* try to find a better solution by reducing the scf difference to + the nearest possible lower scf */ + if (scfPrevNextMax >= scfAct) + scfLo = fixMin(scfAct, scfPrevNextMin); + else + scfLo = scfPrevNextMax; + + if (startSfb < sfbCnt && + scfHi - scfLo <= MAX_SCF_DELTA) { /* region found */ + /* 1. try to save bits by coarser quantization */ + if (scfHi > scf[startSfb]) { + /* calculate the allowed distortion */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + /* sfbDistMax[sfb] = + * (float)pow(qcOutChannel->sfbThreshold[sfb]*sfbDist[sfb]*sfbDist[sfb],1.0f/3.0f); + */ + /* sfbDistMax[sfb] = + * fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergy[sfb]*FL2FXCONST_DBL(1.e-3f)); + */ + /* -0.15571537944 = ld64(1.e-3f)*/ + sfbDistMax[sfb] = fMult(FL2FXCONST_DBL(1.0f / 3.0f), + qcOutChannel->sfbThresholdLdData[sfb]) + + fMult(FL2FXCONST_DBL(1.0f / 3.0f), sfbDist[sfb]) + + fMult(FL2FXCONST_DBL(1.0f / 3.0f), sfbDist[sfb]); + sfbDistMax[sfb] = + fixMax(sfbDistMax[sfb], qcOutChannel->sfbEnergyLdData[sfb] - + FL2FXCONST_DBL(0.15571537944)); + sfbDistMax[sfb] = + fixMin(sfbDistMax[sfb], qcOutChannel->sfbThresholdLdData[sfb]); + } + } + + /* loop over all possible scf values for this region */ + bCheckScf = 1; + for (scfNew = scf[startSfb] + 1; scfNew <= scfHi; scfNew++) { + for (k = 0; k < MAX_GROUPED_SFB; k++) scfTmp[k] = scf[k]; + + /* replace scfs in region by scfNew */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfNew; + } + + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + + /* new bit demand small enough ? */ + if (deltaPeNew < FL2FXCONST_DBL(0.0f)) { + bSuccess = 1; + + /* quantize and calc sum of new distortion */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpecTmp + sfbOffs[sfb], + sfbOffs[sfb + 1] - sfbOffs[sfb], scfNew, dZoneQuantEnable); + + if (sfbDistNew[sfb] > sfbDistMax[sfb]) { + /* no improvement, skip further dist. calculations */ + bSuccess = 0; + if (sfbDistNew[sfb] == qcOutChannel->sfbEnergyLdData[sfb]) { + /* if whole sfb is already quantized to 0, further + checks with even coarser quant. are useless*/ + bCheckScf = 0; + } + break; + } + } + } + if (bCheckScf == 0) /* further calculations useless ? */ + break; + /* distortion small enough ? -> use new scalefactors */ + if (bSuccess) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbOffs[sfb + 1] - sfbOffs[sfb]; k++) + quantSpec[sfbOffs[sfb] + k] = + quantSpecTmp[sfbOffs[sfb] + k]; + } + } + } + } + } + } + + /* 2. only if coarser quantization was not successful, try to find + a better solution by finer quantization and reducing bits for + scalefactor coding */ + if (scfAct == scf[startSfb] && scfLo < scfAct && + scfMax - scfMin <= MAX_SCF_DELTA) { + int bminScfViolation = 0; + + for (k = 0; k < MAX_GROUPED_SFB; k++) scfTmp[k] = scf[k]; + + scfNew = scfLo; + + /* replace scfs in region by scfNew and + check if in all sfb scfNew >= minScf[sfb] */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + scfTmp[sfb] = scfNew; + if (scfNew < minScf[sfb]) bminScfViolation = 1; + } + } + + if (!bminScfViolation) { + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + + deltaSpecPe = FDKaacEnc_calcSpecPeDiff( + psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines, startSfb, stopSfb); + + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe; + } + + /* new bit demand small enough ? */ + if (!bminScfViolation && deltaPeNew < FL2FXCONST_DBL(0.0f)) { + /* quantize and calc sum of new distortion */ + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + + sfbDistNew[sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpecTmp + sfbOffs[sfb], sfbOffs[sfb + 1] - sfbOffs[sfb], + scfNew, dZoneQuantEnable); + + if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) { + /* no improvement, skip further dist. calculations */ + distNewSum = distOldSum << 1; + break; + } + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < fMult(FL2FXCONST_DBL(0.8f), distOldSum)) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + + for (k = 0; k < sfbOffs[sfb + 1] - sfbOffs[sfb]; k++) + quantSpec[sfbOffs[sfb] + k] = quantSpecTmp[sfbOffs[sfb] + k]; + } + } + } + } + } + + /* 3. try to find a better solution (save bits) by only reducing the + scalefactor without new quantization */ + if (scfMax - scfMin <= + MAX_SCF_DELTA - 3) { /* 3 bec. scf is reduced 3 times, + see for loop below */ + + for (k = 0; k < sfbCnt; k++) scfTmp[k] = scf[k]; + + for (i = 0; i < 3; i++) { + scfNew = scfTmp[startSfb] - 1; + /* replace scfs in region by scfNew */ + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) scfTmp[sfb] = scfNew; + } + /* estimate change in bit demand for new scfs */ + deltaScfBits = FDKaacEnc_countScfBitsDiff(scf, scfTmp, sfbCnt, + startSfb, stopSfb); + deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits; + /* new bit demand small enough ? */ + if (deltaPeNew <= FL2FXCONST_DBL(0.0f)) { + bSuccess = 1; + distOldSum = distNewSum = FL2FXCONST_DBL(0.0f); + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scfTmp[sfb] != FDK_INT_MIN) { + FIXP_DBL sfbEnQ; + /* calc the energy and distortion of the quantized spectrum for + a smaller scf */ + FDKaacEnc_calcSfbQuantEnergyAndDist( + qcOutChannel->mdctSpectrum + sfbOffs[sfb], + quantSpec + sfbOffs[sfb], sfbOffs[sfb + 1] - sfbOffs[sfb], + scfNew, &sfbEnQ, &sfbDistNew[sfb]); + + distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT; + distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT; + + /* 0.00259488556167 = ld64(1.122f) */ + /* -0.00778722686652 = ld64(0.7079f) */ + if ((sfbDistNew[sfb] > + (sfbDist[sfb] + FL2FXCONST_DBL(0.00259488556167f))) || + (sfbEnQ < (qcOutChannel->sfbEnergyLdData[sfb] - + FL2FXCONST_DBL(0.00778722686652f)))) { + bSuccess = 0; + break; + } + } + } + /* distortion smaller ? -> use new scalefactors */ + if (distNewSum < distOldSum && bSuccess) { + deltaPe = deltaPeNew; + for (sfb = startSfb; sfb < stopSfb; sfb++) { + if (scf[sfb] != FDK_INT_MIN) { + scf[sfb] = scfNew; + sfbDist[sfb] = sfbDistNew[sfb]; + } + } + } + } + } + } + } + } while (stopSfb <= sfbCnt); +} + +static void FDKaacEnc_EstimateScaleFactorsChannel( + QC_OUT_CHANNEL *qcOutChannel, PSY_OUT_CHANNEL *psyOutChannel, + INT *RESTRICT scf, INT *RESTRICT globalGain, + FIXP_DBL *RESTRICT sfbFormFactorLdData, const INT invQuant, + SHORT *RESTRICT quantSpec, const INT dZoneQuantEnable) { + INT i, j, sfb, sfbOffs; + INT scfInt; + INT maxSf; + INT minSf; + FIXP_DBL threshLdData; + FIXP_DBL energyLdData; + FIXP_DBL energyPartLdData; + FIXP_DBL thresholdPartLdData; + FIXP_DBL scfFract; + FIXP_DBL maxSpec; + INT minScfCalculated[MAX_GROUPED_SFB]; + FIXP_DBL sfbDistLdData[MAX_GROUPED_SFB]; + C_ALLOC_SCRATCH_START(quantSpecTmp, SHORT, (1024)) + INT minSfMaxQuant[MAX_GROUPED_SFB]; + + FIXP_DBL threshConstLdData = + FL2FXCONST_DBL(0.04304511722f); /* log10(6.75)/log10(2.0)/64.0 */ + FIXP_DBL convConst = FL2FXCONST_DBL(0.30102999566f); /* log10(2.0) */ + FIXP_DBL c1Const = + FL2FXCONST_DBL(-0.27083183594f); /* C1 = -69.33295 => C1/2^8 */ + + if (invQuant > 0) { + FDKmemclear(quantSpec, (1024) * sizeof(SHORT)); + } + + /* scfs without energy or with thresh>energy are marked with FDK_INT_MIN */ + for (i = 0; i < psyOutChannel->sfbCnt; i++) { + scf[i] = FDK_INT_MIN; + } + + for (i = 0; i < MAX_GROUPED_SFB; i++) { + minSfMaxQuant[i] = FDK_INT_MIN; + } + + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + threshLdData = qcOutChannel->sfbThresholdLdData[sfbOffs + sfb]; + energyLdData = qcOutChannel->sfbEnergyLdData[sfbOffs + sfb]; + + sfbDistLdData[sfbOffs + sfb] = energyLdData; + + if (energyLdData > threshLdData) { + FIXP_DBL tmp; + + /* energyPart = (float)log10(sfbFormFactor[sfbOffs+sfb]); */ + /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */ + energyPartLdData = + sfbFormFactorLdData[sfbOffs + sfb] + FL2FXCONST_DBL(0.09375f); + + /* influence of allowed distortion */ + /* thresholdPart = (float)log10(6.75*thresh+FLT_MIN); */ + thresholdPartLdData = threshConstLdData + threshLdData; + + /* scf calc */ + /* scfFloat = 8.8585f * (thresholdPart - energyPart); */ + scfFract = thresholdPartLdData - energyPartLdData; + /* conversion from log2 to log10 */ + scfFract = fMult(convConst, scfFract); + /* (8.8585f * scfFract)/8 = 8/8 * scfFract + 0.8585 * scfFract/8 */ + scfFract = scfFract + fMult(FL2FXCONST_DBL(0.8585f), scfFract >> 3); + + /* integer scalefactor */ + /* scfInt = (int)floor(scfFloat); */ + scfInt = + (INT)(scfFract >> + ((DFRACT_BITS - 1) - 3 - + LD_DATA_SHIFT)); /* 3 bits => scfFract/8.0; 6 bits => ld64 */ + + /* maximum of spectrum */ + maxSpec = FL2FXCONST_DBL(0.0f); + + /* Unroll by 4, allow dual memory access */ + DWORD_ALIGNED(qcOutChannel->mdctSpectrum); + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j += 4) { + maxSpec = fMax(maxSpec, + fMax(fMax(fAbs(qcOutChannel->mdctSpectrum[j + 0]), + fAbs(qcOutChannel->mdctSpectrum[j + 1])), + fMax(fAbs(qcOutChannel->mdctSpectrum[j + 2]), + fAbs(qcOutChannel->mdctSpectrum[j + 3])))); + } + /* lower scf limit to avoid quantized values bigger than MAX_QUANT */ + /* C1 = -69.33295f, C2 = 5.77078f = 4/log(2) */ + /* minSfMaxQuant[sfbOffs+sfb] = (int)ceil(C1 + C2*log(maxSpec)); */ + /* C1/2^8 + 4/log(2.0)*log(maxSpec)/2^8 => C1/2^8 + + * log(maxSpec)/log(2.0)*4/2^8 => C1/2^8 + log(maxSpec)/log(2.0)/64.0 */ + + // minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + CalcLdData(maxSpec)) + // >> ((DFRACT_BITS-1)-8))) + 1; + tmp = CalcLdData(maxSpec); + if (c1Const > FL2FXCONST_DBL(-1.f) - tmp) { + minSfMaxQuant[sfbOffs + sfb] = + ((INT)((c1Const + tmp) >> ((DFRACT_BITS - 1) - 8))) + 1; + } else { + minSfMaxQuant[sfbOffs + sfb] = + ((INT)(FL2FXCONST_DBL(-1.f) >> ((DFRACT_BITS - 1) - 8))) + 1; + } + + scfInt = fixMax(scfInt, minSfMaxQuant[sfbOffs + sfb]); + + /* find better scalefactor with analysis by synthesis */ + if (invQuant > 0) { + scfInt = FDKaacEnc_improveScf( + qcOutChannel->mdctSpectrum + + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpec + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpecTmp + psyOutChannel->sfbOffsets[sfbOffs + sfb], + psyOutChannel->sfbOffsets[sfbOffs + sfb + 1] - + psyOutChannel->sfbOffsets[sfbOffs + sfb], + threshLdData, scfInt, minSfMaxQuant[sfbOffs + sfb], + &sfbDistLdData[sfbOffs + sfb], &minScfCalculated[sfbOffs + sfb], + dZoneQuantEnable); + } + scf[sfbOffs + sfb] = scfInt; + } + } + } + + if (invQuant > 0) { + /* try to decrease scf differences */ + FIXP_DBL sfbConstPePart[MAX_GROUPED_SFB]; + FIXP_DBL sfbNRelevantLines[MAX_GROUPED_SFB]; + + for (i = 0; i < psyOutChannel->sfbCnt; i++) + sfbConstPePart[i] = (FIXP_DBL)FDK_INT_MIN; + + FDKaacEnc_calcSfbRelevantLines( + sfbFormFactorLdData, qcOutChannel->sfbEnergyLdData, + qcOutChannel->sfbThresholdLdData, psyOutChannel->sfbOffsets, + psyOutChannel->sfbCnt, psyOutChannel->sfbPerGroup, + psyOutChannel->maxSfbPerGroup, sfbNRelevantLines); + + FDKaacEnc_assimilateSingleScf( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, dZoneQuantEnable, + scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, sfbFormFactorLdData, + sfbNRelevantLines, minScfCalculated, 1); + + if (invQuant > 1) { + FDKaacEnc_assimilateMultipleScf( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + + FDKaacEnc_FDKaacEnc_assimilateMultipleScf2( + psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp, + dZoneQuantEnable, scf, minSfMaxQuant, sfbDistLdData, sfbConstPePart, + sfbFormFactorLdData, sfbNRelevantLines); + } + } + + /* get min scalefac */ + minSf = FDK_INT_MAX; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (scf[sfbOffs + sfb] != FDK_INT_MIN) + minSf = fixMin(minSf, scf[sfbOffs + sfb]); + } + } + + /* limit scf delta */ + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if ((scf[sfbOffs + sfb] != FDK_INT_MIN) && + (minSf + MAX_SCF_DELTA) < scf[sfbOffs + sfb]) { + scf[sfbOffs + sfb] = minSf + MAX_SCF_DELTA; + if (invQuant > 0) { /* changed bands need to be quantized again */ + sfbDistLdData[sfbOffs + sfb] = FDKaacEnc_calcSfbDist( + qcOutChannel->mdctSpectrum + + psyOutChannel->sfbOffsets[sfbOffs + sfb], + quantSpec + psyOutChannel->sfbOffsets[sfbOffs + sfb], + psyOutChannel->sfbOffsets[sfbOffs + sfb + 1] - + psyOutChannel->sfbOffsets[sfbOffs + sfb], + scf[sfbOffs + sfb], dZoneQuantEnable); + } + } + } + } + + /* get max scalefac for global gain */ + maxSf = FDK_INT_MIN; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + maxSf = fixMax(maxSf, scf[sfbOffs + sfb]); + } + } + + /* calc loop scalefactors, if spec is not all zero (i.e. maxSf == -99) */ + if (maxSf > FDK_INT_MIN) { + *globalGain = maxSf; + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + if (scf[sfbOffs + sfb] == FDK_INT_MIN) { + scf[sfbOffs + sfb] = 0; + /* set band explicitely to zero */ + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j++) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } else { + scf[sfbOffs + sfb] = maxSf - scf[sfbOffs + sfb]; + } + } + } + } else { + *globalGain = 0; + /* set spectrum explicitely to zero */ + for (sfbOffs = 0; sfbOffs < psyOutChannel->sfbCnt; + sfbOffs += psyOutChannel->sfbPerGroup) { + for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) { + scf[sfbOffs + sfb] = 0; + /* set band explicitely to zero */ + for (j = psyOutChannel->sfbOffsets[sfbOffs + sfb]; + j < psyOutChannel->sfbOffsets[sfbOffs + sfb + 1]; j++) { + qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f); + } + } + } + } + + /* free quantSpecTmp from scratch */ + C_ALLOC_SCRATCH_END(quantSpecTmp, SHORT, (1024)) +} + +void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL *qcOutChannel[], + const INT invQuant, + const INT dZoneQuantEnable, + const INT nChannels) { + int ch; + + for (ch = 0; ch < nChannels; ch++) { + FDKaacEnc_EstimateScaleFactorsChannel( + qcOutChannel[ch], psyOutChannel[ch], qcOutChannel[ch]->scf, + &qcOutChannel[ch]->globalGain, qcOutChannel[ch]->sfbFormFactorLdData, + invQuant, qcOutChannel[ch]->quantSpec, dZoneQuantEnable); + } +} diff --git a/fdk-aac/libAACenc/src/sf_estim.h b/fdk-aac/libAACenc/src/sf_estim.h new file mode 100644 index 0000000..ab2d3c2 --- /dev/null +++ b/fdk-aac/libAACenc/src/sf_estim.h @@ -0,0 +1,124 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Scale factor estimation + +*******************************************************************************/ + +#ifndef SF_ESTIM_H +#define SF_ESTIM_H + +#include "common_fix.h" + +#include "psy_const.h" +#include "qc_data.h" +#include "interface.h" + +#define FORM_FAC_SHIFT 6 + +void FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL *qcOutChannel[(2)], + PSY_OUT_CHANNEL *psyOutChannel[(2)], + const INT nChannels); + +void FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[], + QC_OUT_CHANNEL *qcOutChannel[], + const INT invQuant, + const INT dZoneQuantEnable, + const INT nChannels); + +#endif diff --git a/fdk-aac/libAACenc/src/spreading.cpp b/fdk-aac/libAACenc/src/spreading.cpp new file mode 100644 index 0000000..0fb43bb --- /dev/null +++ b/fdk-aac/libAACenc/src/spreading.cpp @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Spreading of energy + +*******************************************************************************/ + +#include "spreading.h" + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy) { + int i; + FIXP_DBL delay; + + /* slope to higher frequencies */ + delay = pbSpreadEnergy[0]; + for (i = 1; i < pbCnt; i++) { + delay = fixMax(pbSpreadEnergy[i], fMult(maskHighFactor[i], delay)); + pbSpreadEnergy[i] = delay; + } + + /* slope to lower frequencies */ + delay = pbSpreadEnergy[pbCnt - 1]; + for (i = pbCnt - 2; i >= 0; i--) { + delay = fixMax(pbSpreadEnergy[i], fMult(maskLowFactor[i], delay)); + pbSpreadEnergy[i] = delay; + } +} diff --git a/fdk-aac/libAACenc/src/spreading.h b/fdk-aac/libAACenc/src/spreading.h new file mode 100644 index 0000000..e693031 --- /dev/null +++ b/fdk-aac/libAACenc/src/spreading.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M.Werner + + Description: Spreading of energy and weighted tonality + +*******************************************************************************/ + +#ifndef SPREADING_H +#define SPREADING_H + +#include "common_fix.h" + +void FDKaacEnc_SpreadingMax(const INT pbCnt, + const FIXP_DBL *RESTRICT maskLowFactor, + const FIXP_DBL *RESTRICT maskHighFactor, + FIXP_DBL *RESTRICT pbSpreadEnergy); + +#endif /* #ifndef SPREADING_H */ diff --git a/fdk-aac/libAACenc/src/tns_func.h b/fdk-aac/libAACenc/src/tns_func.h new file mode 100644 index 0000000..6099bc7 --- /dev/null +++ b/fdk-aac/libAACenc/src/tns_func.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Alex Goeschel + + Description: Temporal noise shaping + +*******************************************************************************/ + +#ifndef TNS_FUNC_H +#define TNS_FUNC_H + +#include "common_fix.h" + +#include "psy_configuration.h" + +AAC_ENCODER_ERROR FDKaacEnc_InitTnsConfiguration( + INT bitrate, INT samplerate, INT channels, INT blocktype, INT granuleLength, + INT isLowDelay, INT ldSbrPresent, TNS_CONFIG *tnsConfig, + PSY_CONFIGURATION *psyConfig, INT active, INT useTnsPeak); + +INT FDKaacEnc_TnsDetect(TNS_DATA *tnsData, const TNS_CONFIG *tC, + TNS_INFO *tnsInfo, INT sfbCnt, const FIXP_DBL *spectrum, + INT subBlockNumber, INT blockType); + +void FDKaacEnc_TnsSync(TNS_DATA *tnsDataDest, const TNS_DATA *tnsDataSrc, + TNS_INFO *tnsInfoDest, TNS_INFO *tnsInfoSrc, + const INT blockTypeDest, const INT blockTypeSrc, + const TNS_CONFIG *tC); + +INT FDKaacEnc_TnsEncode(TNS_INFO *tnsInfo, TNS_DATA *tnsData, + const INT numOfSfb, const TNS_CONFIG *tC, + const INT lowPassLine, FIXP_DBL *spectrum, + const INT subBlockNumber, const INT blockType); + +#endif /* TNS_FUNC_H */ diff --git a/fdk-aac/libAACenc/src/tonality.cpp b/fdk-aac/libAACenc/src/tonality.cpp new file mode 100644 index 0000000..334e0f1 --- /dev/null +++ b/fdk-aac/libAACenc/src/tonality.cpp @@ -0,0 +1,219 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: Convert chaos measure to the tonality index + +*******************************************************************************/ + +#include "tonality.h" + +#include "chaosmeasure.h" + +#if defined(__arm__) +#endif + +static const FIXP_DBL normlog = + (FIXP_DBL)0xd977d949; /*FL2FXCONST_DBL(-0.4342944819f * + FDKlog(2.0)/FDKlog(2.7182818)); */ + +static void FDKaacEnc_CalcSfbTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT chaosMeasure, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, const INT *RESTRICT sfbOffset, + FIXP_DBL *RESTRICT sfbEnergyLD64); + +void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, INT sfbCnt, + const INT *sfbOffset, INT usePns) { + INT j; + INT numberOfLines = sfbOffset[sfbCnt]; + + if (usePns) { + C_ALLOC_SCRATCH_START(chaosMeasurePerLine, FIXP_DBL, (1024)) + + /* calculate chaos measure */ + FDKaacEnc_CalculateChaosMeasure(spectrum, numberOfLines, + chaosMeasurePerLine); + + /* smooth ChaosMeasure */ + FIXP_DBL left = chaosMeasurePerLine[0]; + FIXP_DBL right; + for (j = 1; j < (numberOfLines - 1); j += 2) { + right = chaosMeasurePerLine[j]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j] = left; /* 0.25 left + 0.75 right */ + + right = chaosMeasurePerLine[j + 1]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j + 1] = left; + } + if (j == (numberOfLines - 1)) { + right = chaosMeasurePerLine[j]; + right = right - (right >> 2); + left = right + (left >> 2); + chaosMeasurePerLine[j] = left; + } + + FDKaacEnc_CalcSfbTonality(spectrum, sfbMaxScaleSpec, chaosMeasurePerLine, + sfbTonality, sfbCnt, sfbOffset, sfbEnergyLD64); + + C_ALLOC_SCRATCH_END(chaosMeasurePerLine, FIXP_DBL, (1024)) + } +} + +/***************************************************************************** + + functionname: CalculateTonalityIndex + description: computes tonality values out of unpredictability values + limits range and computes log() + returns: + input: ptr to energies, ptr to chaos measure values, + number of sfb + output: sfb wise tonality values + +*****************************************************************************/ +static void FDKaacEnc_CalcSfbTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT chaosMeasure, + FIXP_SGL *RESTRICT sfbTonality, + INT sfbCnt, const INT *RESTRICT sfbOffset, + FIXP_DBL *RESTRICT sfbEnergyLD64) { + INT i; + + for (i = 0; i < sfbCnt; i++) { + FIXP_DBL chaosMeasureSfbLD64; + INT shiftBits = + fixMax(0, sfbMaxScaleSpec[i] - + 4); /* max sfbWidth = 96 ; 2^7=128 => 7/2 = 4 (spc*spc) */ + + INT j; + FIXP_DBL chaosMeasureSfb = FL2FXCONST_DBL(0.0); + + /* calc chaosMeasurePerSfb */ + for (j = (sfbOffset[i + 1] - sfbOffset[i]) - 1; j >= 0; j--) { + FIXP_DBL tmp = (*spectrum++) << shiftBits; + FIXP_DBL lineNrg = fMultDiv2(tmp, tmp); + chaosMeasureSfb = fMultAddDiv2(chaosMeasureSfb, lineNrg, *chaosMeasure++); + } + + /* calc tonalityPerSfb */ + if (chaosMeasureSfb != FL2FXCONST_DBL(0.0)) { + /* add ld(convtone)/64 and 2/64 bec.fMultDiv2 */ + chaosMeasureSfbLD64 = CalcLdData((chaosMeasureSfb)) - sfbEnergyLD64[i]; + chaosMeasureSfbLD64 += FL2FXCONST_DBL(3.0f / 64) - + ((FIXP_DBL)(shiftBits) << (DFRACT_BITS - 6)); + + if (chaosMeasureSfbLD64 > + FL2FXCONST_DBL(-0.0519051)) /* > ld(0.05)+ld(2) */ + { + if (chaosMeasureSfbLD64 <= FL2FXCONST_DBL(0.0)) + sfbTonality[i] = + FX_DBL2FX_SGL(fMultDiv2(chaosMeasureSfbLD64, normlog) << 7); + else + sfbTonality[i] = FL2FXCONST_SGL(0.0); + } else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } else + sfbTonality[i] = (FIXP_SGL)MAXVAL_SGL; + } +} diff --git a/fdk-aac/libAACenc/src/tonality.h b/fdk-aac/libAACenc/src/tonality.h new file mode 100644 index 0000000..c5cf4c5 --- /dev/null +++ b/fdk-aac/libAACenc/src/tonality.h @@ -0,0 +1,115 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Lohwasser + + Description: Calculate tonality index + +*******************************************************************************/ + +#ifndef TONALITY_H +#define TONALITY_H + +#include "common_fix.h" +#include "chaosmeasure.h" + +void FDKaacEnc_CalculateFullTonality(FIXP_DBL *RESTRICT spectrum, + INT *RESTRICT sfbMaxScaleSpec, + FIXP_DBL *RESTRICT sfbEnergyLD64, + FIXP_SGL *RESTRICT sfbTonality, INT sfbCnt, + const INT *sfbOffset, INT usePns); + +#endif /* TONALITY_H */ diff --git a/fdk-aac/libAACenc/src/transform.cpp b/fdk-aac/libAACenc/src/transform.cpp new file mode 100644 index 0000000..08b1c2f --- /dev/null +++ b/fdk-aac/libAACenc/src/transform.cpp @@ -0,0 +1,294 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: FDKaacLdEnc_MdctTransform480: + The module FDKaacLdEnc_MdctTransform will perform the MDCT. + The MDCT supports the sine window and + the zero padded window. The algorithm of the MDCT + can be divided in Windowing, PreModulation, Fft and + PostModulation. + +*******************************************************************************/ + +#include "transform.h" +#include "dct.h" +#include "psy_const.h" +#include "aacEnc_rom.h" +#include "FDK_tools_rom.h" + +#if defined(__arm__) +#endif + +INT FDKaacEnc_Transform_Real(const INT_PCM *pTimeData, + FIXP_DBL *RESTRICT mdctData, const INT blockType, + const INT windowShape, INT *prevWindowShape, + H_MDCT mdctPers, const INT frameLength, + INT *pMdctData_e, INT filterType) { + const INT_PCM *RESTRICT timeData; + + UINT numSpec; + UINT numMdctLines; + UINT offset; + int fr; /* fr: right window slope length */ + SHORT mdctData_e[8]; + + timeData = pTimeData; + + if (blockType == SHORT_WINDOW) { + numSpec = 8; + numMdctLines = frameLength >> 3; + } else { + numSpec = 1; + numMdctLines = frameLength; + } + + offset = (windowShape == LOL_WINDOW) ? ((frameLength * 3) >> 2) : 0; + switch (blockType) { + case LONG_WINDOW: + case STOP_WINDOW: + fr = frameLength - offset; + break; + case START_WINDOW: /* or StopStartSequence */ + case SHORT_WINDOW: + fr = frameLength >> 3; + break; + default: + FDK_ASSERT(0); + return -1; + } + + mdct_block(mdctPers, timeData, frameLength, mdctData, numSpec, numMdctLines, + FDKgetWindowSlope(fr, windowShape), fr, mdctData_e); + + if (blockType == SHORT_WINDOW) { + if (!(mdctData_e[0] == mdctData_e[1] && mdctData_e[1] == mdctData_e[2] && + mdctData_e[2] == mdctData_e[3] && mdctData_e[3] == mdctData_e[4] && + mdctData_e[4] == mdctData_e[5] && mdctData_e[5] == mdctData_e[6] && + mdctData_e[6] == mdctData_e[7])) { + return -1; + } + } + *prevWindowShape = windowShape; + *pMdctData_e = mdctData_e[0]; + + return 0; +} + +INT FDKaacEnc_Transform_Real_Eld(const INT_PCM *pTimeData, + FIXP_DBL *RESTRICT mdctData, + const INT blockType, const INT windowShape, + INT *prevWindowShape, const INT frameLength, + INT *mdctData_e, INT filterType, + FIXP_DBL *RESTRICT overlapAddBuffer) { + const INT_PCM *RESTRICT timeData; + + INT i; + + /* tl: transform length + fl: left window slope length + nl: left window slope offset + fr: right window slope length + nr: right window slope offset */ + const FIXP_WTB *pWindowELD = NULL; + int N = frameLength; + int L = frameLength; + + timeData = pTimeData; + + if (blockType != LONG_WINDOW) { + return -1; + } + + /* + * MDCT scale: + * + 1: fMultDiv2() in windowing. + * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC. + */ + *mdctData_e = 1 + 1; + + switch (frameLength) { + case 512: + pWindowELD = ELDAnalysis512; + break; + case 480: + pWindowELD = ELDAnalysis480; + break; + case 256: + pWindowELD = ELDAnalysis256; + *mdctData_e += 1; + break; + case 240: + pWindowELD = ELDAnalysis240; + *mdctData_e += 1; + break; + case 128: + pWindowELD = ELDAnalysis128; + *mdctData_e += 2; + break; + case 120: + pWindowELD = ELDAnalysis120; + *mdctData_e += 2; + break; + default: + FDK_ASSERT(0); + return -1; + } + + for (i = 0; i < N / 4; i++) { + FIXP_DBL z0, outval; + + z0 = (fMult((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N / 2 - 1 - i]) + << (WTS0 - 1)) + + (fMult((FIXP_PCM)timeData[L + N * 3 / 4 + i], pWindowELD[N / 2 + i]) + << (WTS0 - 1)); + + outval = (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N + N / 2 - 1 - i]) >> + (-WTS1)); + outval += (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 + i], + pWindowELD[N + N / 2 + i]) >> + (-WTS1)); + outval += (fMultDiv2(overlapAddBuffer[N / 2 + i], pWindowELD[2 * N + i]) >> + (-WTS2 - 1)); + + overlapAddBuffer[N / 2 + i] = overlapAddBuffer[i]; + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N / 2 + i] + + (fMultDiv2(overlapAddBuffer[N + N / 2 - 1 - i], + pWindowELD[2 * N + N / 2 + i]) >> + (-WTS2 - 1)); + + mdctData[N - 1 - i] = outval; + overlapAddBuffer[N + N / 2 - 1 - i] = outval; + } + + for (i = N / 4; i < N / 2; i++) { + FIXP_DBL z0, outval; + + z0 = fMult((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N / 2 - 1 - i]) + << (WTS0 - 1); + + outval = (fMultDiv2((FIXP_PCM)timeData[L + N * 3 / 4 - 1 - i], + pWindowELD[N + N / 2 - 1 - i]) >> + (-WTS1)); + outval += (fMultDiv2(overlapAddBuffer[N / 2 + i], pWindowELD[2 * N + i]) >> + (-WTS2 - 1)); + + overlapAddBuffer[N / 2 + i] = + overlapAddBuffer[i] + + (fMult((FIXP_PCM)timeData[L - N / 4 + i], pWindowELD[N / 2 + i]) + << (WTS0 - 1)); + + overlapAddBuffer[i] = z0; + mdctData[i] = overlapAddBuffer[N / 2 + i] + + (fMultDiv2(overlapAddBuffer[N + N / 2 - 1 - i], + pWindowELD[2 * N + N / 2 + i]) >> + (-WTS2 - 1)); + + mdctData[N - 1 - i] = outval; + overlapAddBuffer[N + N / 2 - 1 - i] = outval; + } + dct_IV(mdctData, frameLength, mdctData_e); + + *prevWindowShape = windowShape; + + return 0; +} diff --git a/fdk-aac/libAACenc/src/transform.h b/fdk-aac/libAACenc/src/transform.h new file mode 100644 index 0000000..8f5ff46 --- /dev/null +++ b/fdk-aac/libAACenc/src/transform.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** AAC encoder library ****************************** + + Author(s): M. Werner + + Description: MDCT Transform + +*******************************************************************************/ + +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "mdct.h" +#include "common_fix.h" + +#define WTS0 1 +#define WTS1 0 +#define WTS2 -2 + +/** + * \brief: Performe MDCT transform of time domain data. + * \param timeData pointer to time domain input signal. + * \param mdctData pointer to store frequency domain output data. + * \param blockType index indicating the type of block. Either + * LONG_WINDOW, START_WINDOW, SHORT_WINDOW or STOP_WINDOW. + * \param windowShape index indicating the window slope type to be used. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param previndowShape index indicating the window slope type used + * in the last frame. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param frameLength length of the block. Either 1024 or 960. + * \param mdctData_e pointer to an INT where the exponent of the frequency + * domain output data is stored into. + * \param filterType xxx + * \return 0 in case of success, non-zero in case of error (inconsistent + * parameters). + */ +INT FDKaacEnc_Transform_Real(const INT_PCM* pTimeData, + FIXP_DBL* RESTRICT mdctData, const INT blockType, + const INT windowShape, INT* prevWindowShape, + H_MDCT mdctPers, const INT frameLength, + INT* pMdctData_e, INT filterType); + +/** + * \brief: Performe ELD filterbnank transform of time domain data. + * \param timeData pointer to time domain input signal. + * \param mdctData pointer to store frequency domain output data. + * \param blockType index indicating the type of block. Either + * LONG_WINDOW, START_WINDOW, SHORT_WINDOW or STOP_WINDOW. + * \param windowShape index indicating the window slope type to be used. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param previndowShape index indicating the window slope type used + * in the last frame. + * Values allowed are either SINE_WINDOW or KBD_WINDOW. + * \param frameLength length of the block. Either 1024 or 960. + * \param mdctData_e pointer to an INT where the exponent of the frequency + * domain output data is stored into. + * \param filterType xxx + * \param overlapAddBuffer overlap add buffer for overlap of ELD filterbank + * \return 0 in case of success, non-zero in case of error (inconsistent + * parameters). + */ +INT FDKaacEnc_Transform_Real_Eld(const INT_PCM* pTimeData, + FIXP_DBL* RESTRICT mdctData, + const INT blockType, const INT windowShape, + INT* prevWindowShape, const INT frameLength, + INT* mdctData_e, INT filterType, + FIXP_DBL* RESTRICT overlapAddBuffer); + +#endif /* #!defined (TRANSFORM_H) */ diff --git a/fdk-aac/libArithCoding/include/ac_arith_coder.h b/fdk-aac/libArithCoding/include/ac_arith_coder.h new file mode 100644 index 0000000..130c188 --- /dev/null +++ b/fdk-aac/libArithCoding/include/ac_arith_coder.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************** Arithmetic coder library *************************** + + Author(s): Oliver Weiss + + Description: Interface for Spectral Noiseless Coding Scheme based on an + Arithmetic Coder in Conjunction with an Adaptive Context + +*******************************************************************************/ + +#ifndef AC_ARITH_CODER_H +#define AC_ARITH_CODER_H + +#include "common_fix.h" +#include "FDK_bitstream.h" + +#include "FDK_audio.h" + +typedef enum { ARITH_CODER_OK = 0, ARITH_CODER_ERROR = 5 } ARITH_CODING_ERROR; + +typedef struct { + SHORT m_numberLinesPrev; + UCHAR c_prev[(1024 / 2) + 4]; /* 2-tuple context of previous frame, 4 bit */ +} CArcoData; + +/* prototypes */ + +CArcoData *CArco_Create(void); + +void CArco_Destroy(CArcoData *pArcoData); + +/** + * \brief decode a spectral data element by using an adaptive context dependent + * arithmetic coding scheme + * \param hBs bit stream handle + * \param spectrum pointer to quantized data output. + * \param lg number of quantized spectral coefficients (output by the arithmetic + * decoder). + * \param lg_max max number of quantized spectral coefficients. + * \param arith_reset_flag flag which indicates if the spectral noiseless + * context must be reset + * \return void + */ +ARITH_CODING_ERROR CArco_DecodeArithData(CArcoData *pArcoData, + HANDLE_FDK_BITSTREAM hBs, + FIXP_DBL *RESTRICT spectrum, int lg, + int lg_max, int arith_reset_flag); + +#endif /* AC_ARITH_CODER_H */ diff --git a/fdk-aac/libArithCoding/src/ac_arith_coder.cpp b/fdk-aac/libArithCoding/src/ac_arith_coder.cpp new file mode 100644 index 0000000..a433b08 --- /dev/null +++ b/fdk-aac/libArithCoding/src/ac_arith_coder.cpp @@ -0,0 +1,785 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************** Arithmetic coder library *************************** + + Author(s): Youliy Ninov, Oliver Weiss + + Description: Definition of Spectral Noiseless Coding Scheme based on an + Arithmetic Coder in Conjunction with an Adaptive Context + +*******************************************************************************/ + +#include "ac_arith_coder.h" + +#define cbitsnew 16 +#define stat_bitsnew 14 +#define ari_q4new (((long)1 << cbitsnew) - 1) /* 0xFFFF */ +#define ari_q1new (ari_q4new / 4 + 1) /* 0x4000 */ +#define ari_q2new (2 * ari_q1new) /* 0x8000 */ +#define ari_q3new (3 * ari_q1new) /* 0xC000 */ + +#define VAL_ESC 16 + +/* Arithmetic coder library info */ +#define AC_LIB_VL0 2 +#define AC_LIB_VL1 0 +#define AC_LIB_VL2 0 +#define AC_LIB_TITLE "Arithmetic Coder Lib" +#ifdef __ANDROID__ +#define AC_LIB_BUILD_DATE "" +#define AC_LIB_BUILD_TIME "" +#else +#define AC_LIB_BUILD_DATE __DATE__ +#define AC_LIB_BUILD_TIME __TIME__ +#endif + +const SHORT ari_lsb2[3][4] = { + {12571, 10569, 3696, 0}, {12661, 5700, 3751, 0}, {10827, 6884, 2929, 0}}; + +H_ALLOC_MEM(ArcoData, CArcoData) +/*! The structure ArcoData contains 2-tuple context of previous frame.
+ Dimension: 1 */ +C_ALLOC_MEM(ArcoData, CArcoData, 1) + +/* + This define triggers the use of the pre-known return values of function + get_pk_v2() for the cases, where parameter s is in range + 0x00000000..0x0000000F. Note: These 16 bytes have been moved into the first 4 + entries of ari_merged_hash_ps that are no more referenced. +*/ + +static const ULONG ari_merged_hash_ps[742] = { + 0x00001044UL, 0x00003D0AUL, 0x00005350UL, 0x000074D6UL, 0x0000A49FUL, + 0x0000F96EUL, 0x00111000UL, 0x01111E83UL, 0x01113146UL, 0x01114036UL, + 0x01116863UL, 0x011194E9UL, 0x0111F7EEUL, 0x0112269BUL, 0x01124775UL, + 0x01126DA1UL, 0x0112D912UL, 0x01131AF0UL, 0x011336DDUL, 0x01135CF5UL, + 0x01139DF8UL, 0x01141A5BUL, 0x01144773UL, 0x01146CF5UL, 0x0114FDE9UL, + 0x01166CF5UL, 0x0116FDE4UL, 0x01174CF3UL, 0x011FFDCFUL, 0x01211CC2UL, + 0x01213B2DUL, 0x01214036UL, 0x01216863UL, 0x012194D2UL, 0x0122197FUL, + 0x01223AADUL, 0x01224036UL, 0x01226878UL, 0x0122A929UL, 0x0122F4ABUL, + 0x01232B2DUL, 0x012347B6UL, 0x01237DF8UL, 0x0123B929UL, 0x012417DDUL, + 0x01245D76UL, 0x01249DF8UL, 0x0124F912UL, 0x01255D75UL, 0x0125FDE9UL, + 0x01265D75UL, 0x012B8DF7UL, 0x01311E2AUL, 0x01313B5EUL, 0x0131687BUL, + 0x01321A6DUL, 0x013237BCUL, 0x01326863UL, 0x0132F4EEUL, 0x01332B5EUL, + 0x01335DA1UL, 0x01338E24UL, 0x01341A5EUL, 0x01343DB6UL, 0x01348DF8UL, + 0x01351935UL, 0x01355DB7UL, 0x0135FE12UL, 0x01376DF7UL, 0x013FFE29UL, + 0x01400024UL, 0x01423821UL, 0x014318F6UL, 0x01433821UL, 0x0143F8E5UL, + 0x01443DA1UL, 0x01486E38UL, 0x014FF929UL, 0x01543EE3UL, 0x015FF912UL, + 0x016F298CUL, 0x018A5A69UL, 0x021007F1UL, 0x02112C2CUL, 0x02114B48UL, + 0x02117353UL, 0x0211F4AEUL, 0x02122FEAUL, 0x02124B48UL, 0x02127850UL, + 0x0212F72EUL, 0x02133A9EUL, 0x02134036UL, 0x02138864UL, 0x021414ADUL, + 0x0214379EUL, 0x02145DB6UL, 0x0214FE1FUL, 0x02166DB7UL, 0x02200DC4UL, + 0x02212FEAUL, 0x022147A0UL, 0x02218369UL, 0x0221F7EEUL, 0x02222AADUL, + 0x02224788UL, 0x02226863UL, 0x02229929UL, 0x0222F4ABUL, 0x02232A9EUL, + 0x02234F08UL, 0x02237864UL, 0x0223A929UL, 0x022417DEUL, 0x02244F36UL, + 0x02248863UL, 0x02251A74UL, 0x02256DA1UL, 0x0225FE12UL, 0x02263DB6UL, + 0x02276DF7UL, 0x022FFE29UL, 0x0231186DUL, 0x023137BCUL, 0x02314020UL, + 0x02319ED6UL, 0x0232196DUL, 0x023237BCUL, 0x02325809UL, 0x02329429UL, + 0x023317EDUL, 0x02333F08UL, 0x02335809UL, 0x023378E4UL, 0x02341A7CUL, + 0x02344221UL, 0x0234A8D3UL, 0x023514BCUL, 0x02354221UL, 0x0235F8DFUL, + 0x02364861UL, 0x023FFE29UL, 0x02400024UL, 0x0241583BUL, 0x024214C8UL, + 0x02424809UL, 0x02427EE6UL, 0x02431708UL, 0x02434809UL, 0x02436ED0UL, + 0x02441A76UL, 0x02443821UL, 0x024458E3UL, 0x0244F91FUL, 0x02454863UL, + 0x0246190AUL, 0x02464863UL, 0x024FF929UL, 0x02525ED0UL, 0x025314E1UL, + 0x025348FBUL, 0x025419A1UL, 0x025458D0UL, 0x0254F4E5UL, 0x02552861UL, + 0x025FF912UL, 0x02665993UL, 0x027F5A69UL, 0x029F1481UL, 0x02CF28A4UL, + 0x03100AF0UL, 0x031120AAUL, 0x031147A0UL, 0x03118356UL, 0x031217ECUL, + 0x03123B5EUL, 0x03124008UL, 0x03127350UL, 0x031314AAUL, 0x0313201EUL, + 0x03134F08UL, 0x03136863UL, 0x03141A5EUL, 0x03143F3CUL, 0x03200847UL, + 0x03212AADUL, 0x03214F20UL, 0x03218ED6UL, 0x032218ADUL, 0x032237BCUL, + 0x03225809UL, 0x03229416UL, 0x032317EDUL, 0x03234F20UL, 0x03237350UL, + 0x0323FA6BUL, 0x03243F08UL, 0x03246863UL, 0x0324F925UL, 0x03254221UL, + 0x0325F8DFUL, 0x03264821UL, 0x032FFE29UL, 0x03311E47UL, 0x03313F08UL, + 0x0331580DUL, 0x033214DEUL, 0x03323F08UL, 0x03324020UL, 0x03326350UL, + 0x033294E9UL, 0x033317DEUL, 0x03333F08UL, 0x0333627BUL, 0x0333A9A9UL, + 0x033417FCUL, 0x03343220UL, 0x0334627BUL, 0x0334A9A9UL, 0x0335148AUL, + 0x03353220UL, 0x033588E4UL, 0x03361A4AUL, 0x03363821UL, 0x0336F8D2UL, + 0x03376863UL, 0x03411939UL, 0x0341583BUL, 0x034214C8UL, 0x03424809UL, + 0x03426ED0UL, 0x03431588UL, 0x03434809UL, 0x03436ED0UL, 0x03441A48UL, + 0x0344480DUL, 0x03446ED0UL, 0x03451A4AUL, 0x03453809UL, 0x03455EFBUL, + 0x034614CAUL, 0x03463849UL, 0x034F8924UL, 0x03500A69UL, 0x035252D0UL, + 0x035314E0UL, 0x0353324DUL, 0x03535ED0UL, 0x035414E0UL, 0x0354324DUL, + 0x03545ED0UL, 0x0354F4E8UL, 0x0355384DUL, 0x03555ED0UL, 0x0355F4DFUL, + 0x03564350UL, 0x035969A6UL, 0x035FFA52UL, 0x036649A6UL, 0x036FFA52UL, + 0x037F4F66UL, 0x039D7492UL, 0x03BF6892UL, 0x03DF8A1FUL, 0x04100B84UL, + 0x04112107UL, 0x0411520DUL, 0x041214EAUL, 0x04124F20UL, 0x04131EDEUL, + 0x04133F08UL, 0x04135809UL, 0x0413F42BUL, 0x04142F08UL, 0x04200847UL, + 0x042121FCUL, 0x04214209UL, 0x04221407UL, 0x0422203CUL, 0x04224209UL, + 0x04226350UL, 0x04231A7CUL, 0x04234209UL, 0x0423637BUL, 0x04241A7CUL, + 0x04243220UL, 0x0424627BUL, 0x042514C8UL, 0x04254809UL, 0x042FF8E9UL, + 0x04311E47UL, 0x04313220UL, 0x0431527BUL, 0x043214FCUL, 0x04323220UL, + 0x04326250UL, 0x043315BCUL, 0x04333220UL, 0x0433527BUL, 0x04338413UL, + 0x04341488UL, 0x04344809UL, 0x04346ED0UL, 0x04351F48UL, 0x0435527BUL, + 0x0435F9A5UL, 0x04363809UL, 0x04375EFBUL, 0x043FF929UL, 0x04412E79UL, + 0x0441427BUL, 0x044219B9UL, 0x04423809UL, 0x0442537BUL, 0x044314C8UL, + 0x04432020UL, 0x0443527BUL, 0x044414CAUL, 0x04443809UL, 0x0444537BUL, + 0x04448993UL, 0x0445148AUL, 0x04453809UL, 0x04455ED0UL, 0x0445F4E5UL, + 0x0446384DUL, 0x045009A6UL, 0x045272D3UL, 0x045314A0UL, 0x0453324DUL, + 0x04535ED0UL, 0x045415A0UL, 0x0454324DUL, 0x04545ED0UL, 0x04551F60UL, + 0x0455324DUL, 0x04562989UL, 0x04564350UL, 0x045FF4D2UL, 0x04665993UL, + 0x047FFF62UL, 0x048FF725UL, 0x049F44BDUL, 0x04BFB7E5UL, 0x04EF8A25UL, + 0x04FFFB98UL, 0x051131F9UL, 0x051212C7UL, 0x05134209UL, 0x05200247UL, + 0x05211007UL, 0x05213E60UL, 0x052212C7UL, 0x05224209UL, 0x052319BCUL, + 0x05233220UL, 0x0523527BUL, 0x052414C8UL, 0x05243820UL, 0x053112F9UL, + 0x05313E49UL, 0x05321439UL, 0x05323E49UL, 0x0532537BUL, 0x053314C8UL, + 0x0533480DUL, 0x05337413UL, 0x05341488UL, 0x0534527BUL, 0x0534F4EBUL, + 0x05353809UL, 0x05356ED0UL, 0x0535F4E5UL, 0x0536427BUL, 0x054119B9UL, + 0x054212F9UL, 0x05423249UL, 0x05426ED3UL, 0x05431739UL, 0x05433249UL, + 0x05435ED0UL, 0x0543F4EBUL, 0x05443809UL, 0x05445ED0UL, 0x0544F4E8UL, + 0x0545324DUL, 0x054FF992UL, 0x055362D3UL, 0x0553F5ABUL, 0x05544350UL, + 0x055514CAUL, 0x0555427BUL, 0x0555F4E5UL, 0x0556327BUL, 0x055FF4D2UL, + 0x05665993UL, 0x05774F53UL, 0x059FF728UL, 0x05CC37FDUL, 0x05EFBA28UL, + 0x05FFFB98UL, 0x061131F9UL, 0x06121407UL, 0x06133E60UL, 0x061A72E4UL, + 0x06211E47UL, 0x06214E4BUL, 0x062214C7UL, 0x06223E60UL, 0x062312F9UL, + 0x06233E60UL, 0x063112F9UL, 0x06313E4CUL, 0x063219B9UL, 0x06323E49UL, + 0x06331439UL, 0x06333809UL, 0x06336EE6UL, 0x0633F5ABUL, 0x06343809UL, + 0x0634F42BUL, 0x0635427BUL, 0x063FF992UL, 0x064342FBUL, 0x0643F4EBUL, + 0x0644427BUL, 0x064524C9UL, 0x06655993UL, 0x0666170AUL, 0x066652E6UL, + 0x067A6F56UL, 0x0698473DUL, 0x06CF67D2UL, 0x06EF3A26UL, 0x06FFFAD8UL, + 0x071131CCUL, 0x07211307UL, 0x07222E79UL, 0x072292DCUL, 0x07234E4BUL, + 0x073112F9UL, 0x07322339UL, 0x073632CBUL, 0x073FF992UL, 0x074432CBUL, + 0x075549A6UL, 0x0776FF68UL, 0x07774350UL, 0x0788473DUL, 0x07CF4516UL, + 0x07EF3A26UL, 0x07FFFAD8UL, 0x08222E79UL, 0x083112F9UL, 0x0834330BUL, + 0x0845338BUL, 0x08756F5CUL, 0x0887F725UL, 0x08884366UL, 0x08AF649CUL, + 0x08F00898UL, 0x08FFFAD8UL, 0x091111C7UL, 0x0932330BUL, 0x0945338BUL, + 0x09774F7DUL, 0x0998C725UL, 0x09996416UL, 0x09EF87E5UL, 0x09FFFAD8UL, + 0x0A34330BUL, 0x0A45338BUL, 0x0A77467DUL, 0x0AA9F52BUL, 0x0AAA6416UL, + 0x0ABD67DFUL, 0x0AFFFA18UL, 0x0B33330BUL, 0x0B4443A6UL, 0x0B76467DUL, + 0x0BB9751FUL, 0x0BBB59BDUL, 0x0BEF5892UL, 0x0BFFFAD8UL, 0x0C221339UL, + 0x0C53338EUL, 0x0C76367DUL, 0x0CCAF52EUL, 0x0CCC6996UL, 0x0CFFFA18UL, + 0x0D44438EUL, 0x0D64264EUL, 0x0DDCF52EUL, 0x0DDD5996UL, 0x0DFFFA18UL, + 0x0E43338EUL, 0x0E68465CUL, 0x0EEE651CUL, 0x0EFFFA18UL, 0x0F33238EUL, + 0x0F553659UL, 0x0F8F451CUL, 0x0FAFF8AEUL, 0x0FF00A2EUL, 0x0FFF1ACCUL, + 0x0FFF33BDUL, 0x0FFF7522UL, 0x0FFFFAD8UL, 0x10002C72UL, 0x1111103EUL, + 0x11121E83UL, 0x11131E9AUL, 0x1121115AUL, 0x11221170UL, 0x112316F0UL, + 0x1124175DUL, 0x11311CC2UL, 0x11321182UL, 0x11331D42UL, 0x11411D48UL, + 0x11421836UL, 0x11431876UL, 0x11441DF5UL, 0x1152287BUL, 0x12111903UL, + 0x1212115AUL, 0x121316F0UL, 0x12211B30UL, 0x12221B30UL, 0x12231B02UL, + 0x12311184UL, 0x12321D04UL, 0x12331784UL, 0x12411D39UL, 0x12412020UL, + 0x12422220UL, 0x12511D89UL, 0x1252227BUL, 0x1258184AUL, 0x12832992UL, + 0x1311171AUL, 0x13121B30UL, 0x1312202CUL, 0x131320AAUL, 0x132120AAUL, + 0x132220ADUL, 0x13232FEDUL, 0x13312107UL, 0x13322134UL, 0x13332134UL, + 0x13411D39UL, 0x13431E74UL, 0x13441834UL, 0x134812B4UL, 0x1352230BUL, + 0x13611E4BUL, 0x136522E4UL, 0x141113C2UL, 0x141211C4UL, 0x143121F9UL, + 0x143221F9UL, 0x143321CAUL, 0x14351D34UL, 0x14431E47UL, 0x14441E74UL, + 0x144612B4UL, 0x1452230EUL, 0x14551E74UL, 0x1471130EUL, 0x151113C2UL, + 0x152121F9UL, 0x153121F9UL, 0x153221F9UL, 0x15331007UL, 0x15522E4EUL, + 0x15551E74UL, 0x1571130EUL, 0x161113C7UL, 0x162121F9UL, 0x163121F9UL, + 0x16611E79UL, 0x16661334UL, 0x171113C7UL, 0x172121F9UL, 0x17451E47UL, + 0x1771130CUL, 0x181113C7UL, 0x18211E47UL, 0x18511E4CUL, 0x1882130CUL, + 0x191113C7UL, 0x19331E79UL, 0x1A111307UL, 0x1A311E79UL, 0x1F52230EUL, + 0x200003C1UL, 0x20001027UL, 0x20004467UL, 0x200079E7UL, 0x2000E5EFUL, + 0x21100BC0UL, 0x211129C0UL, 0x21114011UL, 0x211189E7UL, 0x2111F5EFUL, + 0x21124011UL, 0x21127455UL, 0x211325C0UL, 0x21134011UL, 0x21137455UL, + 0x211425C0UL, 0x21212440UL, 0x21213001UL, 0x2121F9EFUL, 0x21222540UL, + 0x21226455UL, 0x2122F5EFUL, 0x21233051UL, 0x2123F56FUL, 0x21244451UL, + 0x21312551UL, 0x21323451UL, 0x21332551UL, 0x21844555UL, 0x221125C0UL, + 0x22113011UL, 0x2211F9EFUL, 0x22123051UL, 0x2212F9EFUL, 0x221329D1UL, + 0x22212541UL, 0x22213011UL, 0x2221F9EFUL, 0x22223451UL, 0x2222F9EFUL, + 0x22232551UL, 0x2223F56FUL, 0x22312551UL, 0x223229D1UL, 0x2232F56FUL, + 0x22332551UL, 0x2233F56FUL, 0x22875555UL, 0x22DAB5D7UL, 0x23112BD1UL, + 0x23115467UL, 0x231225D1UL, 0x232129D1UL, 0x232229D1UL, 0x2322F9EFUL, + 0x23233451UL, 0x2323F9EFUL, 0x23312551UL, 0x233229D1UL, 0x2332F9EFUL, + 0x2333F56FUL, 0x237FF557UL, 0x238569D5UL, 0x23D955D7UL, 0x24100BE7UL, + 0x248789E7UL, 0x24E315D7UL, 0x24FFFBEFUL, 0x259869E7UL, 0x25DFF5EFUL, + 0x25FFFBEFUL, 0x268789E7UL, 0x26DFA5D7UL, 0x26FFFBEFUL, 0x279649E7UL, + 0x27E425D7UL, 0x27FFFBEFUL, 0x288879E7UL, 0x28EFF5EFUL, 0x28FFFBEFUL, + 0x298439E7UL, 0x29F115EFUL, 0x29FFFBEFUL, 0x2A7659E7UL, 0x2AEF75D7UL, + 0x2AFFFBEFUL, 0x2B7C89E7UL, 0x2BEF95D7UL, 0x2BFFFBEFUL, 0x2C6659E7UL, + 0x2CD555D7UL, 0x2CFFFBEFUL, 0x2D6329E7UL, 0x2DDD55E7UL, 0x2DFFFBEBUL, + 0x2E8479D7UL, 0x2EEE35E7UL, 0x2EFFFBEFUL, 0x2F5459E7UL, 0x2FCF85D7UL, + 0x2FFEFBEBUL, 0x2FFFA5EFUL, 0x2FFFEBEFUL, 0x30001AE7UL, 0x30002001UL, + 0x311129C0UL, 0x31221015UL, 0x31232000UL, 0x31332451UL, 0x32112540UL, + 0x32131027UL, 0x32212440UL, 0x33452455UL, 0x4000F9D7UL, 0x4122F9D7UL, + 0x43F65555UL, 0x43FFF5D7UL, 0x44F55567UL, 0x44FFF5D7UL, 0x45F00557UL, + 0x45FFF5D7UL, 0x46F659D7UL, 0x471005E7UL, 0x47F449E7UL, 0x481005E7UL, + 0x48EFA9D5UL, 0x48FFF5EFUL, 0x49F449E7UL, 0x49FFF5EFUL, 0x4AEA79E7UL, + 0x4AFFF5EFUL, 0x4BE9C9D5UL, 0x4BFFF5EFUL, 0x4CE549E7UL, 0x4CFFF5EFUL, + 0x4DE359E7UL, 0x4DFFF5D7UL, 0x4EE469E7UL, 0x4EFFF5D7UL, 0x4FEF39E7UL, + 0x4FFFF5EFUL, 0x6000F9E7UL, 0x69FFF557UL, 0x6FFFF9D7UL, 0x811009D7UL, + 0x8EFFF555UL, 0xFFFFF9E7UL}; + +static const SHORT ari_pk[64][17] = { + {708, 706, 579, 569, 568, 567, 479, 469, 297, 138, 97, 91, 72, 52, 38, 34, + 0}, + {7619, 6917, 6519, 6412, 5514, 5003, 4683, 4563, 3907, 3297, 3125, 3060, + 2904, 2718, 2631, 2590, 0}, + {7263, 4888, 4810, 4803, 1889, 415, 335, 327, 195, 72, 52, 49, 36, 20, 15, + 14, 0}, + {3626, 2197, 2188, 2187, 582, 57, 47, 46, 30, 12, 9, 8, 6, 4, 3, 2, 0}, + {7806, 5541, 5451, 5441, 2720, 834, 691, 674, 487, 243, 179, 167, 139, 98, + 77, 70, 0}, + {6684, 4101, 4058, 4055, 1748, 426, 368, 364, 322, 257, 235, 232, 228, 222, + 217, 215, 0}, + {9162, 5964, 5831, 5819, 3269, 866, 658, 638, 535, 348, 258, 244, 234, 214, + 195, 186, 0}, + {10638, 8491, 8365, 8351, 4418, 2067, 1859, 1834, 1190, 601, 495, 478, 356, + 217, 174, 164, 0}, + {13389, 10514, 10032, 9961, 7166, 3488, 2655, 2524, 2015, 1140, 760, 672, + 585, 426, 325, 283, 0}, + {14861, 12788, 12115, 11952, 9987, 6657, 5323, 4984, 4324, 3001, 2205, 1943, + 1764, 1394, 1115, 978, 0}, + {12876, 10004, 9661, 9610, 7107, 3435, 2711, 2595, 2257, 1508, 1059, 952, + 893, 753, 609, 538, 0}, + {15125, 13591, 13049, 12874, 11192, 8543, 7406, 7023, 6291, 4922, 4104, + 3769, 3465, 2890, 2486, 2275, 0}, + {14574, 13106, 12731, 12638, 10453, 7947, 7233, 7037, 6031, 4618, 4081, + 3906, 3465, 2802, 2476, 2349, 0}, + {15070, 13179, 12517, 12351, 10742, 7657, 6200, 5825, 5264, 3998, 3014, + 2662, 2510, 2153, 1799, 1564, 0}, + {15542, 14466, 14007, 13844, 12489, 10409, 9481, 9132, 8305, 6940, 6193, + 5867, 5458, 4743, 4291, 4047, 0}, + {15165, 14384, 14084, 13934, 12911, 11485, 10844, 10513, 10002, 8993, 8380, + 8051, 7711, 7036, 6514, 6233, 0}, + {15642, 14279, 13625, 13393, 12348, 9971, 8405, 7858, 7335, 6119, 4918, + 4376, 4185, 3719, 3231, 2860, 0}, + {13408, 13407, 11471, 11218, 11217, 11216, 9473, 9216, 6480, 3689, 2857, + 2690, 2256, 1732, 1405, 1302, 0}, + {16098, 15584, 15191, 14931, 14514, 13578, 12703, 12103, 11830, 11172, + 10475, 9867, 9695, 9281, 8825, 8389, 0}, + {15844, 14873, 14277, 13996, 13230, 11535, 10205, 9543, 9107, 8086, 7085, + 6419, 6214, 5713, 5195, 4731, 0}, + {16131, 15720, 15443, 15276, 14848, 13971, 13314, 12910, 12591, 11874, + 11225, 10788, 10573, 10077, 9585, 9209, 0}, + {16331, 16330, 12283, 11435, 11434, 11433, 8725, 8049, 6065, 4138, 3187, + 2842, 2529, 2171, 1907, 1745, 0}, + {16011, 15292, 14782, 14528, 14008, 12767, 11556, 10921, 10591, 9759, 8813, + 8043, 7855, 7383, 6863, 6282, 0}, + {16380, 16379, 15159, 14610, 14609, 14608, 12859, 12111, 11046, 9536, 8348, + 7713, 7216, 6533, 5964, 5546, 0}, + {16367, 16333, 16294, 16253, 16222, 16143, 16048, 15947, 15915, 15832, + 15731, 15619, 15589, 15512, 15416, 15310, 0}, + {15967, 15319, 14937, 14753, 14010, 12638, 11787, 11360, 10805, 9706, 8934, + 8515, 8166, 7456, 6911, 6575, 0}, + {4906, 3005, 2985, 2984, 875, 102, 83, 81, 47, 17, 12, 11, 8, 5, 4, 3, 0}, + {7217, 4346, 4269, 4264, 1924, 428, 340, 332, 280, 203, 179, 175, 171, 164, + 159, 157, 0}, + {16010, 15415, 15032, 14805, 14228, 13043, 12168, 11634, 11265, 10419, 9645, + 9110, 8892, 8378, 7850, 7437, 0}, + {8573, 5218, 5046, 5032, 2787, 771, 555, 533, 443, 286, 218, 205, 197, 181, + 168, 162, 0}, + {11474, 8095, 7822, 7796, 4632, 1443, 1046, 1004, 748, 351, 218, 194, 167, + 121, 93, 83, 0}, + {16152, 15764, 15463, 15264, 14925, 14189, 13536, 13070, 12846, 12314, + 11763, 11277, 11131, 10777, 10383, 10011, 0}, + {14187, 11654, 11043, 10919, 8498, 4885, 3778, 3552, 2947, 1835, 1283, 1134, + 998, 749, 585, 514, 0}, + {14162, 11527, 10759, 10557, 8601, 5417, 4105, 3753, 3286, 2353, 1708, 1473, + 1370, 1148, 959, 840, 0}, + {16205, 15902, 15669, 15498, 15213, 14601, 14068, 13674, 13463, 12970, + 12471, 12061, 11916, 11564, 11183, 10841, 0}, + {15043, 12972, 12092, 11792, 10265, 7446, 5934, 5379, 4883, 3825, 3036, + 2647, 2507, 2185, 1901, 1699, 0}, + {15320, 13694, 12782, 12352, 11191, 8936, 7433, 6671, 6255, 5366, 4622, + 4158, 4020, 3712, 3420, 3198, 0}, + {16255, 16020, 15768, 15600, 15416, 14963, 14440, 14006, 13875, 13534, + 13137, 12697, 12602, 12364, 12084, 11781, 0}, + {15627, 14503, 13906, 13622, 12557, 10527, 9269, 8661, 8117, 6933, 5994, + 5474, 5222, 4664, 4166, 3841, 0}, + {16366, 16365, 14547, 14160, 14159, 14158, 11969, 11473, 8735, 6147, 4911, + 4530, 3865, 3180, 2710, 2473, 0}, + {16257, 16038, 15871, 15754, 15536, 15071, 14673, 14390, 14230, 13842, + 13452, 13136, 13021, 12745, 12434, 12154, 0}, + {15855, 14971, 14338, 13939, 13239, 11782, 10585, 9805, 9444, 8623, 7846, + 7254, 7079, 6673, 6262, 5923, 0}, + {9492, 6318, 6197, 6189, 3004, 652, 489, 477, 333, 143, 96, 90, 78, 60, 50, + 47, 0}, + {16313, 16191, 16063, 15968, 15851, 15590, 15303, 15082, 14968, 14704, + 14427, 14177, 14095, 13899, 13674, 13457, 0}, + {8485, 5473, 5389, 5383, 2411, 494, 386, 377, 278, 150, 117, 112, 103, 89, + 81, 78, 0}, + {10497, 7154, 6959, 6943, 3788, 1004, 734, 709, 517, 238, 152, 138, 120, 90, + 72, 66, 0}, + {16317, 16226, 16127, 16040, 15955, 15762, 15547, 15345, 15277, 15111, + 14922, 14723, 14671, 14546, 14396, 14239, 0}, + {16382, 16381, 15858, 15540, 15539, 15538, 14704, 14168, 13768, 13092, + 12452, 11925, 11683, 11268, 10841, 10460, 0}, + {5974, 3798, 3758, 3755, 1275, 205, 166, 162, 95, 35, 26, 24, 18, 11, 8, 7, + 0}, + {3532, 2258, 2246, 2244, 731, 135, 118, 115, 87, 45, 36, 34, 29, 21, 17, 16, + 0}, + {7466, 4882, 4821, 4811, 2476, 886, 788, 771, 688, 531, 469, 457, 437, 400, + 369, 361, 0}, + {9580, 5772, 5291, 5216, 3444, 1496, 1025, 928, 806, 578, 433, 384, 366, + 331, 296, 273, 0}, + {10692, 7730, 7543, 7521, 4679, 1746, 1391, 1346, 1128, 692, 495, 458, 424, + 353, 291, 268, 0}, + {11040, 7132, 6549, 6452, 4377, 1875, 1253, 1130, 958, 631, 431, 370, 346, + 296, 253, 227, 0}, + {12687, 9332, 8701, 8585, 6266, 3093, 2182, 2004, 1683, 1072, 712, 608, 559, + 458, 373, 323, 0}, + {13429, 9853, 8860, 8584, 6806, 4039, 2862, 2478, 2239, 1764, 1409, 1224, + 1178, 1077, 979, 903, 0}, + {14685, 12163, 11061, 10668, 9101, 6345, 4871, 4263, 3908, 3200, 2668, 2368, + 2285, 2106, 1942, 1819, 0}, + {13295, 11302, 10999, 10945, 7947, 5036, 4490, 4385, 3391, 2185, 1836, 1757, + 1424, 998, 833, 785, 0}, + {4992, 2993, 2972, 2970, 1269, 575, 552, 549, 530, 505, 497, 495, 493, 489, + 486, 485, 0}, + {15419, 13862, 13104, 12819, 11429, 8753, 7220, 6651, 6020, 4667, 3663, + 3220, 2995, 2511, 2107, 1871, 0}, + {12468, 9263, 8912, 8873, 5758, 2193, 1625, 1556, 1187, 589, 371, 330, 283, + 200, 149, 131, 0}, + {15870, 15076, 14615, 14369, 13586, 12034, 10990, 10423, 9953, 8908, 8031, + 7488, 7233, 6648, 6101, 5712, 0}, + {1693, 978, 976, 975, 194, 18, 16, 15, 11, 7, 6, 5, 4, 3, 2, 1, 0}, + {7992, 5218, 5147, 5143, 2152, 366, 282, 276, 173, 59, 38, 35, 27, 16, 11, + 10, 0}}; + +typedef struct { + int low; + int high; + int vobf; +} Tastat; + +static inline INT mul_sbc_14bits(INT r, INT c) { + return (((INT)r) * ((INT)c)) >> stat_bitsnew; +} + +static inline INT ari_decode_14bits(HANDLE_FDK_BITSTREAM hBs, Tastat *s, + const SHORT *RESTRICT c_freq, int cfl) { + INT symbol; + INT low, high, range, value; + INT c; + const SHORT *p; + + low = s->low; + high = s->high; + value = s->vobf; + + range = high - low + 1; + c = (((int)(value - low + 1)) << stat_bitsnew) - ((int)1); + p = (const SHORT *)(c_freq - 1); + + if (cfl == (VAL_ESC + 1)) { + /* In 50% of all cases, the first entry is the right one, so we check it + * prior to all others */ + if ((p[1] * range) > c) { + p += 1; + if ((p[8] * range) > c) { + p += 8; + } + if ((p[4] * range) > c) { + p += 4; + } + if ((p[2] * range) > c) { + p += 2; + } + if ((p[1] * range) > c) { + p += 1; + } + } + } else if (cfl == 4) { + if ((p[2] * range) > c) { + p += 2; + } + if ((p[1] * range) > c) { + p += 1; + } + } else if (cfl == 2) { + if ((p[1] * range) > c) { + p += 1; + } + } else if (cfl == 27) { + const SHORT *p_24 = p + 24; + + if ((p[16] * range) > c) { + p += 16; + } + if ((p[8] * range) > c) { + p += 8; + } + if (p != p_24) { + if ((p[4] * range) > c) { + p += 4; + } + } + if ((p[2] * range) > c) { + p += 2; + } + + if (p != &p_24[2]) { + if ((p[1] * range) > c) { + p += 1; + } + } + } + + symbol = (INT)(p - (const SHORT *)(c_freq - 1)); + + if (symbol) { + high = low + mul_sbc_14bits(range, c_freq[symbol - 1]) - 1; + } + + low += mul_sbc_14bits(range, c_freq[symbol]); + + USHORT us_high = (USHORT)high; + USHORT us_low = (USHORT)low; + while (1) { + if (us_high & 0x8000) { + if (!(us_low & 0x8000)) { + if (us_low & 0x4000 && !(us_high & 0x4000)) { + us_low -= 0x4000; + us_high -= 0x4000; + value -= 0x4000; + } else + break; + } + } + us_low = us_low << 1; + us_high = (us_high << 1) | 1; + value = (value << 1) | FDKreadBit(hBs); + } + s->low = (int)us_low; + s->high = (int)us_high; + s->vobf = value & 0xFFFF; + + return symbol; +} + +static inline void copyTableAmrwbArith2(UCHAR tab[], int sizeIn, int sizeOut) { + int i; + int j; + int k = 2; + + tab += 2; + + if (sizeIn < sizeOut) { + tab[sizeOut + 0] = tab[sizeIn + 0]; + tab[sizeOut + 1] = tab[sizeIn + 1]; + if (sizeIn < (sizeOut >> 2)) { + k = 8; + } else if (sizeIn == (sizeOut >> 2)) { + k = 4; + } + + i = sizeOut - 1; + j = sizeIn - 1; + + for (; i >= 0; j--) { + UCHAR tq_data0 = tab[j]; + + for (int l = (k >> 1); l > 0; l--) { + tab[i--] = tq_data0; + tab[i--] = tq_data0; + } + } + } else { + if (sizeOut < (sizeIn >> 2)) { + k = 8; + } else if (sizeOut == (sizeIn >> 2)) { + k = 4; + } + + for (i = 0, j = 0; i < sizeOut; j += k) { + UCHAR tq_data0 = tab[j]; + + tab[i++] = tq_data0; + } + tab[sizeOut + 0] = tab[sizeIn + 0]; + tab[sizeOut + 1] = tab[sizeIn + 1]; + } +} + +static inline ULONG get_pk_v2(ULONG s) { + const ULONG *p = ari_merged_hash_ps; + ULONG s12 = (fMax((UINT)s, (UINT)1) << 12) - 1; + if (s12 > p[485]) { + p += 486; /* 742 - 256 = 486 */ + } else { + if (s12 > p[255]) p += 256; + } + + if (s12 > p[127]) { + p += 128; + } + if (s12 > p[63]) { + p += 64; + } + if (s12 > p[31]) { + p += 32; + } + if (s12 > p[15]) { + p += 16; + } + if (s12 > p[7]) { + p += 8; + } + if (s12 > p[3]) { + p += 4; + } + if (s12 > p[1]) { + p += 2; + } + ULONG j = p[0]; + if (s12 > j) j = p[1]; + if (s != (j >> 12)) j >>= 6; + return (j & 0x3F); +} + +static ARITH_CODING_ERROR decode2(HANDLE_FDK_BITSTREAM bbuf, + UCHAR *RESTRICT c_prev, + FIXP_DBL *RESTRICT pSpectralCoefficient, + INT n, INT nt) { + Tastat as; + int i, l, r; + INT lev, esc_nb, pki; + USHORT state_inc; + UINT s; + ARITH_CODING_ERROR ErrorStatus = ARITH_CODER_OK; + + int c_3 = 0; /* context of current frame 3 time steps ago */ + int c_2 = 0; /* context of current frame 2 time steps ago */ + int c_1 = 0; /* context of current frame 1 time steps ago */ + int c_0 = 1; /* context of current frame to be calculated */ + + /* ari_start_decoding_14bits */ + as.low = 0; + as.high = ari_q4new; + as.vobf = FDKreadBits(bbuf, cbitsnew); + + /* arith_map_context */ + state_inc = c_prev[0] << 12; + + for (i = 0; i < n; i++) { + /* arith_get_context */ + s = state_inc >> 8; + s = s + (c_prev[i + 1] << 8); + s = (s << 4) + c_1; + + state_inc = s; + + if (i > 3) { + /* Cumulative amplitude below 2 */ + if ((c_1 + c_2 + c_3) < 5) { + s += 0x10000; + } + } + + /* MSBs decoding */ + for (lev = esc_nb = 0;;) { + pki = get_pk_v2(s + (esc_nb << (VAL_ESC + 1))); + r = ari_decode_14bits(bbuf, &as, ari_pk[pki], VAL_ESC + 1); + if (r < VAL_ESC) { + break; + } + + lev++; + + if (lev > 23) return ARITH_CODER_ERROR; + + if (esc_nb < 7) { + esc_nb++; + } + } + + /* Stop symbol */ + if (r == 0) { + if (esc_nb > 0) { + break; /* Stop symbol */ + } + c_0 = 1; + } else /* if (r==0) */ + { + INT b = r >> 2; + INT a = r & 0x3; + + /* LSBs decoding */ + for (l = 0; l < lev; l++) { + { + int pidx = (a == 0) ? 1 : ((b == 0) ? 0 : 2); + r = ari_decode_14bits(bbuf, &as, ari_lsb2[pidx], 4); + } + a = (a << 1) | (r & 1); + b = (b << 1) | (r >> 1); + } + + pSpectralCoefficient[2 * i] = (FIXP_DBL)a; + pSpectralCoefficient[2 * i + 1] = (FIXP_DBL)b; + + c_0 = a + b + 1; + if (c_0 > 0xF) { + c_0 = 0xF; + } + + } /* endif (r==0) */ + + /* arith_update_context */ + c_3 = c_2; + c_2 = c_1; + c_1 = c_0; + c_prev[i] = (UCHAR)c_0; + + } /* for (i=0; i> (bits - 1))) { + pSpectralCoefficient[2 * i] = -pSpectralCoefficient[2 * i]; + } + if (pSpectralCoefficient[2 * i + 1] != (FIXP_DBL)0 && !(r & 1)) { + pSpectralCoefficient[2 * i + 1] = -pSpectralCoefficient[2 * i + 1]; + } + } + } + + FDKmemset(&c_prev[i], 1, sizeof(c_prev[0]) * (nt - i)); + + return ErrorStatus; +} + +CArcoData *CArco_Create(void) { return GetArcoData(); } + +void CArco_Destroy(CArcoData *pArcoData) { FreeArcoData(&pArcoData); } + +ARITH_CODING_ERROR CArco_DecodeArithData(CArcoData *pArcoData, + HANDLE_FDK_BITSTREAM hBs, + FIXP_DBL *RESTRICT mdctSpectrum, + int lg, int lg_max, + int arith_reset_flag) { + ARITH_CODING_ERROR ErrorStatus = ARITH_CODER_OK; + + /* Check lg and lg_max consistency. */ + if (lg_max < lg) { + return ARITH_CODER_ERROR; + } + + FDKmemclear(mdctSpectrum, lg_max * sizeof(FIXP_DBL)); + + /* arith_map_context */ + if (arith_reset_flag) { + FDKmemclear(pArcoData->c_prev, + sizeof(pArcoData->c_prev[0]) * ((lg_max / 2) + 4)); + } else { + if (lg_max != pArcoData->m_numberLinesPrev) { + if (pArcoData->m_numberLinesPrev == 0) { + /* Cannot decode without a valid AC context */ + return ARITH_CODER_ERROR; + } + + /* short-to-long or long-to-short block transition */ + /* Current length differs compared to previous - perform up/downmix of + * m_qbuf */ + copyTableAmrwbArith2(pArcoData->c_prev, pArcoData->m_numberLinesPrev >> 1, + lg_max >> 1); + } + } + + pArcoData->m_numberLinesPrev = lg_max; + + if (lg > 0) { + ErrorStatus = + decode2(hBs, pArcoData->c_prev + 2, mdctSpectrum, lg >> 1, lg_max >> 1); + } else { + FDKmemset(&pArcoData->c_prev[2], 1, + sizeof(pArcoData->c_prev[2]) * (lg_max >> 1)); + } + + if ((INT)FDKgetValidBits(hBs) < 0) { + return ARITH_CODER_ERROR; + } + + return ErrorStatus; +} diff --git a/fdk-aac/libDRCdec/include/FDK_drcDecLib.h b/fdk-aac/libDRCdec/include/FDK_drcDecLib.h new file mode 100644 index 0000000..e187e18 --- /dev/null +++ b/fdk-aac/libDRCdec/include/FDK_drcDecLib.h @@ -0,0 +1,313 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Bernhard Neugebauer + + Description: MPEG-D DRC Decoder + +*******************************************************************************/ + +#ifndef FDK_DRCDECLIB_H +#define FDK_DRCDECLIB_H + +#include "FDK_bitstream.h" +#include "FDK_audio.h" +#include "common_fix.h" + +/* DRC decoder according to ISO/IEC 23003-4 (MPEG-D DRC) */ +/* including ISO/IEC 23003-4/AMD1 (Amendment 1) */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct s_drc_decoder* HANDLE_DRC_DECODER; +typedef struct s_uni_drc_interface* HANDLE_UNI_DRC_INTERFACE; +typedef struct s_selection_process_output* HANDLE_SEL_PROC_OUTPUT; + +typedef enum { + DRC_DEC_SELECTION = 0x1, /* DRC decoder instance for DRC set selection only */ + DRC_DEC_GAIN = 0x2, /* DRC decoder instance for applying DRC only */ + DRC_DEC_ALL = 0x3 /* DRC decoder with full functionality */ +} DRC_DEC_FUNCTIONAL_RANGE; + +typedef enum { + /* get and set userparams */ + DRC_DEC_BOOST, + DRC_DEC_COMPRESS, + /* set only userparams */ + DRC_DEC_LOUDNESS_NORMALIZATION_ON, + DRC_DEC_TARGET_LOUDNESS, /**< target loudness in dB, with exponent e = 7 */ + DRC_DEC_EFFECT_TYPE, + DRC_DEC_EFFECT_TYPE_FALLBACK_CODE, + DRC_DEC_LOUDNESS_MEASUREMENT_METHOD, + /* set only system (not user) parameters */ + DRC_DEC_DOWNMIX_ID, + DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED, /**< number of output channels + notified to FDK_drcDecLib for + choosing an appropriate + downmixInstruction */ + DRC_DEC_BASE_CHANNEL_COUNT, + /* get only system parameters */ + DRC_DEC_IS_MULTIBAND_DRC_1, + DRC_DEC_IS_MULTIBAND_DRC_2, + DRC_DEC_IS_ACTIVE, /**< MPEG-D DRC payload is present and at least one of + Dynamic Range Control (DRC) or Loudness Normalization + (LN) is activated */ + DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED /**< number of output channels if + appropriate downmixInstruction exists + */ +} DRC_DEC_USERPARAM; + +typedef enum { + DRC_DEC_OK = 0, + + DRC_DEC_NOT_OK = -10000, + DRC_DEC_OUT_OF_MEMORY, + DRC_DEC_NOT_OPENED, + DRC_DEC_NOT_READY, + DRC_DEC_PARAM_OUT_OF_RANGE, + DRC_DEC_INVALID_PARAM, + DRC_DEC_UNSUPPORTED_FUNCTION +} DRC_DEC_ERROR; + +typedef enum { + DRC_DEC_TEST_TIME_DOMAIN = -100, + DRC_DEC_TEST_QMF_DOMAIN, + DRC_DEC_TEST_STFT_DOMAIN, + DRC_DEC_CODEC_MODE_UNDEFINED = -1, + DRC_DEC_MPEG_4_AAC, + DRC_DEC_MPEG_D_USAC, + DRC_DEC_MPEG_H_3DA +} DRC_DEC_CODEC_MODE; + +/* Apply only DRC sets dedicated to processing location. + DRC1: before downmix + DRC2: before or after downmix (AMD1: only after downmix) + DRC3: after downmix */ +typedef enum { + DRC_DEC_DRC1, + DRC_DEC_DRC1_DRC2, + DRC_DEC_DRC2, + DRC_DEC_DRC3, + DRC_DEC_DRC2_DRC3 +} DRC_DEC_LOCATION; + +DRC_DEC_ERROR +FDK_drcDec_Open(HANDLE_DRC_DECODER* phDrcDec, + const DRC_DEC_FUNCTIONAL_RANGE functionalRange); + +DRC_DEC_ERROR +FDK_drcDec_SetCodecMode(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_CODEC_MODE codecMode); + +DRC_DEC_ERROR +FDK_drcDec_Init(HANDLE_DRC_DECODER hDrcDec, const int frameSize, + const int sampleRate, const int baseChannelCount); + +DRC_DEC_ERROR +FDK_drcDec_Close(HANDLE_DRC_DECODER* phDrcDec); + +/* set single user request */ +DRC_DEC_ERROR +FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType, + const FIXP_DBL requestValue); + +LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType); + +DRC_DEC_ERROR +FDK_drcDec_SetInterfaceParameters(HANDLE_DRC_DECODER hDrcDec, + HANDLE_UNI_DRC_INTERFACE uniDrcInterface); + +DRC_DEC_ERROR +FDK_drcDec_SetSelectionProcessMpeghParameters_simple( + HANDLE_DRC_DECODER hDrcDec, const int groupPresetIdRequested, + const int numGroupIdsRequested, const int* groupIdsRequested); + +DRC_DEC_ERROR +FDK_drcDec_SetDownmixInstructions(HANDLE_DRC_DECODER hDrcDec, + const int numDowmixId, const int* downmixId, + const int* targetLayout, + const int* targetChannelCount); + +void FDK_drcDec_SetSelectionProcessOutput( + HANDLE_DRC_DECODER hDrcDec, HANDLE_SEL_PROC_OUTPUT hSelProcOutput); + +HANDLE_SEL_PROC_OUTPUT +FDK_drcDec_GetSelectionProcessOutput(HANDLE_DRC_DECODER hDrcDec); + +LONG /* FIXP_DBL, e = 7 */ +FDK_drcDec_GetGroupLoudness(HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + const int groupID, int* groupLoudnessAvailable); + +void FDK_drcDec_SetChannelGains(HANDLE_DRC_DECODER hDrcDec, + const int numChannels, const int frameSize, + FIXP_DBL* channelGainDb, FIXP_DBL* audioBuffer, + const int audioBufferChannelOffset); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcConfig(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessInfoSet(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessBox(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadDownmixInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcCoefficients_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +/* either call FDK_drcDec_ReadUniDrcConfig, FDK_drcDec_ReadLoudnessInfoSet and + FDK_drcDec_ReadUniDrcGain separately, or call FDK_drcDec_ReadUniDrc */ +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream); + +/* calling sequence: + FDK_drcDec_Read...() + FDK_drcDec_SetChannelGains() + FDK_drcDec_Preprocess() + FDK_drcDec_Process...() */ + +DRC_DEC_ERROR +FDK_drcDec_Preprocess(HANDLE_DRC_DECODER hDrcDec); + +DRC_DEC_ERROR +FDK_drcDec_ProcessTime(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, FIXP_DBL* realBuffer, + const int timeDataChannelOffset); + +DRC_DEC_ERROR +FDK_drcDec_ProcessFreq(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL** realBuffer, + FIXP_DBL** imagBuffer); + +DRC_DEC_ERROR +FDK_drcDec_ApplyDownmix(HANDLE_DRC_DECODER hDrcDec, int* reverseInChannelMap, + int* reverseOutChannelMap, FIXP_DBL* realBuffer, + int* pNChannels); + +/* Get library info for this module. */ +DRC_DEC_ERROR +FDK_drcDec_GetLibInfo(LIB_INFO* info); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp b/fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp new file mode 100644 index 0000000..b29b79d --- /dev/null +++ b/fdk-aac/libDRCdec/src/FDK_drcDecLib.cpp @@ -0,0 +1,891 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Bernhard Neugebauer + + Description: MPEG-D DRC Decoder + +*******************************************************************************/ + +#include "drcDec_reader.h" +#include "drcDec_gainDecoder.h" +#include "FDK_drcDecLib.h" + +#include "drcDec_selectionProcess.h" +#include "drcDec_tools.h" + +/* Decoder library info */ +#define DRCDEC_LIB_VL0 2 +#define DRCDEC_LIB_VL1 1 +#define DRCDEC_LIB_VL2 0 +#define DRCDEC_LIB_TITLE "MPEG-D DRC Decoder Lib" +#ifdef __ANDROID__ +#define DRCDEC_LIB_BUILD_DATE "" +#define DRCDEC_LIB_BUILD_TIME "" +#else +#define DRCDEC_LIB_BUILD_DATE __DATE__ +#define DRCDEC_LIB_BUILD_TIME __TIME__ +#endif + +typedef enum { + DRC_DEC_NOT_INITIALIZED = 0, + DRC_DEC_INITIALIZED, + DRC_DEC_NEW_GAIN_PAYLOAD, + DRC_DEC_INTERPOLATION_PREPARED +} DRC_DEC_STATUS; + +struct s_drc_decoder { + DRC_DEC_CODEC_MODE codecMode; + DRC_DEC_FUNCTIONAL_RANGE functionalRange; + DRC_DEC_STATUS status; + + /* handles of submodules */ + HANDLE_DRC_GAIN_DECODER hGainDec; + HANDLE_DRC_SELECTION_PROCESS hSelectionProc; + int selProcInputDiff; + + /* data structs */ + UNI_DRC_CONFIG uniDrcConfig; + LOUDNESS_INFO_SET loudnessInfoSet; + UNI_DRC_GAIN uniDrcGain; + + SEL_PROC_OUTPUT selProcOutput; +} DRC_DECODER; + +static int isResetNeeded(HANDLE_DRC_DECODER hDrcDec, + const SEL_PROC_OUTPUT oldSelProcOutput) { + int i, resetNeeded = 0; + + if (hDrcDec->selProcOutput.numSelectedDrcSets != + oldSelProcOutput.numSelectedDrcSets) { + resetNeeded = 1; + } else { + for (i = 0; i < hDrcDec->selProcOutput.numSelectedDrcSets; i++) { + if (hDrcDec->selProcOutput.selectedDrcSetIds[i] != + oldSelProcOutput.selectedDrcSetIds[i]) + resetNeeded = 1; + if (hDrcDec->selProcOutput.selectedDownmixIds[i] != + oldSelProcOutput.selectedDownmixIds[i]) + resetNeeded = 1; + } + } + + if (hDrcDec->selProcOutput.boost != oldSelProcOutput.boost) resetNeeded = 1; + if (hDrcDec->selProcOutput.compress != oldSelProcOutput.compress) + resetNeeded = 1; + + /* Note: Changes in downmix matrix are not caught, as they don't affect the + * DRC gain decoder */ + + return resetNeeded; +} + +static DRC_DEC_ERROR startSelectionProcess(HANDLE_DRC_DECODER hDrcDec) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int uniDrcConfigHasChanged = 0; + SEL_PROC_OUTPUT oldSelProcOutput = hDrcDec->selProcOutput; + + if (!hDrcDec->status) return DRC_DEC_NOT_READY; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + uniDrcConfigHasChanged = hDrcDec->uniDrcConfig.diff; + if (hDrcDec->uniDrcConfig.diff || hDrcDec->loudnessInfoSet.diff || + hDrcDec->selProcInputDiff) { + /* in case of an error, signal that selection process was not successful + */ + hDrcDec->selProcOutput.numSelectedDrcSets = 0; + + sErr = drcDec_SelectionProcess_Process( + hDrcDec->hSelectionProc, &(hDrcDec->uniDrcConfig), + &(hDrcDec->loudnessInfoSet), &(hDrcDec->selProcOutput)); + if (sErr) return DRC_DEC_OK; + + hDrcDec->selProcInputDiff = 0; + hDrcDec->uniDrcConfig.diff = 0; + hDrcDec->loudnessInfoSet.diff = 0; + } + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + if (isResetNeeded(hDrcDec, oldSelProcOutput) || uniDrcConfigHasChanged) { + dErr = + drcDec_GainDecoder_Config(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), + hDrcDec->selProcOutput.numSelectedDrcSets, + hDrcDec->selProcOutput.selectedDrcSetIds, + hDrcDec->selProcOutput.selectedDownmixIds); + if (dErr) return DRC_DEC_OK; + } + } + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Open(HANDLE_DRC_DECODER* phDrcDec, + const DRC_DEC_FUNCTIONAL_RANGE functionalRange) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + HANDLE_DRC_DECODER hDrcDec; + + *phDrcDec = (HANDLE_DRC_DECODER)FDKcalloc(1, sizeof(DRC_DECODER)); + if (!*phDrcDec) return DRC_DEC_OUT_OF_MEMORY; + hDrcDec = *phDrcDec; + + hDrcDec->functionalRange = functionalRange; + + hDrcDec->status = DRC_DEC_NOT_INITIALIZED; + hDrcDec->codecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_Create(&(hDrcDec->hSelectionProc)); + if (sErr) return DRC_DEC_OUT_OF_MEMORY; + sErr = drcDec_SelectionProcess_Init(hDrcDec->hSelectionProc); + if (sErr) return DRC_DEC_NOT_OK; + hDrcDec->selProcInputDiff = 1; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + dErr = drcDec_GainDecoder_Open(&(hDrcDec->hGainDec)); + if (dErr) return DRC_DEC_OUT_OF_MEMORY; + } + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_SetCodecMode(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_CODEC_MODE codecMode) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == + DRC_DEC_CODEC_MODE_UNDEFINED) { /* Set codec mode, if it is set for the + first time */ + hDrcDec->codecMode = codecMode; + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_SetCodecMode( + hDrcDec->hSelectionProc, (SEL_PROC_CODEC_MODE)codecMode); + if (sErr) return DRC_DEC_NOT_OK; + hDrcDec->selProcInputDiff = 1; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + DELAY_MODE delayMode; + int timeDomainSupported; + SUBBAND_DOMAIN_MODE subbandDomainSupported; + + switch (hDrcDec->codecMode) { + case DRC_DEC_MPEG_4_AAC: + case DRC_DEC_MPEG_D_USAC: + case DRC_DEC_MPEG_H_3DA: + default: + delayMode = DM_REGULAR_DELAY; + } + + switch (hDrcDec->codecMode) { + case DRC_DEC_MPEG_4_AAC: + case DRC_DEC_MPEG_D_USAC: + timeDomainSupported = 1; + subbandDomainSupported = SDM_OFF; + break; + case DRC_DEC_MPEG_H_3DA: + timeDomainSupported = 1; + subbandDomainSupported = SDM_STFT256; + break; + + case DRC_DEC_TEST_TIME_DOMAIN: + timeDomainSupported = 1; + subbandDomainSupported = SDM_OFF; + break; + case DRC_DEC_TEST_QMF_DOMAIN: + timeDomainSupported = 0; + subbandDomainSupported = SDM_QMF64; + break; + case DRC_DEC_TEST_STFT_DOMAIN: + timeDomainSupported = 0; + subbandDomainSupported = SDM_STFT256; + break; + + default: + timeDomainSupported = 0; + subbandDomainSupported = SDM_OFF; + } + + dErr = drcDec_GainDecoder_SetCodecDependentParameters( + hDrcDec->hGainDec, delayMode, timeDomainSupported, + subbandDomainSupported); + if (dErr) return DRC_DEC_NOT_OK; + } + } + + /* Don't allow changing codecMode if it has already been set. */ + if (hDrcDec->codecMode != codecMode) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Init(HANDLE_DRC_DECODER hDrcDec, const int frameSize, + const int sampleRate, const int baseChannelCount) { + DRC_ERROR dErr = DE_OK; + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hDrcDec == NULL || frameSize == 0 || sampleRate == 0 || + baseChannelCount == 0) + return DRC_DEC_OK; /* return without doing anything */ + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, + (FIXP_DBL)baseChannelCount, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_SAMPLE_RATE, (FIXP_DBL)sampleRate, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + } + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + dErr = drcDec_GainDecoder_Init(hDrcDec->hGainDec, frameSize, sampleRate); + if (dErr) return DRC_DEC_NOT_OK; + } + + hDrcDec->status = DRC_DEC_INITIALIZED; + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Close(HANDLE_DRC_DECODER* phDrcDec) { + HANDLE_DRC_DECODER hDrcDec; + + if (phDrcDec == NULL) { + return DRC_DEC_OK; + } + + hDrcDec = *phDrcDec; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->functionalRange & DRC_DEC_GAIN) { + drcDec_GainDecoder_Close(&(hDrcDec->hGainDec)); + } + + if (hDrcDec->functionalRange & DRC_DEC_SELECTION) { + drcDec_SelectionProcess_Delete(&(hDrcDec->hSelectionProc)); + } + + FDKfree(*phDrcDec); + *phDrcDec = NULL; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_SetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType, + const FIXP_DBL requestValue) { + DRCDEC_SELECTION_PROCESS_RETURN sErr = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->functionalRange == DRC_DEC_GAIN) + return DRC_DEC_NOT_OK; /* not supported for DRC_DEC_GAIN. All parameters are + handed over to selection process lib. */ + + switch (requestType) { + case DRC_DEC_BOOST: + sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, + SEL_PROC_BOOST, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_COMPRESS: + sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, + SEL_PROC_COMPRESS, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_LOUDNESS_NORMALIZATION_ON: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON, + requestValue, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_TARGET_LOUDNESS: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_TARGET_LOUDNESS, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_EFFECT_TYPE: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_EFFECT_TYPE, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_DOWNMIX_ID: + sErr = drcDec_SelectionProcess_SetParam(hDrcDec->hSelectionProc, + SEL_PROC_DOWNMIX_ID, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_TARGET_CHANNEL_COUNT_REQUESTED: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_TARGET_CHANNEL_COUNT, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + case DRC_DEC_BASE_CHANNEL_COUNT: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_BASE_CHANNEL_COUNT, requestValue, + &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_NOT_OK; + break; + case DRC_DEC_LOUDNESS_MEASUREMENT_METHOD: + sErr = drcDec_SelectionProcess_SetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_MEASUREMENT_METHOD, + requestValue, &(hDrcDec->selProcInputDiff)); + if (sErr) return DRC_DEC_PARAM_OUT_OF_RANGE; + break; + default: + return DRC_DEC_INVALID_PARAM; + } + + /* All parameters need a new start of the selection process */ + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +LONG FDK_drcDec_GetParam(HANDLE_DRC_DECODER hDrcDec, + const DRC_DEC_USERPARAM requestType) { + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + switch (requestType) { + case DRC_DEC_BOOST: + return (LONG)hDrcDec->selProcOutput.boost; + case DRC_DEC_COMPRESS: + return (LONG)hDrcDec->selProcOutput.compress; + case DRC_DEC_IS_MULTIBAND_DRC_1: + return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0); + case DRC_DEC_IS_MULTIBAND_DRC_2: + return (LONG)bitstreamContainsMultibandDrc(&hDrcDec->uniDrcConfig, 0x7F); + case DRC_DEC_IS_ACTIVE: { + /* MPEG-D DRC is considered active (and overrides MPEG-4 DRC), if + * uniDrc payload is present (loudnessInfoSet and/or uniDrcConfig) + * at least one of DRC and Loudness Control is switched on */ + int drcOn = drcDec_SelectionProcess_GetParam( + hDrcDec->hSelectionProc, SEL_PROC_DYNAMIC_RANGE_CONTROL_ON); + int lnOn = drcDec_SelectionProcess_GetParam( + hDrcDec->hSelectionProc, SEL_PROC_LOUDNESS_NORMALIZATION_ON); + int uniDrcPayloadPresent = + (hDrcDec->loudnessInfoSet.loudnessInfoCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->loudnessInfoSet.loudnessInfoAlbumCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount > 0); + uniDrcPayloadPresent |= + (hDrcDec->uniDrcConfig.downmixInstructionsCount > 0); + return (LONG)(uniDrcPayloadPresent && (drcOn || lnOn)); + } + case DRC_DEC_TARGET_CHANNEL_COUNT_SELECTED: + return (LONG)hDrcDec->selProcOutput.targetChannelCount; + default: + return 0; + } +} + +DRC_DEC_ERROR +FDK_drcDec_SetInterfaceParameters(HANDLE_DRC_DECODER hDrcDec, + HANDLE_UNI_DRC_INTERFACE hUniDrcInterface) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +DRC_DEC_ERROR +FDK_drcDec_SetSelectionProcessMpeghParameters_simple( + HANDLE_DRC_DECODER hDrcDec, const int groupPresetIdRequested, + const int numGroupIdsRequested, const int* groupIdsRequested) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +DRC_DEC_ERROR +FDK_drcDec_SetDownmixInstructions(HANDLE_DRC_DECODER hDrcDec, + const int numDownmixId, const int* downmixId, + const int* targetLayout, + const int* targetChannelCount) { + return DRC_DEC_UNSUPPORTED_FUNCTION; +} + +void FDK_drcDec_SetSelectionProcessOutput( + HANDLE_DRC_DECODER hDrcDec, HANDLE_SEL_PROC_OUTPUT hSelProcOutput) {} + +HANDLE_SEL_PROC_OUTPUT +FDK_drcDec_GetSelectionProcessOutput(HANDLE_DRC_DECODER hDrcDec) { + if (hDrcDec == NULL) return NULL; + + return &(hDrcDec->selProcOutput); +} + +LONG /* FIXP_DBL, e = 7 */ +FDK_drcDec_GetGroupLoudness(HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + const int groupID, int* groupLoudnessAvailable) { + return (LONG)0; +} + +void FDK_drcDec_SetChannelGains(HANDLE_DRC_DECODER hDrcDec, + const int numChannels, const int frameSize, + FIXP_DBL* channelGainDb, FIXP_DBL* audioBuffer, + const int audioBufferChannelOffset) { + int err; + + if (hDrcDec == NULL) return; + + err = drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + hDrcDec->hGainDec, hDrcDec->selProcOutput.loudnessNormalizationGainDb); + if (err) return; + + drcDec_GainDecoder_SetChannelGains(hDrcDec->hGainDec, numChannels, frameSize, + channelGainDb, audioBufferChannelOffset, + audioBuffer); +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcConfig(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { + dErr = drcDec_readUniDrcConfig(hBitstream, &(hDrcDec->uniDrcConfig)); + } else + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occured */ + FDKmemclear(&hDrcDec->uniDrcConfig, sizeof(hDrcDec->uniDrcConfig)); + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadDownmixInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.downmixInstructions, + sizeof(hDrcDec->uniDrcConfig.downmixInstructions)); + hDrcDec->uniDrcConfig.downmixInstructionsCount = 0; + hDrcDec->uniDrcConfig.downmixInstructionsCountV0 = 0; + hDrcDec->uniDrcConfig.downmixInstructionsCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcInstructions_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.drcInstructionsUniDrc, + sizeof(hDrcDec->uniDrcConfig.drcInstructionsUniDrc)); + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCount = 0; + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV0 = 0; + hDrcDec->uniDrcConfig.drcInstructionsUniDrcCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcCoefficients_Box(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->uniDrcConfig.drcCoefficientsUniDrc, + sizeof(hDrcDec->uniDrcConfig.drcCoefficientsUniDrc)); + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCount = 0; + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV0 = 0; + hDrcDec->uniDrcConfig.drcCoefficientsUniDrcCountV1 = 0; + hDrcDec->uniDrcConfig.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessInfoSet(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + if (hDrcDec->codecMode == DRC_DEC_MPEG_D_USAC) { + dErr = drcDec_readLoudnessInfoSet(hBitstream, &(hDrcDec->loudnessInfoSet)); + } else + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); + hDrcDec->loudnessInfoSet.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadLoudnessBox(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + + return DRC_DEC_NOT_OK; + + if (dErr) { + /* clear config, if parsing error occurred */ + FDKmemclear(&hDrcDec->loudnessInfoSet, sizeof(hDrcDec->loudnessInfoSet)); + hDrcDec->loudnessInfoSet.diff = 1; + } + + startSelectionProcess(hDrcDec); + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrcGain(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) { + return DRC_DEC_OK; + } + + dErr = drcDec_readUniDrcGain( + hBitstream, &(hDrcDec->uniDrcConfig), + drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), + drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), + &(hDrcDec->uniDrcGain)); + if (dErr) return DRC_DEC_NOT_OK; + + hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ReadUniDrc(HANDLE_DRC_DECODER hDrcDec, + HANDLE_FDK_BITSTREAM hBitstream) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) return DRC_DEC_NOT_READY; + + dErr = drcDec_readUniDrc( + hBitstream, &(hDrcDec->uniDrcConfig), &(hDrcDec->loudnessInfoSet), + drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec), + drcDec_GainDecoder_GetDeltaTminDefault(hDrcDec->hGainDec), + &(hDrcDec->uniDrcGain)); + if (dErr) return DRC_DEC_NOT_OK; + + startSelectionProcess(hDrcDec); + + hDrcDec->status = DRC_DEC_NEW_GAIN_PAYLOAD; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_Preprocess(HANDLE_DRC_DECODER hDrcDec) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!hDrcDec->status) return DRC_DEC_NOT_READY; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + + if (hDrcDec->status != DRC_DEC_NEW_GAIN_PAYLOAD) { + /* no new gain payload was read, e.g. during concalment or flushing. + Generate DRC gains based on the stored DRC gains of last frames */ + drcDec_GainDecoder_Conceal(hDrcDec->hGainDec, &(hDrcDec->uniDrcConfig), + &(hDrcDec->uniDrcGain)); + } + + dErr = drcDec_GainDecoder_Preprocess( + hDrcDec->hGainDec, &(hDrcDec->uniDrcGain), + hDrcDec->selProcOutput.loudnessNormalizationGainDb, + hDrcDec->selProcOutput.boost, hDrcDec->selProcOutput.compress); + if (dErr) return DRC_DEC_NOT_OK; + hDrcDec->status = DRC_DEC_INTERPOLATION_PREPARED; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ProcessTime(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, FIXP_DBL* realBuffer, + const int timeDataChannelOffset) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) + return DRC_DEC_NOT_READY; + + dErr = drcDec_GainDecoder_ProcessTimeDomain( + hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, + channelOffset, drcChannelOffset, numChannelsProcessed, + timeDataChannelOffset, realBuffer); + if (dErr) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ProcessFreq(HANDLE_DRC_DECODER hDrcDec, const int delaySamples, + const DRC_DEC_LOCATION drcLocation, + const int channelOffset, const int drcChannelOffset, + const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL** realBuffer, + FIXP_DBL** imagBuffer) { + DRC_ERROR dErr = DE_OK; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + if (hDrcDec->status != DRC_DEC_INTERPOLATION_PREPARED) + return DRC_DEC_NOT_READY; + + dErr = drcDec_GainDecoder_ProcessSubbandDomain( + hDrcDec->hGainDec, delaySamples, (GAIN_DEC_LOCATION)drcLocation, + channelOffset, drcChannelOffset, numChannelsProcessed, + processSingleTimeslot, realBuffer, imagBuffer); + if (dErr) return DRC_DEC_NOT_OK; + + return DRC_DEC_OK; +} + +DRC_DEC_ERROR +FDK_drcDec_ApplyDownmix(HANDLE_DRC_DECODER hDrcDec, int* reverseInChannelMap, + int* reverseOutChannelMap, FIXP_DBL* realBuffer, + int* pNChannels) { + SEL_PROC_OUTPUT* pSelProcOutput = &(hDrcDec->selProcOutput); + int baseChCnt = pSelProcOutput->baseChannelCount; + int targetChCnt = pSelProcOutput->targetChannelCount; + int frameSize, n, ic, oc; + FIXP_DBL tmp_out[8]; + FIXP_DBL* audioChannels[8]; + + if (hDrcDec == NULL) return DRC_DEC_NOT_OPENED; + if (!(hDrcDec->functionalRange & DRC_DEC_GAIN)) return DRC_DEC_NOT_OK; + + /* only downmix is performed here, no upmix. + Downmix is only performed if downmix coefficients are provided. + All other cases of downmix and upmix are treated by pcmDmx library. */ + if (pSelProcOutput->downmixMatrixPresent == 0) + return DRC_DEC_OK; /* no downmix */ + if (targetChCnt >= baseChCnt) return DRC_DEC_OK; /* downmix only */ + + /* sanity checks */ + if (realBuffer == NULL) return DRC_DEC_NOT_OK; + if (reverseInChannelMap == NULL) return DRC_DEC_NOT_OK; + if (reverseOutChannelMap == NULL) return DRC_DEC_NOT_OK; + if (baseChCnt > 8) return DRC_DEC_NOT_OK; + if (baseChCnt != *pNChannels) return DRC_DEC_NOT_OK; + if (targetChCnt > 8) return DRC_DEC_NOT_OK; + + frameSize = drcDec_GainDecoder_GetFrameSize(hDrcDec->hGainDec); + + for (ic = 0; ic < baseChCnt; ic++) { + audioChannels[ic] = &(realBuffer[ic * frameSize]); + } + + /* in-place downmix */ + for (n = 0; n < frameSize; n++) { + for (oc = 0; oc < targetChCnt; oc++) { + tmp_out[oc] = (FIXP_DBL)0; + for (ic = 0; ic < baseChCnt; ic++) { + tmp_out[oc] += + fMultDiv2(audioChannels[ic][n], + pSelProcOutput->downmixMatrix[reverseInChannelMap[ic]] + [reverseOutChannelMap[oc]]) + << 3; + } + } + for (oc = 0; oc < targetChCnt; oc++) { + if (oc >= baseChCnt) break; + audioChannels[oc][n] = tmp_out[oc]; + } + } + + for (oc = targetChCnt; oc < baseChCnt; oc++) { + FDKmemset(audioChannels[oc], 0, frameSize * sizeof(FIXP_DBL)); + } + + *pNChannels = targetChCnt; + + return DRC_DEC_OK; +} + +/* Get library info for this module. */ +DRC_DEC_ERROR +FDK_drcDec_GetLibInfo(LIB_INFO* info) { + int i; + + if (info == NULL) { + return DRC_DEC_INVALID_PARAM; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return DRC_DEC_NOT_OK; + } + + /* Add the library info */ + info[i].module_id = FDK_UNIDRCDEC; + info[i].version = LIB_VERSION(DRCDEC_LIB_VL0, DRCDEC_LIB_VL1, DRCDEC_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = DRCDEC_LIB_BUILD_DATE; + info[i].build_time = DRCDEC_LIB_BUILD_TIME; + info[i].title = DRCDEC_LIB_TITLE; + + return DRC_DEC_OK; +} diff --git a/fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp b/fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp new file mode 100644 index 0000000..ca81fad --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_gainDecoder.cpp @@ -0,0 +1,445 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_preprocess.h" +#include "drcGainDec_init.h" +#include "drcGainDec_process.h" +#include "drcDec_tools.h" + +/*******************************************/ +/* static functions */ +/*******************************************/ + +static int _fitsLocation(DRC_INSTRUCTIONS_UNI_DRC* pInst, + const GAIN_DEC_LOCATION drcLocation) { + int downmixId = pInst->drcApplyToDownmix ? pInst->downmixId[0] : 0; + switch (drcLocation) { + case GAIN_DEC_DRC1: + return (downmixId == 0); + case GAIN_DEC_DRC1_DRC2: + return ((downmixId == 0) || (downmixId == DOWNMIX_ID_ANY_DOWNMIX)); + case GAIN_DEC_DRC2: + return (downmixId == DOWNMIX_ID_ANY_DOWNMIX); + case GAIN_DEC_DRC3: + return ((downmixId != 0) && (downmixId != DOWNMIX_ID_ANY_DOWNMIX)); + case GAIN_DEC_DRC2_DRC3: + return (downmixId != 0); + } + return 0; +} + +static void _setChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannelGains, + const FIXP_DBL* channelGainDb) { + int i, channelGain_e; + FIXP_DBL channelGain; + FDK_ASSERT(numChannelGains <= 8); + for (i = 0; i < numChannelGains; i++) { + if (channelGainDb[i] == (FIXP_DBL)MINVAL_DBL) { + hGainDec->channelGain[i] = (FIXP_DBL)0; + } else { + /* add loudness normalisation gain (dB) to channel gain (dB) */ + FIXP_DBL tmp_channelGainDb = (channelGainDb[i] >> 1) + + (hGainDec->loudnessNormalisationGainDb >> 2); + tmp_channelGainDb = + SATURATE_LEFT_SHIFT(tmp_channelGainDb, 1, DFRACT_BITS); + channelGain = dB2lin(tmp_channelGainDb, 8, &channelGain_e); + hGainDec->channelGain[i] = scaleValue(channelGain, channelGain_e - 8); + } + } +} + +/*******************************************/ +/* public functions */ +/*******************************************/ + +DRC_ERROR +drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec) { + DRC_GAIN_DECODER* hGainDec = NULL; + + hGainDec = (DRC_GAIN_DECODER*)FDKcalloc(1, sizeof(DRC_GAIN_DECODER)); + if (hGainDec == NULL) return DE_MEMORY_ERROR; + + hGainDec->multiBandActiveDrcIndex = -1; + hGainDec->channelGainActiveDrcIndex = -1; + + *phGainDec = hGainDec; + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize, + const int sampleRate) { + DRC_ERROR err = DE_OK; + + err = initGainDec(hGainDec, frameSize, sampleRate); + if (err) return err; + + initDrcGainBuffers(hGainDec->frameSize, &hGainDec->drcGainBuffers); + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_SetCodecDependentParameters( + HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode, + const int timeDomainSupported, + const SUBBAND_DOMAIN_MODE subbandDomainSupported) { + if ((delayMode != DM_REGULAR_DELAY) && (delayMode != DM_LOW_DELAY)) { + return DE_NOT_OK; + } + hGainDec->delayMode = delayMode; + hGainDec->timeDomainSupported = timeDomainSupported; + hGainDec->subbandDomainSupported = subbandDomainSupported; + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const UCHAR numSelectedDrcSets, + const SCHAR* selectedDrcSetIds, + const UCHAR* selectedDownmixIds) { + DRC_ERROR err = DE_OK; + int a; + + hGainDec->nActiveDrcs = 0; + hGainDec->multiBandActiveDrcIndex = -1; + hGainDec->channelGainActiveDrcIndex = -1; + for (a = 0; a < numSelectedDrcSets; a++) { + err = initActiveDrc(hGainDec, hUniDrcConfig, selectedDrcSetIds[a], + selectedDownmixIds[a]); + if (err) return err; + } + + err = initActiveDrcOffset(hGainDec); + if (err) return err; + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER* phGainDec) { + if (*phGainDec != NULL) { + FDKfree(*phGainDec); + *phGainDec = NULL; + } + + return DE_OK; +} + +DRC_ERROR +drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, + const FIXP_DBL loudnessNormalizationGainDb, + const FIXP_SGL boost, const FIXP_SGL compress) { + DRC_ERROR err = DE_OK; + int a, c; + + /* lnbPointer is the index on the most recent node buffer */ + hGainDec->drcGainBuffers.lnbPointer++; + if (hGainDec->drcGainBuffers.lnbPointer >= NUM_LNB_FRAMES) + hGainDec->drcGainBuffers.lnbPointer = 0; + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + /* prepare gain interpolation of sequences used by copying and modifying + * nodes in node buffers */ + err = prepareDrcGain(hGainDec, hUniDrcGain, compress, boost, + loudnessNormalizationGainDb, a); + if (err) return err; + } + + for (a = 0; a < MAX_ACTIVE_DRCS; a++) { + for (c = 0; c < 8; c++) { + hGainDec->activeDrc[a] + .lnbIndexForChannel[c][hGainDec->drcGainBuffers.lnbPointer] = + -1; /* "no DRC processing" */ + } + hGainDec->activeDrc[a].subbandGainsReady = 0; + } + + for (c = 0; c < 8; c++) { + hGainDec->drcGainBuffers + .channelGain[c][hGainDec->drcGainBuffers.lnbPointer] = + FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + + return err; +} + +/* create gain sequence out of gain sequences of last frame for concealment and + * flushing */ +DRC_ERROR +drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + int seq, gainSequenceCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (pCoef == NULL) return DE_OK; + + gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12); + + for (seq = 0; seq < gainSequenceCount; seq++) { + int lastNodeIndex = 0; + FIXP_SGL lastGainDb = (FIXP_SGL)0; + + lastNodeIndex = hUniDrcGain->nNodes[seq] - 1; + if ((lastNodeIndex >= 0) && (lastNodeIndex < 16)) { + lastGainDb = hUniDrcGain->gainNode[seq][lastNodeIndex].gainDb; + } + + hUniDrcGain->nNodes[seq] = 1; + if (lastGainDb > (FIXP_SGL)0) { + hUniDrcGain->gainNode[seq][0].gainDb = + FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.9f), lastGainDb)); + } else { + hUniDrcGain->gainNode[seq][0].gainDb = + FX_DBL2FX_SGL(fMult(FL2FXCONST_SGL(0.98f), lastGainDb)); + } + hUniDrcGain->gainNode[seq][0].time = hGainDec->frameSize - 1; + } + return DE_OK; +} + +void drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannels, + const int frameSize, + const FIXP_DBL* channelGainDb, + const int audioBufferChannelOffset, + FIXP_DBL* audioBuffer) { + int c, i; + + if (hGainDec->channelGainActiveDrcIndex >= 0) { + /* channel gains will be applied in drcDec_GainDecoder_ProcessTimeDomain or + * drcDec_GainDecoder_ProcessSubbandDomain, respectively. */ + _setChannelGains(hGainDec, numChannels, channelGainDb); + + if (!hGainDec->status) { /* overwrite previous channel gains at startup */ + DRC_GAIN_BUFFERS* pDrcGainBuffers = &hGainDec->drcGainBuffers; + for (c = 0; c < numChannels; c++) { + for (i = 0; i < NUM_LNB_FRAMES; i++) { + pDrcGainBuffers->channelGain[c][i] = hGainDec->channelGain[c]; + } + } + hGainDec->status = 1; + } + } else { + /* smooth and apply channel gains */ + FIXP_DBL prevChannelGain[8]; + for (c = 0; c < numChannels; c++) { + prevChannelGain[c] = hGainDec->channelGain[c]; + } + + _setChannelGains(hGainDec, numChannels, channelGainDb); + + if (!hGainDec->status) { /* overwrite previous channel gains at startup */ + for (c = 0; c < numChannels; c++) + prevChannelGain[c] = hGainDec->channelGain[c]; + hGainDec->status = 1; + } + + for (c = 0; c < numChannels; c++) { + INT n_min = fMin(fMin(CntLeadingZeros(prevChannelGain[c]), + CntLeadingZeros(hGainDec->channelGain[c])) - + 1, + 9); + FIXP_DBL gain = prevChannelGain[c] << n_min; + FIXP_DBL stepsize = ((hGainDec->channelGain[c] << n_min) - gain); + if (stepsize != (FIXP_DBL)0) { + if (frameSize == 1024) + stepsize = stepsize >> 10; + else + stepsize = (LONG)stepsize / frameSize; + } + n_min = 9 - n_min; +#ifdef FUNCTION_drcDec_GainDecoder_SetChannelGains_func1 + drcDec_GainDecoder_SetChannelGains_func1(audioBuffer, gain, stepsize, + n_min, frameSize); +#else + for (i = 0; i < frameSize; i++) { + audioBuffer[i] = fMultDiv2(audioBuffer[i], gain) << n_min; + gain += stepsize; + } +#endif + audioBuffer += audioBufferChannelOffset; + } + } +} + +DRC_ERROR +drcDec_GainDecoder_ProcessTimeDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* audioIOBuffer) { + DRC_ERROR err = DE_OK; + int a; + + if (!hGainDec->timeDomainSupported) { + return DE_NOT_OK; + } + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue; + + /* Apply DRC */ + err = processDrcTime(hGainDec, a, delaySamples, channelOffset, + drcChannelOffset, numChannelsProcessed, + timeDataChannelOffset, audioIOBuffer); + if (err) return err; + } + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_ProcessSubbandDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL* audioIOBufferReal[], + FIXP_DBL* audioIOBufferImag[]) { + DRC_ERROR err = DE_OK; + int a; + + if (hGainDec->subbandDomainSupported == SDM_OFF) { + return DE_NOT_OK; + } + + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + if (!_fitsLocation(hGainDec->activeDrc[a].pInst, drcLocation)) continue; + + /* Apply DRC */ + err = processDrcSubband(hGainDec, a, delaySamples, channelOffset, + drcChannelOffset, numChannelsProcessed, + processSingleTimeslot, audioIOBufferReal, + audioIOBufferImag); + if (err) return err; + } + + return err; +} + +DRC_ERROR +drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + HANDLE_DRC_GAIN_DECODER hGainDec, FIXP_DBL loudnessNormalizationGainDb) { + hGainDec->loudnessNormalisationGainDb = loudnessNormalizationGainDb; + + return DE_OK; +} + +int drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec) { + if (hGainDec == NULL) return -1; + + return hGainDec->frameSize; +} + +int drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec) { + if (hGainDec == NULL) return -1; + + return hGainDec->deltaTminDefault; +} diff --git a/fdk-aac/libDRCdec/src/drcDec_gainDecoder.h b/fdk-aac/libDRCdec/src/drcDec_gainDecoder.h new file mode 100644 index 0000000..2f4df4c --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_gainDecoder.h @@ -0,0 +1,264 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_GAINDECODER_H +#define DRCDEC_GAINDECODER_H + +#include "drcDecoder.h" + +/* Definitions common to gainDecoder submodule */ + +#define NUM_LNB_FRAMES \ + 5 /* previous frame + this frame + one frame for DM_REGULAR_DELAY + (maximum \ + delaySamples)/frameSize */ + +/* QMF64 */ +#define SUBBAND_NUM_BANDS_QMF64 64 +#define SUBBAND_DOWNSAMPLING_FACTOR_QMF64 64 +#define SUBBAND_ANALYSIS_DELAY_QMF64 320 + +/* QMF71 (according to ISO/IEC 23003-1:2007) */ +#define SUBBAND_NUM_BANDS_QMF71 71 +#define SUBBAND_DOWNSAMPLING_FACTOR_QMF71 64 +#define SUBBAND_ANALYSIS_DELAY_QMF71 320 + 384 + +/* STFT256 (according to ISO/IEC 23008-3:2015/AMD3) */ +#define SUBBAND_NUM_BANDS_STFT256 256 +#define SUBBAND_DOWNSAMPLING_FACTOR_STFT256 256 +#define SUBBAND_ANALYSIS_DELAY_STFT256 256 + +typedef enum { + GAIN_DEC_DRC1, + GAIN_DEC_DRC1_DRC2, + GAIN_DEC_DRC2, + GAIN_DEC_DRC3, + GAIN_DEC_DRC2_DRC3 +} GAIN_DEC_LOCATION; + +typedef struct { + FIXP_DBL gainLin; /* e = 7 */ + SHORT time; +} NODE_LIN; + +typedef struct { + GAIN_INTERPOLATION_TYPE gainInterpolationType; + int nNodes[NUM_LNB_FRAMES]; /* number of nodes, saturated to 16 */ + NODE_LIN linearNode[NUM_LNB_FRAMES][16]; +} LINEAR_NODE_BUFFER; + +typedef struct { + int lnbPointer; + LINEAR_NODE_BUFFER linearNodeBuffer[12]; + LINEAR_NODE_BUFFER dummyLnb; + FIXP_DBL channelGain[8][NUM_LNB_FRAMES]; /* e = 8 */ +} DRC_GAIN_BUFFERS; + +typedef struct { + int activeDrcOffset; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_COEFFICIENTS_UNI_DRC* pCoef; + + DUCKING_MODIFICATION duckingModificationForChannelGroup[8]; + SCHAR channelGroupForChannel[8]; + + UCHAR bandCountForChannelGroup[8]; + UCHAR gainElementForGroup[8]; + UCHAR channelGroupIsParametricDrc[8]; + UCHAR gainElementCount; /* number of different DRC gains inluding all DRC + bands */ + int lnbIndexForChannel[8][NUM_LNB_FRAMES]; + int subbandGainsReady; +} ACTIVE_DRC; + +typedef struct { + int deltaTminDefault; + INT frameSize; + FIXP_DBL loudnessNormalisationGainDb; + DELAY_MODE delayMode; + + int nActiveDrcs; + ACTIVE_DRC activeDrc[MAX_ACTIVE_DRCS]; + int multiBandActiveDrcIndex; + int channelGainActiveDrcIndex; + FIXP_DBL channelGain[8]; /* e = 8 */ + + DRC_GAIN_BUFFERS drcGainBuffers; + FIXP_DBL subbandGains[12][4 * 1024 / 256]; + FIXP_DBL dummySubbandGains[4 * 1024 / 256]; + + int status; + int timeDomainSupported; + SUBBAND_DOMAIN_MODE subbandDomainSupported; +} DRC_GAIN_DECODER, *HANDLE_DRC_GAIN_DECODER; + +/* init functions */ +DRC_ERROR +drcDec_GainDecoder_Open(HANDLE_DRC_GAIN_DECODER* phGainDec); + +DRC_ERROR +drcDec_GainDecoder_Init(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize, + const int sampleRate); + +DRC_ERROR +drcDec_GainDecoder_SetCodecDependentParameters( + HANDLE_DRC_GAIN_DECODER hGainDec, const DELAY_MODE delayMode, + const int timeDomainSupported, + const SUBBAND_DOMAIN_MODE subbandDomainSupported); + +DRC_ERROR +drcDec_GainDecoder_Config(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const UCHAR numSelectedDrcSets, + const SCHAR* selectedDrcSetIds, + const UCHAR* selectedDownmixIds); + +/* close functions */ +DRC_ERROR +drcDec_GainDecoder_Close(HANDLE_DRC_GAIN_DECODER* phGainDec); + +/* process functions */ + +/* call drcDec_GainDecoder_Preprocess first */ +DRC_ERROR +drcDec_GainDecoder_Preprocess(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, + const FIXP_DBL loudnessNormalizationGainDb, + const FIXP_SGL boost, const FIXP_SGL compress); + +/* Then call one of drcDec_GainDecoder_ProcessTimeDomain or + * drcDec_GainDecoder_ProcessSubbandDomain */ +DRC_ERROR +drcDec_GainDecoder_ProcessTimeDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + const GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* audioIOBuffer); + +DRC_ERROR +drcDec_GainDecoder_ProcessSubbandDomain( + HANDLE_DRC_GAIN_DECODER hGainDec, const int delaySamples, + GAIN_DEC_LOCATION drcLocation, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, FIXP_DBL* audioIOBufferReal[], + FIXP_DBL* audioIOBufferImag[]); + +DRC_ERROR +drcDec_GainDecoder_Conceal(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_GainDecoder_SetLoudnessNormalizationGainDb( + HANDLE_DRC_GAIN_DECODER hGainDec, FIXP_DBL loudnessNormalizationGainDb); + +int drcDec_GainDecoder_GetFrameSize(HANDLE_DRC_GAIN_DECODER hGainDec); + +int drcDec_GainDecoder_GetDeltaTminDefault(HANDLE_DRC_GAIN_DECODER hGainDec); + +void drcDec_GainDecoder_SetChannelGains(HANDLE_DRC_GAIN_DECODER hGainDec, + const int numChannels, + const int frameSize, + const FIXP_DBL* channelGainDb, + const int audioBufferChannelOffset, + FIXP_DBL* audioBuffer); + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDec_reader.cpp b/fdk-aac/libDRCdec/src/drcDec_reader.cpp new file mode 100644 index 0000000..6fe7a04 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_reader.cpp @@ -0,0 +1,2029 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "fixpoint_math.h" +#include "drcDec_reader.h" +#include "drcDec_tools.h" +#include "drcDec_rom.h" +#include "drcDecoder.h" + +/* MPEG-D DRC AMD 1 */ + +#define UNIDRCCONFEXT_PARAM_DRC 0x1 +#define UNIDRCCONFEXT_V1 0x2 +#define UNIDRCLOUDEXT_EQ 0x1 + +#define UNIDRCGAINEXT_TERM 0x0 +#define UNIDRCLOUDEXT_TERM 0x0 +#define UNIDRCCONFEXT_TERM 0x0 + +static int _getZ(const int nNodesMax) { + /* Z is the minimum codeword length that is needed to encode all possible + * timeDelta values */ + /* Z = ceil(log2(2*nNodesMax)) */ + int Z = 1; + while ((1 << Z) < (2 * nNodesMax)) { + Z++; + } + return Z; +} + +static int _getTimeDeltaMin(const GAIN_SET* pGset, const int deltaTminDefault) { + if (pGset->timeDeltaMinPresent) { + return pGset->timeDeltaMin; + } else { + return deltaTminDefault; + } +} + +/* compare and assign */ +static inline int _compAssign(UCHAR* dest, const UCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(ULONG* dest, const ULONG src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +typedef const SCHAR (*Huffman)[2]; + +int _decodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to bitbuffer */ +{ + SCHAR index = 0; + int value, bit; + + while (index >= 0) { + bit = FDKreadBits(hBs, 1); + index = h[index][bit]; + } + + value = index + 64; /* Add offset */ + + return value; +} + +/**********/ +/* uniDrc */ +/**********/ + +DRC_ERROR +drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + const int frameSize, const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + DRC_ERROR err = DE_OK; + int loudnessInfoSetPresent, uniDrcConfigPresent; + + loudnessInfoSetPresent = FDKreadBits(hBs, 1); + if (loudnessInfoSetPresent) { + uniDrcConfigPresent = FDKreadBits(hBs, 1); + if (uniDrcConfigPresent) { + err = drcDec_readUniDrcConfig(hBs, hUniDrcConfig); + if (err) return err; + } + err = drcDec_readLoudnessInfoSet(hBs, hLoudnessInfoSet); + if (err) return err; + } + + if (hUniDrcGain != NULL) { + err = drcDec_readUniDrcGain(hBs, hUniDrcConfig, frameSize, deltaTminDefault, + hUniDrcGain); + if (err) return err; + } + + return err; +} + +/**************/ +/* uniDrcGain */ +/**************/ + +static FIXP_SGL _decodeGainInitial( + HANDLE_FDK_BITSTREAM hBs, const GAIN_CODING_PROFILE gainCodingProfile) { + int sign, magn; + FIXP_SGL gainInitial = (FIXP_SGL)0; + switch (gainCodingProfile) { + case GCP_REGULAR: + sign = FDKreadBits(hBs, 1); + magn = FDKreadBits(hBs, 8); + + gainInitial = + (FIXP_SGL)(magn << (FRACT_BITS - 1 - 3 - 7)); /* magn * 0.125; */ + if (sign) gainInitial = -gainInitial; + break; + case GCP_FADING: + sign = FDKreadBits(hBs, 1); + if (sign == 0) + gainInitial = (FIXP_SGL)0; + else { + magn = FDKreadBits(hBs, 10); + gainInitial = -(FIXP_SGL)( + (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */ + } + break; + case GCP_CLIPPING_DUCKING: + sign = FDKreadBits(hBs, 1); + if (sign == 0) + gainInitial = (FIXP_SGL)0; + else { + magn = FDKreadBits(hBs, 8); + gainInitial = -(FIXP_SGL)( + (magn + 1) << (FRACT_BITS - 1 - 3 - 7)); /* - (magn + 1) * 0.125; */ + } + break; + case GCP_CONSTANT: + break; + } + return gainInitial; +} + +static int _decodeNNodes(HANDLE_FDK_BITSTREAM hBs) { + int nNodes = 0, endMarker = 0; + + /* decode number of nodes */ + while (endMarker != 1) { + nNodes++; + if (nNodes >= 128) break; + endMarker = FDKreadBits(hBs, 1); + } + return nNodes; +} + +static void _decodeGains(HANDLE_FDK_BITSTREAM hBs, + const GAIN_CODING_PROFILE gainCodingProfile, + const int nNodes, GAIN_NODE* pNodes) { + int k, deltaGain; + Huffman deltaGainCodebook; + + pNodes[0].gainDb = _decodeGainInitial(hBs, gainCodingProfile); + + if (gainCodingProfile == GCP_CLIPPING_DUCKING) { + deltaGainCodebook = (Huffman)&deltaGain_codingProfile_2_huffman; + } else { + deltaGainCodebook = (Huffman)&deltaGain_codingProfile_0_1_huffman; + } + + for (k = 1; k < nNodes; k++) { + deltaGain = _decodeHuffmanCW(deltaGainCodebook, hBs); + if (k >= 16) continue; + /* gain_dB_e = 7 */ + pNodes[k].gainDb = + pNodes[k - 1].gainDb + + (FIXP_SGL)(deltaGain << (FRACT_BITS - 1 - 7 - + 3)); /* pNodes[k-1].gainDb + 0.125*deltaGain */ + } +} + +static void _decodeSlopes(HANDLE_FDK_BITSTREAM hBs, + const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const int nNodes, GAIN_NODE* pNodes) { + int k = 0; + + if (gainInterpolationType == GIT_SPLINE) { + /* decode slope steepness */ + for (k = 0; k < nNodes; k++) { + _decodeHuffmanCW((Huffman)&slopeSteepness_huffman, hBs); + } + } +} + +static int _decodeTimeDelta(HANDLE_FDK_BITSTREAM hBs, const int Z) { + int prefix, mu; + + prefix = FDKreadBits(hBs, 2); + switch (prefix) { + case 0x0: + return 1; + case 0x1: + mu = FDKreadBits(hBs, 2); + return mu + 2; + case 0x2: + mu = FDKreadBits(hBs, 3); + return mu + 6; + case 0x3: + mu = FDKreadBits(hBs, Z); + return mu + 14; + default: + return 0; + } +} + +static void _decodeTimes(HANDLE_FDK_BITSTREAM hBs, const int deltaTmin, + const int frameSize, const int fullFrame, + const int timeOffset, const int Z, const int nNodes, + GAIN_NODE* pNodes) { + int timeDelta, k; + int timeOffs = timeOffset; + int frameEndFlag, nodeTimeTmp, nodeResFlag; + + if (fullFrame == 0) { + frameEndFlag = FDKreadBits(hBs, 1); + } else { + frameEndFlag = 1; + } + + if (frameEndFlag == + 1) { /* frameEndFlag == 1 signals that the last node is at the end of the + DRC frame */ + nodeResFlag = 0; + for (k = 0; k < nNodes - 1; k++) { + /* decode a delta time value */ + timeDelta = _decodeTimeDelta(hBs, Z); + if (k >= (16 - 1)) continue; + /* frameEndFlag == 1 needs special handling for last node with node + * reservoir */ + nodeTimeTmp = timeOffs + timeDelta * deltaTmin; + if (nodeTimeTmp > frameSize + timeOffset) { + if (nodeResFlag == 0) { + pNodes[k].time = frameSize + timeOffset; + nodeResFlag = 1; + } + pNodes[k + 1].time = nodeTimeTmp; + } else { + pNodes[k].time = nodeTimeTmp; + } + timeOffs = nodeTimeTmp; + } + if (nodeResFlag == 0) { + k = fMin(k, 16 - 1); + pNodes[k].time = frameSize + timeOffset; + } + } else { + for (k = 0; k < nNodes; k++) { + /* decode a delta time value */ + timeDelta = _decodeTimeDelta(hBs, Z); + if (k >= 16) continue; + pNodes[k].time = timeOffs + timeDelta * deltaTmin; + timeOffs = pNodes[k].time; + } + } +} + +static void _readNodes(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet, + const int frameSize, const int timeDeltaMin, + UCHAR* pNNodes, GAIN_NODE* pNodes) { + int timeOffset, drcGainCodingMode, nNodes; + int Z = _getZ(frameSize / timeDeltaMin); + if (gainSet->timeAlignment == 0) { + timeOffset = -1; + } else { + timeOffset = -timeDeltaMin + + (timeDeltaMin - 1) / + 2; /* timeOffset = - deltaTmin + floor((deltaTmin-1)/2); */ + } + + drcGainCodingMode = FDKreadBits(hBs, 1); + if (drcGainCodingMode == 0) { + /* "simple" mode: only one node at the end of the frame with slope = 0 */ + nNodes = 1; + pNodes[0].gainDb = _decodeGainInitial( + hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile); + pNodes[0].time = frameSize + timeOffset; + } else { + nNodes = _decodeNNodes(hBs); + + _decodeSlopes(hBs, (GAIN_INTERPOLATION_TYPE)gainSet->gainInterpolationType, + nNodes, pNodes); + + _decodeTimes(hBs, timeDeltaMin, frameSize, gainSet->fullFrame, timeOffset, + Z, nNodes, pNodes); + + _decodeGains(hBs, (GAIN_CODING_PROFILE)gainSet->gainCodingProfile, nNodes, + pNodes); + } + *pNNodes = (UCHAR)nNodes; +} + +static void _readDrcGainSequence(HANDLE_FDK_BITSTREAM hBs, GAIN_SET* gainSet, + const int frameSize, const int timeDeltaMin, + UCHAR* pNNodes, GAIN_NODE pNodes[16]) { + SHORT timeBufPrevFrame[16], timeBufCurFrame[16]; + int nNodesNodeRes, nNodesCur, k, m; + + if (gainSet->gainCodingProfile == GCP_CONSTANT) { + *pNNodes = 1; + pNodes[0].time = frameSize - 1; + pNodes[0].gainDb = (FIXP_SGL)0; + } else { + _readNodes(hBs, gainSet, frameSize, timeDeltaMin, pNNodes, pNodes); + + /* count number of nodes in node reservoir */ + nNodesNodeRes = 0; + nNodesCur = 0; + /* count and buffer nodes from node reservoir */ + for (k = 0; k < *pNNodes; k++) { + if (k >= 16) continue; + if (pNodes[k].time >= frameSize) { + /* write node reservoir times into buffer */ + timeBufPrevFrame[nNodesNodeRes] = pNodes[k].time; + nNodesNodeRes++; + } else { /* times from current frame */ + timeBufCurFrame[nNodesCur] = pNodes[k].time; + nNodesCur++; + } + } + /* compose right time order (bit reservoir first) */ + for (k = 0; k < nNodesNodeRes; k++) { + /* subtract two time frameSize: one to remove node reservoir offset and + * one to get the negative index relative to the current frame + */ + pNodes[k].time = timeBufPrevFrame[k] - 2 * frameSize; + } + /* ...and times from current frame */ + for (m = 0; m < nNodesCur; m++, k++) { + pNodes[k].time = timeBufCurFrame[m]; + } + } +} + +static DRC_ERROR _readUniDrcGainExtension(HANDLE_FDK_BITSTREAM hBs, + UNI_DRC_GAIN_EXTENSION* pExt) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + + k = 0; + pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4); + while (pExt->uniDrcGainExtType[k] != UNIDRCGAINEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 3); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + + switch (pExt->uniDrcGainExtType[k]) { + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->uniDrcGainExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +DRC_ERROR +drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize, + const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain) { + DRC_ERROR err = DE_OK; + int seq, gainSequenceCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (pCoef == NULL) return DE_OK; + if (hUniDrcGain == NULL) return DE_OK; /* hUniDrcGain not initialized yet */ + + gainSequenceCount = fMin(pCoef->gainSequenceCount, (UCHAR)12); + + for (seq = 0; seq < gainSequenceCount; seq++) { + UCHAR index = pCoef->gainSetIndexForGainSequence[seq]; + GAIN_SET* gainSet; + int timeDeltaMin; + UCHAR tmpNNodes = 0; + GAIN_NODE tmpNodes[16]; + + if ((index >= pCoef->gainSetCount) || (index >= 12)) return DE_NOT_OK; + gainSet = &(pCoef->gainSet[index]); + + timeDeltaMin = _getTimeDeltaMin(gainSet, deltaTminDefault); + + _readDrcGainSequence(hBs, gainSet, frameSize, timeDeltaMin, &tmpNNodes, + tmpNodes); + + hUniDrcGain->nNodes[seq] = tmpNNodes; + FDKmemcpy(hUniDrcGain->gainNode[seq], tmpNodes, + fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE)); + } + + hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1); + if (hUniDrcGain->uniDrcGainExtPresent == 1) { + err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension)); + if (err) return err; + } + + return err; +} + +/****************/ +/* uniDrcConfig */ +/****************/ + +static void _decodeDuckingModification(HANDLE_FDK_BITSTREAM hBs, + DUCKING_MODIFICATION* pDMod, int isBox) { + int bsDuckingScaling, sigma, mu; + + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + pDMod->duckingScalingPresent = FDKreadBits(hBs, 1); + + if (pDMod->duckingScalingPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + bsDuckingScaling = FDKreadBits(hBs, 4); + sigma = bsDuckingScaling >> 3; + mu = bsDuckingScaling & 0x7; + + if (sigma) { + pDMod->duckingScaling = (FIXP_SGL)( + (7 - mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 - 0.125 * (1 + mu); */ + } else { + pDMod->duckingScaling = (FIXP_SGL)( + (9 + mu) << (FRACT_BITS - 1 - 3 - 2)); /* 1.0 + 0.125 * (1 + mu); */ + } + } else { + pDMod->duckingScaling = (FIXP_SGL)(1 << (FRACT_BITS - 1 - 2)); /* 1.0 */ + } +} + +static void _decodeGainModification(HANDLE_FDK_BITSTREAM hBs, const int version, + int bandCount, GAIN_MODIFICATION* pGMod, + int isBox) { + int sign, bsGainOffset, bsAttenuationScaling, bsAmplificationScaling; + + if (version > 0) { + int b, shapeFilterPresent; + + if (isBox) { + FDKpushFor(hBs, 4); /* reserved */ + bandCount = FDKreadBits(hBs, 4); + } + + for (b = 0; b < bandCount; b++) { + if (isBox) { + FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1); + pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1); + pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1); + pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1); + } + + if (!isBox) + pGMod[b].targetCharacteristicLeftPresent = FDKreadBits(hBs, 1); + if (pGMod[b].targetCharacteristicLeftPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicLeftIndex = FDKreadBits(hBs, 4); + } + if (!isBox) + pGMod[b].targetCharacteristicRightPresent = FDKreadBits(hBs, 1); + if (pGMod[b].targetCharacteristicRightPresent) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pGMod[b].targetCharacteristicRightIndex = FDKreadBits(hBs, 4); + } + if (!isBox) pGMod[b].gainScalingPresent = FDKreadBits(hBs, 1); + if (pGMod[b].gainScalingPresent) { + bsAttenuationScaling = FDKreadBits(hBs, 4); + pGMod[b].attenuationScaling = (FIXP_SGL)( + bsAttenuationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */ + bsAmplificationScaling = FDKreadBits(hBs, 4); + pGMod[b].amplificationScaling = (FIXP_SGL)( + bsAmplificationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */ + } + if (!isBox) pGMod[b].gainOffsetPresent = FDKreadBits(hBs, 1); + if (pGMod[b].gainOffsetPresent) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + sign = FDKreadBits(hBs, 1); + bsGainOffset = FDKreadBits(hBs, 5); + pGMod[b].gainOffset = (FIXP_SGL)( + (1 + bsGainOffset) + << (FRACT_BITS - 1 - 2 - 4)); /* (1+bsGainOffset) * 0.25; */ + if (sign) { + pGMod[b].gainOffset = -pGMod[b].gainOffset; + } + } + } + if (bandCount == 1) { + shapeFilterPresent = FDKreadBits(hBs, 1); + if (shapeFilterPresent) { + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + FDKpushFor(hBs, 4); /* pGMod->shapeFilterIndex */ + } else { + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + } + } + } else { + int b, gainScalingPresent, gainOffsetPresent; + FIXP_SGL attenuationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + amplificationScaling = FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + gainOffset = (FIXP_SGL)0; + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + gainScalingPresent = FDKreadBits(hBs, 1); + if (gainScalingPresent) { + bsAttenuationScaling = FDKreadBits(hBs, 4); + attenuationScaling = (FIXP_SGL)( + bsAttenuationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAttenuationScaling * 0.125; */ + bsAmplificationScaling = FDKreadBits(hBs, 4); + amplificationScaling = (FIXP_SGL)( + bsAmplificationScaling + << (FRACT_BITS - 1 - 3 - 2)); /* bsAmplificationScaling * 0.125; */ + } + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + gainOffsetPresent = FDKreadBits(hBs, 1); + if (gainOffsetPresent) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + sign = FDKreadBits(hBs, 1); + bsGainOffset = FDKreadBits(hBs, 5); + gainOffset = + (FIXP_SGL)((1 + bsGainOffset) << (FRACT_BITS - 1 - 2 - + 4)); /* (1+bsGainOffset) * 0.25; */ + if (sign) { + gainOffset = -gainOffset; + } + } + for (b = 0; b < 4; b++) { + pGMod[b].targetCharacteristicLeftPresent = 0; + pGMod[b].targetCharacteristicRightPresent = 0; + pGMod[b].gainScalingPresent = gainScalingPresent; + pGMod[b].attenuationScaling = attenuationScaling; + pGMod[b].amplificationScaling = amplificationScaling; + pGMod[b].gainOffsetPresent = gainOffsetPresent; + pGMod[b].gainOffset = gainOffset; + } + } +} + +static void _readDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, const int version, + DRC_CHARACTERISTIC* pDChar, int isBox) { + if (version == 0) { + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + pDChar->cicpIndex = FDKreadBits(hBs, 7); + if (pDChar->cicpIndex > 0) { + pDChar->present = 1; + pDChar->isCICP = 1; + } else { + pDChar->present = 0; + } + } else { + pDChar->present = FDKreadBits(hBs, 1); + if (isBox) pDChar->isCICP = FDKreadBits(hBs, 1); + if (pDChar->present) { + if (!isBox) pDChar->isCICP = FDKreadBits(hBs, 1); + if (pDChar->isCICP) { + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + pDChar->cicpIndex = FDKreadBits(hBs, 7); + } else { + pDChar->custom.left = FDKreadBits(hBs, 4); + pDChar->custom.right = FDKreadBits(hBs, 4); + } + } + } +} + +static void _readBandBorder(HANDLE_FDK_BITSTREAM hBs, BAND_BORDER* pBBord, + int drcBandType, int isBox) { + if (drcBandType) { + if (isBox) FDKpushFor(hBs, 4); /* reserved */ + pBBord->crossoverFreqIndex = FDKreadBits(hBs, 4); + } else { + if (isBox) FDKpushFor(hBs, 6); /* reserved */ + pBBord->startSubBandIndex = FDKreadBits(hBs, 10); + } +} + +static DRC_ERROR _readGainSet(HANDLE_FDK_BITSTREAM hBs, const int version, + int* gainSequenceIndex, GAIN_SET* pGSet, + int isBox) { + if (isBox) FDKpushFor(hBs, 2); /* reserved */ + pGSet->gainCodingProfile = FDKreadBits(hBs, 2); + pGSet->gainInterpolationType = FDKreadBits(hBs, 1); + pGSet->fullFrame = FDKreadBits(hBs, 1); + pGSet->timeAlignment = FDKreadBits(hBs, 1); + pGSet->timeDeltaMinPresent = FDKreadBits(hBs, 1); + + if (pGSet->timeDeltaMinPresent) { + int bsTimeDeltaMin; + if (isBox) FDKpushFor(hBs, 5); /* reserved */ + bsTimeDeltaMin = FDKreadBits(hBs, 11); + pGSet->timeDeltaMin = bsTimeDeltaMin + 1; + } + + if (pGSet->gainCodingProfile != GCP_CONSTANT) { + int i; + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + pGSet->bandCount = FDKreadBits(hBs, 4); + if (pGSet->bandCount > 4) return DE_MEMORY_ERROR; + + if ((pGSet->bandCount > 1) || isBox) { + pGSet->drcBandType = FDKreadBits(hBs, 1); + } + + for (i = 0; i < pGSet->bandCount; i++) { + if (version == 0) { + *gainSequenceIndex = (*gainSequenceIndex) + 1; + } else { + int indexPresent; + indexPresent = (isBox) ? 1 : FDKreadBits(hBs, 1); + if (indexPresent) { + int bsIndex; + bsIndex = FDKreadBits(hBs, 6); + *gainSequenceIndex = bsIndex; + } else { + *gainSequenceIndex = (*gainSequenceIndex) + 1; + } + } + pGSet->gainSequenceIndex[i] = *gainSequenceIndex; + _readDrcCharacteristic(hBs, version, &(pGSet->drcCharacteristic[i]), + isBox); + } + for (i = 1; i < pGSet->bandCount; i++) { + _readBandBorder(hBs, &(pGSet->bandBorder[i]), pGSet->drcBandType, isBox); + } + } else { + pGSet->bandCount = 1; + *gainSequenceIndex = (*gainSequenceIndex) + 1; + pGSet->gainSequenceIndex[0] = *gainSequenceIndex; + } + + return DE_OK; +} + +static DRC_ERROR _readCustomDrcCharacteristic(HANDLE_FDK_BITSTREAM hBs, + const CHARACTERISTIC_SIDE side, + UCHAR* pCharacteristicFormat, + CUSTOM_DRC_CHAR* pCChar, + int isBox) { + if (isBox) FDKpushFor(hBs, 7); /* reserved */ + *pCharacteristicFormat = FDKreadBits(hBs, 1); + if (*pCharacteristicFormat == CF_SIGMOID) { + int bsGain, bsIoRatio, bsExp; + if (isBox) FDKpushFor(hBs, 1); /* reserved */ + bsGain = FDKreadBits(hBs, 6); + if (side == CS_LEFT) { + pCChar->sigmoid.gain = (FIXP_SGL)(bsGain << (FRACT_BITS - 1 - 6)); + } else { + pCChar->sigmoid.gain = (FIXP_SGL)(-bsGain << (FRACT_BITS - 1 - 6)); + } + bsIoRatio = FDKreadBits(hBs, 4); + /* pCChar->sigmoid.ioRatio = 0.05 + 0.15 * bsIoRatio; */ + pCChar->sigmoid.ioRatio = + FL2FXCONST_SGL(0.05f / (float)(1 << 2)) + + (FIXP_SGL)((((3 * bsIoRatio) << (FRACT_BITS - 1)) / 5) >> 4); + bsExp = FDKreadBits(hBs, 4); + if (bsExp < 15) { + pCChar->sigmoid.exp = (FIXP_SGL)((1 + 2 * bsExp) << (FRACT_BITS - 1 - 5)); + } else { + pCChar->sigmoid.exp = (FIXP_SGL)MAXVAL_SGL; /* represents infinity */ + } + pCChar->sigmoid.flipSign = FDKreadBits(hBs, 1); + } else { /* CF_NODES */ + int i, bsCharacteristicNodeCount, bsNodeLevelDelta, bsNodeGain; + if (isBox) FDKpushFor(hBs, 6); /* reserved */ + bsCharacteristicNodeCount = FDKreadBits(hBs, 2); + pCChar->nodes.characteristicNodeCount = bsCharacteristicNodeCount + 1; + if (pCChar->nodes.characteristicNodeCount > 4) return DE_MEMORY_ERROR; + pCChar->nodes.nodeLevel[0] = DRC_INPUT_LOUDNESS_TARGET_SGL; + pCChar->nodes.nodeGain[0] = (FIXP_SGL)0; + for (i = 0; i < pCChar->nodes.characteristicNodeCount; i++) { + if (isBox) FDKpushFor(hBs, 3); /* reserved */ + bsNodeLevelDelta = FDKreadBits(hBs, 5); + if (side == CS_LEFT) { + pCChar->nodes.nodeLevel[i + 1] = + pCChar->nodes.nodeLevel[i] - + (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7)); + } else { + pCChar->nodes.nodeLevel[i + 1] = + pCChar->nodes.nodeLevel[i] + + (FIXP_SGL)((1 + bsNodeLevelDelta) << (FRACT_BITS - 1 - 7)); + } + bsNodeGain = FDKreadBits(hBs, 8); + pCChar->nodes.nodeGain[i + 1] = (FIXP_SGL)( + (bsNodeGain - 128) + << (FRACT_BITS - 1 - 1 - 7)); /* 0.5f * bsNodeGain - 64.0f; */ + } + } + return DE_OK; +} + +static void _skipLoudEqInstructions(HANDLE_FDK_BITSTREAM hBs) { + int i; + int downmixIdPresent, additionalDownmixIdPresent, + additionalDownmixIdCount = 0; + int drcSetIdPresent, additionalDrcSetIdPresent, additionalDrcSetIdCount = 0; + int eqSetIdPresent, additionalEqSetIdPresent, additionalEqSetIdCount = 0; + int loudEqGainSequenceCount, drcCharacteristicFormatIsCICP; + + FDKpushFor(hBs, 4); /* loudEqSetId */ + FDKpushFor(hBs, 4); /* drcLocation */ + downmixIdPresent = FDKreadBits(hBs, 1); + if (downmixIdPresent) { + FDKpushFor(hBs, 7); /* downmixId */ + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 7); + for (i = 0; i < additionalDownmixIdCount; i++) { + FDKpushFor(hBs, 7); /* additionalDownmixId */ + } + } + } + + drcSetIdPresent = FDKreadBits(hBs, 1); + if (drcSetIdPresent) { + FDKpushFor(hBs, 6); /* drcSetId */ + additionalDrcSetIdPresent = FDKreadBits(hBs, 1); + if (additionalDrcSetIdPresent) { + additionalDrcSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalDrcSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalDrcSetId; */ + } + } + } + + eqSetIdPresent = FDKreadBits(hBs, 1); + if (eqSetIdPresent) { + FDKpushFor(hBs, 6); /* eqSetId */ + additionalEqSetIdPresent = FDKreadBits(hBs, 1); + if (additionalEqSetIdPresent) { + additionalEqSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalEqSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalEqSetId; */ + } + } + } + + FDKpushFor(hBs, 1); /* loudnessAfterDrc */ + FDKpushFor(hBs, 1); /* loudnessAfterEq */ + loudEqGainSequenceCount = FDKreadBits(hBs, 6); + for (i = 0; i < loudEqGainSequenceCount; i++) { + FDKpushFor(hBs, 6); /* gainSequenceIndex */ + drcCharacteristicFormatIsCICP = FDKreadBits(hBs, 1); + if (drcCharacteristicFormatIsCICP) { + FDKpushFor(hBs, 7); /* drcCharacteristic */ + } else { + FDKpushFor(hBs, 4); /* drcCharacteristicLeftIndex */ + FDKpushFor(hBs, 4); /* drcCharacteristicRightIndex */ + } + FDKpushFor(hBs, 6); /* frequencyRangeIndex */ + FDKpushFor(hBs, 3); /* bsLoudEqScaling */ + FDKpushFor(hBs, 5); /* bsLoudEqOffset */ + } +} + +static void _skipEqSubbandGainSpline(HANDLE_FDK_BITSTREAM hBs) { + int nEqNodes, k, bits; + nEqNodes = FDKreadBits(hBs, 5); + nEqNodes += 2; + for (k = 0; k < nEqNodes; k++) { + bits = FDKreadBits(hBs, 1); + if (!bits) { + FDKpushFor(hBs, 4); + } + } + FDKpushFor(hBs, 4 * (nEqNodes - 1)); + bits = FDKreadBits(hBs, 2); + switch (bits) { + case 0: + FDKpushFor(hBs, 5); + break; + case 1: + case 2: + FDKpushFor(hBs, 4); + break; + case 3: + FDKpushFor(hBs, 3); + break; + } + FDKpushFor(hBs, 5 * (nEqNodes - 1)); +} + +static void _skipEqCoefficients(HANDLE_FDK_BITSTREAM hBs) { + int j, k; + int eqDelayMaxPresent; + int uniqueFilterBlockCount, filterElementCount, filterElementGainPresent; + int uniqueTdFilterElementCount, eqFilterFormat, bsRealZeroRadiusOneCount, + realZeroCount, genericZeroCount, realPoleCount, complexPoleCount, + firFilterOrder; + int uniqueEqSubbandGainsCount, eqSubbandGainRepresentation, + eqSubbandGainCount; + EQ_SUBBAND_GAIN_FORMAT eqSubbandGainFormat; + + eqDelayMaxPresent = FDKreadBits(hBs, 1); + if (eqDelayMaxPresent) { + FDKpushFor(hBs, 8); /* bsEqDelayMax */ + } + + uniqueFilterBlockCount = FDKreadBits(hBs, 6); + for (j = 0; j < uniqueFilterBlockCount; j++) { + filterElementCount = FDKreadBits(hBs, 6); + for (k = 0; k < filterElementCount; k++) { + FDKpushFor(hBs, 6); /* filterElementIndex */ + filterElementGainPresent = FDKreadBits(hBs, 1); + if (filterElementGainPresent) { + FDKpushFor(hBs, 10); /* bsFilterElementGain */ + } + } + } + uniqueTdFilterElementCount = FDKreadBits(hBs, 6); + for (j = 0; j < uniqueTdFilterElementCount; j++) { + eqFilterFormat = FDKreadBits(hBs, 1); + if (eqFilterFormat == 0) { /* pole/zero */ + bsRealZeroRadiusOneCount = FDKreadBits(hBs, 3); + realZeroCount = FDKreadBits(hBs, 6); + genericZeroCount = FDKreadBits(hBs, 6); + realPoleCount = FDKreadBits(hBs, 4); + complexPoleCount = FDKreadBits(hBs, 4); + FDKpushFor(hBs, 2 * bsRealZeroRadiusOneCount * 1); + FDKpushFor(hBs, realZeroCount * 8); + FDKpushFor(hBs, genericZeroCount * 14); + FDKpushFor(hBs, realPoleCount * 8); + FDKpushFor(hBs, complexPoleCount * 14); + } else { /* FIR coefficients */ + firFilterOrder = FDKreadBits(hBs, 7); + FDKpushFor(hBs, 1); + FDKpushFor(hBs, (firFilterOrder / 2 + 1) * 11); + } + } + uniqueEqSubbandGainsCount = FDKreadBits(hBs, 6); + if (uniqueEqSubbandGainsCount > 0) { + eqSubbandGainRepresentation = FDKreadBits(hBs, 1); + eqSubbandGainFormat = (EQ_SUBBAND_GAIN_FORMAT)FDKreadBits(hBs, 4); + switch (eqSubbandGainFormat) { + case GF_QMF32: + eqSubbandGainCount = 32; + break; + case GF_QMFHYBRID39: + eqSubbandGainCount = 39; + break; + case GF_QMF64: + eqSubbandGainCount = 64; + break; + case GF_QMFHYBRID71: + eqSubbandGainCount = 71; + break; + case GF_QMF128: + eqSubbandGainCount = 128; + break; + case GF_QMFHYBRID135: + eqSubbandGainCount = 135; + break; + case GF_UNIFORM: + default: + eqSubbandGainCount = FDKreadBits(hBs, 8); + eqSubbandGainCount++; + break; + } + for (k = 0; k < uniqueEqSubbandGainsCount; k++) { + if (eqSubbandGainRepresentation == 1) { + _skipEqSubbandGainSpline(hBs); + } else { + FDKpushFor(hBs, eqSubbandGainCount * 9); + } + } + } +} + +static void _skipTdFilterCascade(HANDLE_FDK_BITSTREAM hBs, + const int eqChannelGroupCount) { + int i, eqCascadeGainPresent, filterBlockCount, eqPhaseAlignmentPresent; + for (i = 0; i < eqChannelGroupCount; i++) { + eqCascadeGainPresent = FDKreadBits(hBs, 1); + if (eqCascadeGainPresent) { + FDKpushFor(hBs, 10); /* bsEqCascadeGain */ + } + filterBlockCount = FDKreadBits(hBs, 4); + FDKpushFor(hBs, filterBlockCount * 7); /* filterBlockIndex */ + } + eqPhaseAlignmentPresent = FDKreadBits(hBs, 1); + { + if (eqPhaseAlignmentPresent) { + for (i = 0; i < eqChannelGroupCount; i++) { + FDKpushFor(hBs, (eqChannelGroupCount - i - 1) * 1); + } + } + } +} + +static DRC_ERROR _skipEqInstructions(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int c, i, k, channelCount; + int downmixIdPresent, downmixId, eqApplyToDownmix, additionalDownmixIdPresent, + additionalDownmixIdCount = 0; + int additionalDrcSetIdPresent, additionalDrcSetIdCount; + int dependsOnEqSetPresent, eqChannelGroupCount, tdFilterCascadePresent, + subbandGainsPresent, eqTransitionDurationPresent; + + FDKpushFor(hBs, 6); /* eqSetId */ + FDKpushFor(hBs, 4); /* eqSetComplexityLevel */ + downmixIdPresent = FDKreadBits(hBs, 1); + if (downmixIdPresent) { + downmixId = FDKreadBits(hBs, 7); + eqApplyToDownmix = FDKreadBits(hBs, 1); + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 7); + FDKpushFor(hBs, additionalDownmixIdCount * 7); /* additionalDownmixId */ + } + } else { + downmixId = 0; + eqApplyToDownmix = 0; + } + FDKpushFor(hBs, 6); /* drcSetId */ + additionalDrcSetIdPresent = FDKreadBits(hBs, 1); + if (additionalDrcSetIdPresent) { + additionalDrcSetIdCount = FDKreadBits(hBs, 6); + for (i = 0; i < additionalDrcSetIdCount; i++) { + FDKpushFor(hBs, 6); /* additionalDrcSetId */ + } + } + FDKpushFor(hBs, 16); /* eqSetPurpose */ + dependsOnEqSetPresent = FDKreadBits(hBs, 1); + if (dependsOnEqSetPresent) { + FDKpushFor(hBs, 6); /* dependsOnEqSet */ + } else { + FDKpushFor(hBs, 1); /* noIndependentEqUse */ + } + + channelCount = hUniDrcConfig->channelLayout.baseChannelCount; + if ((downmixIdPresent == 1) && (eqApplyToDownmix == 1) && (downmixId != 0) && + (downmixId != DOWNMIX_ID_ANY_DOWNMIX) && + (additionalDownmixIdCount == 0)) { + DOWNMIX_INSTRUCTIONS* pDown = + selectDownmixInstructions(hUniDrcConfig, downmixId); + if (pDown == NULL) return DE_NOT_OK; + + channelCount = + pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/ + } else if ((downmixId == DOWNMIX_ID_ANY_DOWNMIX) || + (additionalDownmixIdCount > 1)) { + channelCount = 1; + } + + eqChannelGroupCount = 0; + for (c = 0; c < channelCount; c++) { + UCHAR eqChannelGroupForChannel[8]; + int newGroup = 1; + if (c >= 8) return DE_MEMORY_ERROR; + eqChannelGroupForChannel[c] = FDKreadBits(hBs, 7); + for (k = 0; k < c; k++) { + if (eqChannelGroupForChannel[c] == eqChannelGroupForChannel[k]) { + newGroup = 0; + } + } + if (newGroup == 1) { + eqChannelGroupCount += 1; + } + } + tdFilterCascadePresent = FDKreadBits(hBs, 1); + if (tdFilterCascadePresent) { + _skipTdFilterCascade(hBs, eqChannelGroupCount); + } + subbandGainsPresent = FDKreadBits(hBs, 1); + if (subbandGainsPresent) { + FDKpushFor(hBs, eqChannelGroupCount * 6); /* subbandGainsIndex */ + } + eqTransitionDurationPresent = FDKreadBits(hBs, 1); + if (eqTransitionDurationPresent) { + FDKpushFor(hBs, 5); /* bsEqTransitionDuration */ + } + return err; +} + +static void _skipDrcCoefficientsBasic(HANDLE_FDK_BITSTREAM hBs) { + FDKpushFor(hBs, 4); /* drcLocation */ + FDKpushFor(hBs, 7); /* drcCharacteristic */ +} + +static DRC_ERROR _readDrcCoefficientsUniDrc(HANDLE_FDK_BITSTREAM hBs, + const int version, + DRC_COEFFICIENTS_UNI_DRC* pCoef) { + DRC_ERROR err = DE_OK; + int i, bsDrcFrameSize; + int gainSequenceIndex = -1; + + pCoef->drcLocation = FDKreadBits(hBs, 4); + pCoef->drcFrameSizePresent = FDKreadBits(hBs, 1); + + if (pCoef->drcFrameSizePresent == 1) { + bsDrcFrameSize = FDKreadBits(hBs, 15); + pCoef->drcFrameSize = bsDrcFrameSize + 1; + } + if (version == 0) { + int gainSequenceCount = 0, gainSetCount; + pCoef->characteristicLeftCount = 0; + pCoef->characteristicRightCount = 0; + gainSetCount = FDKreadBits(hBs, 6); + pCoef->gainSetCount = fMin(gainSetCount, 12); + for (i = 0; i < gainSetCount; i++) { + GAIN_SET tmpGset; + FDKmemclear(&tmpGset, sizeof(GAIN_SET)); + err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0); + if (err) return err; + gainSequenceCount += tmpGset.bandCount; + + if (i >= 12) continue; + pCoef->gainSet[i] = tmpGset; + } + pCoef->gainSequenceCount = gainSequenceCount; + } else { /* (version == 1) */ + UCHAR drcCharacteristicLeftPresent, drcCharacteristicRightPresent; + UCHAR shapeFiltersPresent, shapeFilterCount, tmpPresent; + int gainSetCount; + drcCharacteristicLeftPresent = FDKreadBits(hBs, 1); + if (drcCharacteristicLeftPresent) { + pCoef->characteristicLeftCount = FDKreadBits(hBs, 4); + if ((pCoef->characteristicLeftCount + 1) > 8) return DE_MEMORY_ERROR; + for (i = 0; i < pCoef->characteristicLeftCount; i++) { + err = _readCustomDrcCharacteristic( + hBs, CS_LEFT, &(pCoef->characteristicLeftFormat[i + 1]), + &(pCoef->customCharacteristicLeft[i + 1]), 0); + if (err) return err; + } + } + drcCharacteristicRightPresent = FDKreadBits(hBs, 1); + if (drcCharacteristicRightPresent) { + pCoef->characteristicRightCount = FDKreadBits(hBs, 4); + if ((pCoef->characteristicRightCount + 1) > 8) return DE_MEMORY_ERROR; + for (i = 0; i < pCoef->characteristicRightCount; i++) { + err = _readCustomDrcCharacteristic( + hBs, CS_RIGHT, &(pCoef->characteristicRightFormat[i + 1]), + &(pCoef->customCharacteristicRight[i + 1]), 0); + if (err) return err; + } + } + shapeFiltersPresent = FDKreadBits(hBs, 1); + if (shapeFiltersPresent) { + shapeFilterCount = FDKreadBits(hBs, 4); + for (i = 0; i < shapeFilterCount; i++) { + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* lfCutParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* lfBoostParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* hfCutParams */ + FDKpushFor(hBs, 5); + + tmpPresent = FDKreadBits(hBs, 1); + if (tmpPresent) /* hfBoostParams */ + FDKpushFor(hBs, 5); + } + } + pCoef->gainSequenceCount = FDKreadBits(hBs, 6); + gainSetCount = FDKreadBits(hBs, 6); + pCoef->gainSetCount = fMin(gainSetCount, 12); + for (i = 0; i < gainSetCount; i++) { + GAIN_SET tmpGset; + FDKmemclear(&tmpGset, sizeof(GAIN_SET)); + err = _readGainSet(hBs, version, &gainSequenceIndex, &tmpGset, 0); + if (err) return err; + + if (i >= 12) continue; + pCoef->gainSet[i] = tmpGset; + } + } + for (i = 0; i < 12; i++) { + pCoef->gainSetIndexForGainSequence[i] = 255; + } + for (i = 0; i < pCoef->gainSetCount; i++) { + int b; + for (b = 0; b < pCoef->gainSet[i].bandCount; b++) { + if (pCoef->gainSet[i].gainSequenceIndex[b] >= 12) continue; + pCoef->gainSetIndexForGainSequence[pCoef->gainSet[i] + .gainSequenceIndex[b]] = i; + } + } + + return err; +} + +static void _skipDrcInstructionsBasic(HANDLE_FDK_BITSTREAM hBs) { + int drcSetEffect; + int additionalDownmixIdPresent, additionalDownmixIdCount, + limiterPeakTargetPresent; + int drcSetTargetLoudnessPresent, drcSetTargetLoudnessValueLowerPresent; + + FDKpushFor(hBs, 6); /* drcSetId */ + FDKpushFor(hBs, 4); /* drcLocation */ + FDKpushFor(hBs, 7); /* downmixId */ + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 3); + FDKpushFor(hBs, 7 * additionalDownmixIdCount); /* additionalDownmixId */ + } + + drcSetEffect = FDKreadBits(hBs, 16); + if (!(drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF))) { + limiterPeakTargetPresent = FDKreadBits(hBs, 1); + if (limiterPeakTargetPresent) { + FDKpushFor(hBs, 8); /* bsLimiterPeakTarget */ + } + } + + drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessPresent) { + FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueUpper */ + drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessValueLowerPresent) { + FDKpushFor(hBs, 6); /* bsDrcSetTargetLoudnessValueLower */ + } + } +} + +static DRC_ERROR _readDrcInstructionsUniDrc(HANDLE_FDK_BITSTREAM hBs, + const int version, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRC_INSTRUCTIONS_UNI_DRC* pInst) { + DRC_ERROR err = DE_OK; + int i, g, c; + int downmixIdPresent, additionalDownmixIdPresent, additionalDownmixIdCount; + int bsLimiterPeakTarget, channelCount; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + int repeatParameters, bsRepeatParametersCount; + int repeatSequenceIndex, bsRepeatSequenceCount; + SCHAR* gainSetIndex = pInst->gainSetIndex; + SCHAR channelGroupForChannel[8]; + DUCKING_MODIFICATION duckingModificationForChannelGroup[8]; + + pInst->drcSetId = FDKreadBits(hBs, 6); + if (version == 0) { + /* Assume all v0 DRC sets to be manageable in terms of complexity */ + pInst->drcSetComplexityLevel = 2; + } else { + pInst->drcSetComplexityLevel = FDKreadBits(hBs, 4); + } + pInst->drcLocation = FDKreadBits(hBs, 4); + if (version == 0) { + downmixIdPresent = 1; + } else { + downmixIdPresent = FDKreadBits(hBs, 1); + } + if (downmixIdPresent) { + pInst->downmixId[0] = FDKreadBits(hBs, 7); + if (version == 0) { + if (pInst->downmixId[0] == 0) + pInst->drcApplyToDownmix = 0; + else + pInst->drcApplyToDownmix = 1; + } else { + pInst->drcApplyToDownmix = FDKreadBits(hBs, 1); + } + + additionalDownmixIdPresent = FDKreadBits(hBs, 1); + if (additionalDownmixIdPresent) { + additionalDownmixIdCount = FDKreadBits(hBs, 3); + if ((1 + additionalDownmixIdCount) > 8) return DE_MEMORY_ERROR; + for (i = 0; i < additionalDownmixIdCount; i++) { + pInst->downmixId[i + 1] = FDKreadBits(hBs, 7); + } + pInst->downmixIdCount = 1 + additionalDownmixIdCount; + } else { + pInst->downmixIdCount = 1; + } + } else { + pInst->downmixId[0] = 0; + pInst->downmixIdCount = 1; + } + + pInst->drcSetEffect = FDKreadBits(hBs, 16); + + if ((pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) { + pInst->limiterPeakTargetPresent = FDKreadBits(hBs, 1); + if (pInst->limiterPeakTargetPresent) { + bsLimiterPeakTarget = FDKreadBits(hBs, 8); + pInst->limiterPeakTarget = -(FIXP_SGL)( + bsLimiterPeakTarget + << (FRACT_BITS - 1 - 3 - 5)); /* - bsLimiterPeakTarget * 0.125; */ + } + } + + pInst->drcSetTargetLoudnessPresent = FDKreadBits(hBs, 1); + + /* set default values */ + pInst->drcSetTargetLoudnessValueUpper = 0; + pInst->drcSetTargetLoudnessValueLower = -63; + + if (pInst->drcSetTargetLoudnessPresent == 1) { + int bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower; + int drcSetTargetLoudnessValueLowerPresent; + bsDrcSetTargetLoudnessValueUpper = FDKreadBits(hBs, 6); + pInst->drcSetTargetLoudnessValueUpper = + bsDrcSetTargetLoudnessValueUpper - 63; + drcSetTargetLoudnessValueLowerPresent = FDKreadBits(hBs, 1); + if (drcSetTargetLoudnessValueLowerPresent == 1) { + bsDrcSetTargetLoudnessValueLower = FDKreadBits(hBs, 6); + pInst->drcSetTargetLoudnessValueLower = + bsDrcSetTargetLoudnessValueLower - 63; + } + } + + pInst->dependsOnDrcSetPresent = FDKreadBits(hBs, 1); + + pInst->noIndependentUse = 0; + if (pInst->dependsOnDrcSetPresent) { + pInst->dependsOnDrcSet = FDKreadBits(hBs, 6); + } else { + pInst->noIndependentUse = FDKreadBits(hBs, 1); + } + + if (version == 0) { + pInst->requiresEq = 0; + } else { + pInst->requiresEq = FDKreadBits(hBs, 1); + } + + pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation); + + pInst->drcChannelCount = channelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + DUCKING_MODIFICATION* pDModForChannel = + pInst->duckingModificationForChannel; + c = 0; + while (c < channelCount) { + int bsGainSetIndex; + bsGainSetIndex = FDKreadBits(hBs, 6); + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + _decodeDuckingModification(hBs, &(pDModForChannel[c]), 0); + + c++; + repeatParameters = FDKreadBits(hBs, 1); + if (repeatParameters == 1) { + bsRepeatParametersCount = FDKreadBits(hBs, 5); + bsRepeatParametersCount += 1; + for (i = 0; i < bsRepeatParametersCount; i++) { + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = gainSetIndex[c - 1]; + pDModForChannel[c] = pDModForChannel[c - 1]; + c++; + } + } + } + if (c > channelCount) { + return DE_NOT_OK; + } + + err = deriveDrcChannelGroups( + pInst->drcSetEffect, pInst->drcChannelCount, gainSetIndex, + pDModForChannel, &pInst->nDrcChannelGroups, + pInst->gainSetIndexForChannelGroup, channelGroupForChannel, + duckingModificationForChannelGroup); + if (err) return (err); + } else { + int deriveChannelCount = 0; + if (((version == 0) || (pInst->drcApplyToDownmix != 0)) && + (pInst->downmixId[0] != DOWNMIX_ID_BASE_LAYOUT) && + (pInst->downmixId[0] != DOWNMIX_ID_ANY_DOWNMIX) && + (pInst->downmixIdCount == 1)) { + if (hUniDrcConfig->downmixInstructionsCount != 0) { + DOWNMIX_INSTRUCTIONS* pDown = + selectDownmixInstructions(hUniDrcConfig, pInst->downmixId[0]); + if (pDown == NULL) return DE_NOT_OK; + pInst->drcChannelCount = channelCount = + pDown->targetChannelCount; /* targetChannelCountFromDownmixId*/ + } else { + deriveChannelCount = 1; + channelCount = 1; + } + } else if (((version == 0) || (pInst->drcApplyToDownmix != 0)) && + ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) || + (pInst->downmixIdCount > 1))) { + /* Set maximum channel count as upper border. The effective channel count + * is set at the process function. */ + pInst->drcChannelCount = 8; + channelCount = 1; + } + + c = 0; + while (c < channelCount) { + int bsGainSetIndex; + bsGainSetIndex = FDKreadBits(hBs, 6); + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + c++; + repeatSequenceIndex = FDKreadBits(hBs, 1); + + if (repeatSequenceIndex == 1) { + bsRepeatSequenceCount = FDKreadBits(hBs, 5); + bsRepeatSequenceCount += 1; + if (deriveChannelCount) { + channelCount = 1 + bsRepeatSequenceCount; + } + for (i = 0; i < bsRepeatSequenceCount; i++) { + if (c >= 8) return DE_MEMORY_ERROR; + gainSetIndex[c] = bsGainSetIndex - 1; + c++; + } + } + } + if (c > channelCount) { + return DE_NOT_OK; + } + if (deriveChannelCount) { + pInst->drcChannelCount = channelCount; + } + + /* DOWNMIX_ID_ANY_DOWNMIX: channelCount is 1. Distribute gainSetIndex to all + * channels. */ + if ((pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) || + (pInst->downmixIdCount > 1)) { + for (c = 1; c < pInst->drcChannelCount; c++) { + gainSetIndex[c] = gainSetIndex[0]; + } + } + + err = deriveDrcChannelGroups(pInst->drcSetEffect, pInst->drcChannelCount, + gainSetIndex, NULL, &pInst->nDrcChannelGroups, + pInst->gainSetIndexForChannelGroup, + channelGroupForChannel, NULL); + if (err) return (err); + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int set, bandCount; + set = pInst->gainSetIndexForChannelGroup[g]; + + /* get bandCount */ + if (pCoef != NULL && set < pCoef->gainSetCount) { + bandCount = pCoef->gainSet[set].bandCount; + } else { + bandCount = 1; + } + + _decodeGainModification(hBs, version, bandCount, + pInst->gainModificationForChannelGroup[g], 0); + } + } + + return err; +} + +static DRC_ERROR _readChannelLayout(HANDLE_FDK_BITSTREAM hBs, + CHANNEL_LAYOUT* pChan) { + DRC_ERROR err = DE_OK; + + pChan->baseChannelCount = FDKreadBits(hBs, 7); + + if (pChan->baseChannelCount > 8) return DE_NOT_OK; + + pChan->layoutSignalingPresent = FDKreadBits(hBs, 1); + + if (pChan->layoutSignalingPresent) { + pChan->definedLayout = FDKreadBits(hBs, 8); + + if (pChan->definedLayout == 0) { + int i; + for (i = 0; i < pChan->baseChannelCount; i++) { + if (i < 8) { + pChan->speakerPosition[i] = FDKreadBits(hBs, 7); + } else { + FDKpushFor(hBs, 7); + } + } + } + } + return err; +} + +static DRC_ERROR _readDownmixInstructions(HANDLE_FDK_BITSTREAM hBs, + const int version, + CHANNEL_LAYOUT* pChan, + DOWNMIX_INSTRUCTIONS* pDown) { + DRC_ERROR err = DE_OK; + + pDown->downmixId = FDKreadBits(hBs, 7); + pDown->targetChannelCount = FDKreadBits(hBs, 7); + pDown->targetLayout = FDKreadBits(hBs, 8); + pDown->downmixCoefficientsPresent = FDKreadBits(hBs, 1); + + if (pDown->downmixCoefficientsPresent) { + int nDownmixCoeffs = pDown->targetChannelCount * pChan->baseChannelCount; + int i; + if (nDownmixCoeffs > 8 * 8) return DE_NOT_OK; + if (version == 0) { + pDown->bsDownmixOffset = 0; + for (i = 0; i < nDownmixCoeffs; i++) { + /* LFE downmix coefficients are not supported. */ + pDown->downmixCoefficient[i] = downmixCoeff[FDKreadBits(hBs, 4)]; + } + } else { + pDown->bsDownmixOffset = FDKreadBits(hBs, 4); + for (i = 0; i < nDownmixCoeffs; i++) { + pDown->downmixCoefficient[i] = downmixCoeffV1[FDKreadBits(hBs, 5)]; + } + } + } + return err; +} + +static DRC_ERROR _readDrcExtensionV1(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int downmixInstructionsV1Present; + int drcCoeffsAndInstructionsUniDrcV1Present; + int loudEqInstructionsPresent, loudEqInstructionsCount; + int eqPresent, eqInstructionsCount; + int i, offset; + int diff = hUniDrcConfig->diff; + + downmixInstructionsV1Present = FDKreadBits(hBs, 1); + if (downmixInstructionsV1Present == 1) { + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, + FDKreadBits(hBs, 7)); + offset = hUniDrcConfig->downmixInstructionsCountV0; + hUniDrcConfig->downmixInstructionsCount = fMin( + (UCHAR)(offset + hUniDrcConfig->downmixInstructionsCountV1), (UCHAR)6); + for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV1; i++) { + DOWNMIX_INSTRUCTIONS tmpDown; + FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS)); + err = _readDownmixInstructions(hBs, 1, &hUniDrcConfig->channelLayout, + &tmpDown); + if (err) return err; + if ((offset + i) >= 6) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpDown, + &(hUniDrcConfig->downmixInstructions[offset + i]), + sizeof(DOWNMIX_INSTRUCTIONS)) != 0); + hUniDrcConfig->downmixInstructions[offset + i] = tmpDown; + } + } else { + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV1, 0); + } + + drcCoeffsAndInstructionsUniDrcV1Present = FDKreadBits(hBs, 1); + if (drcCoeffsAndInstructionsUniDrcV1Present == 1) { + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, + FDKreadBits(hBs, 3)); + offset = hUniDrcConfig->drcCoefficientsUniDrcCountV0; + hUniDrcConfig->drcCoefficientsUniDrcCount = + fMin((UCHAR)(offset + hUniDrcConfig->drcCoefficientsUniDrcCountV1), + (UCHAR)2); + for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV1; i++) { + DRC_COEFFICIENTS_UNI_DRC tmpCoef; + FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC)); + err = _readDrcCoefficientsUniDrc(hBs, 1, &tmpCoef); + if (err) return err; + if ((offset + i) >= 2) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpCoef, + &(hUniDrcConfig->drcCoefficientsUniDrc[offset + i]), + sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0); + hUniDrcConfig->drcCoefficientsUniDrc[offset + i] = tmpCoef; + } + + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, + FDKreadBits(hBs, 6)); + offset = hUniDrcConfig->drcInstructionsUniDrcCount; + hUniDrcConfig->drcInstructionsUniDrcCount = + fMin((UCHAR)(offset + hUniDrcConfig->drcInstructionsUniDrcCountV1), + (UCHAR)12); + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC tmpInst; + FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + err = _readDrcInstructionsUniDrc(hBs, 1, hUniDrcConfig, &tmpInst); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpInst, + &(hUniDrcConfig->drcInstructionsUniDrc[offset + i]), + sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0); + hUniDrcConfig->drcInstructionsUniDrc[offset + i] = tmpInst; + } + } else { + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV1, 0); + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV1, 0); + } + + loudEqInstructionsPresent = FDKreadBits(hBs, 1); + if (loudEqInstructionsPresent == 1) { + loudEqInstructionsCount = FDKreadBits(hBs, 4); + for (i = 0; i < loudEqInstructionsCount; i++) { + _skipLoudEqInstructions(hBs); + } + } + + eqPresent = FDKreadBits(hBs, 1); + if (eqPresent == 1) { + _skipEqCoefficients(hBs); + eqInstructionsCount = FDKreadBits(hBs, 4); + for (i = 0; i < eqInstructionsCount; i++) { + _skipEqInstructions(hBs, hUniDrcConfig); + } + } + + hUniDrcConfig->diff = diff; + + return err; +} + +static DRC_ERROR _readUniDrcConfigExtension( + HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + INT nBitsRemaining; + UNI_DRC_CONFIG_EXTENSION* pExt = &(hUniDrcConfig->uniDrcConfigExt); + + k = 0; + pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4); + while (pExt->uniDrcConfigExtType[k] != UNIDRCCONFEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 4); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + nBitsRemaining = (INT)FDKgetValidBits(hBs); + + switch (pExt->uniDrcConfigExtType[k]) { + case UNIDRCCONFEXT_V1: + err = _readDrcExtensionV1(hBs, hUniDrcConfig); + if (err) return err; + if (nBitsRemaining != + ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs))) + return DE_NOT_OK; + break; + case UNIDRCCONFEXT_PARAM_DRC: + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->uniDrcConfigExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +DRC_ERROR +drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRC_ERROR err = DE_OK; + int i, diff = 0; + int drcDescriptionBasicPresent, drcCoefficientsBasicCount, + drcInstructionsBasicCount; + CHANNEL_LAYOUT tmpChan; + FDKmemclear(&tmpChan, sizeof(CHANNEL_LAYOUT)); + if (hUniDrcConfig == NULL) return DE_NOT_OK; + + diff |= _compAssign(&hUniDrcConfig->sampleRatePresent, FDKreadBits(hBs, 1)); + + if (hUniDrcConfig->sampleRatePresent == 1) { + diff |= + _compAssign(&hUniDrcConfig->sampleRate, FDKreadBits(hBs, 18) + 1000); + } + + diff |= _compAssign(&hUniDrcConfig->downmixInstructionsCountV0, + FDKreadBits(hBs, 7)); + + drcDescriptionBasicPresent = FDKreadBits(hBs, 1); + if (drcDescriptionBasicPresent == 1) { + drcCoefficientsBasicCount = FDKreadBits(hBs, 3); + drcInstructionsBasicCount = FDKreadBits(hBs, 4); + } else { + drcCoefficientsBasicCount = 0; + drcInstructionsBasicCount = 0; + } + + diff |= _compAssign(&hUniDrcConfig->drcCoefficientsUniDrcCountV0, + FDKreadBits(hBs, 3)); + diff |= _compAssign(&hUniDrcConfig->drcInstructionsUniDrcCountV0, + FDKreadBits(hBs, 6)); + + err = _readChannelLayout(hBs, &tmpChan); + if (err) return err; + + if (!diff) + diff |= (FDKmemcmp(&tmpChan, &hUniDrcConfig->channelLayout, + sizeof(CHANNEL_LAYOUT)) != 0); + hUniDrcConfig->channelLayout = tmpChan; + + hUniDrcConfig->downmixInstructionsCount = + fMin(hUniDrcConfig->downmixInstructionsCountV0, (UCHAR)6); + for (i = 0; i < hUniDrcConfig->downmixInstructionsCountV0; i++) { + DOWNMIX_INSTRUCTIONS tmpDown; + FDKmemclear(&tmpDown, sizeof(DOWNMIX_INSTRUCTIONS)); + err = _readDownmixInstructions(hBs, 0, &hUniDrcConfig->channelLayout, + &tmpDown); + if (err) return err; + if (i >= 6) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpDown, &(hUniDrcConfig->downmixInstructions[i]), + sizeof(DOWNMIX_INSTRUCTIONS)) != 0); + hUniDrcConfig->downmixInstructions[i] = tmpDown; + } + + for (i = 0; i < drcCoefficientsBasicCount; i++) { + _skipDrcCoefficientsBasic(hBs); + } + for (i = 0; i < drcInstructionsBasicCount; i++) { + _skipDrcInstructionsBasic(hBs); + } + + hUniDrcConfig->drcCoefficientsUniDrcCount = + fMin(hUniDrcConfig->drcCoefficientsUniDrcCountV0, (UCHAR)2); + for (i = 0; i < hUniDrcConfig->drcCoefficientsUniDrcCountV0; i++) { + DRC_COEFFICIENTS_UNI_DRC tmpCoef; + FDKmemclear(&tmpCoef, sizeof(DRC_COEFFICIENTS_UNI_DRC)); + err = _readDrcCoefficientsUniDrc(hBs, 0, &tmpCoef); + if (err) return err; + if (i >= 2) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpCoef, &(hUniDrcConfig->drcCoefficientsUniDrc[i]), + sizeof(DRC_COEFFICIENTS_UNI_DRC)) != 0); + hUniDrcConfig->drcCoefficientsUniDrc[i] = tmpCoef; + } + + hUniDrcConfig->drcInstructionsUniDrcCount = + fMin(hUniDrcConfig->drcInstructionsUniDrcCountV0, (UCHAR)12); + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCountV0; i++) { + DRC_INSTRUCTIONS_UNI_DRC tmpInst; + FDKmemclear(&tmpInst, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + err = _readDrcInstructionsUniDrc(hBs, 0, hUniDrcConfig, &tmpInst); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpInst, &(hUniDrcConfig->drcInstructionsUniDrc[i]), + sizeof(DRC_INSTRUCTIONS_UNI_DRC)) != 0); + hUniDrcConfig->drcInstructionsUniDrc[i] = tmpInst; + } + + diff |= + _compAssign(&hUniDrcConfig->uniDrcConfigExtPresent, FDKreadBits(hBs, 1)); + hUniDrcConfig->diff = diff; + + if (hUniDrcConfig->uniDrcConfigExtPresent == 1) { + err = _readUniDrcConfigExtension(hBs, hUniDrcConfig); + if (err) return err; + } + + return err; +} + +/*******************/ +/* loudnessInfoSet */ +/*******************/ + +static DRC_ERROR _decodeMethodValue(HANDLE_FDK_BITSTREAM hBs, + const UCHAR methodDefinition, + FIXP_DBL* methodValue, INT isBox) { + int tmp; + FIXP_DBL val; + switch (methodDefinition) { + case MD_UNKNOWN_OTHER: + case MD_PROGRAM_LOUDNESS: + case MD_ANCHOR_LOUDNESS: + case MD_MAX_OF_LOUDNESS_RANGE: + case MD_MOMENTARY_LOUDNESS_MAX: + case MD_SHORT_TERM_LOUDNESS_MAX: + tmp = FDKreadBits(hBs, 8); + val = FL2FXCONST_DBL(-57.75f / (float)(1 << 7)) + + (FIXP_DBL)( + tmp << (DFRACT_BITS - 1 - 2 - 7)); /* -57.75 + tmp * 0.25; */ + break; + case MD_LOUDNESS_RANGE: + tmp = FDKreadBits(hBs, 8); + if (tmp == 0) + val = (FIXP_DBL)0; + else if (tmp <= 128) + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 2 - 7)); /* tmp * 0.25; */ + else if (tmp <= 204) { + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 1 - 7)) - + FL2FXCONST_DBL(32.0f / (float)(1 << 7)); /* 0.5 * tmp - 32.0f; */ + } else { + /* downscale by 1 more bit to prevent overflow at intermediate result */ + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 8)) - + FL2FXCONST_DBL(134.0f / (float)(1 << 8)); /* tmp - 134.0; */ + val <<= 1; + } + break; + case MD_MIXING_LEVEL: + tmp = FDKreadBits(hBs, isBox ? 8 : 5); + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)) + + FL2FXCONST_DBL(80.0f / (float)(1 << 7)); /* tmp + 80.0; */ + break; + case MD_ROOM_TYPE: + tmp = FDKreadBits(hBs, isBox ? 8 : 2); + val = (FIXP_DBL)(tmp << (DFRACT_BITS - 1 - 7)); /* tmp; */ + break; + case MD_SHORT_TERM_LOUDNESS: + tmp = FDKreadBits(hBs, 8); + val = FL2FXCONST_DBL(-116.0f / (float)(1 << 7)) + + (FIXP_DBL)( + tmp << (DFRACT_BITS - 1 - 1 - 7)); /* -116.0 + tmp * 0.5; */ + break; + default: + return DE_NOT_OK; /* invalid methodDefinition value */ + } + *methodValue = val; + return DE_OK; +} + +static DRC_ERROR _readLoudnessMeasurement(HANDLE_FDK_BITSTREAM hBs, + LOUDNESS_MEASUREMENT* pMeas) { + DRC_ERROR err = DE_OK; + + pMeas->methodDefinition = FDKreadBits(hBs, 4); + err = + _decodeMethodValue(hBs, pMeas->methodDefinition, &pMeas->methodValue, 0); + if (err) return err; + pMeas->measurementSystem = FDKreadBits(hBs, 4); + pMeas->reliability = FDKreadBits(hBs, 2); + + return err; +} + +static DRC_ERROR _readLoudnessInfo(HANDLE_FDK_BITSTREAM hBs, const int version, + LOUDNESS_INFO* loudnessInfo) { + DRC_ERROR err = DE_OK; + int bsSamplePeakLevel, bsTruePeakLevel, i; + int measurementCount; + + loudnessInfo->drcSetId = FDKreadBits(hBs, 6); + if (version >= 1) { + loudnessInfo->eqSetId = FDKreadBits(hBs, 6); + } else { + loudnessInfo->eqSetId = 0; + } + loudnessInfo->downmixId = FDKreadBits(hBs, 7); + + loudnessInfo->samplePeakLevelPresent = FDKreadBits(hBs, 1); + if (loudnessInfo->samplePeakLevelPresent) { + bsSamplePeakLevel = FDKreadBits(hBs, 12); + if (bsSamplePeakLevel == 0) { + loudnessInfo->samplePeakLevelPresent = 0; + loudnessInfo->samplePeakLevel = (FIXP_DBL)0; + } else { /* 20.0 - bsSamplePeakLevel * 0.03125; */ + loudnessInfo->samplePeakLevel = + FL2FXCONST_DBL(20.0f / (float)(1 << 7)) - + (FIXP_DBL)(bsSamplePeakLevel << (DFRACT_BITS - 1 - 5 - 7)); + } + } + + loudnessInfo->truePeakLevelPresent = FDKreadBits(hBs, 1); + if (loudnessInfo->truePeakLevelPresent) { + bsTruePeakLevel = FDKreadBits(hBs, 12); + if (bsTruePeakLevel == 0) { + loudnessInfo->truePeakLevelPresent = 0; + loudnessInfo->truePeakLevel = (FIXP_DBL)0; + } else { + loudnessInfo->truePeakLevel = + FL2FXCONST_DBL(20.0f / (float)(1 << 7)) - + (FIXP_DBL)(bsTruePeakLevel << (DFRACT_BITS - 1 - 5 - 7)); + } + loudnessInfo->truePeakLevelMeasurementSystem = FDKreadBits(hBs, 4); + loudnessInfo->truePeakLevelReliability = FDKreadBits(hBs, 2); + } + + measurementCount = FDKreadBits(hBs, 4); + loudnessInfo->measurementCount = fMin(measurementCount, 8); + for (i = 0; i < measurementCount; i++) { + LOUDNESS_MEASUREMENT tmpMeas; + FDKmemclear(&tmpMeas, sizeof(LOUDNESS_MEASUREMENT)); + err = _readLoudnessMeasurement(hBs, &tmpMeas); + if (err) return err; + if (i >= 8) continue; + loudnessInfo->loudnessMeasurement[i] = tmpMeas; + } + + return err; +} + +static DRC_ERROR _readLoudnessInfoSetExtEq( + HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int i, offset; + int diff = hLoudnessInfoSet->diff; + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV1, + FDKreadBits(hBs, 6)); + diff |= + _compAssign(&hLoudnessInfoSet->loudnessInfoCountV1, FDKreadBits(hBs, 6)); + + offset = hLoudnessInfoSet->loudnessInfoAlbumCountV0; + hLoudnessInfoSet->loudnessInfoAlbumCount = fMin( + (UCHAR)(offset + hLoudnessInfoSet->loudnessInfoAlbumCountV1), (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV1; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 1, &tmpLoud); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, + &(hLoudnessInfoSet->loudnessInfoAlbum[offset + i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfoAlbum[offset + i] = tmpLoud; + } + + offset = hLoudnessInfoSet->loudnessInfoCountV0; + hLoudnessInfoSet->loudnessInfoCount = + fMin((UCHAR)(offset + hLoudnessInfoSet->loudnessInfoCountV1), (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV1; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 1, &tmpLoud); + if (err) return err; + if ((offset + i) >= 12) continue; + if (!diff) + diff |= + (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[offset + i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfo[offset + i] = tmpLoud; + } + hLoudnessInfoSet->diff = diff; + return err; +} + +static DRC_ERROR _readLoudnessInfoSetExtension( + HANDLE_FDK_BITSTREAM hBs, HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int k, bitSizeLen, extSizeBits, bitSize; + INT nBitsRemaining; + LOUDNESS_INFO_SET_EXTENSION* pExt = &(hLoudnessInfoSet->loudnessInfoSetExt); + + k = 0; + pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4); + while (pExt->loudnessInfoSetExtType[k] != UNIDRCLOUDEXT_TERM) { + if (k >= (8 - 1)) return DE_MEMORY_ERROR; + bitSizeLen = FDKreadBits(hBs, 4); + extSizeBits = bitSizeLen + 4; + + bitSize = FDKreadBits(hBs, extSizeBits); + pExt->extBitSize[k] = bitSize + 1; + nBitsRemaining = (INT)FDKgetValidBits(hBs); + + switch (pExt->loudnessInfoSetExtType[k]) { + case UNIDRCLOUDEXT_EQ: + err = _readLoudnessInfoSetExtEq(hBs, hLoudnessInfoSet); + if (err) return err; + if (nBitsRemaining != + ((INT)pExt->extBitSize[k] + (INT)FDKgetValidBits(hBs))) + return DE_NOT_OK; + break; + /* add future extensions here */ + default: + FDKpushFor(hBs, pExt->extBitSize[k]); + break; + } + k++; + pExt->loudnessInfoSetExtType[k] = FDKreadBits(hBs, 4); + } + + return err; +} + +/* Parser for loundessInfoSet() */ +DRC_ERROR +drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet) { + DRC_ERROR err = DE_OK; + int i, diff = 0; + if (hLoudnessInfoSet == NULL) return DE_NOT_OK; + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoAlbumCountV0, + FDKreadBits(hBs, 6)); + diff |= + _compAssign(&hLoudnessInfoSet->loudnessInfoCountV0, FDKreadBits(hBs, 6)); + + hLoudnessInfoSet->loudnessInfoAlbumCount = + fMin(hLoudnessInfoSet->loudnessInfoAlbumCountV0, (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCountV0; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 0, &tmpLoud); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfoAlbum[i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfoAlbum[i] = tmpLoud; + } + + hLoudnessInfoSet->loudnessInfoCount = + fMin(hLoudnessInfoSet->loudnessInfoCountV0, (UCHAR)12); + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCountV0; i++) { + LOUDNESS_INFO tmpLoud; + FDKmemclear(&tmpLoud, sizeof(LOUDNESS_INFO)); + err = _readLoudnessInfo(hBs, 0, &tmpLoud); + if (err) return err; + if (i >= 12) continue; + if (!diff) + diff |= (FDKmemcmp(&tmpLoud, &(hLoudnessInfoSet->loudnessInfo[i]), + sizeof(LOUDNESS_INFO)) != 0); + hLoudnessInfoSet->loudnessInfo[i] = tmpLoud; + } + + diff |= _compAssign(&hLoudnessInfoSet->loudnessInfoSetExtPresent, + FDKreadBits(hBs, 1)); + hLoudnessInfoSet->diff = diff; + + if (hLoudnessInfoSet->loudnessInfoSetExtPresent) { + err = _readLoudnessInfoSetExtension(hBs, hLoudnessInfoSet); + if (err) return err; + } + + return err; +} diff --git a/fdk-aac/libDRCdec/src/drcDec_reader.h b/fdk-aac/libDRCdec/src/drcDec_reader.h new file mode 100644 index 0000000..1ab9b58 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_reader.h @@ -0,0 +1,130 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_READER_H +#define DRCDEC_READER_H + +#include "drcDecoder.h" +#include "drcDec_types.h" +#include "FDK_bitstream.h" + +DRC_ERROR +drcDec_readUniDrc(HANDLE_FDK_BITSTREAM hBs, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + const int frameSize, const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int frameSize, + const int deltaTminDefault, + HANDLE_UNI_DRC_GAIN hUniDrcGain); + +DRC_ERROR +drcDec_readUniDrcConfig(HANDLE_FDK_BITSTREAM hBs, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +DRC_ERROR +drcDec_readLoudnessInfoSet(HANDLE_FDK_BITSTREAM hBs, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet); + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDec_rom.cpp b/fdk-aac/libDRCdec/src/drcDec_rom.cpp new file mode 100644 index 0000000..9f89689 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_rom.cpp @@ -0,0 +1,323 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_rom.h" + +const SCHAR deltaGain_codingProfile_0_1_huffman[24][2] = { + {1, 2}, {3, 4}, {-63, -65}, {5, -66}, {-64, 6}, {-80, 7}, + {8, 9}, {-68, 10}, {11, 12}, {-56, -67}, {-61, 13}, {-62, -69}, + {14, 15}, {16, -72}, {-71, 17}, {-70, -60}, {18, -59}, {19, 20}, + {21, -79}, {-57, -73}, {22, -58}, {-76, 23}, {-75, -74}, {-78, -77}}; + +const SCHAR deltaGain_codingProfile_2_huffman[48][2] = { + {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}, {11, 12}, + {13, -65}, {14, -64}, {15, -66}, {16, -67}, {17, 18}, {19, -68}, + {20, -63}, {-69, 21}, {-59, 22}, {-61, -62}, {-60, 23}, {24, -58}, + {-70, -57}, {-56, -71}, {25, 26}, {27, -55}, {-72, 28}, {-54, 29}, + {-53, 30}, {-73, -52}, {31, -74}, {32, 33}, {-75, 34}, {-76, 35}, + {-51, 36}, {-78, 37}, {-77, 38}, {-96, 39}, {-48, 40}, {-50, -79}, + {41, 42}, {-80, -81}, {-82, 43}, {44, -49}, {45, -84}, {-83, -89}, + {-86, 46}, {-90, -85}, {-91, -93}, {-92, 47}, {-88, -87}, {-95, -94}}; + +const FIXP_SGL slopeSteepness[] = {FL2FXCONST_SGL(-3.0518f / (float)(1 << 2)), + FL2FXCONST_SGL(-1.2207f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.4883f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.1953f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.0781f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.0312f / (float)(1 << 2)), + FL2FXCONST_SGL(-0.005f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(0.005f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0312f / (float)(1 << 2)), + FL2FXCONST_SGL(0.0781f / (float)(1 << 2)), + FL2FXCONST_SGL(0.1953f / (float)(1 << 2)), + FL2FXCONST_SGL(0.4883f / (float)(1 << 2)), + FL2FXCONST_SGL(1.2207f / (float)(1 << 2)), + FL2FXCONST_SGL(3.0518f / (float)(1 << 2))}; + +const SCHAR slopeSteepness_huffman[14][2] = { + {1, -57}, {-58, 2}, {3, 4}, {5, 6}, {7, -56}, + {8, -60}, {-61, -55}, {9, -59}, {10, -54}, {-64, 11}, + {-51, 12}, {-62, -50}, {-63, 13}, {-52, -53}}; + +const FIXP_DBL downmixCoeff[] = { + FL2FXCONST_DBL(1.0000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.9440608763 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8912509381 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8413951416 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7943282347 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7498942093 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7079457844 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6683439176 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6309573445 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5956621435 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5623413252 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5308844442 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5011872336 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4216965034 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3548133892 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0000000000 / (float)(1 << 2))}; + +const FIXP_DBL downmixCoeffV1[] = { + FL2FXCONST_DBL(3.1622776602 / (float)(1 << 2)), + FL2FXCONST_DBL(1.9952623150 / (float)(1 << 2)), + FL2FXCONST_DBL(1.6788040181 / (float)(1 << 2)), + FL2FXCONST_DBL(1.4125375446 / (float)(1 << 2)), + FL2FXCONST_DBL(1.1885022274 / (float)(1 << 2)), + FL2FXCONST_DBL(1.0000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.9440608763 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8912509381 / (float)(1 << 2)), + FL2FXCONST_DBL(0.8413951416 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7943282347 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7498942093 / (float)(1 << 2)), + FL2FXCONST_DBL(0.7079457844 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6683439176 / (float)(1 << 2)), + FL2FXCONST_DBL(0.6309573445 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5956621435 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5623413252 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5308844442 / (float)(1 << 2)), + FL2FXCONST_DBL(0.5011872336 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4731512590 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4466835922 / (float)(1 << 2)), + FL2FXCONST_DBL(0.4216965034 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3981071706 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3548133892 / (float)(1 << 2)), + FL2FXCONST_DBL(0.3162277660 / (float)(1 << 2)), + FL2FXCONST_DBL(0.2818382931 / (float)(1 << 2)), + FL2FXCONST_DBL(0.2511886432 / (float)(1 << 2)), + FL2FXCONST_DBL(0.1778279410 / (float)(1 << 2)), + FL2FXCONST_DBL(0.1000000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0562341325 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0316227766 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0100000000 / (float)(1 << 2)), + FL2FXCONST_DBL(0.0000000000 / (float)(1 << 2))}; + +const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidLeft[] = { + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 1 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.2f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 2 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.4f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 3 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.6f / (float)(1 << 2)), + FL2FXCONST_SGL(9.0f / (float)(1 << 5)), 0}, /* 4 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.8f / (float)(1 << 2)), + FL2FXCONST_SGL(6.0f / (float)(1 << 5)), 0}, /* 5 */ + {FL2FXCONST_SGL(32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + FL2FXCONST_SGL(5.0f / (float)(1 << 5)), 0}, /* 6 */ +}; + +const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidRight[] = { + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.0f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 1 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.2f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 2 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.4f / (float)(1 << 2)), + FL2FXCONST_SGL(12.0f / (float)(1 << 5)), 0}, /* 3 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.6f / (float)(1 << 2)), + FL2FXCONST_SGL(10.0f / (float)(1 << 5)), 0}, /* 4 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(0.8f / (float)(1 << 2)), + FL2FXCONST_SGL(8.0f / (float)(1 << 5)), 0}, /* 5 */ + {FL2FXCONST_SGL(-32.0f / (float)(1 << 6)), + FL2FXCONST_SGL(1.0f / (float)(1 << 2)), + FL2FXCONST_SGL(6.0f / (float)(1 << 5)), 0}, /* 6 */ +}; + +const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesLeft[] = { + {2, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-41.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-53.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(6.0f / (float)(1 << 7))}}, /* 7 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-43.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(6.0f / (float)(1 << 7))}}, /* 8 */ + {2, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-41.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-65.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(12.0f / (float)(1 << 7))}}, /* 9 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-55.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(12.0f / (float)(1 << 7))}}, /* 10 */ + {1, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-50.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(15.0f / (float)(1 << 7))}} /* 11 */ +}; + +const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesRight[] = { + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-21.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-11.0f / (float)(1 << 7)), + FL2FXCONST_SGL(9.0f / (float)(1 << 7)), + FL2FXCONST_SGL(19.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 7 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 8 */ + {3, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-21.0f / (float)(1 << 7)), + FL2FXCONST_SGL(9.0f / (float)(1 << 7)), + FL2FXCONST_SGL(29.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-15.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-35.0f / (float)(1 << 7))}}, /* 9 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}}, /* 10 */ + {4, + {FL2FXCONST_SGL(-31.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-26.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-16.0f / (float)(1 << 7)), + FL2FXCONST_SGL(4.0f / (float)(1 << 7)), + FL2FXCONST_SGL(14.0f / (float)(1 << 7))}, + {FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(0.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-5.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-24.0f / (float)(1 << 7)), + FL2FXCONST_SGL(-34.0f / (float)(1 << 7))}} /* 11 */ +}; diff --git a/fdk-aac/libDRCdec/src/drcDec_rom.h b/fdk-aac/libDRCdec/src/drcDec_rom.h new file mode 100644 index 0000000..daee882 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_rom.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_ROM_H +#define DRCDEC_ROM_H + +extern const SCHAR deltaGain_codingProfile_0_1_huffman[24][2]; +extern const SCHAR deltaGain_codingProfile_2_huffman[48][2]; + +extern const FIXP_SGL slopeSteepness[]; +extern const SCHAR slopeSteepness_huffman[14][2]; + +extern const FIXP_DBL downmixCoeff[]; +extern const FIXP_DBL downmixCoeffV1[]; + +extern const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidLeft[]; +extern const CUSTOM_DRC_CHAR_SIGMOID cicpDrcCharSigmoidRight[]; +extern const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesLeft[]; +extern const CUSTOM_DRC_CHAR_NODES cicpDrcCharNodesRight[]; + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp b/fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp new file mode 100644 index 0000000..9228197 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_selectionProcess.cpp @@ -0,0 +1,3099 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Andreas Hoelzer + + Description: DRC Set Selection + +*******************************************************************************/ + +#include "drcDec_selectionProcess.h" +#include "drcDec_tools.h" + +#define UNDEFINED_LOUDNESS_VALUE (FIXP_DBL) MAXVAL_DBL + +typedef enum { + DETR_NONE = 0, + DETR_NIGHT = 1, + DETR_NOISY = 2, + DETR_LIMITED = 3, + DETR_LOWLEVEL = 4, + DETR_DIALOG = 5, + DETR_GENERAL_COMPR = 6, + DETR_EXPAND = 7, + DETR_ARTISTIC = 8, + DETR_COUNT +} DRC_EFFECT_TYPE_REQUEST; + +typedef enum { + DFRT_EFFECT_TYPE, + DFRT_DYNAMIC_RANGE, + DFRT_DRC_CHARACTERISTIC +} DRC_FEATURE_REQUEST_TYPE; + +typedef enum { + MDR_DEFAULT = 0, + MDR_PROGRAM_LOUDNESS = 1, + MDR_ANCHOR_LOUDNESS = 2 +} METHOD_DEFINITION_REQUEST; + +typedef enum { + MSR_DEFAULT = 0, + MSR_BS_1770_4 = 1, + MSR_USER = 2, + MSR_EXPERT_PANEL = 3, + MSR_RESERVED_A = 4, + MSR_RESERVED_B = 5, + MSR_RESERVED_C = 6, + MSR_RESERVED_D = 7, + MSR_RESERVED_E = 8 +} MEASUREMENT_SYSTEM_REQUEST; + +typedef enum { + LPR_DEFAULT = 0, + LPR_OFF = 1, + LPR_HIGHPASS = 2 +} LOUDNESS_PREPROCESSING_REQUEST; + +typedef enum { + DRMRT_SHORT_TERM_LOUDNESS_TO_AVG = 0, + DRMRT_MOMENTARY_LOUDNESS_TO_AVG = 1, + DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG = 2 +} DYN_RANGE_MEASUREMENT_REQUEST_TYPE; + +typedef enum { + TCRT_DOWNMIX_ID = 0, + TCRT_TARGET_LAYOUT = 1, + TCRT_TARGET_CHANNEL_COUNT = 2 +} TARGET_CONFIG_REQUEST_TYPE; + +typedef shouldBeUnion { + struct { + UCHAR numRequests; + UCHAR numRequestsDesired; + DRC_EFFECT_TYPE_REQUEST request[MAX_REQUESTS_DRC_EFFECT_TYPE]; + } drcEffectType; + struct { + DYN_RANGE_MEASUREMENT_REQUEST_TYPE measurementRequestType; + UCHAR requestedIsRange; + FIXP_DBL requestValue; /* e = 7 */ + FIXP_DBL requestValueMin; /* e = 7 */ + FIXP_DBL requestValueMax; /* e = 7 */ + } dynamicRange; + UCHAR drcCharacteristic; +} +DRC_FEATURE_REQUEST; + +typedef struct { + /* system parameters */ + SCHAR baseChannelCount; + SCHAR baseLayout; /* not supported */ + TARGET_CONFIG_REQUEST_TYPE targetConfigRequestType; + UCHAR numDownmixIdRequests; + UCHAR downmixIdRequested[MAX_REQUESTS_DOWNMIX_ID]; + UCHAR targetLayoutRequested; + UCHAR targetChannelCountRequested; + LONG audioSampleRate; /* needed for complexity estimation, currently not + supported */ + + /* loudness normalization parameters */ + UCHAR loudnessNormalizationOn; + FIXP_DBL targetLoudness; /* e = 7 */ + UCHAR albumMode; + UCHAR peakLimiterPresent; + UCHAR loudnessDeviationMax; /* resolution: 1 dB */ + METHOD_DEFINITION_REQUEST loudnessMeasurementMethod; + MEASUREMENT_SYSTEM_REQUEST loudnessMeasurementSystem; + LOUDNESS_PREPROCESSING_REQUEST loudnessMeasurementPreProc; /* not supported */ + LONG deviceCutOffFrequency; /* not supported */ + FIXP_DBL loudnessNormalizationGainDbMax; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainModificationDb; /* e = 7 */ + FIXP_DBL outputPeakLevelMax; /* e = 7 */ + + /* dynamic range control parameters */ + UCHAR dynamicRangeControlOn; + UCHAR numDrcFeatureRequests; + DRC_FEATURE_REQUEST_TYPE drcFeatureRequestType[MAX_REQUESTS_DRC_FEATURE]; + DRC_FEATURE_REQUEST drcFeatureRequest[MAX_REQUESTS_DRC_FEATURE]; + + /* other */ + FIXP_SGL boost; /* e = 1 */ + FIXP_SGL compress; /* e = 1 */ + UCHAR drcCharacteristicTarget; /* not supported */ +} SEL_PROC_INPUT, *HANDLE_SEL_PROC_INPUT; + +/* Table E.1 of ISO/IEC DIS 23003-4: Recommended order of fallback effect type + * requests */ +static DRC_EFFECT_TYPE_REQUEST fallbackEffectTypeRequests[6][5] = { + /* Night */ {DETR_GENERAL_COMPR, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, + DETR_DIALOG}, + /* Noisy */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}, + /* Limited */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LOWLEVEL, DETR_DIALOG}, + /* LowLevel */ + {DETR_GENERAL_COMPR, DETR_NOISY, DETR_NIGHT, DETR_LIMITED, DETR_DIALOG}, + /* Dialog */ + {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL}, + /* General */ + {DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}}; + +/*******************************************/ +typedef struct { + UCHAR selectionFlag; + UCHAR downmixIdRequestIndex; + FIXP_DBL outputPeakLevel; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDbAdjusted; /* e = 7 */ + FIXP_DBL outputLoudness; /* e = 7 */ + DRC_INSTRUCTIONS_UNI_DRC* pInst; + +} DRCDEC_SELECTION_DATA; + +typedef struct { + UCHAR numData; + DRCDEC_SELECTION_DATA data[(12 + 1 + 6)]; + +} DRCDEC_SELECTION; + +/*******************************************/ +/* helper functions */ +/*******************************************/ + +static int _isError(int x) { + if (x < DRCDEC_SELECTION_PROCESS_WARNING) { + return 1; + } + + return 0; +} + +/* compare and assign */ +static inline int _compAssign(UCHAR* dest, const UCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(SCHAR* dest, const SCHAR src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(FIXP_DBL* dest, const FIXP_DBL src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(FIXP_SGL* dest, const FIXP_SGL src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = src; + return diff; +} + +static inline int _compAssign(TARGET_CONFIG_REQUEST_TYPE* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (TARGET_CONFIG_REQUEST_TYPE)src; + return diff; +} + +static inline int _compAssign(METHOD_DEFINITION_REQUEST* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (METHOD_DEFINITION_REQUEST)src; + return diff; +} + +static inline int _compAssign(DRC_FEATURE_REQUEST_TYPE* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (DRC_FEATURE_REQUEST_TYPE)src; + return diff; +} + +static inline int _compAssign(DRC_EFFECT_TYPE_REQUEST* dest, const int src) { + int diff = 0; + if (*dest != src) diff = 1; + *dest = (DRC_EFFECT_TYPE_REQUEST)src; + return diff; +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( + DRCDEC_SELECTION* pSelection); + +static DRCDEC_SELECTION_DATA* _drcdec_selection_add( + DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn); + +static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection); + +static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection); + +static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num); + +static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( + DRCDEC_SELECTION* pSelection, int at); + +static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +/*******************************************/ +/* declarations of static functions */ +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( + HANDLE_SEL_PROC_INPUT hSelProcInput); + +static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( + HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected); + +static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + UCHAR downmixIdRequested, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int albumMode, int* peakToAveragePresent, FIXP_DBL* peakToAverage); + +static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected); + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( + HANDLE_SEL_PROC_OUTPUT hSelProcOutput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); + +static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, + METHOD_DEFINITION_REQUEST measurementMethodRequested, + MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, + FIXP_DBL targetLoudness, int drcSetId, int downmixIdRequested, + FIXP_DBL* pLoudnessNormalizationGain, FIXP_DBL* pLoudness); + +static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, + int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel); + +static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + int downmixIdRequested, int* explicitPeakInformationPresent, + FIXP_DBL* signalPeakLevelOut, /* e = 7 */ + SEL_PROC_CODEC_MODE codecMode); + +static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( + LOUDNESS_INFO* loudnessInfo, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int* pLoudnessPeakToAverageValuePresent, + FIXP_DBL* pLoudnessPeakToAverageValue); + +static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected); + +static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, + int methodDefinition, int startIndex); + +/*******************************************/ +/* public functions */ +/*******************************************/ + +struct s_drcdec_selection_process { + SEL_PROC_CODEC_MODE codecMode; + SEL_PROC_INPUT selProcInput; + DRCDEC_SELECTION + selectionData[2]; /* 2 instances, one before and one after selection */ +}; + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance) { + HANDLE_DRC_SELECTION_PROCESS hInstance; + hInstance = (HANDLE_DRC_SELECTION_PROCESS)FDKcalloc( + 1, sizeof(struct s_drcdec_selection_process)); + + if (!hInstance) return DRCDEC_SELECTION_PROCESS_OUTOFMEMORY; + + hInstance->codecMode = SEL_PROC_CODEC_MODE_UNDEFINED; + + *phInstance = hInstance; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance) { + if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _initDefaultParams(&hInstance->selProcInput); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + switch (codecMode) { + case SEL_PROC_MPEG_4_AAC: + case SEL_PROC_MPEG_D_USAC: + case SEL_PROC_TEST_TIME_DOMAIN: + case SEL_PROC_TEST_QMF_DOMAIN: + case SEL_PROC_TEST_STFT_DOMAIN: + hInstance->codecMode = codecMode; + break; + + case SEL_PROC_CODEC_MODE_UNDEFINED: + default: + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + retVal = _initCodecModeParams(&(hInstance->selProcInput), + hInstance->codecMode = codecMode); + + return retVal; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType, + FIXP_DBL requestValue, int* pDiff) { + INT requestValueInt = (INT)requestValue; + int i, diff = 0; + SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); + + switch (requestType) { + case SEL_PROC_LOUDNESS_NORMALIZATION_ON: + if ((requestValueInt != 0) && (requestValueInt != 1)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= + _compAssign(&pSelProcInput->loudnessNormalizationOn, requestValueInt); + break; + case SEL_PROC_TARGET_LOUDNESS: + /* Lower boundary: drcSetTargetLoudnessValueLower default value. + Upper boundary: drcSetTargetLoudnessValueUpper default value */ + if ((requestValue < FL2FXCONST_DBL(-63.0f / (float)(1 << 7))) || + (requestValue > (FIXP_DBL)0)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + if (requestValue > + FL2FXCONST_DBL(-10.0f / + (float)(1 << 7))) /* recommended maximum value */ + requestValue = FL2FXCONST_DBL(-10.0f / (float)(1 << 7)); + diff |= _compAssign(&pSelProcInput->targetLoudness, requestValue); + break; + case SEL_PROC_EFFECT_TYPE: + if ((requestValueInt < -1) || (requestValueInt >= DETR_COUNT)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + /* Caution. This overrides all drcFeatureRequests requested so far! */ + if (requestValueInt == -1) { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 0); + } else if (requestValueInt == DETR_NONE) { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); + diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 0); + } else { + diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); + diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 1); + diff |= _compAssign(&pSelProcInput->drcFeatureRequestType[0], + DFRT_EFFECT_TYPE); + diff |= _compAssign(&pSelProcInput->drcFeatureRequest[0] + .drcEffectType.numRequestsDesired, + 1); + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.request[0], + requestValueInt); + if ((requestValueInt > DETR_NONE) && + (requestValueInt <= DETR_GENERAL_COMPR)) { + /* use fallback effect type requests */ + for (i = 0; i < 5; i++) { + diff |= + _compAssign(&pSelProcInput->drcFeatureRequest[0] + .drcEffectType.request[i + 1], + fallbackEffectTypeRequests[requestValueInt - 1][i]); + } + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, + 6); + } else { + diff |= _compAssign( + &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, + 1); + } + } + break; + case SEL_PROC_LOUDNESS_MEASUREMENT_METHOD: + if ((requestValueInt < 0) || (requestValueInt > 2)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->loudnessMeasurementMethod, + requestValueInt); + break; + case SEL_PROC_DOWNMIX_ID: + diff |= + _compAssign(&pSelProcInput->targetConfigRequestType, TCRT_DOWNMIX_ID); + if (requestValueInt < 0) { /* negative requests signal no downmixId */ + diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 0); + } else { + diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 1); + diff |= + _compAssign(&pSelProcInput->downmixIdRequested[0], requestValueInt); + } + break; + case SEL_PROC_TARGET_LAYOUT: + /* Request target layout according to ChannelConfiguration in ISO/IEC + * 23001-8 (CICP) */ + if ((requestValueInt < 1) || (requestValueInt > 63)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->targetConfigRequestType, + TCRT_TARGET_LAYOUT); + diff |= + _compAssign(&pSelProcInput->targetLayoutRequested, requestValueInt); + break; + case SEL_PROC_TARGET_CHANNEL_COUNT: + if ((requestValueInt < 1) || (requestValueInt > 8)) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->targetConfigRequestType, + TCRT_TARGET_CHANNEL_COUNT); + diff |= _compAssign(&pSelProcInput->targetChannelCountRequested, + requestValueInt); + break; + case SEL_PROC_BASE_CHANNEL_COUNT: + if (requestValueInt < 0) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->baseChannelCount, requestValueInt); + break; + case SEL_PROC_SAMPLE_RATE: + if (requestValueInt < 0) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->audioSampleRate, requestValueInt); + break; + case SEL_PROC_BOOST: + if ((requestValue < (FIXP_DBL)0) || + (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= _compAssign(&pSelProcInput->boost, FX_DBL2FX_SGL(requestValue)); + break; + case SEL_PROC_COMPRESS: + if ((requestValue < (FIXP_DBL)0) || + (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) + return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; + diff |= + _compAssign(&pSelProcInput->compress, FX_DBL2FX_SGL(requestValue)); + break; + default: + return DRCDEC_SELECTION_PROCESS_INVALID_PARAM; + } + + if (pDiff != NULL) { + *pDiff |= diff; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +FIXP_DBL +drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType) { + SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); + + switch (requestType) { + case SEL_PROC_LOUDNESS_NORMALIZATION_ON: + return (FIXP_DBL)pSelProcInput->loudnessNormalizationOn; + case SEL_PROC_DYNAMIC_RANGE_CONTROL_ON: + return (FIXP_DBL)pSelProcInput->dynamicRangeControlOn; + default: + return (FIXP_DBL)0; + } +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance) { + if (phInstance == NULL || *phInstance == NULL) + return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + FDKfree(*phInstance); + *phInstance = NULL; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Process(HANDLE_DRC_SELECTION_PROCESS hInstance, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + HANDLE_SEL_PROC_OUTPUT hSelProcOutput) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + DRCDEC_SELECTION* pCandidatesSelected; + DRCDEC_SELECTION* pCandidatesPotential; + + if (hInstance == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + pCandidatesSelected = &(hInstance->selectionData[0]); + pCandidatesPotential = &(hInstance->selectionData[1]); + _drcdec_selection_setNumber(pCandidatesSelected, 0); + _drcdec_selection_setNumber(pCandidatesPotential, 0); + + retVal = _generateVirtualDrcSets(&(hInstance->selProcInput), hUniDrcConfig, + hInstance->codecMode); + if (retVal) return (retVal); + + if (hInstance->selProcInput.baseChannelCount != + hUniDrcConfig->channelLayout.baseChannelCount) { + hInstance->selProcInput.baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + } + + if ((hInstance->selProcInput.targetConfigRequestType != 0) || + (hInstance->selProcInput.targetConfigRequestType == 0 && + hInstance->selProcInput.numDownmixIdRequests == 0)) { + retVal = _channelLayoutToDownmixIdMapping(&(hInstance->selProcInput), + hUniDrcConfig); + + if (_isError(retVal)) return (retVal); + } + + retVal = _drcSetPreSelection(&(hInstance->selProcInput), hUniDrcConfig, + hLoudnessInfoSet, &pCandidatesPotential, + &pCandidatesSelected, hInstance->codecMode); + if (retVal) return (retVal); + + if (hInstance->selProcInput.albumMode) { + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _selectAlbumLoudness(hLoudnessInfoSet, pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { + _swapSelection(&pCandidatesPotential, &pCandidatesSelected); + } + } + + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _drcSetRequestSelection(&(hInstance->selProcInput), hUniDrcConfig, + hLoudnessInfoSet, &pCandidatesPotential, + &pCandidatesSelected); + if (retVal) return (retVal); + + retVal = _drcSetFinalSelection(&(hInstance->selProcInput), hUniDrcConfig, + &pCandidatesPotential, &pCandidatesSelected, + hInstance->codecMode); + if (retVal) return (retVal); + + retVal = _generateOutputInfo( + &(hInstance->selProcInput), hSelProcOutput, hUniDrcConfig, + hLoudnessInfoSet, &(pCandidatesSelected->data[0]), hInstance->codecMode); + + if (_isError(retVal)) return (retVal); + + retVal = _selectDownmixMatrix(hSelProcOutput, hUniDrcConfig); + if (retVal) return (retVal); + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ +/* static functions */ +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( + HANDLE_SEL_PROC_INPUT hSelProcInput) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + /* system parameters */ + hSelProcInput->baseChannelCount = -1; + hSelProcInput->baseLayout = -1; + hSelProcInput->targetConfigRequestType = TCRT_DOWNMIX_ID; + hSelProcInput->numDownmixIdRequests = 0; + + /* loudness normalization parameters */ + hSelProcInput->albumMode = 0; + hSelProcInput->peakLimiterPresent = 0; + hSelProcInput->loudnessNormalizationOn = 1; + hSelProcInput->targetLoudness = FL2FXCONST_DBL(-24.0f / (float)(1 << 7)); + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->loudnessMeasurementMethod = MDR_DEFAULT; + hSelProcInput->loudnessMeasurementSystem = MSR_DEFAULT; + hSelProcInput->loudnessMeasurementPreProc = LPR_DEFAULT; + hSelProcInput->deviceCutOffFrequency = 500; + hSelProcInput->loudnessNormalizationGainDbMax = + (FIXP_DBL)MAXVAL_DBL; /* infinity as default */ + hSelProcInput->loudnessNormalizationGainModificationDb = (FIXP_DBL)0; + hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; + if (hSelProcInput->peakLimiterPresent == 1) { + hSelProcInput->outputPeakLevelMax = FL2FXCONST_DBL(6.0f / (float)(1 << 7)); + } + + /* dynamic range control parameters */ + hSelProcInput->dynamicRangeControlOn = 1; + + hSelProcInput->numDrcFeatureRequests = 0; + + /* other parameters */ + hSelProcInput->boost = FL2FXCONST_SGL(1.f / (float)(1 << 1)); + hSelProcInput->compress = FL2FXCONST_SGL(1.f / (float)(1 << 1)); + hSelProcInput->drcCharacteristicTarget = 0; + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( + HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; + + switch (codecMode) { + case SEL_PROC_MPEG_H_3DA: + hSelProcInput->loudnessDeviationMax = 0; + hSelProcInput->peakLimiterPresent = 1; /* peak limiter is mandatory */ + /* The peak limiter also has to catch overshoots due to user + interactivity, downmixing etc. Therefore the maximum output peak level is + reduced to 0 dB. */ + hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; + break; + case SEL_PROC_MPEG_4_AAC: + case SEL_PROC_MPEG_D_USAC: + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->peakLimiterPresent = 1; + /* A peak limiter is present at the end of the decoder, therefore we can + * allow for a maximum output peak level greater than full scale + */ + hSelProcInput->outputPeakLevelMax = + FL2FXCONST_DBL(6.0f / (float)(1 << 7)); + break; + case SEL_PROC_TEST_TIME_DOMAIN: + case SEL_PROC_TEST_QMF_DOMAIN: + case SEL_PROC_TEST_STFT_DOMAIN: + /* for testing, adapt to default settings in reference software */ + hSelProcInput->loudnessNormalizationOn = 0; + hSelProcInput->dynamicRangeControlOn = 0; + break; + case SEL_PROC_CODEC_MODE_UNDEFINED: + default: + hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; + hSelProcInput->peakLimiterPresent = 0; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + DOWNMIX_INSTRUCTIONS* pDown = NULL; + + int i; + + hSelProcInput->numDownmixIdRequests = 0; + + switch (hSelProcInput->targetConfigRequestType) { + case TCRT_DOWNMIX_ID: + if (hSelProcInput->numDownmixIdRequests == 0) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + break; + + case TCRT_TARGET_LAYOUT: + if (hSelProcInput->targetLayoutRequested == hSelProcInput->baseLayout) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + pDown = &(hUniDrcConfig->downmixInstructions[i]); + + if (hSelProcInput->targetLayoutRequested == pDown->targetLayout) { + hSelProcInput + ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = + pDown->downmixId; + hSelProcInput->numDownmixIdRequests++; + } + } + } + + if (hSelProcInput->baseLayout == -1) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + break; + + case TCRT_TARGET_CHANNEL_COUNT: + if (hSelProcInput->targetChannelCountRequested == + hSelProcInput->baseChannelCount) { + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + pDown = &(hUniDrcConfig->downmixInstructions[i]); + + if (hSelProcInput->targetChannelCountRequested == + pDown->targetChannelCount) { + hSelProcInput + ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = + pDown->downmixId; + hSelProcInput->numDownmixIdRequests++; + } + } + } + + if (hSelProcInput->baseChannelCount == -1) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + } + + if (hSelProcInput->numDownmixIdRequests == 0) { + retVal = DRCDEC_SELECTION_PROCESS_WARNING; + hSelProcInput->downmixIdRequested[0] = 0; + hSelProcInput->numDownmixIdRequests = 1; + } + + break; + + default: + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +/*******************************************/ + +/* Note: Numbering of DRC pre-selection steps according to MPEG-D Part-4 DRC + * Amd1 */ + +/* #1: DownmixId of DRC set matches the requested downmixId. + #2: Output channel layout of DRC set matches the requested layout. + #3: Channel count of DRC set matches the requested channel count. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement123( + int nRequestedDownmixId, DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + int* pMatchFound) { + int i; + *pMatchFound = 0; + + for (i = 0; i < pDrcInstructionUniDrc->downmixIdCount; i++) { + if ((pDrcInstructionUniDrc->downmixId[i] == nRequestedDownmixId) || + (pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_ANY_DOWNMIX) || + ((pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_BASE_LAYOUT) && + (pDrcInstructionUniDrc->drcSetId > 0))) { + *pMatchFound = 1; + break; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #4: The DRC set is not a "Fade-" or "Ducking-" only DRC set. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement4( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int nDynamicRangeControlOn, + int* pMatchFound) { + *pMatchFound = 0; + + if (nDynamicRangeControlOn == 1) { + if ((pDrcInstruction->drcSetEffect != EB_FADE) && + (pDrcInstruction->drcSetEffect != EB_DUCK_OTHER) && + (pDrcInstruction->drcSetEffect != EB_DUCK_SELF) && + (pDrcInstruction->drcSetEffect != 0 || pDrcInstruction->drcSetId < 0)) { + *pMatchFound = 1; + } + } else { + *pMatchFound = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #5: The number of DRC bands is supported. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement5( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRC_COEFFICIENTS_UNI_DRC* pCoef, int* pMatchFound) { + int i; + + *pMatchFound = 1; + + if (pCoef == NULL) /* check for parametricDRC */ + { + *pMatchFound = 1; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < pDrcInstructionUniDrc->nDrcChannelGroups; i++) { + int indexDrcCoeff = pDrcInstructionUniDrc->gainSetIndexForChannelGroup[i]; + int bandCount = 0; + + if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ + { + *pMatchFound = 1; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + GAIN_SET* gainSet = &(pCoef->gainSet[indexDrcCoeff]); + bandCount = gainSet->bandCount; + + if (bandCount > 4) { + *pMatchFound = 0; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #6: Independent use of DRC set is permitted.*/ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement6( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { + *pMatchFound = 0; + + if (((pDrcInstructionUniDrc->dependsOnDrcSetPresent == 0) && + (pDrcInstructionUniDrc->noIndependentUse == 0)) || + (pDrcInstructionUniDrc->dependsOnDrcSetPresent == 1)) { + *pMatchFound = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #7: DRC sets that require EQ are only permitted if EQ is supported. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement7( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { + *pMatchFound = 1; + + if (pDrcInstructionUniDrc->requiresEq) { + /* EQ is not supported */ + *pMatchFound = 0; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static void _setSelectionDataInfo( + DRCDEC_SELECTION_DATA* pData, FIXP_DBL loudness, /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDb, /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDbMax, /* e = 7 */ + FIXP_DBL loudnessDeviationMax, /* e = 7 */ + FIXP_DBL signalPeakLevel, /* e = 7 */ + FIXP_DBL outputPeakLevelMax, /* e = 7 */ + int applyAdjustment) { + FIXP_DBL adjustment = 0; /* e = 8 */ + + /* use e = 8 for all function parameters to prevent overflow */ + loudness >>= 1; + loudnessNormalizationGainDb >>= 1; + loudnessNormalizationGainDbMax >>= 1; + loudnessDeviationMax >>= 1; + signalPeakLevel >>= 1; + outputPeakLevelMax >>= 1; + + if (applyAdjustment) { + adjustment = + fMax((FIXP_DBL)0, signalPeakLevel + loudnessNormalizationGainDb - + outputPeakLevelMax); + adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); + } + + pData->loudnessNormalizationGainDbAdjusted = fMin( + loudnessNormalizationGainDb - adjustment, loudnessNormalizationGainDbMax); + pData->outputLoudness = loudness + pData->loudnessNormalizationGainDbAdjusted; + pData->outputPeakLevel = + signalPeakLevel + pData->loudnessNormalizationGainDbAdjusted; + + /* shift back to e = 7 using saturation */ + pData->loudnessNormalizationGainDbAdjusted = SATURATE_LEFT_SHIFT( + pData->loudnessNormalizationGainDbAdjusted, 1, DFRACT_BITS); + pData->outputLoudness = + SATURATE_LEFT_SHIFT(pData->outputLoudness, 1, DFRACT_BITS); + pData->outputPeakLevel = + SATURATE_LEFT_SHIFT(pData->outputPeakLevel, 1, DFRACT_BITS); +} + +static int _targetLoudnessInRange( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, FIXP_DBL targetLoudness) { + int retVal = 0; + + FIXP_DBL drcSetTargetLoudnessValueUpper = + ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueUpper) + << (DFRACT_BITS - 1 - 7); + FIXP_DBL drcSetTargetLoudnessValueLower = + ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueLower) + << (DFRACT_BITS - 1 - 7); + + if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && + drcSetTargetLoudnessValueUpper >= targetLoudness && + drcSetTargetLoudnessValueLower < targetLoudness) { + retVal = 1; + } + + return retVal; +} + +/* #8: The range of the target loudness specified for a DRC set has to include + * the requested decoder target loudness. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement8( + SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int explicitPeakInformationPresent; + FIXP_DBL signalPeakLevel; + int addToCandidate = 0; + + FIXP_DBL loudnessNormalizationGainDb; + FIXP_DBL loudness; + + FIXP_DBL loudnessDeviationMax = + ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) << (DFRACT_BITS - 1 - 7); + ; + + if (hSelProcInput->loudnessNormalizationOn) { + retVal = _getLoudness(hLoudnessInfoSet, hSelProcInput->albumMode, + hSelProcInput->loudnessMeasurementMethod, + hSelProcInput->loudnessMeasurementSystem, + hSelProcInput->targetLoudness, + pDrcInstructionUniDrc->drcSetId, + hSelProcInput->downmixIdRequested[downmixIdIndex], + &loudnessNormalizationGainDb, &loudness); + if (retVal) return (retVal); + } else { + loudnessNormalizationGainDb = (FIXP_DBL)0; + loudness = UNDEFINED_LOUDNESS_VALUE; + } + + retVal = _getSignalPeakLevel( + hSelProcInput, hUniDrcConfig, hLoudnessInfoSet, pDrcInstructionUniDrc, + hSelProcInput->downmixIdRequested[downmixIdIndex], + &explicitPeakInformationPresent, &signalPeakLevel, codecMode + + ); + if (retVal) return (retVal); + + if (hSelProcInput->dynamicRangeControlOn) { + if (explicitPeakInformationPresent == 0) { + if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && + ((hSelProcInput->loudnessNormalizationOn && + _targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) || + !hSelProcInput->loudnessNormalizationOn)) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesSelected); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 0); + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = + 1; /* signal pre-selection step dealing with drcSetTargetLoudness */ + + if (hSelProcInput->loudnessNormalizationOn) { + pData->outputPeakLevel = + hSelProcInput->targetLoudness - + (((FIXP_DBL)pData->pInst->drcSetTargetLoudnessValueUpper) + << (DFRACT_BITS - 1 - 7)); + } else { + pData->outputPeakLevel = (FIXP_DBL)0; + } + } else { + if ((!hSelProcInput->loudnessNormalizationOn) || + (!pDrcInstructionUniDrc->drcSetTargetLoudnessPresent) || + (hSelProcInput->loudnessNormalizationOn && + _targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness))) { + addToCandidate = 1; + } + } + } else { + addToCandidate = 1; + } + + if (addToCandidate) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesPotential); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 0); + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = 0; + } + } else { + if (pDrcInstructionUniDrc->drcSetId < 0) { + DRCDEC_SELECTION_DATA* pData = + _drcdec_selection_addNew(pCandidatesSelected); + if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, + hSelProcInput->loudnessNormalizationGainDbMax, + loudnessDeviationMax, signalPeakLevel, + hSelProcInput->outputPeakLevelMax, 1); + + pData->downmixIdRequestIndex = downmixIdIndex; + pData->pInst = pDrcInstructionUniDrc; + pData->selectionFlag = 0; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/* #9: Clipping is minimized. */ +static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement9( + SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->outputPeakLevel <= hSelProcInput->outputPeakLevelMax) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelectionSingleInstruction( + SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int matchFound = 0; + DRC_COEFFICIENTS_UNI_DRC* pCoef = + selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + + retVal = _preSelectionRequirement123( + hSelProcInput->downmixIdRequested[downmixIdIndex], pDrcInstructionUniDrc, + &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement4(pDrcInstructionUniDrc, + hSelProcInput->dynamicRangeControlOn, + &matchFound); + + if (!retVal && matchFound) + retVal = + _preSelectionRequirement5(pDrcInstructionUniDrc, pCoef, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement6(pDrcInstructionUniDrc, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement7(pDrcInstructionUniDrc, &matchFound); + + if (!retVal && matchFound) + retVal = _preSelectionRequirement8( + hSelProcInput, downmixIdIndex, hUniDrcConfig, hLoudnessInfoSet, + pDrcInstructionUniDrc, pCandidatesPotential, pCandidatesSelected, + codecMode); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetSelectionAddCandidates( + SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int nHitCount = 0; + int i; + + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) { + nHitCount++; + } + } + + if (nHitCount != 0) { + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, + hSelProcInput->targetLoudness)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } else { + FIXP_DBL lowestPeakLevel = MAXVAL_DBL; /* e = 7 */ + FIXP_DBL peakLevel = 0; /* e = 7 */ + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel < lowestPeakLevel) { + lowestPeakLevel = peakLevel; + } + } + + /* add all with lowest peak level or max 1dB above */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + FIXP_DBL loudnessDeviationMax = + ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) + << (DFRACT_BITS - 1 - 7); /* e = 7 */ + + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel == lowestPeakLevel || + peakLevel <= + lowestPeakLevel + FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + FIXP_DBL adjustment = + fMax((FIXP_DBL)0, peakLevel - hSelProcInput->outputPeakLevelMax); + adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); + + pCandidate->loudnessNormalizationGainDbAdjusted -= adjustment; + pCandidate->outputPeakLevel -= adjustment; + pCandidate->outputLoudness -= adjustment; + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _dependentDrcInstruction( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_INSTRUCTIONS_UNI_DRC* pInst, + DRC_INSTRUCTIONS_UNI_DRC** ppDrcInstructionsDependent) { + int i; + DRC_INSTRUCTIONS_UNI_DRC* pDependentDrc = NULL; + + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + pDependentDrc = + (DRC_INSTRUCTIONS_UNI_DRC*)&(hUniDrcConfig->drcInstructionsUniDrc[i]); + + if (pDependentDrc->drcSetId == pInst->dependsOnDrcSet) { + break; + } + } + + if (i == hUniDrcConfig->drcInstructionsUniDrcCount) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (pDependentDrc->dependsOnDrcSetPresent == 1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + *ppDrcInstructionsDependent = pDependentDrc; + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcSetEffectNone( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if ((pCandidate->pInst->drcSetEffect & 0xff) == 0) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleEffectType( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_EFFECT_TYPE_REQUEST effectType, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionsDependent; + + if (effectType == DETR_NONE) { + retVal = _selectDrcSetEffectNone(hUniDrcConfig, pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } else { + int effectBitPosition = 1 << (effectType - 1); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + if (!pInst->dependsOnDrcSetPresent) { + if ((pInst->drcSetEffect & effectBitPosition)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } else { + retVal = _dependentDrcInstruction(hUniDrcConfig, pInst, + &pDrcInstructionsDependent); + if (retVal) return (retVal); + + if (((pInst->drcSetEffect & effectBitPosition)) || + ((pDrcInstructionsDependent->drcSetEffect & effectBitPosition))) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectEffectTypeFeature( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_FEATURE_REQUEST drcFeatureRequest, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + int desiredEffectTypeFound = 0; + + for (i = 0; i < drcFeatureRequest.drcEffectType.numRequestsDesired; i++) { + retVal = _selectSingleEffectType( + hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], + *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + desiredEffectTypeFound = 1; + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + } + + if (!desiredEffectTypeFound) { + for (i = drcFeatureRequest.drcEffectType.numRequestsDesired; + i < drcFeatureRequest.drcEffectType.numRequests; i++) { + retVal = _selectSingleEffectType( + hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], + *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + break; + } + } + } + + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDynamicRange( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRC_FEATURE_REQUEST drcFeatureRequest, UCHAR* pDownmixIdRequested, + int albumMode, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + int peakToAveragePresent; + FIXP_DBL peakToAverage; + + FIXP_DBL minVal = MAXVAL_DBL; + FIXP_DBL val = 0; + + int numSelectedCandidates = _drcdec_selection_getNumber(ppCandidatesSelected); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + retVal = _dynamicRangeMeasurement( + hLoudnessInfoSet, pCandidate->pInst, + pDownmixIdRequested[pCandidate->downmixIdRequestIndex], + drcFeatureRequest.dynamicRange.measurementRequestType, albumMode, + &peakToAveragePresent, &peakToAverage); + if (retVal) return (retVal); + + if (peakToAveragePresent) { + if (!drcFeatureRequest.dynamicRange.requestedIsRange) { + val = fAbs(drcFeatureRequest.dynamicRange.requestValue - peakToAverage); + + if (minVal > val) { + minVal = val; + + _drcdec_selection_setNumber(ppCandidatesSelected, + numSelectedCandidates); + } + if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + if ((peakToAverage >= drcFeatureRequest.dynamicRange.requestValueMin) && + (peakToAverage <= drcFeatureRequest.dynamicRange.requestValueMax)) { + if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleDrcCharacteristic( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int requestedDrcCharacteristic, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + int i, j, b; + int hit = 0; + + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + GAIN_SET* pGainSet = NULL; + + if (requestedDrcCharacteristic < 1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + pCoef = selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + + if (pCoef == NULL) /* check for parametricDRC */ + { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(*ppCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + hit = 0; + + for (j = 0; j < pInst->nDrcChannelGroups; j++) { + int bandCount = 0; + int indexDrcCoeff = pInst->gainSetIndexForChannelGroup[j]; + + if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ + { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + pGainSet = &(pCoef->gainSet[indexDrcCoeff]); + bandCount = pGainSet->bandCount; + + for (b = 0; b < bandCount; b++) { + if ((pGainSet->drcCharacteristic[b].isCICP) && + (pGainSet->drcCharacteristic[b].cicpIndex == + requestedDrcCharacteristic)) { + hit = 1; + break; + } + } + + if (hit) break; + } + + if (hit) { + if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcCharacteristic( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int drcCharacteristicRequested, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + const int secondTry[12] = {0, 2, 3, 4, 5, 6, 5, 9, 10, 7, 8, 10}; + + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, drcCharacteristicRequested, ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return (retVal); + + if ((drcCharacteristicRequested <= 11) && + (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0)) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, secondTry[drcCharacteristicRequested], + ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + if ((drcCharacteristicRequested >= 2) && + (drcCharacteristicRequested <= 5)) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, drcCharacteristicRequested - 1, ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return (retVal); + } else if (drcCharacteristicRequested == 11) { + retVal = _selectSingleDrcCharacteristic( + hUniDrcConfig, 9, ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + } + + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->outputPeakLevel <= FIXP_DBL(0)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_downmixId( + HANDLE_SEL_PROC_INPUT hSelProcInput, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + int i, j; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(*ppCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + for (j = 0; j < pInst->downmixIdCount; j++) { + if (DOWNMIX_ID_BASE_LAYOUT != pInst->downmixId[j] && + DOWNMIX_ID_ANY_DOWNMIX != pInst->downmixId[j] && + hSelProcInput + ->downmixIdRequested[pCandidate->downmixIdRequestIndex] == + pInst->downmixId[j]) { + if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static int _crossSum(int value) { + int sum = 0; + + while (value != 0) { + if ((value & 1) == 1) { + sum++; + } + + value >>= 1; + } + + return sum; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_effectTypes( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + int minNumEffects = 1000; + int numEffects = 0; + int effects = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + effects = pInst->drcSetEffect; + effects &= 0xffff ^ (EB_GENERAL_COMPR); + numEffects = _crossSum(effects); + + if (numEffects < minNumEffects) { + minNumEffects = numEffects; + } + } + + /* add all with minimum number of effects */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pInst = pCandidate->pInst; + + effects = pInst->drcSetEffect; + effects &= 0xffff ^ (EB_GENERAL_COMPR); + numEffects = _crossSum(effects); + + if (numEffects == minNumEffects) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectSmallestTargetLoudnessValueUpper( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + SCHAR minVal = 0x7F; + SCHAR val = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; + + if (val < minVal) { + minVal = val; + } + } + + /* add all with same smallest drcSetTargetLoudnessValueUpper */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; + + if (val == minVal) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_targetLoudness( + FIXP_DBL targetLoudness, DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (pCandidate->selectionFlag == 0) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { + retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; + + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + pDrcInstructionUniDrc = pCandidate->pInst; + + if (_targetLoudnessInRange(pDrcInstructionUniDrc, targetLoudness)) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { + _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); + + retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, + pCandidatesSelected); + if (retVal) return (retVal); + } + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValueLargest( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + FIXP_DBL largestPeakLevel = MINVAL_DBL; + FIXP_DBL peakLevel = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel > largestPeakLevel) { + largestPeakLevel = peakLevel; + } + } + + /* add all with same largest peak level */ + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + peakLevel = pCandidate->outputPeakLevel; + + if (peakLevel == largestPeakLevel) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_drcSetId( + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i; + int largestId = -1000; + int id = 0; + DRCDEC_SELECTION_DATA* pCandidate = NULL; + DRCDEC_SELECTION_DATA* pCandidateSelected = NULL; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + id = pCandidate->pInst->drcSetId; + + if (id > largestId) { + largestId = id; + pCandidateSelected = pCandidate; + } + } + + if (pCandidateSelected != NULL) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidateSelected) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 1) { + _swapSelection(ppCandidatesPotential, ppCandidatesSelected); + /* finished */ + } else /* > 1 */ + { + retVal = _drcSetFinalSelection_peakValue0(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_downmixId( + hSelProcInput, ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_effectTypes(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_targetLoudness( + hSelProcInput->targetLoudness, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_peakValueLargest(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + retVal = _drcSetFinalSelection_drcSetId(*ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + } + } + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + SEL_PROC_CODEC_MODE codecMode) { + int i; + int nMixes = hUniDrcConfig->downmixInstructionsCount + 1; + int index = hUniDrcConfig->drcInstructionsUniDrcCount; + int indexVirtual = -1; + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = + &(hUniDrcConfig->drcInstructionsUniDrc[index]); + + if (codecMode == SEL_PROC_MPEG_H_3DA) { + nMixes = 1; + } + + if ((index + nMixes) > (12 + 1 + 6)) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + + pDrcInstruction->drcSetId = indexVirtual; + index++; + indexVirtual--; + pDrcInstruction->downmixIdCount = 1; + + if ((codecMode == SEL_PROC_MPEG_H_3DA) && + (hSelProcInput->numDownmixIdRequests)) { + pDrcInstruction->downmixId[0] = hSelProcInput->downmixIdRequested[0]; + } else { + pDrcInstruction->downmixId[0] = DOWNMIX_ID_BASE_LAYOUT; + } + + for (i = 1; i < nMixes; i++) { + pDrcInstruction = &(hUniDrcConfig->drcInstructionsUniDrc[index]); + FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); + pDrcInstruction->drcSetId = indexVirtual; + pDrcInstruction->downmixId[0] = + hUniDrcConfig->downmixInstructions[i - 1].downmixId; + pDrcInstruction->downmixIdCount = 1; + index++; + indexVirtual--; + } + + hUniDrcConfig->drcInstructionsCountInclVirtual = + hUniDrcConfig->drcInstructionsUniDrcCount + nMixes; + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + int i, j; + int hasDependend = 0; + int hasFading = 0; + int hasDucking = 0; + int selectedDrcSetIds; + int selectedDownmixIds; + FIXP_DBL mixingLevel = 0; + int albumMode = hSelProcInput->albumMode; + UCHAR* pDownmixIdRequested = hSelProcInput->downmixIdRequested; + FIXP_SGL boost = hSelProcInput->boost; + FIXP_SGL compress = hSelProcInput->compress; + + hSelProcOutput->numSelectedDrcSets = 1; + hSelProcOutput->selectedDrcSetIds[0] = pSelectionData->pInst->drcSetId; + hSelProcOutput->selectedDownmixIds[0] = + pSelectionData->pInst->drcApplyToDownmix == 1 + ? pSelectionData->pInst->downmixId[0] + : 0; + hSelProcOutput->loudnessNormalizationGainDb = + pSelectionData->loudnessNormalizationGainDbAdjusted + + hSelProcInput->loudnessNormalizationGainModificationDb; + hSelProcOutput->outputPeakLevelDb = pSelectionData->outputPeakLevel; + + hSelProcOutput->boost = boost; + hSelProcOutput->compress = compress; + hSelProcOutput->baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->activeDownmixId = + pDownmixIdRequested[pSelectionData->downmixIdRequestIndex]; + + _getMixingLevel(hLoudnessInfoSet, *pDownmixIdRequested, + hSelProcOutput->selectedDrcSetIds[0], albumMode, + &mixingLevel); + hSelProcOutput->mixingLevel = mixingLevel; + + /*dependent*/ + if (pSelectionData->pInst->dependsOnDrcSetPresent) { + int dependsOnDrcSetID = pSelectionData->pInst->dependsOnDrcSet; + + for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { + if (hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId == + dependsOnDrcSetID) { + hSelProcOutput->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + hSelProcOutput->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 + ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] + : 0; + hSelProcOutput->numSelectedDrcSets++; + hasDependend = 1; + break; + } + } + } + + /* fading */ + if (hSelProcInput->albumMode == 0) { + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + + if (pInst->drcSetEffect & EB_FADE) { + if (pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) { + hSelProcOutput->numSelectedDrcSets = hasDependend + 1; + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 + ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] + : 0; + hSelProcOutput->numSelectedDrcSets++; + hasFading = 1; + + } else { + retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + /* ducking */ + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (j = 0; j < pInst->downmixIdCount; j++) { + if (pInst->downmixId[j] == hSelProcOutput->activeDownmixId) { + hSelProcOutput->numSelectedDrcSets = + hasDependend + 1; /* ducking overrides fading */ + + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + /* force ducking DRC set to be processed on base layout */ + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; + hSelProcOutput->numSelectedDrcSets++; + hasDucking = 1; + } + } + } + } + + /* repeat for DOWNMIX_ID_BASE_LAYOUT if no ducking found*/ + + if (!hasDucking) { + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + DRC_INSTRUCTIONS_UNI_DRC* pInst = + &(hUniDrcConfig->drcInstructionsUniDrc[i]); + + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (j = 0; j < pInst->downmixIdCount; j++) { + if (pInst->downmixId[j] == DOWNMIX_ID_BASE_LAYOUT) { + hSelProcOutput->numSelectedDrcSets = hasDependend + hasFading + 1; + hSelProcOutput + ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = + hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; + /* force ducking DRC set to be processed on base layout */ + hSelProcOutput + ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; + hSelProcOutput->numSelectedDrcSets++; + } + } + } + } + } + + if (hSelProcOutput->numSelectedDrcSets > 3) { + /* maximum permitted number of applied DRC sets is 3, see section 6.3.5 of + * ISO/IEC 23003-4 */ + hSelProcOutput->numSelectedDrcSets = 0; + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + /* sorting: Ducking/Fading -> Dependent -> Selected */ + if (hSelProcOutput->numSelectedDrcSets == 3) { + selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; + selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; + hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[2]; + hSelProcOutput->selectedDownmixIds[0] = + hSelProcOutput->selectedDownmixIds[2]; + hSelProcOutput->selectedDrcSetIds[2] = selectedDrcSetIds; + hSelProcOutput->selectedDownmixIds[2] = selectedDownmixIds; + } else if (hSelProcOutput->numSelectedDrcSets == 2) { + selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; + selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; + hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[1]; + hSelProcOutput->selectedDownmixIds[0] = + hSelProcOutput->selectedDownmixIds[1]; + hSelProcOutput->selectedDrcSetIds[1] = selectedDrcSetIds; + hSelProcOutput->selectedDownmixIds[1] = selectedDownmixIds; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( + HANDLE_SEL_PROC_OUTPUT hSelProcOutput, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { + int i; + hSelProcOutput->baseChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetChannelCount = + hUniDrcConfig->channelLayout.baseChannelCount; + hSelProcOutput->targetLayout = -1; + hSelProcOutput->downmixMatrixPresent = 0; + + if (hSelProcOutput->activeDownmixId != 0) { + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + DOWNMIX_INSTRUCTIONS* pDown = &(hUniDrcConfig->downmixInstructions[i]); + + if (hSelProcOutput->activeDownmixId == pDown->downmixId) { + hSelProcOutput->targetChannelCount = pDown->targetChannelCount; + hSelProcOutput->targetLayout = pDown->targetLayout; + + if (pDown->downmixCoefficientsPresent) { + int j, k; + FIXP_DBL downmixOffset = getDownmixOffset( + pDown, hSelProcOutput->baseChannelCount); /* e = 1 */ + + for (j = 0; j < hSelProcOutput->baseChannelCount; j++) { + for (k = 0; k < hSelProcOutput->targetChannelCount; k++) { + hSelProcOutput->downmixMatrix[j][k] = + fMultDiv2( + downmixOffset, + pDown->downmixCoefficient[j + k * hSelProcOutput + ->baseChannelCount]) + << 2; + } + } + + hSelProcOutput->downmixMatrixPresent = 1; + } + break; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int i, j; + + for (i = 0; i < hSelProcInput->numDownmixIdRequests; i++) { + for (j = 0; j < hUniDrcConfig->drcInstructionsCountInclVirtual; j++) { + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = + &(hUniDrcConfig->drcInstructionsUniDrc[j]); + retVal = _drcSetPreSelectionSingleInstruction( + hSelProcInput, i, hUniDrcConfig, hLoudnessInfoSet, pDrcInstruction, + *ppCandidatesPotential, *ppCandidatesSelected, codecMode); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + + retVal = _preSelectionRequirement9(hSelProcInput, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + retVal = _drcSetSelectionAddCandidates( + hSelProcInput, *ppCandidatesPotential, *ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( + SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION_PROCESS_RETURN retVal; + int i; + + if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { + retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (hSelProcInput->dynamicRangeControlOn) { + if (hSelProcInput->numDrcFeatureRequests == 0) { + retVal = _selectDrcSetEffectNone(hUniDrcConfig, *ppCandidatesPotential, + *ppCandidatesSelected); + if (retVal) return (retVal); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { + DRC_FEATURE_REQUEST fallbackRequest; + fallbackRequest.drcEffectType.numRequests = 5; + fallbackRequest.drcEffectType.numRequestsDesired = 5; + fallbackRequest.drcEffectType.request[0] = DETR_GENERAL_COMPR; + fallbackRequest.drcEffectType.request[1] = DETR_NIGHT; + fallbackRequest.drcEffectType.request[2] = DETR_NOISY; + fallbackRequest.drcEffectType.request[3] = DETR_LIMITED; + fallbackRequest.drcEffectType.request[4] = DETR_LOWLEVEL; + + retVal = _selectEffectTypeFeature(hUniDrcConfig, fallbackRequest, + ppCandidatesPotential, + ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } else { + for (i = 0; i < hSelProcInput->numDrcFeatureRequests; i++) { + if (hSelProcInput->drcFeatureRequestType[i] == DFRT_EFFECT_TYPE) { + retVal = _selectEffectTypeFeature( + hUniDrcConfig, hSelProcInput->drcFeatureRequest[i], + ppCandidatesPotential, ppCandidatesSelected); + + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + else if (hSelProcInput->drcFeatureRequestType[i] == + DFRT_DYNAMIC_RANGE) { + retVal = _selectDynamicRange( + hUniDrcConfig, hLoudnessInfoSet, + hSelProcInput->drcFeatureRequest[i], + hSelProcInput->downmixIdRequested, hSelProcInput->albumMode, + *ppCandidatesPotential, *ppCandidatesSelected); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else if (hSelProcInput->drcFeatureRequestType[i] == + DFRT_DRC_CHARACTERISTIC) { + retVal = _selectDrcCharacteristic( + hUniDrcConfig, + hSelProcInput->drcFeatureRequest[i].drcCharacteristic, + ppCandidatesPotential, ppCandidatesSelected); + + if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { + _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); + } + if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ +static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + UCHAR downmixIdRequested, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int albumMode, int* pPeakToAveragePresent, FIXP_DBL* pPeakToAverage) { + int i; + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + int drcSetId = fMax(0, pInst->drcSetId); + + *pPeakToAveragePresent = 0; + + if (albumMode) { + for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCount; i++) { + LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfoAlbum[i]); + + if (drcSetId == pLoudnessInfo->drcSetId) { + if (downmixIdRequested == pLoudnessInfo->downmixId) { + retVal = _extractLoudnessPeakToAverageValue( + pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, + pPeakToAverage); + if (retVal) return (retVal); + } + } + } + } + + if (*pPeakToAveragePresent == 0) { + for (i = 0; i < hLoudnessInfoSet->loudnessInfoCount; i++) { + LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfo[i]); + + if (drcSetId == pLoudnessInfo->drcSetId) { + if (downmixIdRequested == pLoudnessInfo->downmixId) { + retVal = _extractLoudnessPeakToAverageValue( + pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, + pPeakToAverage); + if (retVal) return (retVal); + } + } + } + } + + return retVal; +} +/*******************************************/ + +static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( + DRCDEC_SELECTION* pSelection) { + if (pSelection->numData < (12 + 1 + 6)) { + DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); + FDKmemset(pData, 0, sizeof(DRCDEC_SELECTION_DATA)); + pSelection->numData++; + + return pData; + } else { + return NULL; + } +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_add( + DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn) { + if (pSelection->numData < (12 + 1 + 6)) { + DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); + FDKmemcpy(pData, pDataIn, sizeof(DRCDEC_SELECTION_DATA)); + pSelection->numData++; + return pData; + } else { + return NULL; + } +} + +static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection) { + return pSelection->numData = 0; +} + +static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection) { + return pSelection->numData; +} + +static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num) { + if (num >= 0 && num < pSelection->numData) { + return pSelection->numData = num; + } else { + return pSelection->numData; + } +} + +static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( + DRCDEC_SELECTION* pSelection, int at) { + if (at >= 0 && at < (12 + 1 + 6)) { + return &(pSelection->data[at]); + } else { + return NULL; + } +} + +static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; + *ppCandidatesPotential = *ppCandidatesSelected; + *ppCandidatesSelected = pTmp; + _drcdec_selection_clear(*ppCandidatesSelected); + return 0; +} + +static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, + DRCDEC_SELECTION** ppCandidatesSelected) { + DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; + *ppCandidatesPotential = *ppCandidatesSelected; + *ppCandidatesSelected = pTmp; + return 0; +} + +/*******************************************/ + +static LOUDNESS_INFO* _getLoudnessInfoStructure( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode) { + int i, j; + int count; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + for (j = 0; j < pLoudnessInfo[i].measurementCount; j++) { + if ((pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 1) || + (pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 2)) { + return &pLoudnessInfo[i]; + } + } + } + } + + return NULL; +} + +static LOUDNESS_INFO* _getApplicableLoudnessInfoStructure( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, + int downmixIdRequested, int albumMode) { + LOUDNESS_INFO* pLoudnessInfo = NULL; + + /* default value */ + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, + downmixIdRequested, albumMode); + + /* fallback values */ + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, + downmixIdRequested, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0, + downmixIdRequested, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0x7F, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0, albumMode); + } + + if (pLoudnessInfo == NULL) { + pLoudnessInfo = + _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0, albumMode); + } + + return pLoudnessInfo; +} + +/*******************************************/ + +typedef struct { + FIXP_DBL value; + int order; +} VALUE_ORDER; + +void _initValueOrder(VALUE_ORDER* pValue) { + pValue->value = (FIXP_DBL)0; + pValue->order = -1; +} + +enum { + MS_BONUS0 = 0, + MS_BONUS1770, + MS_BONUSUSER, + MS_BONUSEXPERT, + MS_RESA, + MS_RESB, + MS_RESC, + MS_RESD, + MS_RESE, + MS_PROGRAMLOUDNESS, + MS_PEAKLOUDNESS +}; + +static DRCDEC_SELECTION_PROCESS_RETURN _getMethodValue( + VALUE_ORDER* pValueOrder, FIXP_DBL value, int measurementSystem, + int measurementSystemRequested) { + const int rows = 11; + const int columns = 12; + const int pOrdering[rows][columns] = { + {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* default = bonus1770 */ + {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* bonus1770 */ + {0, 0, 1, 0, 8, 5, 0, 2, 3, 4, 6, 7}, /* bonusUser */ + {0, 0, 3, 0, 1, 8, 0, 4, 5, 6, 7, 2}, /* bonusExpert */ + {0, 0, 5, 0, 1, 3, 0, 8, 6, 7, 4, 2}, /* ResA */ + {0, 0, 5, 0, 1, 3, 0, 6, 8, 7, 4, 2}, /* ResB */ + {0, 0, 5, 0, 1, 3, 0, 6, 7, 8, 4, 2}, /* ResC */ + {0, 0, 3, 0, 1, 7, 0, 4, 5, 6, 8, 2}, /* ResD */ + {0, 0, 1, 0, 7, 5, 0, 2, 3, 4, 6, 8}, /* ResE */ + {0, 0, 1, 0, 0, 0, 0, 2, 3, 4, 0, 0}, /* ProgramLoudness */ + {0, 7, 0, 0, 0, 0, 6, 5, 4, 3, 2, 1} /* PeakLoudness */ + }; + + if (measurementSystemRequested < 0 || measurementSystemRequested >= rows || + measurementSystem < 0 || measurementSystem >= columns) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + if (pOrdering[measurementSystemRequested][measurementSystem] > + pValueOrder->order) { + pValueOrder->order = + pOrdering[measurementSystemRequested][measurementSystem]; + pValueOrder->value = value; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, + METHOD_DEFINITION_REQUEST measurementMethodRequested, + MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, + FIXP_DBL targetLoudness, /* e = 7 */ + int drcSetId, int downmixIdRequested, + FIXP_DBL* pLoudnessNormalizationGain, /* e = 7 */ + FIXP_DBL* pLoudness) /* e = 7 */ +{ + int index; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + VALUE_ORDER valueOrder; + + /* map MDR_DEFAULT to MDR_PROGRAM_LOUDNESS */ + METHOD_DEFINITION_REQUEST requestedMethodDefinition = + measurementMethodRequested < MDR_ANCHOR_LOUDNESS ? MDR_PROGRAM_LOUDNESS + : MDR_ANCHOR_LOUDNESS; + + if (measurementMethodRequested > MDR_ANCHOR_LOUDNESS) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + + _initValueOrder(&valueOrder); + + *pLoudness = UNDEFINED_LOUDNESS_VALUE; + *pLoudnessNormalizationGain = (FIXP_DBL)0; + + if (drcSetId < 0) { + drcSetId = 0; + } + + pLoudnessInfo = _getApplicableLoudnessInfoStructure( + hLoudnessInfoSet, drcSetId, downmixIdRequested, albumMode); + + if (albumMode && (pLoudnessInfo == NULL)) { + pLoudnessInfo = _getApplicableLoudnessInfoStructure( + hLoudnessInfoSet, drcSetId, downmixIdRequested, 0); + } + + if (pLoudnessInfo == NULL) { + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + index = -1; + + do { + index = _findMethodDefinition(pLoudnessInfo, requestedMethodDefinition, + index + 1); + + if (index >= 0) { + _getMethodValue( + &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, + pLoudnessInfo->loudnessMeasurement[index].measurementSystem, + measurementSystemRequested); + } + } while (index >= 0); + + /* repeat with other method definition */ + if (valueOrder.order == -1) { + index = -1; + + do { + index = _findMethodDefinition( + pLoudnessInfo, + requestedMethodDefinition == MDR_PROGRAM_LOUDNESS + ? MDR_ANCHOR_LOUDNESS + : MDR_PROGRAM_LOUDNESS, + index + 1); + + if (index >= 0) { + _getMethodValue( + &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, + pLoudnessInfo->loudnessMeasurement[index].measurementSystem, + measurementSystemRequested); + } + } while (index >= 0); + } + + if (valueOrder.order == -1) { + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } else { + *pLoudnessNormalizationGain = targetLoudness - valueOrder.value; + *pLoudness = valueOrder.value; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static int _truePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + int drcSetId, int downmixId, int albumMode) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].truePeakLevelPresent) return 1; + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getTruePeakLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode, FIXP_DBL* pTruePeakLevel) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].truePeakLevelPresent) { + *pTruePeakLevel = pLoudnessInfo[i].truePeakLevel; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _samplePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + int drcSetId, int downmixId, + int albumMode) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].samplePeakLevelPresent) return 1; + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getSamplePeakLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, + int albumMode, FIXP_DBL* pSamplePeakLevel /* e = 7 */ +) { + int i; + int count; + LOUDNESS_INFO* pLoudnessInfo = NULL; + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((pLoudnessInfo[i].drcSetId == drcSetId) && + (pLoudnessInfo[i].downmixId == downmixId)) { + if (pLoudnessInfo[i].samplePeakLevelPresent) { + *pSamplePeakLevel = pLoudnessInfo[i].samplePeakLevel; + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _limiterPeakTargetIsPresent( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId) { + int i; + + if (pDrcInstruction->limiterPeakTargetPresent) { + if ((pDrcInstruction->downmixId[0] == downmixId) || + (pDrcInstruction->downmixId[0] == 0x7F)) { + return 1; + } + + for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { + if (pDrcInstruction->downmixId[i] == downmixId) { + return 1; + } + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getLimiterPeakTarget( + DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId, + FIXP_DBL* pLimiterPeakTarget) { + int i; + + if (pDrcInstruction->limiterPeakTargetPresent) { + if ((pDrcInstruction->downmixId[0] == downmixId) || + (pDrcInstruction->downmixId[0] == 0x7F)) { + *pLimiterPeakTarget = + ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + + for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { + if (pDrcInstruction->downmixId[i] == downmixId) { + *pLimiterPeakTarget = + ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); + return DRCDEC_SELECTION_PROCESS_NO_ERROR; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NOT_OK; +} + +static int _downmixCoefficientsArePresent(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + int downmixId, int* pIndex) { + int i; + *pIndex = -1; + + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + if (hUniDrcConfig->downmixInstructions[i].downmixId == downmixId) { + if (hUniDrcConfig->downmixInstructions[i].downmixCoefficientsPresent) { + *pIndex = i; + return 1; + } + } + } + + return 0; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( + HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, + int downmixIdRequested, int* explicitPeakInformationPresent, + FIXP_DBL* signalPeakLevelOut, /* e = 7 */ + SEL_PROC_CODEC_MODE codecMode + +) { + DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; + + int albumMode = hSelProcInput->albumMode; + + FIXP_DBL signalPeakLevelTmp = (FIXP_DBL)0; + FIXP_DBL signalPeakLevel = FIXP_DBL(0); + + int dmxId = downmixIdRequested; + + int drcSetId = pInst->drcSetId; + + if (drcSetId < 0) { + drcSetId = 0; + } + + *explicitPeakInformationPresent = 1; + + if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, + albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, + &signalPeakLevel); + if (retVal) return (retVal); + } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, dmxId)) { + retVal = _getLimiterPeakTarget(pInst, drcSetId, dmxId, &signalPeakLevel); + if (retVal) return (retVal); + } else if (dmxId != 0) { + int downmixInstructionIndex = 0; + FIXP_DBL downmixPeakLevelDB = 0; + + *explicitPeakInformationPresent = 0; + + signalPeakLevelTmp = FIXP_DBL(0); + + if (_downmixCoefficientsArePresent(hUniDrcConfig, dmxId, + &downmixInstructionIndex)) { + FIXP_DBL dB_m; + int dB_e; + FIXP_DBL coeff; + FIXP_DBL sum, maxSum; /* e = 7, so it is possible to sum up up to 32 + downmix coefficients (with e = 2) */ + int i, j; + DOWNMIX_INSTRUCTIONS* pDown = + &(hUniDrcConfig->downmixInstructions[downmixInstructionIndex]); + FIXP_DBL downmixOffset = getDownmixOffset( + pDown, hUniDrcConfig->channelLayout.baseChannelCount); /* e = 1 */ + maxSum = (FIXP_DBL)0; + + for (i = 0; i < pDown->targetChannelCount; i++) { + sum = (FIXP_DBL)0; + for (j = 0; j < hUniDrcConfig->channelLayout.baseChannelCount; j++) { + coeff = pDown->downmixCoefficient[j + i * hUniDrcConfig->channelLayout + .baseChannelCount]; + sum += coeff >> 5; + } + if (maxSum < sum) maxSum = sum; + } + + maxSum = fMultDiv2(maxSum, downmixOffset) << 2; + + if (maxSum == FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + downmixPeakLevelDB = (FIXP_DBL)0; + } else { + dB_m = lin2dB(maxSum, 7, &dB_e); /* e_maxSum = 7 */ + downmixPeakLevelDB = + scaleValue(dB_m, dB_e - 7); /* e_downmixPeakLevelDB = 7 */ + } + } + + if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, albumMode)) { + retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, + albumMode)) { + retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, + &signalPeakLevelTmp); + if (retVal) return (retVal); + } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, 0)) { + retVal = _getLimiterPeakTarget(pInst, drcSetId, 0, &signalPeakLevelTmp); + if (retVal) return (retVal); + } + + signalPeakLevel = signalPeakLevelTmp + downmixPeakLevelDB; + } else { + signalPeakLevel = FIXP_DBL(0); /* worst case estimate */ + *explicitPeakInformationPresent = FIXP_DBL(0); + } + + *signalPeakLevelOut = signalPeakLevel; + + return retVal; +} + +static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( + LOUDNESS_INFO* loudnessInfo, + DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, + int* pLoudnessPeakToAverageValuePresent, + FIXP_DBL* pLoudnessPeakToAverageValue) { + int i; + + VALUE_ORDER valueOrderLoudness; + VALUE_ORDER valueOrderPeakLoudness; + + _initValueOrder(&valueOrderLoudness); + _initValueOrder(&valueOrderPeakLoudness); + + LOUDNESS_MEASUREMENT* pLoudnessMeasure = NULL; + + *pLoudnessPeakToAverageValuePresent = 0; + + for (i = 0; i < loudnessInfo->measurementCount; i++) { + pLoudnessMeasure = &(loudnessInfo->loudnessMeasurement[i]); + + if (pLoudnessMeasure->methodDefinition == MD_PROGRAM_LOUDNESS) { + _getMethodValue(&valueOrderLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PROGRAMLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_SHORT_TERM_LOUDNESS_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_SHORT_TERM_LOUDNESS_MAX)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_MOMENTARY_LOUDNESS_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_MOMENTARY_LOUDNESS_MAX)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + + if ((dynamicRangeMeasurementType == DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG) && + (pLoudnessMeasure->methodDefinition == MD_MAX_OF_LOUDNESS_RANGE)) { + _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, + pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); + } + } + + if ((valueOrderLoudness.order > -1) && (valueOrderPeakLoudness.order > -1)) { + *pLoudnessPeakToAverageValue = + valueOrderPeakLoudness.value - valueOrderLoudness.value; + *pLoudnessPeakToAverageValuePresent = 1; + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + DRCDEC_SELECTION* pCandidatesPotential, + DRCDEC_SELECTION* pCandidatesSelected) { + int i, j; + + for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { + DRCDEC_SELECTION_DATA* pCandidate = + _drcdec_selection_getAt(pCandidatesPotential, i); + if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; + + for (j = 0; j < hLoudnessInfoSet->loudnessInfoAlbumCount; j++) { + if (pCandidate->pInst->drcSetId == + hLoudnessInfoSet->loudnessInfoAlbum[j].drcSetId) { + if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) + return DRCDEC_SELECTION_PROCESS_NOT_OK; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ + +static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, + int methodDefinition, int startIndex) { + int i; + int index = -1; + + for (i = startIndex; i < pLoudnessInfo->measurementCount; i++) { + if (pLoudnessInfo->loudnessMeasurement[i].methodDefinition == + methodDefinition) { + index = i; + break; + } + } + + return index; +} + +/*******************************************/ + +static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, + int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel) { + const FIXP_DBL mixingLevelDefault = FL2FXCONST_DBL(85.0f / (float)(1 << 7)); + + int i; + int count; + + LOUDNESS_INFO* pLoudnessInfo = NULL; + + *pMixingLevel = mixingLevelDefault; + + if (drcSetIdRequested < 0) { + drcSetIdRequested = 0; + } + + if (albumMode) { + count = hLoudnessInfoSet->loudnessInfoAlbumCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; + } else { + count = hLoudnessInfoSet->loudnessInfoCount; + pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; + } + + for (i = 0; i < count; i++) { + if ((drcSetIdRequested == pLoudnessInfo[i].drcSetId) && + ((downmixIdRequested == pLoudnessInfo[i].downmixId) || + (DOWNMIX_ID_ANY_DOWNMIX == pLoudnessInfo[i].downmixId))) { + int index = _findMethodDefinition(&pLoudnessInfo[i], MD_MIXING_LEVEL, 0); + + if (index >= 0) { + *pMixingLevel = pLoudnessInfo[i].loudnessMeasurement[index].methodValue; + break; + } + } + } + + return DRCDEC_SELECTION_PROCESS_NO_ERROR; +} + +/*******************************************/ diff --git a/fdk-aac/libDRCdec/src/drcDec_selectionProcess.h b/fdk-aac/libDRCdec/src/drcDec_selectionProcess.h new file mode 100644 index 0000000..9e0e3fb --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_selectionProcess.h @@ -0,0 +1,217 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): Andreas Hoelzer + + Description: DRC Set Selection + +*******************************************************************************/ + +#ifndef DRCDEC_SELECTIONPROCESS_H +#define DRCDEC_SELECTIONPROCESS_H + +#include "drcDec_types.h" +#include "drcDecoder.h" + +/* DRC set selection according to section 6.2 of ISO/IEC 23003-4 (MPEG-D DRC) */ +/* including ISO/IEC 23003-4/AMD1 (Amendment 1) */ + +typedef struct s_drcdec_selection_process* HANDLE_DRC_SELECTION_PROCESS; + +typedef enum { + DRCDEC_SELECTION_PROCESS_NO_ERROR = 0, + + DRCDEC_SELECTION_PROCESS_WARNING = -1000, + + DRCDEC_SELECTION_PROCESS_NOT_OK = -2000, + DRCDEC_SELECTION_PROCESS_OUTOFMEMORY, + DRCDEC_SELECTION_PROCESS_INVALID_HANDLE, + DRCDEC_SELECTION_PROCESS_NOT_SUPPORTED, + DRCDEC_SELECTION_PROCESS_INVALID_PARAM, + DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE + +} DRCDEC_SELECTION_PROCESS_RETURN; + +typedef enum { + SEL_PROC_TEST_TIME_DOMAIN = -100, + SEL_PROC_TEST_QMF_DOMAIN, + SEL_PROC_TEST_STFT_DOMAIN, + + SEL_PROC_CODEC_MODE_UNDEFINED = -1, + SEL_PROC_MPEG_4_AAC, + SEL_PROC_MPEG_D_USAC, + SEL_PROC_MPEG_H_3DA +} SEL_PROC_CODEC_MODE; + +typedef enum { + /* set and get user param */ + SEL_PROC_LOUDNESS_NORMALIZATION_ON, + /* get only user param */ + SEL_PROC_DYNAMIC_RANGE_CONTROL_ON, + /* set only user params */ + SEL_PROC_TARGET_LOUDNESS, + SEL_PROC_EFFECT_TYPE, + SEL_PROC_EFFECT_TYPE_FALLBACK_CODE, + SEL_PROC_LOUDNESS_MEASUREMENT_METHOD, + SEL_PROC_DOWNMIX_ID, + SEL_PROC_TARGET_LAYOUT, + SEL_PROC_TARGET_CHANNEL_COUNT, + SEL_PROC_BASE_CHANNEL_COUNT, + SEL_PROC_SAMPLE_RATE, + SEL_PROC_BOOST, + SEL_PROC_COMPRESS +} SEL_PROC_USER_PARAM; + +typedef struct s_selection_process_output { + FIXP_DBL outputPeakLevelDb; /* e = 7 */ + FIXP_DBL loudnessNormalizationGainDb; /* e = 7 */ + FIXP_DBL outputLoudness; /* e = 7 */ + + UCHAR numSelectedDrcSets; + SCHAR selectedDrcSetIds[MAX_ACTIVE_DRCS]; + UCHAR selectedDownmixIds[MAX_ACTIVE_DRCS]; + + UCHAR activeDownmixId; + UCHAR baseChannelCount; + UCHAR targetChannelCount; + SCHAR targetLayout; + UCHAR downmixMatrixPresent; + FIXP_DBL downmixMatrix[8][8]; /* e = 2 */ + + FIXP_SGL boost; /* e = 1 */ + FIXP_SGL compress; /* e = 1 */ + + FIXP_DBL mixingLevel; /* e = 7 */ + +} SEL_PROC_OUTPUT, *HANDLE_SEL_PROC_OUTPUT; + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_CODEC_MODE codecMode); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType, + FIXP_DBL requestValue, int* pDiff); + +FIXP_DBL +drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, + const SEL_PROC_USER_PARAM requestType); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_SetMpeghParams( + HANDLE_DRC_SELECTION_PROCESS hInstance, const int numGroupIdsRequested, + const int* groupIdRequested, const int numGroupPresetIdsRequested, + const int* groupPresetIdRequested, + const int* numMembersGroupPresetIdsRequested, + const int groupPresetIdRequestedPreference, int* pDiff); + +DRCDEC_SELECTION_PROCESS_RETURN +drcDec_SelectionProcess_Process(HANDLE_DRC_SELECTION_PROCESS hInstance, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, + HANDLE_SEL_PROC_OUTPUT hSelProcOutput); + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDec_tools.cpp b/fdk-aac/libDRCdec/src/drcDec_tools.cpp new file mode 100644 index 0000000..9a6feb1 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_tools.cpp @@ -0,0 +1,371 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_tools.h" +#include "fixpoint_math.h" +#include "drcDecoder.h" + +int getDeltaTmin(const int sampleRate) { + /* half_ms = round (0.0005 * sampleRate); */ + int half_ms = (sampleRate + 1000) / 2000; + int deltaTmin = 1; + if (sampleRate < 1000) { + return DE_NOT_OK; + } + while (deltaTmin <= half_ms) { + deltaTmin = deltaTmin << 1; + } + return deltaTmin; +} + +DRC_COEFFICIENTS_UNI_DRC* selectDrcCoefficients( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int location) { + int n; + int c = -1; + for (n = 0; n < hUniDrcConfig->drcCoefficientsUniDrcCount; n++) { + if (hUniDrcConfig->drcCoefficientsUniDrc[n].drcLocation == location) { + c = n; + } + } + if (c >= 0) { + return &(hUniDrcConfig->drcCoefficientsUniDrc[c]); + } + return NULL; /* possible during bitstream parsing */ +} + +DRC_INSTRUCTIONS_UNI_DRC* selectDrcInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetId) { + int i; + for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { + if (hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId == drcSetId) { + return &(hUniDrcConfig->drcInstructionsUniDrc[i]); + } + } + return NULL; +} + +DOWNMIX_INSTRUCTIONS* selectDownmixInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int downmixId) { + int i; + for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { + if (hUniDrcConfig->downmixInstructions[i].downmixId == downmixId) { + return &(hUniDrcConfig->downmixInstructions[i]); + } + } + return NULL; +} + +DRC_ERROR +deriveDrcChannelGroups( + const int drcSetEffect, /* in */ + const int channelCount, /* in */ + const SCHAR* gainSetIndex, /* in */ + const DUCKING_MODIFICATION* duckingModificationForChannel, /* in */ + UCHAR* nDrcChannelGroups, /* out */ + SCHAR* uniqueIndex, /* out (gainSetIndexForChannelGroup) */ + SCHAR* groupForChannel, /* out */ + DUCKING_MODIFICATION* duckingModificationForChannelGroup) /* out */ +{ + int duckingSequence = -1; + int c, n, g, match, idx; + FIXP_SGL factor; + FIXP_SGL uniqueScaling[8]; + + for (g = 0; g < 8; g++) { + uniqueIndex[g] = -10; + uniqueScaling[g] = FIXP_SGL(-1.0f); + } + + g = 0; + + if (drcSetEffect & EB_DUCK_OTHER) { + for (c = 0; c < channelCount; c++) { + match = 0; + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + factor = duckingModificationForChannel[c].duckingScaling; + if (idx < 0) { + for (n = 0; n < g; n++) { + if (uniqueScaling[n] == factor) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + uniqueScaling[g] = factor; + groupForChannel[c] = g; + g++; + } + } else { + if ((duckingSequence > 0) && (duckingSequence != idx)) { + return DE_NOT_OK; + } + duckingSequence = idx; + groupForChannel[c] = -1; + } + } + if (duckingSequence == -1) { + return DE_NOT_OK; + } + } else if (drcSetEffect & EB_DUCK_SELF) { + for (c = 0; c < channelCount; c++) { + match = 0; + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + factor = duckingModificationForChannel[c].duckingScaling; + if (idx >= 0) { + for (n = 0; n < g; n++) { + if ((uniqueIndex[n] == idx) && (uniqueScaling[n] == factor)) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + uniqueScaling[g] = factor; + groupForChannel[c] = g; + g++; + } + } else { + groupForChannel[c] = -1; + } + } + } else { /* no ducking */ + for (c = 0; c < channelCount; c++) { + if (c >= 8) return DE_MEMORY_ERROR; + idx = gainSetIndex[c]; + match = 0; + if (idx >= 0) { + for (n = 0; n < g; n++) { + if (uniqueIndex[n] == idx) { + match = 1; + groupForChannel[c] = n; + break; + } + } + if (match == 0) { + if (g >= 8) return DE_MEMORY_ERROR; + uniqueIndex[g] = idx; + groupForChannel[c] = g; + g++; + } + } else { + groupForChannel[c] = -1; + } + } + } + *nDrcChannelGroups = g; + + if (drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (g = 0; g < *nDrcChannelGroups; g++) { + if (drcSetEffect & EB_DUCK_OTHER) { + uniqueIndex[g] = duckingSequence; + } + duckingModificationForChannelGroup[g].duckingScaling = uniqueScaling[g]; + if (uniqueScaling[g] != FL2FXCONST_SGL(1.0f / (float)(1 << 2))) { + duckingModificationForChannelGroup[g].duckingScalingPresent = 1; + } else { + duckingModificationForChannelGroup[g].duckingScalingPresent = 0; + } + } + } + + return DE_OK; +} + +FIXP_DBL +dB2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e) { + /* get linear value from dB. + return lin_val = 10^(dB_val/20) = 2^(log2(10)/20*dB_val) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL lin_m = + f2Pow(fMult(dB_m, FL2FXCONST_DBL(0.1660964f * (float)(1 << 2))), dB_e - 2, + pLin_e); + + return lin_m; +} + +FIXP_DBL +lin2dB(const FIXP_DBL lin_m, const int lin_e, int* pDb_e) { + /* get dB value from linear value. + return dB_val = 20*log10(lin_val) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL dB_m; + + if (lin_m == (FIXP_DBL)0) { /* return very small value representing -inf */ + dB_m = (FIXP_DBL)MINVAL_DBL; + *pDb_e = DFRACT_BITS - 1; + } else { + /* 20*log10(lin_val) = 20/log2(10)*log2(lin_val) */ + dB_m = fMultDiv2(FL2FXCONST_DBL(6.02059991f / (float)(1 << 3)), + fLog2(lin_m, lin_e, pDb_e)); + *pDb_e += 3 + 1; + } + + return dB_m; +} + +FIXP_DBL +approxDb2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e) { + /* get linear value from approximate dB. + return lin_val = 2^(dB_val/6) + with dB_val = dB_m *2^dB_e and lin_val = lin_m * 2^lin_e */ + FIXP_DBL lin_m = + f2Pow(fMult(dB_m, FL2FXCONST_DBL(0.1666667f * (float)(1 << 2))), dB_e - 2, + pLin_e); + + return lin_m; +} + +int bitstreamContainsMultibandDrc(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const int downmixId) { + int i, g, d, seq; + DRC_INSTRUCTIONS_UNI_DRC* pInst; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + int isMultiband = 0; + + pCoef = selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); + if (pCoef == NULL) return 0; + + for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { + pInst = &(hUniDrcConfig->drcInstructionsUniDrc[i]); + for (d = 0; d < pInst->downmixIdCount; d++) { + if (downmixId == pInst->downmixId[d]) { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + seq = pInst->gainSetIndexForChannelGroup[g]; + if (pCoef->gainSet[seq].bandCount > 1) { + isMultiband = 1; + } + } + } + } + } + + return isMultiband; +} + +FIXP_DBL getDownmixOffset(DOWNMIX_INSTRUCTIONS* pDown, int baseChannelCount) { + FIXP_DBL downmixOffset = FL2FXCONST_DBL(1.0f / (1 << 1)); /* e = 1 */ + if ((pDown->bsDownmixOffset == 1) || (pDown->bsDownmixOffset == 2)) { + int e_a, e_downmixOffset; + FIXP_DBL a, q; + if (baseChannelCount <= pDown->targetChannelCount) return downmixOffset; + + q = fDivNorm((FIXP_DBL)pDown->targetChannelCount, + (FIXP_DBL)baseChannelCount); /* e = 0 */ + a = lin2dB(q, 0, &e_a); + if (pDown->bsDownmixOffset == 2) { + e_a += 1; /* a *= 2 */ + } + /* a = 0.5 * round (a) */ + a = fixp_round(a, e_a) >> 1; + downmixOffset = dB2lin(a, e_a, &e_downmixOffset); + downmixOffset = scaleValue(downmixOffset, e_downmixOffset - 1); + } + return downmixOffset; +} diff --git a/fdk-aac/libDRCdec/src/drcDec_tools.h b/fdk-aac/libDRCdec/src/drcDec_tools.h new file mode 100644 index 0000000..77a0ab7 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_tools.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_TOOLS_H +#define DRCDEC_TOOLS_H + +#include "drcDec_types.h" +#include "drcDec_selectionProcess.h" + +int getDeltaTmin(const int sampleRate); + +DRC_COEFFICIENTS_UNI_DRC* selectDrcCoefficients( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int location); + +DRC_INSTRUCTIONS_UNI_DRC* selectDrcInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetId); + +DOWNMIX_INSTRUCTIONS* selectDownmixInstructions( + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int downmixId); + +DRC_ERROR +deriveDrcChannelGroups( + const int drcSetEffect, /* in */ + const int channelCount, /* in */ + const SCHAR* gainSetIndex, /* in */ + const DUCKING_MODIFICATION* duckingModificationForChannel, /* in */ + UCHAR* nDrcChannelGroups, /* out */ + SCHAR* uniqueIndex, /* out (gainSetIndexForChannelGroup) */ + SCHAR* groupForChannel, /* out */ + DUCKING_MODIFICATION* duckingModificationForChannelGroup); /* out */ + +FIXP_DBL +dB2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e); + +FIXP_DBL +lin2dB(const FIXP_DBL lin_m, const int lin_e, int* pDb_e); + +FIXP_DBL +approxDb2lin(const FIXP_DBL dB_m, const int dB_e, int* pLin_e); + +int bitstreamContainsMultibandDrc(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + const int downmixId); + +FIXP_DBL +getDownmixOffset(DOWNMIX_INSTRUCTIONS* pDown, int baseChannelCount); + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDec_types.h b/fdk-aac/libDRCdec/src/drcDec_types.h new file mode 100644 index 0000000..28c17f3 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDec_types.h @@ -0,0 +1,428 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDEC_TYPES_H +#define DRCDEC_TYPES_H + +#include "common_fix.h" + +/* Data structures corresponding to static and dynamic DRC/Loudness payload + as defined in section 7 of MPEG-D DRC standard, ISO/IEC 23003-4 */ + +/**************/ +/* uniDrcGain */ +/**************/ + +typedef struct { + FIXP_SGL gainDb; /* e = 7 */ + SHORT time; +} GAIN_NODE; + +/* uniDrcGainExtension() (Table 56) */ +typedef struct { + UCHAR uniDrcGainExtType[8]; + ULONG extBitSize[8 - 1]; +} UNI_DRC_GAIN_EXTENSION; + +/* uniDrcGain() (Table 55) */ +typedef struct { + UCHAR nNodes[12]; /* unsaturated value, i.e. as provided in bitstream */ + GAIN_NODE gainNode[12][16]; + + UCHAR uniDrcGainExtPresent; + UNI_DRC_GAIN_EXTENSION uniDrcGainExtension; +} UNI_DRC_GAIN, *HANDLE_UNI_DRC_GAIN; + +/****************/ +/* uniDrcConfig */ +/****************/ + +typedef enum { + EB_NIGHT = 0x0001, + EB_NOISY = 0x0002, + EB_LIMITED = 0x0004, + EB_LOWLEVEL = 0x0008, + EB_DIALOG = 0x0010, + EB_GENERAL_COMPR = 0x0020, + EB_EXPAND = 0x0040, + EB_ARTISTIC = 0x0080, + EB_CLIPPING = 0x0100, + EB_FADE = 0x0200, + EB_DUCK_OTHER = 0x0400, + EB_DUCK_SELF = 0x0800 +} EFFECT_BIT; + +typedef enum { + GCP_REGULAR = 0, + GCP_FADING = 1, + GCP_CLIPPING_DUCKING = 2, + GCP_CONSTANT = 3 +} GAIN_CODING_PROFILE; + +typedef enum { GIT_SPLINE = 0, GIT_LINEAR = 1 } GAIN_INTERPOLATION_TYPE; + +typedef enum { CS_LEFT = 0, CS_RIGHT = 1 } CHARACTERISTIC_SIDE; + +typedef enum { CF_SIGMOID = 0, CF_NODES = 1 } CHARACTERISTIC_FORMAT; + +typedef enum { + GF_QMF32 = 0x1, + GF_QMFHYBRID39 = 0x2, + GF_QMF64 = 0x3, + GF_QMFHYBRID71 = 0x4, + GF_QMF128 = 0x5, + GF_QMFHYBRID135 = 0x6, + GF_UNIFORM = 0x7 +} EQ_SUBBAND_GAIN_FORMAT; + +typedef struct { + UCHAR duckingScalingPresent; + FIXP_SGL duckingScaling; /* e = 2 */ +} DUCKING_MODIFICATION; + +typedef struct { + UCHAR targetCharacteristicLeftPresent; + UCHAR targetCharacteristicLeftIndex; + UCHAR targetCharacteristicRightPresent; + UCHAR targetCharacteristicRightIndex; + UCHAR gainScalingPresent; + FIXP_SGL attenuationScaling; /* e = 2 */ + FIXP_SGL amplificationScaling; /* e = 2 */ + UCHAR gainOffsetPresent; + FIXP_SGL gainOffset; /* e = 4 */ +} GAIN_MODIFICATION; + +typedef union { + UCHAR crossoverFreqIndex; + USHORT startSubBandIndex; +} BAND_BORDER; + +typedef struct { + UCHAR left; + UCHAR right; +} CUSTOM_INDEX; + +typedef struct { + UCHAR present; + UCHAR isCICP; + union { + UCHAR cicpIndex; + CUSTOM_INDEX custom; + }; +} DRC_CHARACTERISTIC; + +typedef struct { + UCHAR gainCodingProfile; + UCHAR gainInterpolationType; + UCHAR fullFrame; + UCHAR timeAlignment; + UCHAR timeDeltaMinPresent; + USHORT timeDeltaMin; + UCHAR bandCount; + UCHAR drcBandType; + UCHAR gainSequenceIndex[4]; + DRC_CHARACTERISTIC drcCharacteristic[4]; + BAND_BORDER bandBorder[4]; +} GAIN_SET; + +typedef struct { + FIXP_SGL gain; /* e = 6 */ + FIXP_SGL ioRatio; /* e = 2 */ + FIXP_SGL exp; /* e = 5 */ + UCHAR flipSign; +} CUSTOM_DRC_CHAR_SIGMOID; + +typedef struct { + UCHAR characteristicNodeCount; + FIXP_SGL nodeLevel[4 + 1]; /* e = 7 */ + FIXP_SGL nodeGain[4 + 1]; /* e = 7 */ +} CUSTOM_DRC_CHAR_NODES; + +typedef shouldBeUnion { + CUSTOM_DRC_CHAR_SIGMOID sigmoid; + CUSTOM_DRC_CHAR_NODES nodes; +} +CUSTOM_DRC_CHAR; + +/* drcCoefficientsUniDrc() (Table 67) */ +typedef struct { + UCHAR drcLocation; + UCHAR drcFrameSizePresent; + USHORT drcFrameSize; + UCHAR characteristicLeftCount; + UCHAR characteristicLeftFormat[8]; + CUSTOM_DRC_CHAR customCharacteristicLeft[8]; + UCHAR characteristicRightCount; + UCHAR characteristicRightFormat[8]; + CUSTOM_DRC_CHAR customCharacteristicRight[8]; + UCHAR + gainSequenceCount; /* unsaturated value, i.e. as provided in bitstream */ + UCHAR gainSetCount; /* saturated to 12 */ + GAIN_SET gainSet[12]; + /* derived data */ + UCHAR gainSetIndexForGainSequence[12]; +} DRC_COEFFICIENTS_UNI_DRC; + +/* drcInstructionsUniDrc() (Table 72) */ +typedef struct { + SCHAR drcSetId; + UCHAR drcSetComplexityLevel; + UCHAR drcLocation; + UCHAR drcApplyToDownmix; + UCHAR downmixIdCount; + UCHAR downmixId[8]; + USHORT drcSetEffect; + UCHAR limiterPeakTargetPresent; + FIXP_SGL limiterPeakTarget; /* e = 5 */ + UCHAR drcSetTargetLoudnessPresent; + SCHAR drcSetTargetLoudnessValueUpper; + SCHAR drcSetTargetLoudnessValueLower; + UCHAR dependsOnDrcSetPresent; + union { + SCHAR dependsOnDrcSet; + UCHAR noIndependentUse; + }; + UCHAR requiresEq; + shouldBeUnion { + GAIN_MODIFICATION gainModificationForChannelGroup[8][4]; + DUCKING_MODIFICATION duckingModificationForChannel[8]; + }; + SCHAR gainSetIndex[8]; + + /* derived data */ + UCHAR drcChannelCount; + UCHAR nDrcChannelGroups; + SCHAR gainSetIndexForChannelGroup[8]; +} DRC_INSTRUCTIONS_UNI_DRC; + +/* channelLayout() (Table 62) */ +typedef struct { + UCHAR baseChannelCount; + UCHAR layoutSignalingPresent; + UCHAR definedLayout; + UCHAR speakerPosition[8]; +} CHANNEL_LAYOUT; + +/* downmixInstructions() (Table 63) */ +typedef struct { + UCHAR downmixId; + UCHAR targetChannelCount; + UCHAR targetLayout; + UCHAR downmixCoefficientsPresent; + UCHAR bsDownmixOffset; + FIXP_DBL downmixCoefficient[8 * 8]; /* e = 2 */ +} DOWNMIX_INSTRUCTIONS; + +typedef struct { + UCHAR uniDrcConfigExtType[8]; + ULONG extBitSize[8 - 1]; +} UNI_DRC_CONFIG_EXTENSION; + +/* uniDrcConfig() (Table 57) */ +typedef struct { + UCHAR sampleRatePresent; + ULONG sampleRate; + UCHAR downmixInstructionsCountV0; + UCHAR downmixInstructionsCountV1; + UCHAR downmixInstructionsCount; /* saturated to 6 */ + UCHAR drcCoefficientsUniDrcCountV0; + UCHAR drcCoefficientsUniDrcCountV1; + UCHAR drcCoefficientsUniDrcCount; /* saturated to 2 */ + UCHAR drcInstructionsUniDrcCountV0; + UCHAR drcInstructionsUniDrcCountV1; + UCHAR drcInstructionsUniDrcCount; /* saturated to (12 + 1 + 6) */ + CHANNEL_LAYOUT channelLayout; + DOWNMIX_INSTRUCTIONS downmixInstructions[6]; + DRC_COEFFICIENTS_UNI_DRC drcCoefficientsUniDrc[2]; + DRC_INSTRUCTIONS_UNI_DRC drcInstructionsUniDrc[(12 + 1 + 6)]; + UCHAR uniDrcConfigExtPresent; + UNI_DRC_CONFIG_EXTENSION uniDrcConfigExt; + + /* derived data */ + UCHAR drcInstructionsCountInclVirtual; + UCHAR diff; +} UNI_DRC_CONFIG, *HANDLE_UNI_DRC_CONFIG; + +/*******************/ +/* loudnessInfoSet */ +/*******************/ + +typedef enum { + MD_UNKNOWN_OTHER = 0, + MD_PROGRAM_LOUDNESS = 1, + MD_ANCHOR_LOUDNESS = 2, + MD_MAX_OF_LOUDNESS_RANGE = 3, + MD_MOMENTARY_LOUDNESS_MAX = 4, + MD_SHORT_TERM_LOUDNESS_MAX = 5, + MD_LOUDNESS_RANGE = 6, + MD_MIXING_LEVEL = 7, + MD_ROOM_TYPE = 8, + MD_SHORT_TERM_LOUDNESS = 9 +} METHOD_DEFINITION; + +typedef enum { + MS_UNKNOWN_OTHER = 0, + MS_EBU_R_128 = 1, + MS_BS_1770_4 = 2, + MS_BS_1770_4_PRE_PROCESSING = 3, + MS_USER = 4, + MS_EXPERT_PANEL = 5, + MS_BS_1771_1 = 6, + MS_RESERVED_A = 7, + MS_RESERVED_B = 8, + MS_RESERVED_C = 9, + MS_RESERVED_D = 10, + MS_RESERVED_E = 11 +} MEASUREMENT_SYSTEM; + +typedef enum { + R_UKNOWN = 0, + R_UNVERIFIED = 1, + R_CEILING = 2, + R_ACCURATE = 3 +} RELIABILITY; + +typedef struct { + UCHAR methodDefinition; + FIXP_DBL methodValue; /* e = 7 for all methodDefinitions */ + UCHAR measurementSystem; + UCHAR reliability; +} LOUDNESS_MEASUREMENT; + +/* loudnessInfo() (Table 59) */ +typedef struct { + SCHAR drcSetId; + UCHAR eqSetId; + UCHAR downmixId; + UCHAR samplePeakLevelPresent; + FIXP_DBL samplePeakLevel; /* e = 7 */ + UCHAR truePeakLevelPresent; + FIXP_DBL truePeakLevel; /* e = 7 */ + UCHAR truePeakLevelMeasurementSystem; + UCHAR truePeakLevelReliability; + UCHAR measurementCount; /* saturated to 8 */ + LOUDNESS_MEASUREMENT loudnessMeasurement[8]; +} LOUDNESS_INFO; + +/* loudnessInfoSetExtension() (Table 61) */ +typedef struct { + UCHAR loudnessInfoSetExtType[8]; + ULONG extBitSize[8 - 1]; +} LOUDNESS_INFO_SET_EXTENSION; + +/* loudnessInfoSet() (Table 58) */ +typedef struct { + UCHAR loudnessInfoAlbumCountV0; + UCHAR loudnessInfoAlbumCountV1; + UCHAR loudnessInfoAlbumCount; /* saturated to 12 */ + UCHAR loudnessInfoCountV0; + UCHAR loudnessInfoCountV1; + UCHAR loudnessInfoCount; /* saturated to 12 */ + LOUDNESS_INFO loudnessInfoAlbum[12]; + LOUDNESS_INFO loudnessInfo[12]; + UCHAR loudnessInfoSetExtPresent; + LOUDNESS_INFO_SET_EXTENSION loudnessInfoSetExt; + /* derived data */ + UCHAR diff; +} LOUDNESS_INFO_SET, *HANDLE_LOUDNESS_INFO_SET; + +#endif diff --git a/fdk-aac/libDRCdec/src/drcDecoder.h b/fdk-aac/libDRCdec/src/drcDecoder.h new file mode 100644 index 0000000..9826a7b --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcDecoder.h @@ -0,0 +1,142 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCDECODER_H +#define DRCDECODER_H + +/* drcDecoder.h: definitions used in all submodules */ + +#define MAX_ACTIVE_DRCS 3 + +typedef enum { DM_REGULAR_DELAY = 0, DM_LOW_DELAY = 1 } DELAY_MODE; + +typedef enum { + DE_OK = 0, + DE_NOT_OK = -100, + DE_PARAM_OUT_OF_RANGE, + DE_PARAM_INVALID, + DE_MEMORY_ERROR +} DRC_ERROR; + +typedef enum { SDM_OFF, SDM_QMF64, SDM_QMF71, SDM_STFT256 } SUBBAND_DOMAIN_MODE; + +#define DOWNMIX_ID_BASE_LAYOUT 0x0 +#define DOWNMIX_ID_ANY_DOWNMIX 0x7F +#define DRC_SET_ID_NO_DRC 0x0 +#define DRC_SET_ID_ANY_DRC 0x3F + +#define LOCATION_MP4_INSTREAM_UNIDRC 0x1 +#define LOCATION_MP4_DYN_RANGE_INFO 0x2 +#define LOCATION_MP4_COMPRESSION_VALUE 0x3 +#define LOCATION_SELECTED \ + LOCATION_MP4_INSTREAM_UNIDRC /* set to location selected by system */ + +#define MAX_REQUESTS_DOWNMIX_ID 15 +#define MAX_REQUESTS_DRC_FEATURE 7 +#define MAX_REQUESTS_DRC_EFFECT_TYPE 15 + +#define DEFAULT_LOUDNESS_DEVIATION_MAX 63 + +#define DRC_INPUT_LOUDNESS_TARGET FL2FXCONST_DBL(-31.0f / (float)(1 << 7)) +#define DRC_INPUT_LOUDNESS_TARGET_SGL FL2FXCONST_SGL(-31.0f / (float)(1 << 7)) + +#endif diff --git a/fdk-aac/libDRCdec/src/drcGainDec_init.cpp b/fdk-aac/libDRCdec/src/drcGainDec_init.cpp new file mode 100644 index 0000000..38f3243 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_init.cpp @@ -0,0 +1,344 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_tools.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_init.h" + +static DRC_ERROR _generateDrcInstructionsDerivedData( + HANDLE_DRC_GAIN_DECODER hGainDec, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, + DRC_INSTRUCTIONS_UNI_DRC* pInst, DRC_COEFFICIENTS_UNI_DRC* pCoef, + ACTIVE_DRC* pActiveDrc) { + DRC_ERROR err = DE_OK; + int g; + int gainElementCount = 0; + UCHAR nDrcChannelGroups = 0; + SCHAR gainSetIndexForChannelGroup[8]; + + err = deriveDrcChannelGroups( + pInst->drcSetEffect, pInst->drcChannelCount, pInst->gainSetIndex, + pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF) + ? pInst->duckingModificationForChannel + : NULL, + &nDrcChannelGroups, gainSetIndexForChannelGroup, + pActiveDrc->channelGroupForChannel, + pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF) + ? pActiveDrc->duckingModificationForChannelGroup + : NULL); + if (err) return (err); + + /* sanity check */ + if (nDrcChannelGroups != pInst->nDrcChannelGroups) return DE_NOT_OK; + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (gainSetIndexForChannelGroup[g] != pInst->gainSetIndexForChannelGroup[g]) + return DE_NOT_OK; + } + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int seq = pInst->gainSetIndexForChannelGroup[g]; + if (seq != -1 && (hUniDrcConfig->drcCoefficientsUniDrcCount == 0 || + seq >= pCoef->gainSetCount)) { + pActiveDrc->channelGroupIsParametricDrc[g] = 1; + } else { + pActiveDrc->channelGroupIsParametricDrc[g] = 0; + if (seq >= pCoef->gainSetCount) { + return DE_NOT_OK; + } + } + } + + /* gainElementCount */ + if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + pActiveDrc->bandCountForChannelGroup[g] = 1; + } + pActiveDrc->gainElementCount = + pInst->nDrcChannelGroups; /* one gain element per channel group */ + } else { + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (pActiveDrc->channelGroupIsParametricDrc[g]) { + gainElementCount++; + pActiveDrc->bandCountForChannelGroup[g] = 1; + } else { + int seq, bandCount; + seq = pInst->gainSetIndexForChannelGroup[g]; + bandCount = pCoef->gainSet[seq].bandCount; + pActiveDrc->bandCountForChannelGroup[g] = bandCount; + gainElementCount += bandCount; + } + } + pActiveDrc->gainElementCount = gainElementCount; + } + + /* prepare gainElementForGroup (cumulated sum of bandCountForChannelGroup) */ + pActiveDrc->gainElementForGroup[0] = 0; + for (g = 1; g < pInst->nDrcChannelGroups; g++) { + pActiveDrc->gainElementForGroup[g] = + pActiveDrc->gainElementForGroup[g - 1] + + pActiveDrc->bandCountForChannelGroup[g - 1]; /* index of first gain + sequence in channel + group */ + } + + return DE_OK; +} + +DRC_ERROR +initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize, + const int sampleRate) { + int i, j, k; + + if (frameSize < 1) { + return DE_NOT_OK; + } + + hGainDec->frameSize = frameSize; + + if (hGainDec->frameSize * 1000 < sampleRate) { + return DE_NOT_OK; + } + + hGainDec->deltaTminDefault = getDeltaTmin(sampleRate); + if (hGainDec->deltaTminDefault > hGainDec->frameSize) { + return DE_NOT_OK; + } + + for (i = 0; i < MAX_ACTIVE_DRCS; i++) { + for (j = 0; j < 8; j++) { + /* use startup node at the beginning */ + hGainDec->activeDrc[i].lnbIndexForChannel[j][0] = 0; + for (k = 1; k < NUM_LNB_FRAMES; k++) { + hGainDec->activeDrc[i].lnbIndexForChannel[j][k] = -1; + } + } + } + + for (j = 0; j < 8; j++) { + hGainDec->channelGain[j] = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + + for (i = 0; i < 4 * 1024 / 256; i++) { + hGainDec->dummySubbandGains[i] = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + } + + hGainDec->status = 0; /* startup */ + + return DE_OK; +} + +void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers) { + int i, c, j; + /* prepare 12 instances of node buffers */ + for (i = 0; i < 12; i++) { + for (j = 0; j < NUM_LNB_FRAMES; j++) { + drcGainBuffers->linearNodeBuffer[i].nNodes[j] = 1; + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].gainLin = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + if (j == 0) { + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = + 0; /* initialize last node with startup node */ + } else { + drcGainBuffers->linearNodeBuffer[i].linearNode[j][0].time = + frameSize - 1; + } + } + } + + /* prepare dummyLnb, a linearNodeBuffer containing a constant gain of 0 dB, + * for the "no DRC processing" case */ + drcGainBuffers->dummyLnb.gainInterpolationType = GIT_LINEAR; + for (i = 0; i < NUM_LNB_FRAMES; i++) { + drcGainBuffers->dummyLnb.nNodes[i] = 1; + drcGainBuffers->dummyLnb.linearNode[i][0].gainLin = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + drcGainBuffers->dummyLnb.linearNode[i][0].time = frameSize - 1; + } + + /* prepare channelGain delay line */ + for (c = 0; c < 8; c++) { + for (i = 0; i < NUM_LNB_FRAMES; i++) { + drcGainBuffers->channelGain[c][i] = + FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + } + } + + drcGainBuffers->lnbPointer = 0; +} + +DRC_ERROR +initActiveDrc(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetIdSelected, + const int downmixIdSelected) { + int g, isMultiband = 0; + DRC_ERROR err = DE_OK; + DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; + DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; + + pInst = selectDrcInstructions(hUniDrcConfig, drcSetIdSelected); + if (pInst == NULL) { + return DE_NOT_OK; + } + + if (pInst->drcSetId >= 0) { + pCoef = selectDrcCoefficients(hUniDrcConfig, pInst->drcLocation); + if (pCoef == NULL) { + return DE_NOT_OK; + } + + if (pCoef->drcFrameSizePresent) { + if (pCoef->drcFrameSize != hGainDec->frameSize) { + return DE_NOT_OK; + } + } + + err = _generateDrcInstructionsDerivedData( + hGainDec, hUniDrcConfig, pInst, pCoef, + &(hGainDec->activeDrc[hGainDec->nActiveDrcs])); + if (err) return err; + } + + hGainDec->activeDrc[hGainDec->nActiveDrcs].pInst = pInst; + hGainDec->activeDrc[hGainDec->nActiveDrcs].pCoef = pCoef; + + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + if (hGainDec->activeDrc[hGainDec->nActiveDrcs].bandCountForChannelGroup[g] > + 1) { + if (hGainDec->multiBandActiveDrcIndex != -1) { + return DE_NOT_OK; + } + isMultiband = 1; + } + } + + if (isMultiband) { + /* Keep activeDrc index of multiband DRC set */ + hGainDec->multiBandActiveDrcIndex = hGainDec->nActiveDrcs; + } + + if ((hGainDec->channelGainActiveDrcIndex == -1) && + (downmixIdSelected == DOWNMIX_ID_BASE_LAYOUT) && + (hUniDrcConfig->drcInstructionsUniDrcCount > + 0)) { /* use this activeDrc to apply channelGains */ + hGainDec->channelGainActiveDrcIndex = hGainDec->nActiveDrcs; + } + + hGainDec->nActiveDrcs++; + if (hGainDec->nActiveDrcs > MAX_ACTIVE_DRCS) return DE_NOT_OK; + + return DE_OK; +} + +DRC_ERROR +initActiveDrcOffset(HANDLE_DRC_GAIN_DECODER hGainDec) { + int a, accGainElementCount; + + accGainElementCount = 0; + for (a = 0; a < hGainDec->nActiveDrcs; a++) { + hGainDec->activeDrc[a].activeDrcOffset = accGainElementCount; + accGainElementCount += hGainDec->activeDrc[a].gainElementCount; + } + + if (accGainElementCount > 12) return DE_NOT_OK; + + return DE_OK; +} diff --git a/fdk-aac/libDRCdec/src/drcGainDec_init.h b/fdk-aac/libDRCdec/src/drcGainDec_init.h new file mode 100644 index 0000000..9215bc3 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_init.h @@ -0,0 +1,120 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_INIT_H +#define DRCGAINDEC_INIT_H + +DRC_ERROR +initGainDec(HANDLE_DRC_GAIN_DECODER hGainDec, const int frameSize, + const int sampleRate); + +void initDrcGainBuffers(const int frameSize, DRC_GAIN_BUFFERS* drcGainBuffers); + +DRC_ERROR +initActiveDrc(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_CONFIG hUniDrcConfig, const int drcSetIdSelected, + const int downmixIdSelected); + +DRC_ERROR +initActiveDrcOffset(HANDLE_DRC_GAIN_DECODER hGainDec); + +#endif diff --git a/fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp b/fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp new file mode 100644 index 0000000..c543c53 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_preprocess.cpp @@ -0,0 +1,715 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_preprocess.h" +#include "drcDec_tools.h" +#include "FDK_matrixCalloc.h" +#include "drcDec_rom.h" + +#define SLOPE_FACTOR_DB_TO_LINEAR \ + FL2FXCONST_DBL(0.1151f * (float)(1 << 3)) /* ln(10) / 20 */ + +typedef struct { + int drcSetEffect; + DUCKING_MODIFICATION* pDMod; + GAIN_MODIFICATION* pGMod; + int drcCharacteristicPresent; + CHARACTERISTIC_FORMAT characteristicFormatSource[2]; + const CUSTOM_DRC_CHAR* pCCharSource[2]; + CHARACTERISTIC_FORMAT characteristicFormatTarget[2]; + const CUSTOM_DRC_CHAR* pCCharTarget[2]; + int slopeIsNegative; + int limiterPeakTargetPresent; + FIXP_SGL limiterPeakTarget; + FIXP_DBL loudnessNormalizationGainDb; + FIXP_SGL compress; + FIXP_SGL boost; +} NODE_MODIFICATION; + +static DRC_ERROR _getCicpCharacteristic( + const int cicpCharacteristic, + CHARACTERISTIC_FORMAT pCharacteristicFormat[2], + const CUSTOM_DRC_CHAR* pCCharSource[2]) { + if ((cicpCharacteristic < 1) || (cicpCharacteristic > 11)) { + return DE_NOT_OK; + } + + if (cicpCharacteristic < 7) { /* sigmoid characteristic */ + pCharacteristicFormat[CS_LEFT] = CF_SIGMOID; + pCCharSource[CS_LEFT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidLeft[cicpCharacteristic - + 1]); + pCharacteristicFormat[CS_RIGHT] = CF_SIGMOID; + pCCharSource[CS_RIGHT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidRight[cicpCharacteristic - + 1]); + } else { /* nodes characteristic */ + pCharacteristicFormat[CS_LEFT] = CF_NODES; + pCCharSource[CS_LEFT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesLeft[cicpCharacteristic - 7]); + pCharacteristicFormat[CS_RIGHT] = CF_NODES; + pCCharSource[CS_RIGHT] = + (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesRight[cicpCharacteristic - + 7]); + } + return DE_OK; +} + +static int _getSign(FIXP_SGL in) { + if (in > (FIXP_DBL)0) return 1; + if (in < (FIXP_DBL)0) return -1; + return 0; +} + +static DRC_ERROR _getSlopeSign(const CHARACTERISTIC_FORMAT drcCharFormat, + const CUSTOM_DRC_CHAR* pCChar, int* pSlopeSign) { + if (drcCharFormat == CF_SIGMOID) { + *pSlopeSign = (pCChar->sigmoid.flipSign ? 1 : -1); + } else { + int k, slopeSign = 0, tmp_slopeSign; + for (k = 0; k < pCChar->nodes.characteristicNodeCount; k++) { + if (pCChar->nodes.nodeLevel[k + 1] > pCChar->nodes.nodeLevel[k]) { + tmp_slopeSign = + _getSign(pCChar->nodes.nodeGain[k + 1] - pCChar->nodes.nodeGain[k]); + } else { + tmp_slopeSign = -_getSign(pCChar->nodes.nodeGain[k + 1] - + pCChar->nodes.nodeGain[k]); + } + if ((slopeSign || tmp_slopeSign) && (slopeSign == -tmp_slopeSign)) + return DE_NOT_OK; /* DRC characteristic is not invertible */ + else + slopeSign = tmp_slopeSign; + } + *pSlopeSign = slopeSign; + } + return DE_OK; +} + +static DRC_ERROR _isSlopeNegative(const CHARACTERISTIC_FORMAT drcCharFormat[2], + const CUSTOM_DRC_CHAR* pCChar[2], + int* pSlopeIsNegative) { + DRC_ERROR err = DE_OK; + int slopeSign[2] = {0, 0}; + + err = _getSlopeSign(drcCharFormat[CS_LEFT], pCChar[CS_LEFT], + &slopeSign[CS_LEFT]); + if (err) return err; + + err = _getSlopeSign(drcCharFormat[CS_RIGHT], pCChar[CS_RIGHT], + &slopeSign[CS_RIGHT]); + if (err) return err; + + if ((slopeSign[CS_LEFT] || slopeSign[CS_RIGHT]) && + (slopeSign[CS_LEFT] == -slopeSign[CS_RIGHT])) + return DE_NOT_OK; /* DRC characteristic is not invertible */ + + *pSlopeIsNegative = (slopeSign[CS_LEFT] < 0); + return DE_OK; +} + +static DRC_ERROR _prepareDrcCharacteristic(const DRC_CHARACTERISTIC* pDChar, + DRC_COEFFICIENTS_UNI_DRC* pCoef, + const int b, + NODE_MODIFICATION* pNodeMod) { + DRC_ERROR err = DE_OK; + pNodeMod->drcCharacteristicPresent = pDChar->present; + if (pNodeMod->drcCharacteristicPresent) { + if (pDChar->isCICP == 1) { + err = _getCicpCharacteristic(pDChar->cicpIndex, + pNodeMod->characteristicFormatSource, + pNodeMod->pCCharSource); + if (err) return err; + } else { + pNodeMod->characteristicFormatSource[CS_LEFT] = + (CHARACTERISTIC_FORMAT) + pCoef->characteristicLeftFormat[pDChar->custom.left]; + pNodeMod->pCCharSource[CS_LEFT] = + &(pCoef->customCharacteristicLeft[pDChar->custom.left]); + pNodeMod->characteristicFormatSource[CS_RIGHT] = + (CHARACTERISTIC_FORMAT) + pCoef->characteristicRightFormat[pDChar->custom.right]; + pNodeMod->pCCharSource[CS_RIGHT] = + &(pCoef->customCharacteristicRight[pDChar->custom.right]); + } + err = _isSlopeNegative(pNodeMod->characteristicFormatSource, + pNodeMod->pCCharSource, &pNodeMod->slopeIsNegative); + if (err) return err; + + if (pNodeMod->pGMod != NULL) { + if (pNodeMod->pGMod[b].targetCharacteristicLeftPresent) { + pNodeMod->characteristicFormatTarget[CS_LEFT] = + (CHARACTERISTIC_FORMAT)pCoef->characteristicLeftFormat + [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]; + pNodeMod->pCCharTarget[CS_LEFT] = + &(pCoef->customCharacteristicLeft + [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]); + } + if (pNodeMod->pGMod[b].targetCharacteristicRightPresent) { + pNodeMod->characteristicFormatTarget[CS_RIGHT] = + (CHARACTERISTIC_FORMAT)pCoef->characteristicRightFormat + [pNodeMod->pGMod[b].targetCharacteristicRightIndex]; + pNodeMod->pCCharTarget[CS_RIGHT] = + &(pCoef->customCharacteristicRight + [pNodeMod->pGMod[b].targetCharacteristicRightIndex]); + } + } + } + return DE_OK; +} + +static DRC_ERROR _compressorIO_sigmoid_common( + const FIXP_DBL tmp, /* e = 7 */ + const FIXP_DBL gainDbLimit, /* e = 6 */ + const FIXP_DBL exp, /* e = 5 */ + const int inverse, FIXP_DBL* out) /* e = 7 */ +{ + FIXP_DBL x, tmp1, tmp2, invExp, denom; + int e_x, e_tmp1, e_tmp2, e_invExp, e_denom, e_out; + + if (exp < FL2FXCONST_DBL(1.0f / (float)(1 << 5))) { + return DE_NOT_OK; + } + + /* x = tmp / gainDbLimit; */ + x = fDivNormSigned(tmp, gainDbLimit, &e_x); + e_x += 7 - 6; + if (x < (FIXP_DBL)0) { + return DE_NOT_OK; + } + + /* out = tmp / pow(1.0f +/- pow(x, exp), 1.0f/exp); */ + tmp1 = fPow(x, e_x, exp, 5, &e_tmp1); + if (inverse) tmp1 = -tmp1; + tmp2 = fAddNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), 1, tmp1, e_tmp1, + &e_tmp2); + invExp = fDivNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), exp, &e_invExp); + e_invExp += 1 - 5; + denom = fPow(tmp2, e_tmp2, invExp, e_invExp, &e_denom); + *out = fDivNormSigned(tmp, denom, &e_out); + e_out += 7 - e_denom; + *out = scaleValueSaturate(*out, e_out - 7); + return DE_OK; +} + +static DRC_ERROR _compressorIO_sigmoid(const CUSTOM_DRC_CHAR_SIGMOID* pCChar, + const FIXP_DBL inLevelDb, /* e = 7 */ + FIXP_DBL* outGainDb) /* e = 7 */ +{ + FIXP_DBL tmp; + FIXP_SGL exp = pCChar->exp; + DRC_ERROR err = DE_OK; + + tmp = fMultDiv2((DRC_INPUT_LOUDNESS_TARGET >> 1) - (inLevelDb >> 1), + pCChar->ioRatio); + tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1 + 1, DFRACT_BITS); + if (exp < (FIXP_SGL)MAXVAL_SGL) { + /* x = tmp / gainDbLimit; */ + /* *outGainDb = tmp / pow(1.0f + pow(x, exp), 1.0f/exp); */ + err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), + FX_SGL2FX_DBL(exp), 0, outGainDb); + if (err) return err; + } else { + *outGainDb = + tmp; /* scaling of outGainDb (7) is equal to scaling of tmp (7) */ + } + if (pCChar->flipSign == 1) { + *outGainDb = -*outGainDb; + } + return err; +} + +static DRC_ERROR _compressorIO_sigmoid_inverse( + const CUSTOM_DRC_CHAR_SIGMOID* pCChar, const FIXP_SGL gainDb, + FIXP_DBL* inLev) { + DRC_ERROR err = DE_OK; + FIXP_SGL ioRatio = pCChar->ioRatio; + FIXP_SGL exp = pCChar->exp; + FIXP_DBL tmp = FX_SGL2FX_DBL(gainDb), tmp_out; + int e_out; + + if (pCChar->flipSign == 1) { + tmp = -tmp; + } + if (exp < (FIXP_SGL)MAXVAL_SGL) { + /* x = tmp / gainDbLimit; */ + /* tmp = tmp / pow(1.0f - pow(x, exp), 1.0f / exp); */ + err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), + FX_SGL2FX_DBL(exp), 1, &tmp); + if (err) return err; + } + if (ioRatio == (FIXP_SGL)0) { + return DE_NOT_OK; + } + tmp_out = fDivNormSigned(tmp, FX_SGL2FX_DBL(ioRatio), &e_out); + e_out += 7 - 2; + tmp_out = fAddNorm(DRC_INPUT_LOUDNESS_TARGET, 7, -tmp_out, e_out, &e_out); + *inLev = scaleValueSaturate(tmp_out, e_out - 7); + + return err; +} + +static DRC_ERROR _compressorIO_nodes(const CUSTOM_DRC_CHAR_NODES* pCChar, + const FIXP_DBL inLevelDb, /* e = 7 */ + FIXP_DBL* outGainDb) /* e = 7 */ +{ + int n; + FIXP_DBL w; + const FIXP_SGL* nodeLevel = pCChar->nodeLevel; + const FIXP_SGL* nodeGain = pCChar->nodeGain; + + if (inLevelDb < DRC_INPUT_LOUDNESS_TARGET) { + for (n = 0; n < pCChar->characteristicNodeCount; n++) { + if ((inLevelDb <= FX_SGL2FX_DBL(nodeLevel[n])) && + (inLevelDb > FX_SGL2FX_DBL(nodeLevel[n + 1]))) { + w = fDivNorm(inLevelDb - FX_SGL2FX_DBL(nodeLevel[n + 1]), + FX_SGL2FX_DBL(nodeLevel[n] - nodeLevel[n + 1])); + *outGainDb = fMult(w, nodeGain[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); + /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ + return DE_OK; + } + } + } else { + for (n = 0; n < pCChar->characteristicNodeCount; n++) { + if ((inLevelDb >= FX_SGL2FX_DBL(nodeLevel[n])) && + (inLevelDb < FX_SGL2FX_DBL(nodeLevel[n + 1]))) { + w = fDivNorm(FX_SGL2FX_DBL(nodeLevel[n + 1]) - inLevelDb, + FX_SGL2FX_DBL(nodeLevel[n + 1] - nodeLevel[n])); + *outGainDb = fMult(w, nodeGain[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); + /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ + return DE_OK; + } + } + } + *outGainDb = FX_SGL2FX_DBL(nodeGain[pCChar->characteristicNodeCount]); + return DE_OK; +} + +static DRC_ERROR _compressorIO_nodes_inverse( + const CUSTOM_DRC_CHAR_NODES* pCChar, const FIXP_SGL gainDb, /* e = 7 */ + FIXP_DBL* inLev) /* e = 7 */ +{ + int n; + int k; + FIXP_DBL w; + int gainIsNegative = 0; + const FIXP_SGL* nodeLevel = pCChar->nodeLevel; + const FIXP_SGL* nodeGain = pCChar->nodeGain; + int nodeCount = pCChar->characteristicNodeCount; + for (k = 0; k < nodeCount; k++) { + if (pCChar->nodeGain[k + 1] < (FIXP_SGL)0) { + gainIsNegative = 1; + } + } + if (gainIsNegative == 1) { + if (gainDb <= nodeGain[nodeCount]) { + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } else { + if (gainDb >= (FIXP_SGL)0) { + *inLev = DRC_INPUT_LOUDNESS_TARGET; + } else { + for (n = 0; n < nodeCount; n++) { + if ((gainDb <= nodeGain[n]) && (gainDb > nodeGain[n + 1])) { + FIXP_SGL gainDelta = nodeGain[n] - nodeGain[n + 1]; + if (gainDelta == (FIXP_SGL)0) { + *inLev = FX_SGL2FX_DBL(nodeLevel[n]); + return DE_OK; + } + w = fDivNorm(gainDb - nodeGain[n + 1], gainDelta); + *inLev = fMult(w, nodeLevel[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); + /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ + return DE_OK; + } + } + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } + } + } else { + if (gainDb >= nodeGain[nodeCount]) { + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } else { + if (gainDb <= (FIXP_SGL)0) { + *inLev = DRC_INPUT_LOUDNESS_TARGET; + } else { + for (n = 0; n < nodeCount; n++) { + if ((gainDb >= nodeGain[n]) && (gainDb < nodeGain[n + 1])) { + FIXP_SGL gainDelta = nodeGain[n + 1] - nodeGain[n]; + if (gainDelta == (FIXP_SGL)0) { + *inLev = FX_SGL2FX_DBL(nodeLevel[n]); + return DE_OK; + } + w = fDivNorm(nodeGain[n + 1] - gainDb, gainDelta); + *inLev = fMult(w, nodeLevel[n]) + + fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); + /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ + return DE_OK; + } + } + *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); + } + } + } + return DE_OK; +} + +static DRC_ERROR _mapGain(const CHARACTERISTIC_FORMAT pCCharFormatSource, + const CUSTOM_DRC_CHAR* pCCharSource, + const CHARACTERISTIC_FORMAT pCCharFormatTarget, + const CUSTOM_DRC_CHAR* pCCharTarget, + const FIXP_SGL gainInDb, /* e = 7 */ + FIXP_DBL* gainOutDb) /* e = 7 */ +{ + FIXP_DBL inLevel = (FIXP_DBL)0; + DRC_ERROR err = DE_OK; + + switch (pCCharFormatSource) { + case CF_SIGMOID: + err = _compressorIO_sigmoid_inverse( + (const CUSTOM_DRC_CHAR_SIGMOID*)pCCharSource, gainInDb, &inLevel); + if (err) return err; + break; + case CF_NODES: + err = _compressorIO_nodes_inverse( + (const CUSTOM_DRC_CHAR_NODES*)pCCharSource, gainInDb, &inLevel); + if (err) return err; + break; + default: + return DE_NOT_OK; + } + switch (pCCharFormatTarget) { + case CF_SIGMOID: + err = _compressorIO_sigmoid((const CUSTOM_DRC_CHAR_SIGMOID*)pCCharTarget, + inLevel, gainOutDb); + if (err) return err; + break; + case CF_NODES: + err = _compressorIO_nodes((const CUSTOM_DRC_CHAR_NODES*)pCCharTarget, + inLevel, gainOutDb); + if (err) return err; + break; + default: + break; + } + return DE_OK; +} + +static DRC_ERROR _toLinear( + const NODE_MODIFICATION* nodeMod, const int drcBand, + const FIXP_SGL gainDb, /* in: gain value in dB, e = 7 */ + const FIXP_SGL slopeDb, /* in: slope value in dB/deltaTmin, e = 2 */ + FIXP_DBL* gainLin, /* out: linear gain value, e = 7 */ + FIXP_DBL* slopeLin) /* out: linear slope value, e = 7 */ +{ + FIXP_DBL gainRatio_m = FL2FXCONST_DBL(1.0f / (float)(1 << 1)); + GAIN_MODIFICATION* pGMod = NULL; + DUCKING_MODIFICATION* pDMod = nodeMod->pDMod; + FIXP_DBL tmp_dbl, gainDb_modified, gainDb_offset, gainDb_out, gainLin_m, + slopeLin_m; + int gainLin_e, gainRatio_e = 1, gainDb_out_e; + if (nodeMod->pGMod != NULL) { + pGMod = &(nodeMod->pGMod[drcBand]); + } + if (((nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) && + (nodeMod->drcSetEffect != EB_FADE) && + (nodeMod->drcSetEffect != EB_CLIPPING)) { + DRC_ERROR err = DE_OK; + FIXP_DBL gainDbMapped; + + if ((pGMod != NULL) && (nodeMod->drcCharacteristicPresent)) { + if (((gainDb > (FIXP_SGL)0) && nodeMod->slopeIsNegative) || + ((gainDb < (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) { + /* left side */ + if (pGMod->targetCharacteristicLeftPresent == 1) { + err = _mapGain(nodeMod->characteristicFormatSource[CS_LEFT], + nodeMod->pCCharSource[CS_LEFT], + nodeMod->characteristicFormatTarget[CS_LEFT], + nodeMod->pCCharTarget[CS_LEFT], gainDb, &gainDbMapped); + if (err) return err; + gainRatio_m = fDivNormSigned( + gainDbMapped, FX_SGL2FX_DBL(gainDb), + &gainRatio_e); /* target characteristic in payload */ + } + } + + else { /* if (((gainDb < (FIXP_SGL)0) && nodeMod->slopeIsNegative) || + ((gainDb > (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) */ + + /* right side */ + if (pGMod->targetCharacteristicRightPresent == 1) { + err = + _mapGain(nodeMod->characteristicFormatSource[CS_RIGHT], + nodeMod->pCCharSource[CS_RIGHT], + nodeMod->characteristicFormatTarget[CS_RIGHT], + nodeMod->pCCharTarget[CS_RIGHT], gainDb, &gainDbMapped); + if (err) return err; + gainRatio_m = fDivNormSigned( + gainDbMapped, FX_SGL2FX_DBL(gainDb), + &gainRatio_e); /* target characteristic in payload */ + } + } + } + if (gainDb < (FIXP_SGL)0) { + gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->compress); + } else { + gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->boost); + } + gainRatio_e += 2; + } + if ((pGMod != NULL) && (pGMod->gainScalingPresent == 1)) { + if (gainDb < (FIXP_SGL)0) { + gainRatio_m = fMultDiv2(gainRatio_m, pGMod->attenuationScaling); + } else { + gainRatio_m = fMultDiv2(gainRatio_m, pGMod->amplificationScaling); + } + gainRatio_e += 3; + } + if ((pDMod != NULL) && + (nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) && + (pDMod->duckingScalingPresent == 1)) { + gainRatio_m = fMultDiv2(gainRatio_m, pDMod->duckingScaling); + gainRatio_e += 3; + } + + gainDb_modified = + fMultDiv2(gainDb, gainRatio_m); /* resulting e: 7 + gainRatio_e + 1*/ + gainDb_offset = (FIXP_DBL)0; + + if ((pGMod != NULL) && (pGMod->gainOffsetPresent == 1)) { + /* *gainLin *= (float)pow(2.0, (double)(pGMod->gainOffset/6.0f)); */ + gainDb_offset += FX_SGL2FX_DBL(pGMod->gainOffset) >> 4; /* resulting e: 8 */ + } + if ((nodeMod->limiterPeakTargetPresent == 1) && + (nodeMod->drcSetEffect == + EB_CLIPPING)) { /* The only drcSetEffect is "clipping prevention" */ + /* loudnessNormalizationGainModificationDb is included in + * loudnessNormalizationGainDb */ + /* *gainLin *= (float)pow(2.0, max(0.0, -nodeModification->limiterPeakTarget + * - nodeModification->loudnessNormalizationGainDb)/6.0); */ + gainDb_offset += fMax( + (FIXP_DBL)0, + (FX_SGL2FX_DBL(-nodeMod->limiterPeakTarget) >> 3) - + (nodeMod->loudnessNormalizationGainDb >> 1)); /* resulting e: 8 */ + } + if (gainDb_offset != (FIXP_DBL)0) { + gainDb_out = fAddNorm(gainDb_modified, 7 + gainRatio_e + 1, gainDb_offset, + 8, &gainDb_out_e); + } else { + gainDb_out = gainDb_modified; + gainDb_out_e = 7 + gainRatio_e + 1; + } + + /* *gainLin = (float)pow(2.0, (double)(gainDb_modified[1] / 6.0f)); */ + gainLin_m = approxDb2lin(gainDb_out, gainDb_out_e, &gainLin_e); + *gainLin = scaleValueSaturate(gainLin_m, gainLin_e - 7); + + /* *slopeLin = SLOPE_FACTOR_DB_TO_LINEAR * gainRatio * *gainLin * slopeDb; */ + if (slopeDb == (FIXP_SGL)0) { + *slopeLin = (FIXP_DBL)0; + } else { + tmp_dbl = + fMult(slopeDb, SLOPE_FACTOR_DB_TO_LINEAR); /* resulting e: 2 - 3 = -1 */ + tmp_dbl = fMult(tmp_dbl, gainRatio_m); /* resulting e: -1 + gainRatio_e */ + if (gainDb_offset != + (FIXP_DBL)0) { /* recalculate gainLin from gainDb that wasn't modified + by gainOffset and limiterPeakTarget */ + gainLin_m = approxDb2lin(gainDb_modified, 7 + gainRatio_e, &gainLin_e); + } + slopeLin_m = fMult(tmp_dbl, gainLin_m); + *slopeLin = + scaleValueSaturate(slopeLin_m, -1 + gainRatio_e + gainLin_e - 7); + } + + if ((nodeMod->limiterPeakTargetPresent == 1) && + (nodeMod->drcSetEffect == EB_CLIPPING)) { + if (*gainLin >= FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { + *gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + *slopeLin = (FIXP_DBL)0; + } + } + + return DE_OK; +} + +/* prepare buffers containing linear nodes for each gain sequence */ +DRC_ERROR +prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress, + const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb, + const int activeDrcIndex) { + int b, g, gainElementIndex; + DRC_GAIN_BUFFERS* drcGainBuffers = &(hGainDec->drcGainBuffers); + NODE_MODIFICATION nodeMod; + FDKmemclear(&nodeMod, sizeof(NODE_MODIFICATION)); + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst; + if (pInst == NULL) return DE_NOT_OK; + + nodeMod.drcSetEffect = pInst->drcSetEffect; + + nodeMod.compress = compress; + nodeMod.boost = boost; + nodeMod.loudnessNormalizationGainDb = loudnessNormalizationGainDb; + nodeMod.limiterPeakTargetPresent = pInst->limiterPeakTargetPresent; + nodeMod.limiterPeakTarget = pInst->limiterPeakTarget; + + gainElementIndex = 0; + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + int gainSetIndex = 0; + int nDrcBands = 0; + DRC_COEFFICIENTS_UNI_DRC* pCoef = pActiveDrc->pCoef; + if (pCoef == NULL) return DE_NOT_OK; + + if (!pActiveDrc->channelGroupIsParametricDrc[g]) { + gainSetIndex = pInst->gainSetIndexForChannelGroup[g]; + + if (nodeMod.drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { + nodeMod.pDMod = &(pActiveDrc->duckingModificationForChannelGroup[g]); + nodeMod.pGMod = NULL; + } else { + nodeMod.pGMod = pInst->gainModificationForChannelGroup[g]; + nodeMod.pDMod = NULL; + } + + nDrcBands = pActiveDrc->bandCountForChannelGroup[g]; + for (b = 0; b < nDrcBands; b++) { + DRC_ERROR err = DE_OK; + GAIN_SET* pGainSet = &(pCoef->gainSet[gainSetIndex]); + int seq = pGainSet->gainSequenceIndex[b]; + DRC_CHARACTERISTIC* pDChar = &(pGainSet->drcCharacteristic[b]); + + /* linearNodeBuffer contains a copy of the gain sequences (consisting of + nodes) that are relevant for decoding. It also contains gain + sequences of previous frames. */ + LINEAR_NODE_BUFFER* pLnb = + &(drcGainBuffers->linearNodeBuffer[pActiveDrc->activeDrcOffset + + gainElementIndex]); + int i, lnbp; + lnbp = drcGainBuffers->lnbPointer; + pLnb->gainInterpolationType = + (GAIN_INTERPOLATION_TYPE)pGainSet->gainInterpolationType; + + err = _prepareDrcCharacteristic(pDChar, pCoef, b, &nodeMod); + if (err) return err; + + /* copy a node buffer and convert from dB to linear */ + pLnb->nNodes[lnbp] = fMin((int)hUniDrcGain->nNodes[seq], 16); + for (i = 0; i < pLnb->nNodes[lnbp]; i++) { + FIXP_DBL gainLin, slopeLin; + err = _toLinear(&nodeMod, b, hUniDrcGain->gainNode[seq][i].gainDb, + (FIXP_SGL)0, &gainLin, &slopeLin); + if (err) return err; + pLnb->linearNode[lnbp][i].gainLin = gainLin; + pLnb->linearNode[lnbp][i].time = hUniDrcGain->gainNode[seq][i].time; + } + gainElementIndex++; + } + } else { + /* parametric DRC not supported */ + gainElementIndex++; + } + } + return DE_OK; +} diff --git a/fdk-aac/libDRCdec/src/drcGainDec_preprocess.h b/fdk-aac/libDRCdec/src/drcGainDec_preprocess.h new file mode 100644 index 0000000..4647407 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_preprocess.h @@ -0,0 +1,111 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_PREPROCESS_H +#define DRCGAINDEC_PREPROCESS_H + +DRC_ERROR +prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec, + HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress, + const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb, + const int activeDrcIndex); +#endif diff --git a/fdk-aac/libDRCdec/src/drcGainDec_process.cpp b/fdk-aac/libDRCdec/src/drcGainDec_process.cpp new file mode 100644 index 0000000..70c9533 --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_process.cpp @@ -0,0 +1,532 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "drcDec_types.h" +#include "drcDec_gainDecoder.h" +#include "drcGainDec_process.h" + +#define E_TGAINSTEP 12 + +static DRC_ERROR _prepareLnbIndex(ACTIVE_DRC* pActiveDrc, + const int channelOffset, + const int drcChannelOffset, + const int numChannelsProcessed, + const int lnbPointer) { + int g, c; + DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst; + + /* channelOffset: start index of physical channels + numChannelsProcessed: number of processed channels, physical channels and + DRC channels channelOffset + drcChannelOffset: start index of DRC channels, + i.e. the channel order referenced in pInst.sequenceIndex */ + + /* sanity checks */ + if ((channelOffset + numChannelsProcessed) > 8) return DE_NOT_OK; + + if ((channelOffset + drcChannelOffset + numChannelsProcessed) > 8) + return DE_NOT_OK; + + if ((channelOffset + drcChannelOffset) < 0) return DE_NOT_OK; + + /* prepare lnbIndexForChannel, a map of indices from each channel to its + * corresponding linearNodeBuffer instance */ + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + if (pInst->drcSetId > 0) { + int drcChannel = c + drcChannelOffset; + /* fallback for configuration with more physical channels than DRC + channels: reuse DRC gain of first channel. This is necessary for HE-AAC + mono with stereo output */ + if (drcChannel >= pInst->drcChannelCount) drcChannel = 0; + g = pActiveDrc->channelGroupForChannel[drcChannel]; + if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) { + pActiveDrc->lnbIndexForChannel[c][lnbPointer] = + pActiveDrc->activeDrcOffset + pActiveDrc->gainElementForGroup[g]; + } + } + } + + return DE_OK; +} + +static DRC_ERROR _interpolateDrcGain( + const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const SHORT timePrev, /* time0 */ + const SHORT tGainStep, /* time1 - time0 */ + const SHORT start, const SHORT stop, const SHORT stepsize, + const FIXP_DBL gainLeft, const FIXP_DBL gainRight, const FIXP_DBL slopeLeft, + const FIXP_DBL slopeRight, FIXP_DBL* buffer) { + int n, n_buf; + int start_modulo, start_offset; + + if (tGainStep < 0) { + return DE_NOT_OK; + } + if (tGainStep == 0) { + return DE_OK; + } + + /* get start index offset and buffer index for downsampled interpolation */ + /* start_modulo = (start+timePrev)%stepsize; */ /* stepsize is a power of 2 */ + start_modulo = (start + timePrev) & (stepsize - 1); + start_offset = (start_modulo ? stepsize - start_modulo : 0); + /* n_buf = (start + timePrev + start_offset)/stepsize; */ + n_buf = (start + timePrev + start_offset) >> (15 - fixnormz_S(stepsize)); + + { /* gainInterpolationType == GIT_LINEAR */ + LONG a; + /* runs = ceil((stop - start - start_offset)/stepsize). This works for + * stepsize = 2^N only. */ + INT runs = (INT)(stop - start - start_offset + stepsize - 1) >> + (30 - CountLeadingBits(stepsize)); + INT n_min = fMin( + fMin(CntLeadingZeros(gainRight), CntLeadingZeros(gainLeft)) - 1, 8); + a = (LONG)((gainRight << n_min) - (gainLeft << n_min)) / tGainStep; + LONG a_step = a * stepsize; + n = start + start_offset; + a = a * n + (LONG)(gainLeft << n_min); + buffer += n_buf; +#if defined(FUNCTION_interpolateDrcGain_func1) + interpolateDrcGain_func1(buffer, a, a_step, n_min, runs); +#else + a -= a_step; + n_min = 8 - n_min; + for (int i = 0; i < runs; i++) { + a += a_step; + buffer[i] = fMultDiv2(buffer[i], (FIXP_DBL)a) << n_min; + } +#endif /* defined(FUNCTION_interpolateDrcGain_func1) */ + } + return DE_OK; +} + +static DRC_ERROR _processNodeSegments( + const int frameSize, const GAIN_INTERPOLATION_TYPE gainInterpolationType, + const int nNodes, const NODE_LIN* pNodeLin, const int offset, + const SHORT stepsize, + const NODE_LIN nodePrevious, /* the last node of the previous frame */ + const FIXP_DBL channelGain, FIXP_DBL* buffer) { + DRC_ERROR err = DE_OK; + SHORT timePrev, duration, start, stop, time; + int n; + FIXP_DBL gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)), gainLinPrev; + FIXP_DBL slopeLin = (FIXP_DBL)0, slopeLinPrev = (FIXP_DBL)0; + + timePrev = nodePrevious.time + offset; + gainLinPrev = nodePrevious.gainLin; + for (n = 0; n < nNodes; n++) { + time = pNodeLin[n].time + offset; + duration = time - timePrev; + gainLin = pNodeLin[n].gainLin; + if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8))) + gainLin = + SATURATE_LEFT_SHIFT(fMultDiv2(gainLin, channelGain), 9, DFRACT_BITS); + + if ((timePrev >= (frameSize - 1)) || + (time < 0)) { /* This segment (between previous and current node) lies + outside of this audio frame */ + timePrev = time; + gainLinPrev = gainLin; + slopeLinPrev = slopeLin; + continue; + } + + /* start and stop are the boundaries of the region of this segment that lie + within this audio frame. Their values are relative to the beginning of + this segment. stop is the first sample that isn't processed any more. */ + start = fMax(-timePrev, 1); + stop = fMin(time, (SHORT)(frameSize - 1)) - timePrev + 1; + + err = _interpolateDrcGain(gainInterpolationType, timePrev, duration, start, + stop, stepsize, gainLinPrev, gainLin, + slopeLinPrev, slopeLin, buffer); + if (err) return err; + + timePrev = time; + gainLinPrev = gainLin; + } + return err; +} + +/* process DRC on time-domain signal */ +DRC_ERROR +processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* deinterleavedAudio) { + DRC_ERROR err = DE_OK; + int c, b, i; + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers); + int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx; + LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer; + LINEAR_NODE_BUFFER* pDummyLnb = &(pDrcGainBuffers->dummyLnb); + int offset = 0; + + if (hGainDec->delayMode == DM_REGULAR_DELAY) { + offset = hGainDec->frameSize; + } + + if ((delaySamples + offset) > + (NUM_LNB_FRAMES - 2) * + hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES + should be increased */ + return DE_NOT_OK; + + err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset, + numChannelsProcessed, lnbPointer); + if (err) return err; + + deinterleavedAudio += + channelOffset * timeDataChannelOffset; /* apply channelOffset */ + + /* signal processing loop */ + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + pDrcGainBuffers->channelGain[c][lnbPointer] = hGainDec->channelGain[c]; + + b = 0; + { + LINEAR_NODE_BUFFER *pLnb, *pLnbPrevious; + NODE_LIN nodePrevious; + int lnbPointerDiff; + FIXP_DBL channelGain; + /* get pointer to oldest linearNodes */ + lnbIx = lnbPointer + 1 - NUM_LNB_FRAMES; + while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES; + + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + channelGain = pDrcGainBuffers->channelGain[c][lnbIx]; + else + channelGain = FL2FXCONST_DBL(1.0f / (float)(1 << 8)); + + /* Loop over all node buffers in linearNodeBuffer. + All nodes which are not relevant for the current frame are sorted out + inside _processNodeSegments. */ + for (i = 0; i < NUM_LNB_FRAMES - 1; i++) { + /* Prepare previous node */ + if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0) + pLnbPrevious = &( + pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]); + else + pLnbPrevious = pDummyLnb; + nodePrevious = + pLnbPrevious->linearNode[lnbIx][pLnbPrevious->nNodes[lnbIx] - 1]; + nodePrevious.time -= hGainDec->frameSize; + if (channelGain != FL2FXCONST_DBL(1.0f / (float)(1 << 8))) + nodePrevious.gainLin = SATURATE_LEFT_SHIFT( + fMultDiv2(nodePrevious.gainLin, + pDrcGainBuffers->channelGain[c][lnbIx]), + 9, DFRACT_BITS); + + /* Prepare current linearNodeBuffer instance */ + lnbIx++; + if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0; + + /* if lnbIndexForChannel changes over time, use the old indices for + * smooth transitions */ + if (pActiveDrc->lnbIndexForChannel[c][lnbIx] >= 0) + pLnb = &( + pLinearNodeBuffer[pActiveDrc->lnbIndexForChannel[c][lnbIx] + b]); + else /* lnbIndexForChannel = -1 means "no DRC processing", due to + drcInstructionsIndex < 0, drcSetId < 0 or channel group < 0 */ + pLnb = pDummyLnb; + + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + channelGain = pDrcGainBuffers->channelGain[c][lnbIx]; + + /* number of frames of offset with respect to lnbPointer */ + lnbPointerDiff = i - (NUM_LNB_FRAMES - 2); + + err = _processNodeSegments( + hGainDec->frameSize, pLnb->gainInterpolationType, + pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx], + lnbPointerDiff * hGainDec->frameSize + delaySamples + offset, 1, + nodePrevious, channelGain, deinterleavedAudio); + if (err) return err; + } + deinterleavedAudio += timeDataChannelOffset; /* proceed to next channel */ + } + } + return DE_OK; +} + +/* process DRC on subband-domain signal */ +DRC_ERROR +processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, + FIXP_DBL* deinterleavedAudioReal[], + FIXP_DBL* deinterleavedAudioImag[]) { + DRC_ERROR err = DE_OK; + int b, c, g, m, m_start, m_stop, s, i; + FIXP_DBL gainSb; + DRC_INSTRUCTIONS_UNI_DRC* pInst = hGainDec->activeDrc[activeDrcIndex].pInst; + DRC_GAIN_BUFFERS* pDrcGainBuffers = &(hGainDec->drcGainBuffers); + ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); + int activeDrcOffset = pActiveDrc->activeDrcOffset; + int lnbPointer = pDrcGainBuffers->lnbPointer, lnbIx; + LINEAR_NODE_BUFFER* pLinearNodeBuffer = pDrcGainBuffers->linearNodeBuffer; + FIXP_DBL(*subbandGains)[4 * 1024 / 256] = hGainDec->subbandGains; + FIXP_DBL* dummySubbandGains = hGainDec->dummySubbandGains; + SUBBAND_DOMAIN_MODE subbandDomainMode = hGainDec->subbandDomainSupported; + int signalIndex = 0; + int frameSizeSb = 0; + int nDecoderSubbands; + SHORT L = 0; /* L: downsampling factor */ + int offset = 0; + FIXP_DBL *audioReal = NULL, *audioImag = NULL; + + if (hGainDec->delayMode == DM_REGULAR_DELAY) { + offset = hGainDec->frameSize; + } + + if ((delaySamples + offset) > + (NUM_LNB_FRAMES - 2) * + hGainDec->frameSize) /* if delaySamples is too big, NUM_LNB_FRAMES + should be increased */ + return DE_NOT_OK; + + switch (subbandDomainMode) { +#if ((1024 / 256) >= (4096 / SUBBAND_DOWNSAMPLING_FACTOR_QMF64)) + case SDM_QMF64: + nDecoderSubbands = SUBBAND_NUM_BANDS_QMF64; + L = SUBBAND_DOWNSAMPLING_FACTOR_QMF64; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF64; */ + break; + case SDM_QMF71: + nDecoderSubbands = SUBBAND_NUM_BANDS_QMF71; + L = SUBBAND_DOWNSAMPLING_FACTOR_QMF71; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_QMF71; */ + break; +#else + case SDM_QMF64: + case SDM_QMF71: + /* QMF domain processing is not supported. */ + return DE_NOT_OK; +#endif + case SDM_STFT256: + nDecoderSubbands = SUBBAND_NUM_BANDS_STFT256; + L = SUBBAND_DOWNSAMPLING_FACTOR_STFT256; + /* analysisDelay = SUBBAND_ANALYSIS_DELAY_STFT256; */ + break; + default: + return DE_NOT_OK; + } + + /* frameSizeSb = hGainDec->frameSize/L; */ /* L is a power of 2 */ + frameSizeSb = + hGainDec->frameSize >> (15 - fixnormz_S(L)); /* timeslots per frame */ + + if ((processSingleTimeslot < 0) || (processSingleTimeslot >= frameSizeSb)) { + m_start = 0; + m_stop = frameSizeSb; + } else { + m_start = processSingleTimeslot; + m_stop = m_start + 1; + } + + err = _prepareLnbIndex(pActiveDrc, channelOffset, drcChannelOffset, + numChannelsProcessed, lnbPointer); + if (err) return err; + + if (!pActiveDrc->subbandGainsReady) /* only for the first time per frame that + processDrcSubband is called */ + { + /* write subbandGains */ + for (g = 0; g < pInst->nDrcChannelGroups; g++) { + b = 0; + { + LINEAR_NODE_BUFFER* pLnb = + &(pLinearNodeBuffer[activeDrcOffset + + pActiveDrc->gainElementForGroup[g] + b]); + NODE_LIN nodePrevious; + int lnbPointerDiff; + + for (m = 0; m < frameSizeSb; m++) { + subbandGains[activeDrcOffset + g][b * frameSizeSb + m] = + FL2FXCONST_DBL(1.0f / (float)(1 << 7)); + } + + lnbIx = lnbPointer - (NUM_LNB_FRAMES - 1); + while (lnbIx < 0) lnbIx += NUM_LNB_FRAMES; + + /* Loop over all node buffers in linearNodeBuffer. + All nodes which are not relevant for the current frame are sorted out + inside _processNodeSegments. */ + for (i = 0; i < NUM_LNB_FRAMES - 1; i++) { + /* Prepare previous node */ + nodePrevious = pLnb->linearNode[lnbIx][pLnb->nNodes[lnbIx] - 1]; + nodePrevious.time -= hGainDec->frameSize; + + lnbIx++; + if (lnbIx >= NUM_LNB_FRAMES) lnbIx = 0; + + /* number of frames of offset with respect to lnbPointer */ + lnbPointerDiff = i - (NUM_LNB_FRAMES - 2); + + err = _processNodeSegments( + hGainDec->frameSize, pLnb->gainInterpolationType, + pLnb->nNodes[lnbIx], pLnb->linearNode[lnbIx], + lnbPointerDiff * hGainDec->frameSize + delaySamples + offset - + (L - 1) / 2, + L, nodePrevious, FL2FXCONST_DBL(1.0f / (float)(1 << 8)), + &(subbandGains[activeDrcOffset + g][b * frameSizeSb])); + if (err) return err; + } + } + } + pActiveDrc->subbandGainsReady = 1; + } + + for (c = channelOffset; c < channelOffset + numChannelsProcessed; c++) { + FIXP_DBL* thisSubbandGainsBuffer; + if (pInst->drcSetId > 0) + g = pActiveDrc->channelGroupForChannel[c + drcChannelOffset]; + else + g = -1; + + audioReal = deinterleavedAudioReal[signalIndex]; + if (subbandDomainMode != SDM_STFT256) { + audioImag = deinterleavedAudioImag[signalIndex]; + } + + if ((g >= 0) && !pActiveDrc->channelGroupIsParametricDrc[g]) { + thisSubbandGainsBuffer = subbandGains[activeDrcOffset + g]; + } else { + thisSubbandGainsBuffer = dummySubbandGains; + } + + for (m = m_start; m < m_stop; m++) { + INT n_min = 8; + { /* single-band DRC */ + gainSb = thisSubbandGainsBuffer[m]; + if (activeDrcIndex == hGainDec->channelGainActiveDrcIndex) + gainSb = SATURATE_LEFT_SHIFT( + fMultDiv2(gainSb, hGainDec->channelGain[c]), 9, DFRACT_BITS); + /* normalize gainSb for keeping signal precision */ + n_min = fMin(CntLeadingZeros(gainSb) - 1, n_min); + gainSb <<= n_min; + n_min = 8 - n_min; + if (subbandDomainMode == + SDM_STFT256) { /* For STFT filterbank, real and imaginary parts are + interleaved. */ + for (s = 0; s < nDecoderSubbands; s++) { + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + } + } else { + for (s = 0; s < nDecoderSubbands; s++) { + *audioReal = fMultDiv2(*audioReal, gainSb) << n_min; + audioReal++; + *audioImag = fMultDiv2(*audioImag, gainSb) << n_min; + audioImag++; + } + } + } + } + signalIndex++; + } + return DE_OK; +} diff --git a/fdk-aac/libDRCdec/src/drcGainDec_process.h b/fdk-aac/libDRCdec/src/drcGainDec_process.h new file mode 100644 index 0000000..f751aba --- /dev/null +++ b/fdk-aac/libDRCdec/src/drcGainDec_process.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* MPEG-D DRC decoder library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef DRCGAINDEC_PROCESS_H +#define DRCGAINDEC_PROCESS_H + +DRC_ERROR +processDrcTime(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int timeDataChannelOffset, FIXP_DBL* deinterleavedAudio); + +DRC_ERROR +processDrcSubband(HANDLE_DRC_GAIN_DECODER hGainDec, const int activeDrcIndex, + const int delaySamples, const int channelOffset, + const int drcChannelOffset, const int numChannelsProcessed, + const int processSingleTimeslot, + FIXP_DBL* deinterleavedAudioReal[], + FIXP_DBL* deinterleavedAudioImag[]); +#endif diff --git a/fdk-aac/libFDK/include/FDK_archdef.h b/fdk-aac/libFDK/include/FDK_archdef.h new file mode 100644 index 0000000..b4fef8a --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_archdef.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef FDK_ARCHDEF_H +#define FDK_ARCHDEF_H + +/* Unify some few toolchain specific defines to avoid having large "or" macro + * contraptions all over the source code. */ + +/* Use single macro (the GCC built in macro) for architecture identification + * independent of the particular toolchain */ +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || \ + defined(__i686__) || (defined(_MSC_VER) && defined(_M_IX86)) || \ + (defined(_MSC_VER) && defined(_M_X64)) || defined(__x86_64__) +#define __x86__ +#endif + +#if defined(_M_ARM) && !defined(__arm__) || defined(__aarch64__) || defined(_M_ARM64) +#define __arm__ +#endif + +#if defined(_ARCH_PPC) && !defined(__powerpc__) +#define __powerpc__ 1 +#endif + +#if (__TARGET_ARCH_ARM == 5) || defined(__TARGET_FEATURE_DSPMUL) || \ + (_M_ARM == 5) || defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_7EM__) +/* Define __ARM_ARCH_5TE__ if armv5te features are supported */ +#define __ARM_ARCH_5TE__ +#endif + +#if (__TARGET_ARCH_ARM == 6) || defined(__ARM_ARCH_6J__) || \ + defined(__ARM_ARCH_6ZK__) +/* Define __ARM_ARCH_6__ if the armv6 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#endif + +#if defined(__TARGET_ARCH_7_R) || defined(__ARM_ARCH_7R__) +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_R__ +#endif + +#if defined(__TARGET_ARCH_7_A) || defined(__ARM_ARCH_7A__) || \ + ((__ARM_ARCH == 8) && (__ARM_32BIT_STATE == 1)) +/* Define __ARM_ARCH_7_A__ if the armv7 intructions are being supported. */ +#define __ARM_ARCH_5TE__ +#define __ARM_ARCH_6__ +#define __ARM_ARCH_7_A__ +#endif + +#if defined(__TARGET_ARCH_7_M) || defined(__ARM_ARCH_7_M__) +/* Define __ARM_ARCH_7M__ if the ARMv7-M instructions are being supported, e.g. + * Cortex-M3. */ +#define __ARM_ARCH_7M__ +#endif + +#if defined(__TARGET_ARCH_7E_M) || defined(__ARM_ARCH_7E_M__) +/* Define __ARM_ARCH_7EM__ if the ARMv7-ME instructions are being supported, + * e.g. Cortex-M4. */ +#define __ARM_ARCH_7EM__ +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +#define __ARM_ARCH_8__ +#endif + +#ifdef _M_ARM +#include "armintr.h" +#endif + +/* Define preferred Multiplication type */ + +#if defined(__mips__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT +#undef WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_8__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_5TE__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7M__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && defined(__ARM_ARCH_7EM__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#elif defined(__arm__) && !defined(__ARM_ARCH_5TE__) +#define ARCH_PREFER_MULT_16x16 +#undef SINETABLE_16BIT +#undef WINDOWTABLE_16BIT +#undef POW2COEFF_16BIT +#undef LDCOEFF_16BIT + +#elif defined(__x86__) +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define WINDOWTABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT + +#elif defined(__powerpc__) +#define ARCH_PREFER_MULT_32x32 +#define ARCH_PREFER_MULT_32x16 +#define SINETABLE_16BIT +#define POW2COEFF_16BIT +#define LDCOEFF_16BIT +#define WINDOWTABLE_16BIT + +#else +#warning >>>> Please set architecture characterization defines for your platform (FDK_HIGH_PERFORMANCE)! <<<< + +#endif /* Architecture switches */ + +#ifdef SINETABLE_16BIT +#define FIXP_STB FIXP_SGL /* STB sinus Tab used in transformation */ +#define FIXP_STP FIXP_SPK +#define STC(a) (FX_DBL2FXCONST_SGL(a)) +#else +#define FIXP_STB FIXP_DBL +#define FIXP_STP FIXP_DPK +#define STC(a) ((FIXP_DBL)(LONG)(a)) +#endif /* defined(SINETABLE_16BIT) */ + +#define STCP(cos, sin) \ + { \ + { STC(cos), STC(sin) } \ + } + +#ifdef WINDOWTABLE_16BIT +#define FIXP_WTB FIXP_SGL /* single FIXP_SGL values */ +#define FX_DBL2FX_WTB(x) FX_DBL2FX_SGL(x) +#define FIXP_WTP FIXP_SPK /* packed FIXP_SGL values */ +#define WTC(a) FX_DBL2FXCONST_SGL(a) +#else /* SINETABLE_16BIT */ +#define FIXP_WTB FIXP_DBL +#define FX_DBL2FX_WTB(x) (x) +#define FIXP_WTP FIXP_DPK +#define WTC(a) (FIXP_DBL)(a) +#endif /* SINETABLE_16BIT */ + +#define WTCP(a, b) \ + { \ + { WTC(a), WTC(b) } \ + } + +#endif /* FDK_ARCHDEF_H */ diff --git a/fdk-aac/libFDK/include/FDK_bitbuffer.h b/fdk-aac/libFDK/include/FDK_bitbuffer.h new file mode 100644 index 0000000..19a24b3 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_bitbuffer.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: common bitbuffer read/write routines + +*******************************************************************************/ + +#ifndef FDK_BITBUFFER_H +#define FDK_BITBUFFER_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* leave 3 bits headroom so MAX_BUFSIZE can be represented in bits as well. */ +#define MAX_BUFSIZE_BYTES (0x10000000) + +typedef struct { + UINT ValidBits; + UINT ReadOffset; + UINT WriteOffset; + UINT BitNdx; + + UCHAR *Buffer; + UINT bufSize; + UINT bufBits; +} FDK_BITBUF; + +typedef FDK_BITBUF *HANDLE_FDK_BITBUF; + +#ifdef __cplusplus +extern "C" { +#endif + +extern const UINT BitMask[32 + 1]; + +/** The BitBuffer Functions are called straight from FDK_bitstream Interface. + For Functions functional survey look there. +*/ + +void FDK_CreateBitBuffer(HANDLE_FDK_BITBUF *hBitBuffer, UCHAR *pBuffer, + UINT bufSize); + +void FDK_InitBitBuffer(HANDLE_FDK_BITBUF hBitBuffer, UCHAR *pBuffer, + UINT bufSize, UINT validBits); + +void FDK_ResetBitBuffer(HANDLE_FDK_BITBUF hBitBuffer); + +void FDK_DeleteBitBuffer(HANDLE_FDK_BITBUF hBitBuffer); + +INT FDK_get(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits); + +INT FDK_get32(HANDLE_FDK_BITBUF hBitBuf); + +void FDK_put(HANDLE_FDK_BITBUF hBitBuffer, UINT value, const UINT numberOfBits); + +INT FDK_getBwd(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits); +void FDK_putBwd(HANDLE_FDK_BITBUF hBitBuffer, UINT value, + const UINT numberOfBits); + +void FDK_pushBack(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, + UCHAR config); + +void FDK_pushForward(HANDLE_FDK_BITBUF hBitBuffer, const UINT numberOfBits, + UCHAR config); + +UINT FDK_getValidBits(HANDLE_FDK_BITBUF hBitBuffer); + +INT FDK_getFreeBits(HANDLE_FDK_BITBUF hBitBuffer); + +void FDK_Feed(HANDLE_FDK_BITBUF hBitBuffer, const UCHAR inputBuffer[], + const UINT bufferSize, UINT *bytesValid); + +void FDK_Copy(HANDLE_FDK_BITBUF hBitBufDst, HANDLE_FDK_BITBUF hBitBufSrc, + UINT *bytesValid); + +void FDK_Fetch(HANDLE_FDK_BITBUF hBitBuffer, UCHAR outBuf[], UINT *writeBytes); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/fdk-aac/libFDK/include/FDK_bitstream.h b/fdk-aac/libFDK/include/FDK_bitstream.h new file mode 100644 index 0000000..f799026 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_bitstream.h @@ -0,0 +1,642 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: bitstream interface to bitbuffer routines + +*******************************************************************************/ + +#ifndef FDK_BITSTREAM_H +#define FDK_BITSTREAM_H + +#include "FDK_bitbuffer.h" +#include "machine_type.h" + +#include "genericStds.h" + +#define CACHE_BITS 32 + +#define BUFSIZE_DUMMY_VALUE MAX_BUFSIZE_BYTES + +typedef enum { BS_READER, BS_WRITER } FDK_BS_CFG; + +typedef struct { + UINT CacheWord; + UINT BitsInCache; + FDK_BITBUF hBitBuf; + UINT ConfigCache; +} FDK_BITSTREAM; + +typedef FDK_BITSTREAM *HANDLE_FDK_BITSTREAM; + +/** + * \brief CreateBitStream Function. + * + * Create and initialize bitstream with extern allocated buffer. + * + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array. (awaits size 2^n and <= + * MAX_BUFSIZE_BYTES) + * \param config Initialize BitStream as Reader or Writer. + */ +FDK_INLINE +HANDLE_FDK_BITSTREAM FDKcreateBitStream(UCHAR *pBuffer, UINT bufSize, + FDK_BS_CFG config = BS_READER) { + HANDLE_FDK_BITSTREAM hBitStream = + (HANDLE_FDK_BITSTREAM)FDKcalloc(1, sizeof(FDK_BITSTREAM)); + if (hBitStream == NULL) return NULL; + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, 0); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; + + return hBitStream; +} + +/** + * \brief Initialize BistreamBuffer. BitBuffer can point to filled BitBuffer + * array . + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param pBuffer Pointer to BitBuffer array. + * \param bufSize Length of BitBuffer array in bytes. (awaits size 2^n and <= + * MAX_BUFSIZE_BYTES) + * \param validBits Number of valid BitBuffer filled Bits. + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE +void FDKinitBitStream(HANDLE_FDK_BITSTREAM hBitStream, UCHAR *pBuffer, + UINT bufSize, UINT validBits, + FDK_BS_CFG config = BS_READER) { + FDK_InitBitBuffer(&hBitStream->hBitBuf, pBuffer, bufSize, validBits); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; +} + +/** + * \brief ResetBitbuffer Function. Reset states in BitBuffer and Cache. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param config Initialize BitStream as Reader or Writer. + * \return void + */ +FDK_INLINE void FDKresetBitbuffer(HANDLE_FDK_BITSTREAM hBitStream, + FDK_BS_CFG config = BS_READER) { + FDK_ResetBitBuffer(&hBitStream->hBitBuf); + + /* init cache */ + hBitStream->CacheWord = hBitStream->BitsInCache = 0; + hBitStream->ConfigCache = config; +} + +/** DeleteBitStream. + + Deletes the in Create Bitstream allocated BitStream and BitBuffer. +*/ +FDK_INLINE void FDKdeleteBitStream(HANDLE_FDK_BITSTREAM hBitStream) { + FDK_DeleteBitBuffer(&hBitStream->hBitBuf); + FDKfree(hBitStream); +} + +/** + * \brief ReadBits Function (forward). This function returns a number of + * sequential bits from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. ( (0),1 <= + * numberOfBits <= 32) + * \return the requested bits, right aligned + * \return + */ + +FDK_INLINE UINT FDKreadBits(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + UINT bits = 0; + INT missingBits = (INT)numberOfBits - (INT)hBitStream->BitsInCache; + + FDK_ASSERT(numberOfBits <= 32); + if (missingBits > 0) { + if (missingBits != 32) bits = hBitStream->CacheWord << missingBits; + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache += CACHE_BITS; + } + + hBitStream->BitsInCache -= numberOfBits; + + return (bits | (hBitStream->CacheWord >> hBitStream->BitsInCache)) & + BitMask[numberOfBits]; +} + +FDK_INLINE UINT FDKreadBit(HANDLE_FDK_BITSTREAM hBitStream) { + if (!hBitStream->BitsInCache) { + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache = CACHE_BITS - 1; + return hBitStream->CacheWord >> 31; + } + hBitStream->BitsInCache--; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & 1; +} + +/** + * \brief Read2Bits Function (forward). This function reads 2 sequential + * bits from the input bitstream. It is the optimized version + of FDKreadBits() for reading 2 bits. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return the requested bits, right aligned + * \return + */ +FDK_INLINE UINT FDKread2Bits(HANDLE_FDK_BITSTREAM hBitStream) { + /* + ** Version corresponds to optimized FDKreadBits implementation + ** calling FDK_get32, that keeps read pointer aligned. + */ + UINT bits = 0; + INT missingBits = 2 - (INT)hBitStream->BitsInCache; + if (missingBits > 0) { + bits = hBitStream->CacheWord << missingBits; + hBitStream->CacheWord = FDK_get32(&hBitStream->hBitBuf); + hBitStream->BitsInCache += CACHE_BITS; + } + + hBitStream->BitsInCache -= 2; + + return (bits | (hBitStream->CacheWord >> hBitStream->BitsInCache)) & 0x3; +} + +/** + * \brief ReadBits Function (backward). This function returns a number of + * sequential bits from the input bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKreadBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if (hBitStream->BitsInCache <= numberOfBits) { + const INT freeBits = (CACHE_BITS - 1) - hBitStream->BitsInCache; + + hBitStream->CacheWord = (hBitStream->CacheWord << freeBits) | + FDK_getBwd(&hBitStream->hBitBuf, freeBits); + hBitStream->BitsInCache += freeBits; + } + + hBitStream->BitsInCache -= numberOfBits; + + return (hBitStream->CacheWord >> hBitStream->BitsInCache) & validMask; +} + +/** + * \brief read an integer value using a varying number of bits from the + * bitstream + * + * q.v. ISO/IEC FDIS 23003-3 Table 16 + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param nBits1 number of bits to read for a small integer value or escape + * value + * \param nBits2 number of bits to read for a medium sized integer value or + * escape value + * \param nBits3 number of bits to read for a large integer value + * \return integer value read from bitstream + */ +FDK_INLINE UINT escapedValue(HANDLE_FDK_BITSTREAM hBitStream, int nBits1, + int nBits2, int nBits3) { + UINT value = FDKreadBits(hBitStream, nBits1); + + if (value == (UINT)(1 << nBits1) - 1) { + UINT valueAdd = FDKreadBits(hBitStream, nBits2); + value += valueAdd; + if (valueAdd == (UINT)(1 << nBits2) - 1) { + value += FDKreadBits(hBitStream, nBits3); + } + } + + return value; +} + +/** + * \brief return a number of bits from the bitBuffer. + * You have to know what you do! Cache has to be synchronized before + * using this function. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numBits The number of bits to be retrieved. + * \return the requested bits, right aligned + */ +FDK_INLINE UINT FDKgetBits(HANDLE_FDK_BITSTREAM hBitStream, UINT numBits) { + return FDK_get(&hBitStream->hBitBuf, numBits); +} + +/** + * \brief WriteBits Function. This function writes numberOfBits of value into + * bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value The data to be written + * \param numberOfBits The number of bits to be written + * \return Number of bits written + */ +FDK_INLINE UCHAR FDKwriteBits(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if (hBitStream == NULL) { + return numberOfBits; + } + + if ((hBitStream->BitsInCache + numberOfBits) < CACHE_BITS) { + hBitStream->BitsInCache += numberOfBits; + hBitStream->CacheWord = + (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } else { + /* Put always 32 bits into memory */ + /* - fill cache's LSBits with MSBits of value */ + /* - store 32 bits in memory using subroutine */ + /* - fill remaining bits into cache's LSBits */ + /* - upper bits in cache are don't care */ + + /* Compute number of bits to be filled into cache */ + int missing_bits = CACHE_BITS - hBitStream->BitsInCache; + int remaining_bits = numberOfBits - missing_bits; + value = value & validMask; + /* Avoid shift left by 32 positions */ + UINT CacheWord = + (missing_bits == 32) ? 0 : (hBitStream->CacheWord << missing_bits); + CacheWord |= (value >> (remaining_bits)); + FDK_put(&hBitStream->hBitBuf, CacheWord, 32); + + hBitStream->CacheWord = value; + hBitStream->BitsInCache = remaining_bits; + } + + return numberOfBits; +} + +/** + * \brief WriteBits Function (backward). This function writes numberOfBits of + * value into bitstream. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value Variable holds data to be written. + * \param numberOfBits The number of bits to be written. + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteBitsBwd(HANDLE_FDK_BITSTREAM hBitStream, UINT value, + const UINT numberOfBits) { + const UINT validMask = BitMask[numberOfBits]; + + if ((hBitStream->BitsInCache + numberOfBits) <= CACHE_BITS) { + hBitStream->BitsInCache += numberOfBits; + hBitStream->CacheWord = + (hBitStream->CacheWord << numberOfBits) | (value & validMask); + } else { + FDK_putBwd(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + hBitStream->BitsInCache = numberOfBits; + hBitStream->CacheWord = (value & validMask); + } + + return numberOfBits; +} + +/** + * \brief write an integer value using a varying number of bits from the + * bitstream + * + * q.v. ISO/IEC FDIS 23003-3 Table 16 + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param value the data to be written + * \param nBits1 number of bits to write for a small integer value or escape + * value + * \param nBits2 number of bits to write for a medium sized integer value or + * escape value + * \param nBits3 number of bits to write for a large integer value + * \return number of bits written + */ +FDK_INLINE UCHAR FDKwriteEscapedValue(HANDLE_FDK_BITSTREAM hBitStream, + UINT value, UINT nBits1, UINT nBits2, + UINT nBits3) { + UCHAR nbits = 0; + UINT tmp = (1 << nBits1) - 1; + + if (value < tmp) { + nbits += FDKwriteBits(hBitStream, value, nBits1); + } else { + nbits += FDKwriteBits(hBitStream, tmp, nBits1); + value -= tmp; + tmp = (1 << nBits2) - 1; + + if (value < tmp) { + nbits += FDKwriteBits(hBitStream, value, nBits2); + } else { + nbits += FDKwriteBits(hBitStream, tmp, nBits2); + value -= tmp; + + nbits += FDKwriteBits(hBitStream, value, nBits3); + } + } + + return nbits; +} + +/** + * \brief SyncCache Function. Clear cache after read forward. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCache(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream->ConfigCache == BS_READER) + FDK_pushBack(&hBitStream->hBitBuf, hBitStream->BitsInCache, + hBitStream->ConfigCache); + else if (hBitStream->BitsInCache) /* BS_WRITER */ + FDK_put(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + + hBitStream->BitsInCache = 0; + hBitStream->CacheWord = 0; +} + +/** + * \brief SyncCache Function. Clear cache after read backwards. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return void + */ +FDK_INLINE void FDKsyncCacheBwd(HANDLE_FDK_BITSTREAM hBitStream) { + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward(&hBitStream->hBitBuf, hBitStream->BitsInCache, + hBitStream->ConfigCache); + } else { /* BS_WRITER */ + FDK_putBwd(&hBitStream->hBitBuf, hBitStream->CacheWord, + hBitStream->BitsInCache); + } + + hBitStream->BitsInCache = 0; + hBitStream->CacheWord = 0; +} + +/** + * \brief Byte Alignment Function with anchor + * This function performs the byte_alignment() syntactic function on the + * input stream, i.e. some bits will be discarded so that the next bits to be + * read/written would be aligned on a byte boundary with respect to the + * given alignment anchor. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param alignmentAnchor bit position to be considered as origin for byte + * alignment + * \return void + */ +FDK_INLINE void FDKbyteAlign(HANDLE_FDK_BITSTREAM hBitStream, + UINT alignmentAnchor) { + FDKsyncCache(hBitStream); + if (hBitStream->ConfigCache == BS_READER) { + FDK_pushForward( + &hBitStream->hBitBuf, + (UINT)((INT)8 - (((INT)alignmentAnchor - + (INT)FDK_getValidBits(&hBitStream->hBitBuf)) & + 0x07)) & + 0x07, + hBitStream->ConfigCache); + } else { + FDK_put(&hBitStream->hBitBuf, 0, + (8 - ((FDK_getValidBits(&hBitStream->hBitBuf) - alignmentAnchor) & + 0x07)) & + 0x07); + } +} + +/** + * \brief Push Back(Cache) / For / BiDirectional Function. + * PushBackCache function ungets a number of bits erroneously + * read/written by the last Get() call. NB: The number of bits to be stuffed + * back into the stream may never exceed the number of bits returned by + * the immediately preceding Get() call. + * + * PushBack function ungets a number of bits (combines cache and bitbuffer + * indices) PushFor function gets a number of bits (combines cache and + * bitbuffer indices) PushBiDirectional gets/ungets number of bits as + * defined in PusBack/For function NB: The sign of bits is not known, so + * the function checks direction and calls appropriate function. (positive + * sign pushFor, negative sign pushBack ) + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param numberOfBits The number of bits to be pushed back/for. + * \return void + */ +FDK_INLINE void FDKpushBackCache(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + FDK_ASSERT((hBitStream->BitsInCache + numberOfBits) <= CACHE_BITS); + hBitStream->BitsInCache += numberOfBits; +} + +FDK_INLINE void FDKpushBack(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + if ((hBitStream->BitsInCache + numberOfBits) < CACHE_BITS && + (hBitStream->ConfigCache == BS_READER)) { + hBitStream->BitsInCache += numberOfBits; + FDKsyncCache(hBitStream); /* sync cache to avoid invalid cache */ + } else { + FDKsyncCache(hBitStream); + FDK_pushBack(&hBitStream->hBitBuf, numberOfBits, hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushFor(HANDLE_FDK_BITSTREAM hBitStream, + const UINT numberOfBits) { + if ((hBitStream->BitsInCache > numberOfBits) && + (hBitStream->ConfigCache == BS_READER)) { + hBitStream->BitsInCache -= numberOfBits; + } else { + FDKsyncCache(hBitStream); + FDK_pushForward(&hBitStream->hBitBuf, numberOfBits, + hBitStream->ConfigCache); + } +} + +FDK_INLINE void FDKpushBiDirectional(HANDLE_FDK_BITSTREAM hBitStream, + const INT numberOfBits) { + if (numberOfBits >= 0) + FDKpushFor(hBitStream, numberOfBits); + else + FDKpushBack(hBitStream, -numberOfBits); +} + +/** + * \brief GetValidBits Function. Clear cache and return valid Bits from + * Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of valid bits that still can be read or were already written. + * + */ +FDK_INLINE UINT FDKgetValidBits(HANDLE_FDK_BITSTREAM hBitStream) { + FDKsyncCache(hBitStream); + return FDK_getValidBits(&hBitStream->hBitBuf); +} + +/** + * \brief return amount of unused Bits from Bitbuffer. + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \return amount of free bits that still can be written into the bitstream + */ +FDK_INLINE INT FDKgetFreeBits(HANDLE_FDK_BITSTREAM hBitStream) { + return FDK_getFreeBits(&hBitStream->hBitBuf); +} + +/** + * \brief Fill the BitBuffer with a number of input bytes from external source. + * The bytesValid variable returns the number of ramaining valid bytes in + * extern inputBuffer. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param inputBuffer Pointer to input buffer with bitstream data. + * \param bufferSize Total size of inputBuffer array. + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: bytes + * still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKfeedBuffer(HANDLE_FDK_BITSTREAM hBitStream, + const UCHAR inputBuffer[], const UINT bufferSize, + UINT *bytesValid) { + FDKsyncCache(hBitStream); + FDK_Feed(&hBitStream->hBitBuf, inputBuffer, bufferSize, bytesValid); +} + +/** + * \brief fill destination BitBuffer with a number of bytes from source + * BitBuffer. The bytesValid variable returns the number of ramaining valid + * bytes in source BitBuffer. + * + * \param hBSDst HANDLE_FDK_BITSTREAM handle to write data into + * \param hBSSrc HANDLE_FDK_BITSTREAM handle to read data from + * \param bytesValid Input: number of valid bytes in inputBuffer. Output: + * bytes still left unread in inputBuffer. + * \return void + */ +FDK_INLINE void FDKcopyBuffer(HANDLE_FDK_BITSTREAM hBSDst, + HANDLE_FDK_BITSTREAM hBSSrc, UINT *bytesValid) { + FDKsyncCache(hBSSrc); + FDK_Copy(&hBSDst->hBitBuf, &hBSSrc->hBitBuf, bytesValid); +} + +/** + * \brief fill the outputBuffer with all valid bytes hold in BitBuffer. The + * WriteBytes variable returns the number of written Bytes. + * + * \param hBitStream HANDLE_FDK_BITSTREAM handle + * \param outputBuffer Pointer to output buffer. + * \param writeBytes Number of bytes write to output buffer. + * \return void + */ +FDK_INLINE void FDKfetchBuffer(HANDLE_FDK_BITSTREAM hBitStream, + UCHAR *outputBuffer, UINT *writeBytes) { + FDKsyncCache(hBitStream); + FDK_Fetch(&hBitStream->hBitBuf, outputBuffer, writeBytes); +} + +#endif diff --git a/fdk-aac/libFDK/include/FDK_core.h b/fdk-aac/libFDK/include/FDK_core.h new file mode 100644 index 0000000..9543522 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_core.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: FDK tools versioning support + +*******************************************************************************/ + +#ifndef FDK_CORE_H +#define FDK_CORE_H + +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Get FDK_tools library information. + * @return Return 0 on success and a negative errorcode on failure (see + * errorcodes.h). + */ +int FDK_toolsGetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/fdk-aac/libFDK/include/FDK_crc.h b/fdk-aac/libFDK/include/FDK_crc.h new file mode 100644 index 0000000..6c7040c --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_crc.h @@ -0,0 +1,225 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: CRC calculation + +*******************************************************************************/ + +#ifndef FDK_CRC_H +#define FDK_CRC_H + +#include "FDK_bitstream.h" + +#define MAX_CRC_REGS \ + 3 /*!< Maximal number of overlapping crc region in ADTS channel pair element \ + is two. Select three independent regions preventively. */ + +/** + * This structure describes single crc region used for crc calculation. + */ +typedef struct { + UCHAR isActive; + INT maxBits; + INT bitBufCntBits; + INT validBits; + +} CCrcRegData; + +/** + * CRC info structure. + */ +typedef struct { + CCrcRegData crcRegData[MAX_CRC_REGS]; /*!< Multiple crc region description. */ + const USHORT* + pCrcLookup; /*!< Pointer to lookup table filled in FDK_crcInit(). */ + + USHORT crcPoly; /*!< CRC generator polynom. */ + USHORT crcMask; /*!< CRC mask. */ + USHORT startValue; /*!< CRC start value. */ + UCHAR crcLen; /*!< CRC length. */ + + UINT regStart; /*!< Start region marker for synchronization. */ + UINT regStop; /*!< Stop region marker for synchronization. */ + + USHORT crcValue; /*!< Crc value to be calculated. */ + +} FDK_CRCINFO; + +/** + * CRC info handle. + */ +typedef FDK_CRCINFO* HANDLE_FDK_CRCINFO; + +/** + * \brief Initialize CRC structure. + * + * The function initializes existing crc info structure with denoted + * configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info + * structure. + * \param crcPoly Configure crc polynom. + * \param crcStartValue Configure crc start value. + * \param crcLen Configure crc length. + * + * \return none + */ +void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, + const UINT crcStartValue, const UINT crcLen); + +/** + * \brief Reset CRC info structure. + * + * This function clears all intern states of the crc structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return none + */ +void FDKcrcReset(HANDLE_FDK_CRCINFO hCrcInfo); + +/** + * \brief Start CRC region with maximum number of bits. + * + * This function marks position in bitstream to be used as start point for crc + * calculation. Bitstream range for crc calculation can be limited or kept + * dynamic depending on mBits parameter. The crc region has to be terminated + * with FDKcrcEndReg() in each case. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param mBits Number of bits in crc region to be calculated. + * - mBits > 0: Zero padding will be used for CRC + * calculation, if there are less than mBits bits available. + * - mBits < 0: No zero padding is done. + * - mBits = 0: The number of bits used in crc + * calculation is dynamically, depending on bitstream position between + * FDKcrcStartReg() and FDKcrcEndReg() + * call. + * + * \return ID for the created region, -1 in case of an error + */ +INT FDKcrcStartReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT mBits); + +/** + * \brief Ends CRC region. + * + * This function terminates crc region specified with FDKcrcStartReg(). The + * number of bits in crc region depends on mBits parameter of FDKcrcStartReg(). + * This function calculates and updates crc in info structure. + * + * \param hCrcInfo Pointer to crc info stucture. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID created in FDKcrcStartReg(). + * + * \return 0 on success + */ +INT FDKcrcEndReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT reg); + +/** + * \brief This function returns crc value from info struct. + * + * \param hCrcInfo Pointer to crc info stucture. + * + * \return CRC value masked with crc length. + */ +USHORT FDKcrcGetCRC(const HANDLE_FDK_CRCINFO hCrcInfo); + +#endif /* FDK_CRC_H */ diff --git a/fdk-aac/libFDK/include/FDK_decorrelate.h b/fdk-aac/libFDK/include/FDK_decorrelate.h new file mode 100644 index 0000000..733aaae --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_decorrelate.h @@ -0,0 +1,314 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Decorrelator + +*******************************************************************************/ + +#ifndef FDK_DECORRELATE_H +#define FDK_DECORRELATE_H + +#include "common_fix.h" + +#define FIXP_MPS FIXP_DBL + +#ifndef ARCH_PREFER_MULT_32x32 +#define FIXP_DECORR FIXP_SGL +#define FX_DECORR2FX_DBL FX_SGL2FX_DBL +#define FX_DECORR2FX_SGL +#define FX_DBL2FX_DECORR FX_DBL2FX_SGL +#define FX_SGL2FX_DECORR +#define DECORR(a) (FX_DBL2FXCONST_SGL(a)) +#define FL2FXCONST_DECORR FL2FXCONST_SGL +#else +#define FIXP_DECORR FIXP_DBL +#define FX_DECORR2FX_DBL +#define FX_DECORR2FX_SGL FX_DBL2FX_SGL +#define FX_DBL2FX_DECORR +#define FX_SGL2FX_DECORR FX_SGL2FX_DBL +#define DECORR(a) FIXP_DBL(a) +#define FL2FXCONST_DECORR FL2FXCONST_DBL +#endif + +/*--------------- enums -------------------------------*/ + +/** + * Decorrelator types. + */ +typedef enum { + DECORR_MPS, /**< Decorrelator type used by MPS LP/HQ */ + DECORR_PS, /**< Decorrelator type used by HEAACv2 and MPS LP */ + DECORR_USAC, /**< Decorrelator type used by USAC */ + DECORR_LD /**< Decorrelator type used by MPS Low Delay */ +} FDK_DECORR_TYPE; + +/** + * Ducker types. + */ +typedef enum { + DUCKER_AUTOMATIC, /**< FDKdecorrelateInit() chooses correct ducker type + depending on provided parameters. */ + DUCKER_MPS, /**< Force ducker type to MPS. */ + DUCKER_PS /**< Force ducker type to PS. */ +} FDK_DUCKER_TYPE; + +/** + * Reverb band types. + */ +typedef enum { + NOT_EXIST, /**< Mark reverb band as non-existing (number of bands = 0). */ + DELAY, /**< Reverb bands just contains delay elements and no allpass filters. + */ + COMMON_REAL, /**< Real filter coeffs, common filter coeffs within one reverb + band */ + COMMON_CPLX, /**< Complex filter coeffs, common filter coeffs within one + reverb band */ + INDEP_CPLX, /**< Complex filter coeffs, independent filter coeffs for each + hybrid band */ + INDEP_CPLX_PS /**< PS optimized implementation of general INDEP_CPLX type */ +} REVBAND_FILT_TYPE; + +typedef struct DECORR_DEC *HANDLE_DECORR_DEC; + +typedef struct DUCKER_INSTANCE { + int hybridBands; + int parameterBands; + int partiallyComplex; + FDK_DUCKER_TYPE duckerType; + + const UCHAR *qs_next; + const UCHAR *mapProcBands2HybBands; + const UCHAR *mapHybBands2ProcBands; + /* interleaved SmoothDirectNrg[] and SmoothReverbNrg[], + non-interleaved SmoothDirectNrg[] in case of parametric stereo */ + FIXP_MPS SmoothDirRevNrg[2 * (28)]; + + /* + parametric stereo + */ + FIXP_MPS peakDecay[(28)]; + FIXP_MPS peakDiff[(28)]; + FIXP_DBL maxValDirectData; + FIXP_DBL maxValReverbData; + SCHAR scaleDirectNrg; + SCHAR scaleReverbNrg; + SCHAR scaleSmoothDirRevNrg; + SCHAR headroomSmoothDirRevNrg; + +} DUCKER_INSTANCE; + +typedef struct DECORR_FILTER_INSTANCE { + FIXP_MPS *stateCplx; + FIXP_DBL *DelayBufferCplx; + + const FIXP_DECORR *numeratorReal; + const FIXP_STP *coeffsPacked; + const FIXP_DECORR *denominatorReal; +} DECORR_FILTER_INSTANCE; + +typedef struct DECORR_DEC { + INT L_stateBufferCplx; + FIXP_DBL *stateBufferCplx; + INT L_delayBufferCplx; + FIXP_DBL *delayBufferCplx; + + const REVBAND_FILT_TYPE *REV_filtType; + const UCHAR *REV_bandOffset; + const UCHAR *REV_delay; + const SCHAR *REV_filterOrder; + INT reverbBandDelayBufferIndex[(4)]; + UCHAR stateBufferOffset[(3)]; + + DECORR_FILTER_INSTANCE Filter[(71)]; + DUCKER_INSTANCE ducker; + + int numbins; + int partiallyComplex; +} DECORR_DEC; + +/** + * \brief Create one instance of Decorrelator. + * + * \param hDecorrDec A pointer to a decorrelator instance which was + * allocated externally. + * \param bufferCplx Externally allocated buffer (allocate (2*( ( 825 ) + * + ( 373 ) )) FIXP_DBL values). + * \param bufLen Length of bufferCplx. Must be >= (2*( ( 825 ) + ( + * 373 ) )). + * + * \return 0 on success. + */ +INT FDKdecorrelateOpen(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *bufferCplx, + const INT bufLen); + +/** + * \brief Initialize and configure Decorrelator instance. + * + * \param hDecorrDec A Decorrelator handle. + * \param nrHybBands Number of (hybrid) bands. + * \param decorrType Decorrelator type to use. + * \param duckerType Ducker type to use (in general use + * DUCKER_AUTOMATIC). + * \param decorrConfig Depending on decorrType values of 0,1,2 are + * allowed. + * \param seed Seed of decorrelator instance. Allowed maximum + * valued depends on decorrType. + * \param partiallyComplex Low power or high quality processing 0: HQ, 1: LQ + * (only allowed for DECORR_MPS | DECORR_PS). + * \param useFractDelay Indicate usage of fractional delay 0: off, 1: on + * (currently not supported). + * \param isLegacyPS Indicate if DECORR_PS is used for HEAACv2 (for all + * other cases: isLegacyPS = 0). The purpose of this parameter is to select the + * correct number of param bands for the ducker. + * \param initStatesFlag Indicates whether the states buffer has to be + * cleared. + * + * \return 0 on success. + */ +INT FDKdecorrelateInit(HANDLE_DECORR_DEC hDecorrDec, const INT nrHybBands, + const FDK_DECORR_TYPE decorrType, + const FDK_DUCKER_TYPE duckerType, const INT decorrConfig, + const INT seed, const INT partiallyComplex, + const INT useFractDelay, const INT isLegacyPS, + const INT initStatesFlag); + +/** + * \brief Apply Decorrelator on input data. + * + * Function applies decorrelator and ducker inplace on hybrid input data. + * Modified hybrid data will be returned inplace. + * + * \param hDecorrDec A decorrelator handle. + * \param dataRealIn In (hybrid) data. + * \param dataImagIn In (hybrid) data. + * \param dataRealOut Out (hybrid) data (can be same as dataRealIn for + * in-place calculation). + * \param dataImagOut Out (hybrid) data (can be same as dataImagIn for + * in-place calculation). + * \param startHybBand Hybrid band to start with decorrelation. + * + * \return 0 on success. + */ +INT FDKdecorrelateApply(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, + FIXP_DBL *dataImagOut, const INT startHybBand); + +/** + * \brief Destroy a Decorrelator instance. + * + * Deallocate whole memory of decorraltor and inside ducker. + * + * \param hDecorrDec Pointer to a decoderrolator handle. Null initialized on + * return. + * + * \return 0 on success. + */ +INT FDKdecorrelateClose(HANDLE_DECORR_DEC hDecorrDec); + +/** + * \brief Get max value address of direct signal. + * + * Get max value address of direct signal needed for ducker energy calculation. + * + * \param hDecorrDec Pointer to a decoderrolator handle. + * + * \return address of max value + */ +FIXP_DBL *getAddrDirectSignalMaxVal(HANDLE_DECORR_DEC hDecorrDec); + +#endif /* FDK_DECORRELATE_H */ diff --git a/fdk-aac/libFDK/include/FDK_hybrid.h b/fdk-aac/libFDK/include/FDK_hybrid.h new file mode 100644 index 0000000..583f299 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_hybrid.h @@ -0,0 +1,255 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Hybrid Filterbank + +*******************************************************************************/ + +#ifndef FDK_HYBRID_H +#define FDK_HYBRID_H + +#include "common_fix.h" + +/*--------------- enums -------------------------------*/ + +/** + * Hybrid Filterband modes. + */ +typedef enum { + THREE_TO_TEN, + THREE_TO_TWELVE, + THREE_TO_SIXTEEN + +} FDK_HYBRID_MODE; + +/*--------------- structure definitions ---------------*/ +typedef const struct FDK_HYBRID_SETUP *HANDLE_FDK_HYBRID_SETUP; + +typedef struct { + FIXP_DBL *bufferLFReal[3]; /*!< LF real filter states. */ + FIXP_DBL *bufferLFImag[3]; /*!< LF imag filter states. */ + FIXP_DBL *bufferHFReal[13]; /*!< HF real delay lines. */ + FIXP_DBL *bufferHFImag[13]; /*!< HF imag delay lines. */ + + INT bufferLFpos; /*!< Position to write incoming data into ringbuffer. */ + INT bufferHFpos; /*!< Delay line positioning. */ + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + UCHAR hfMode; /*!< Flag signalizes treatment of HF bands. */ + + FIXP_DBL *pLFmemory; /*!< Pointer to LF states buffer. */ + FIXP_DBL *pHFmemory; /*!< Pointer to HF states buffer. */ + + UINT LFmemorySize; /*!< Size of LF states buffer. */ + UINT HFmemorySize; /*!< Size of HF states buffer. */ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_ANA_HYB_FILTER; + +typedef struct { + INT nrBands; /*!< Number of QMF bands. */ + INT cplxBands; /*!< Number of complex QMF bands.*/ + + HANDLE_FDK_HYBRID_SETUP pSetup; /*!< Pointer to filter setup. */ + +} FDK_SYN_HYB_FILTER; + +typedef FDK_ANA_HYB_FILTER *HANDLE_FDK_ANA_HYB_FILTER; +typedef FDK_SYN_HYB_FILTER *HANDLE_FDK_SYN_HYB_FILTER; + +/** + * \brief Create one instance of Hybrid Analyis Filterbank. + * + * \param hAnalysisHybFilter Pointer to an outlying allocated Hybrid Analysis + * Filterbank structure. + * \param pLFmemory Pointer to outlying buffer used LF filtering. + * \param LFmemorySize Size of pLFmemory in bytes. + * \param pHFmemory Pointer to outlying buffer used HF delay line. + * \param HFmemorySize Size of pLFmemory in bytes. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisOpen(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, const UINT HFmemorySize); + +/** + * \brief Initialize and configure Hybrid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * \param initStatesFlag Indicates whether the states buffer has to be + * cleared. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisInit(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands, const INT initStatesFlag); + +/** + * \brief Adjust Hybrid Analysis Filterbank states. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param scalingValue Scaling value to be applied on filter states. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisScaleStates(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue); + +/** + * \brief Apply Hybrid Analysis Filterbank on Qmf input data. + * + * \param hAnalysisHybFilter A Hybrid Analysis Filterbank handle. + * \param pQmfReal Qmf input data. + * \param pQmfImag Qmf input data. + * \param pHybridReal Hybrid output data. + * \param pHybridImag Hybrid output data. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisApply(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag); + +/** + * \brief Close a Hybrid Analysis Filterbank instance. + * + * \param hAnalysisHybFilter Pointer to a Hybrid Analysis Filterbank instance. + * + * \return 0 on success. + */ +INT FDKhybridAnalysisClose(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter); + +/** + * \brief Initialize and configure Hybrdid Synthesis Filterbank instance. + * + * \param hSynthesisHybFilter A Hybrid Synthesis Filterbank handle. + * \param mode Select hybrid filter configuration. + * \param qmfBands Number of qmf bands to be processed. + * \param cplxBands Number of complex qmf bands to be processed. + * + * \return 0 on success. + */ +INT FDKhybridSynthesisInit(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands); + +/** + * \brief Apply Hybrid Analysis Filterbank on Hybrid data. + * + * \param hSynthesisHybFilter A Hybrid Analysis Filterbandk handle. + * \param pHybridReal Hybrid input data. + * \param pHybridImag Hybrid input data. + * \param pQmfReal Qmf output data. + * \param pQmfImag Qmf output data. + * + */ +void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag); + +#endif /* FDK_HYBRID_H */ diff --git a/fdk-aac/libFDK/include/FDK_lpc.h b/fdk-aac/libFDK/include/FDK_lpc.h new file mode 100644 index 0000000..851dd1f --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_lpc.h @@ -0,0 +1,218 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: LPC related functions + +*******************************************************************************/ + +#ifndef FDK_LPC_H +#define FDK_LPC_H + +#include "common_fix.h" + +#define LPC_MAX_ORDER 24 + +/* + * Experimental solution for lattice filter substitution. + * LPC_SYNTHESIS_IIR macro must be activated in aacdec_tns.cpp. + * When LPC_SYNTHESIS_IIR enabled, there will be a substitution of the default + * lpc synthesis lattice filter by an IIR synthesis filter (with a conversionof + * the filter coefs). LPC_TNS related macros are intended to implement the data + * types used by the CLpc_Synthesis variant which is used for this solution. + * */ + +/* #define LPC_TNS_LOWER_PRECISION */ + +typedef FIXP_DBL FIXP_LPC_TNS; +#define FX_DBL2FX_LPC_TNS(x) (x) +#define FX_DBL2FXCONST_LPC_TNS(x) (x) +#define FX_LPC_TNS2FX_DBL(x) (x) +#define FL2FXCONST_LPC_TNS(val) FL2FXCONST_DBL(val) +#define MAXVAL_LPC_TNS MAXVAL_DBL + +typedef FIXP_SGL FIXP_LPC; +#define FX_DBL2FX_LPC(x) FX_DBL2FX_SGL((FIXP_DBL)(x)) +#define FX_DBL2FXCONST_LPC(x) FX_DBL2FXCONST_SGL(x) +#define FX_LPC2FX_DBL(x) FX_SGL2FX_DBL(x) +#define FL2FXCONST_LPC(val) FL2FXCONST_SGL(val) +#define MAXVAL_LPC MAXVAL_SGL + +/** + * \brief Obtain residual signal through LPC analysis. + * \param signal pointer to buffer holding signal to be analysed. Residual is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param lpcCoeff_m the LPC filter coefficient mantissas + * \param lpcCoeff_e the LPC filter coefficient exponent + * \param order the LPC filter order (size of coeff) + * \param filtState Pointer to state buffer of size order + * \param filtStateIndex pointer to state index storage + */ +void CLpc_Analysis(FIXP_DBL signal[], const int signal_size, + const FIXP_LPC lpcCoeff_m[], const int lpcCoeff_e, + const int order, FIXP_DBL *filtState, int *filtStateIndex); + +/** + * \brief Synthesize signal fom residual through LPC synthesis, using LP + * coefficients. + * \param signal pointer to buffer holding the residual signal. The synthesis is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param inc buffer traversal increment for signal + * \param coeff the LPC filter coefficients + * \param coeff_e exponent of coeff + * \param order the LPC filter order (size of coeff) + * \param state state buffer of size LPC_MAX_ORDER + * \param pStateIndex pointer to state index storage + */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC_TNS *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex); +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC coeff[], const int coeff_e, + const int order, FIXP_DBL *filtState, int *pStateIndex); + +/** + * \brief Synthesize signal fom residual through LPC synthesis, using ParCor + * coefficients. The algorithm assumes a filter gain of max 1.0. If the filter + * gain is higher, this must be accounted into the values of signal_e + * and/or signal_e_out to avoid overflows. + * \param signal pointer to buffer holding the residual signal. The synthesis is + * returned there (in place) + * \param signal_size the size of the input data in pData + * \param inc buffer traversal increment for signal + * \param coeff the LPC filter coefficients + * \param coeff_e exponent of coeff + * \param order the LPC filter order (size of coeff) + * \param state state buffer of size LPC_MAX_ORDER + */ +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_SGL *coeff, + const int order, FIXP_DBL *state); + +void CLpc_SynthesisLattice(FIXP_DBL *RESTRICT signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_DBL *RESTRICT coeff, + const int order, FIXP_DBL *RESTRICT state); + +/** + * \brief + */ +INT CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[], FIXP_LPC_TNS LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]); +INT CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[], FIXP_LPC LpcCoeff[], + const int numOfCoeff, FIXP_DBL workBuffer[]); + +/** + * \brief Calculate ParCor (Partial autoCorrelation, reflection) coefficients + * from autocorrelation coefficients using the Schur algorithm (instead of + * Levinson Durbin). + * \param acorr order+1 autocorrelation coefficients + * \param reflCoeff output reflection /ParCor coefficients. The first + * coefficient which is always 1.0 is ommitted. + * \param order number of acorr / reflCoeff coefficients. + * \param pPredictionGain_m prediction gain mantissa + * \param pPredictionGain_e prediction gain exponent + */ +void CLpc_AutoToParcor(FIXP_DBL acorr[], const int acorr_e, + FIXP_LPC reflCoeff[], const int order, + FIXP_DBL *pPredictionGain_m, INT *pPredictionGain_e); + +#endif /* FDK_LPC_H */ diff --git a/fdk-aac/libFDK/include/FDK_matrixCalloc.h b/fdk-aac/libFDK/include/FDK_matrixCalloc.h new file mode 100644 index 0000000..ffb54fe --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_matrixCalloc.h @@ -0,0 +1,230 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: matrix memory allocation + +*******************************************************************************/ + +#ifndef FDK_MATRIXCALLOC_H +#define FDK_MATRIXCALLOC_H + +#include "machine_type.h" +#include "genericStds.h" + +/* It is recommended to use FDK_ALLOCATE_MEMORY_1D instead of fdkCallocMatrix1D + */ +void* fdkCallocMatrix1D(UINT dim1, UINT size); +void* fdkCallocMatrix1D_aligned(UINT dim1, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_1D_INT instead of + * fdkCallocMatrix1D_int */ +void* fdkCallocMatrix1D_int(UINT dim1, UINT size, MEMORY_SECTION s); +void* fdkCallocMatrix1D_int_aligned(UINT dim1, UINT size, MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_1D instead of fdkFreeMatrix1D */ +void fdkFreeMatrix1D(void* p); +void fdkFreeMatrix1D_aligned(void* p); + +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D instead of fdkCallocMatrix2D + */ +void** fdkCallocMatrix2D(UINT dim1, UINT dim2, UINT size); +void** fdkCallocMatrix2D_aligned(UINT dim1, UINT dim2, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D_INT instead of + * fdkCallocMatrix2D_int */ +void** fdkCallocMatrix2D_int(UINT dim1, UINT dim2, UINT size, MEMORY_SECTION s); +/* It is recommended to use FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED instead of + * fdkCallocMatrix2D_int_aligned */ +void** fdkCallocMatrix2D_int_aligned(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_2D instead of fdkFreeMatrix2D */ +void fdkFreeMatrix2D(void** p); +/* It is recommended to use FDK_FREE_MEMORY_2D_ALIGNED instead of + * fdkFreeMatrix2D_aligned */ +void fdkFreeMatrix2D_aligned(void** p); + +/* It is recommended to use FDK_ALLOCATE_MEMORY_3D instead of fdkCallocMatrix3D + */ +void*** fdkCallocMatrix3D(UINT dim1, UINT dim2, UINT dim3, UINT size); +/* It is recommended to use FDK_ALLOCATE_MEMORY_3D_INT instead of + * fdkCallocMatrix3D_int */ +void*** fdkCallocMatrix3D_int(UINT dim1, UINT dim2, UINT dim3, UINT size, + MEMORY_SECTION s); +/* It is recommended to use FDK_FREE_MEMORY_3D instead of fdkFreeMatrix3D */ +void fdkFreeMatrix3D(void*** p); + +#define FDK_ALLOCATE_MEMORY_1D(a, dim1, type) \ + if (((a) = (type*)fdkCallocMatrix1D((dim1), sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_ALIGNED(a, dim1, type) \ + if (((a) = (type*)fdkCallocMatrix1D_aligned((dim1), sizeof(type))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_P(a, dim1, type, ptype) \ + if (((a) = (ptype)fdkCallocMatrix1D((dim1), sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_1D_INT(a, dim1, type, s) \ + if (((a) = (type*)fdkCallocMatrix1D_int((dim1), sizeof(type), (s))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_1D(a) \ + do { \ + fdkFreeMatrix1D((void*)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_FREE_MEMORY_1D_ALIGNED(a) \ + do { \ + fdkFreeMatrix1D_aligned((void*)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_ALLOCATE_MEMORY_2D(a, dim1, dim2, type) \ + if (((a) = (type**)fdkCallocMatrix2D((dim1), (dim2), sizeof(type))) == \ + NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_2D_INT(a, dim1, dim2, type, s) \ + if (((a) = (type**)fdkCallocMatrix2D_int((dim1), (dim2), sizeof(type), \ + (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(a, dim1, dim2, type, s) \ + if (((a) = (type**)fdkCallocMatrix2D_int_aligned( \ + (dim1), (dim2), sizeof(type), (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_2D(a) \ + do { \ + fdkFreeMatrix2D((void**)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_FREE_MEMORY_2D_ALIGNED(a) \ + do { \ + fdkFreeMatrix2D_aligned((void**)(a)); \ + (a) = NULL; \ + } while (0) + +#define FDK_ALLOCATE_MEMORY_3D(a, dim1, dim2, dim3, type) \ + if (((a) = (type***)fdkCallocMatrix3D((dim1), (dim2), (dim3), \ + sizeof(type))) == NULL) { \ + goto bail; \ + } + +#define FDK_ALLOCATE_MEMORY_3D_INT(a, dim1, dim2, dim3, type, s) \ + if (((a) = (type***)fdkCallocMatrix3D_int((dim1), (dim2), (dim3), \ + sizeof(type), (s))) == NULL) { \ + goto bail; \ + } + +#define FDK_FREE_MEMORY_3D(a) \ + do { \ + fdkFreeMatrix3D((void***)(a)); \ + (a) = NULL; \ + } while (0) + +#endif /* FDK_MATRIXCALLOC_H */ diff --git a/fdk-aac/libFDK/include/FDK_qmf_domain.h b/fdk-aac/libFDK/include/FDK_qmf_domain.h new file mode 100644 index 0000000..5c12682 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_qmf_domain.h @@ -0,0 +1,416 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Matthias Hildenbrand + + Description: Module to efficiently handle QMF data for multiple channels and + to share the data between e.g. SBR and MPS + +*******************************************************************************/ + +#ifndef FDK_QMF_DOMAIN_H +#define FDK_QMF_DOMAIN_H + +#include "qmf.h" + +typedef enum { + QMF_DOMAIN_OK = 0x0, /*!< No error occurred. */ + QMF_DOMAIN_OUT_OF_MEMORY = + 0x1, /*!< QMF-Configuration demands for more memory than allocated on + heap. */ + QMF_DOMAIN_INIT_ERROR = + 0x2, /*!< An error during filterbank-setup occurred. */ + QMF_DOMAIN_RESAMPLER_INIT_ERROR = + 0x3 /*!< An error during QMF-resampler-setup occurred. */ +} QMF_DOMAIN_ERROR; + +#define CMPLX_MOD (2) + +#define QMF_MAX_WB_SECTIONS (5) /* maximum number of workbuffer sections */ +#define QMF_WB_SECTION_SIZE (1024 * 2) + +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL) +H_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL) + +#define QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS (64) +#define QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS (QMF_MAX_SYNTHESIS_BANDS) +#define QMF_DOMAIN_MAX_QMF_PROC_BANDS (64) +#define QMF_DOMAIN_MAX_TIMESLOTS (64) +#define QMF_DOMAIN_MAX_OV_TIMESLOTS (12) + +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_16 (16) +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_24 (24) +#define QMF_DOMAIN_ANALYSIS_QMF_BANDS_32 (32) + +#define QMF_DOMAIN_TIMESLOTS_16 (16) +#define QMF_DOMAIN_TIMESLOTS_32 (32) + +#define QMF_DOMAIN_OV_TIMESLOTS_16 (3) +#define QMF_DOMAIN_OV_TIMESLOTS_32 (6) + +H_ALLOC_MEM(AnaQmfStates, FIXP_QAS) +H_ALLOC_MEM(SynQmfStates, FIXP_QSS) +H_ALLOC_MEM(QmfSlotsReal, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag, FIXP_DBL *) +H_ALLOC_MEM(QmfOverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(AnaQmfStates16, FIXP_QAS) +H_ALLOC_MEM(AnaQmfStates24, FIXP_QAS) +H_ALLOC_MEM(AnaQmfStates32, FIXP_QAS) +H_ALLOC_MEM(QmfSlotsReal16, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsReal32, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag16, FIXP_DBL *) +H_ALLOC_MEM(QmfSlotsImag32, FIXP_DBL *) +H_ALLOC_MEM(QmfOverlapBuffer16, FIXP_DBL) +H_ALLOC_MEM(QmfOverlapBuffer32, FIXP_DBL) + +#define QDOM_PCM INT_PCM + +/** + * Structure to hold the configuration data which is global whithin a QMF domain + * instance. + */ +typedef struct { + UCHAR qmfDomainExplicitConfig; /*!< Flag to signal that QMF domain is set + explicitly instead of SBR and MPS init + routines. */ + UCHAR nInputChannels; /*!< Number of QMF input channels. */ + UCHAR nInputChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nOutputChannels; /*!< Number of QMF output channels. */ + UCHAR nOutputChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + parkChannel; /*!< signal to automatically allocate additional memory to + park a channel if only one processing channel is + available. */ + UCHAR parkChannel_requested; + QDOM_PCM + *TDinput; /*!< Pointer to time domain data used as input for the QMF + analysis. */ + FIXP_DBL * + pWorkBuffer[QMF_MAX_WB_SECTIONS]; /*!< Pointerarray to volatile memory. */ + UINT flags; /*!< Flags to be set on all QMF analysis/synthesis filter + instances. */ + UINT flags_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nBandsAnalysis; /*!< Number of QMF analysis bands for all input + channels. */ + UCHAR nBandsAnalysis_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + USHORT nBandsSynthesis; /*!< Number of QMF synthesis bands for all output + channels. */ + USHORT + nBandsSynthesis_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nQmfTimeSlots; /*!< Number of QMF time slots (stored in work buffer + memory). */ + UCHAR nQmfTimeSlots_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + nQmfOvTimeSlots; /*!< Number of QMF overlap/delay time slots (stored in + persistent memory). */ + UCHAR nQmfOvTimeSlots_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR nQmfProcBands; /*!< Number of QMF bands which are processed by the + decoder. Typically this is equal to nBandsSynthesis + but it may differ if the QMF based resampler is being + used. */ + UCHAR nQmfProcBands_requested; /*!< Corresponding requested not yet active + configuration parameter. */ + UCHAR + nQmfProcChannels; /*!< Number of complete QMF channels which need to + coexist in memory at the same time. For most cases + this is 1 which means the work buffer can be shared + between audio channels. */ + UCHAR + nQmfProcChannels_requested; /*!< Corresponding requested not yet active + configuration parameter. */ +} FDK_QMF_DOMAIN_GC; +typedef FDK_QMF_DOMAIN_GC *HANDLE_FDK_QMF_DOMAIN_GC; + +/** + * Structure representing one QMF input channel. This includes the QMF analysis + * and the QMF domain data representation needed by the codec. Work buffer data + * may be shared between channels if the codec processes all QMF channels in a + * consecutive order. + */ +typedef struct { + HANDLE_FDK_QMF_DOMAIN_GC + pGlobalConf; /*!< Pointer to global configuration structure. */ + QMF_FILTER_BANK fb; /*!< QMF (analysis) filter bank structure. */ + QMF_SCALE_FACTOR scaling; /*!< Structure with scaling information. */ + UCHAR workBuf_nTimeSlots; /*!< Work buffer dimension for this channel is + (workBuf_nTimeSlots * workBuf_nBands * + CMPLX_MOD). */ + UCHAR workBuf_nBands; /*!< Work buffer dimension for this channel is + (workBuf_nTimeSlots * workBuf_nBands * CMPLX_MOD). */ + USHORT workBufferOffset; /*!< Offset within work buffer. */ + USHORT workBufferSectSize; /*!< Size of work buffer section. */ + FIXP_QAS * + pAnaQmfStates; /*!< Pointer to QMF analysis states (persistent memory). */ + FIXP_DBL + *pOverlapBuffer; /*!< Pointer to QMF overlap/delay memory (persistent + memory). */ + FIXP_DBL **pWorkBuffer; /*!< Pointer array to available work buffers. */ + FIXP_DBL * + *hQmfSlotsReal; /*!< Handle for QMF real data time slot pointer array. */ + FIXP_DBL **hQmfSlotsImag; /*!< Handle for QMF imaginary data time slot pointer + array. */ +} FDK_QMF_DOMAIN_IN; +typedef FDK_QMF_DOMAIN_IN *HANDLE_FDK_QMF_DOMAIN_IN; + +/** + * Structure representing one QMF output channel. + */ +typedef struct { + QMF_FILTER_BANK fb; /*!< QMF (synthesis) filter bank structure. */ + FIXP_QSS *pSynQmfStates; /*!< Pointer to QMF synthesis states (persistent + memory). */ +} FDK_QMF_DOMAIN_OUT; +typedef FDK_QMF_DOMAIN_OUT *HANDLE_FDK_QMF_DOMAIN_OUT; + +/** + * Structure representing the QMF domain for multiple channels. + */ +typedef struct { + FDK_QMF_DOMAIN_GC globalConf; /*!< Global configuration structure. */ + FDK_QMF_DOMAIN_IN + QmfDomainIn[((8) + (1))]; /*!< Array of QMF domain input structures */ + FDK_QMF_DOMAIN_OUT + QmfDomainOut[((8) + (1))]; /*!< Array of QMF domain output structures */ +} FDK_QMF_DOMAIN; +typedef FDK_QMF_DOMAIN *HANDLE_FDK_QMF_DOMAIN; + +/** + * \brief Check whether analysis- and synthesis-filterbank-states have been + * initialized. + * + * \param qd Pointer to QMF domain structure. + * + * \return 1 if initialized, 0 else + */ +int FDK_QmfDomain_IsInitialized(const HANDLE_FDK_QMF_DOMAIN qd); + +/** + * \brief Initialize QMF analysis and synthesis filter banks and set up QMF data + * representation. + * + * \param qd Pointer to QMF domain structure. + * \param extra_flags Initialize filter banks with extra flags which were not + * set in the global config flags field. + * + * \return 0 on success. + */ +int FDK_QmfDomain_InitFilterBank(HANDLE_FDK_QMF_DOMAIN qd, UINT extra_flags); + +/** + * \brief When QMF processing of one channel is finished copy the overlap/delay + * part into the persistent memory to be used in the next frame. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param offset + * + * \return void + */ +void FDK_QmfDomain_SaveOverlap(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, int offset); + +/** + * \brief Get one slot of QMF data and adapt the scaling. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ts Time slot number to be obtained. + * \param start_band Start index of QMF bands to be obtained. + * \param stop_band Stop index of QMF band to be obtained. + * \param pQmfOutReal Output buffer (real QMF data). + * \param pQmfOutImag Output buffer (imag QMF data). + * \param exp_out Target exponent (scaling) of data. + * + * \return void + */ +void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, + const int start_band, const int stop_band, + FIXP_DBL *pQmfOutReal, FIXP_DBL *pQmfOutImag, + const int exp_out); + +/** + * \brief Direct access to the work buffer associated with a certain channel (no + * time slot pointer array is used). + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ts Time slot number to be obtained. + * \param ppQmfReal Returns the pointer to the requested part of the work buffer + * (real time slot). + * \param ppQmfImag Returns the pointer to the requested part of the work buffer + * (imag time slot). + * + * \return void + */ +void FDK_QmfDomain_GetWorkBuffer(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + const int ts, FIXP_DBL **ppQmfReal, + FIXP_DBL **ppQmfImag); + +/** + * \brief For the case that the work buffer associated to this channel is not + * identical to the processing channel work buffer copy the data into the + * processing channel. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \return void + */ +void FDK_QmfDomain_WorkBuffer2ProcChannel(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch); + +/** + * \brief For the case of stereoCfgIndex3 with HBE the HBE buffer is copied into + * the processing channel work buffer and the processing channel work buffer is + * copied into the HBE buffer. + * + * \param qd_ch Pointer to a QMF domain input channel. + * \param ppQmfReal Pointer to a HBE QMF data buffer (real). + * \param ppQmfImag Pointer to a HBE QMF data buffer (imag). + * + * \return void + */ +void FDK_QmfDomain_QmfData2HBE(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + FIXP_DBL **ppQmfReal, FIXP_DBL **ppQmfImag); + +/** + * \brief Set all fields for requested parametervalues in global config struct + * FDK_QMF_DOMAIN_GC to 0. + * + * \param hgc Pointer to a QMF domain global config struct. + */ +void FDK_QmfDomain_ClearRequested(HANDLE_FDK_QMF_DOMAIN_GC hgc); + +/** + * \brief Check for parameter-change requests in global config and + * (re-)configure QMF domain accordingly. + * + * \param hqd Pointer to QMF domain + * + * \return errorcode + */ +QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Free QMF workbuffer, QMF persistent memory and configuration + * variables. + * + * \param hqd Pointer to QMF domain + */ +void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Clear QMF overlap buffers and QMF filter bank states. + * + * \param hqd Pointer to QMF domain + */ +QMF_DOMAIN_ERROR FDK_QmfDomain_ClearPersistentMemory(HANDLE_FDK_QMF_DOMAIN hqd); + +/** + * \brief Free QMF workbuffer and QMF persistent memory. + * + * \param hqd Pointer to QMF domain + * + * \param dmx_lp_mode downmix low power mode flag + */ +void FDK_QmfDomain_Close(HANDLE_FDK_QMF_DOMAIN hqd); + +#endif /* FDK_QMF_DOMAIN_H */ diff --git a/fdk-aac/libFDK/include/FDK_tools_rom.h b/fdk-aac/libFDK/include/FDK_tools_rom.h new file mode 100644 index 0000000..d1cb980 --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_tools_rom.h @@ -0,0 +1,398 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Oliver Moser + + Description: ROM tables used by FDK tools + +*******************************************************************************/ + +#ifndef FDK_TOOLS_ROM_H +#define FDK_TOOLS_ROM_H + +#include "common_fix.h" +#include "FDK_audio.h" + +/* sinetables */ + +/* None radix2 rotation vectors */ +extern RAM_ALIGN const FIXP_STB RotVectorReal60[60]; +extern RAM_ALIGN const FIXP_STB RotVectorImag60[60]; +extern RAM_ALIGN const FIXP_STB RotVectorReal192[192]; +extern RAM_ALIGN const FIXP_STB RotVectorImag192[192]; +extern RAM_ALIGN const FIXP_STB RotVectorReal240[210]; +extern RAM_ALIGN const FIXP_STB RotVectorImag240[210]; +extern RAM_ALIGN const FIXP_STB RotVectorReal480[480]; +extern RAM_ALIGN const FIXP_STB RotVectorImag480[480]; +extern RAM_ALIGN const FIXP_STB RotVectorReal6[6]; +extern RAM_ALIGN const FIXP_STB RotVectorImag6[6]; +extern RAM_ALIGN const FIXP_STB RotVectorReal12[12]; +extern RAM_ALIGN const FIXP_STB RotVectorImag12[12]; +extern RAM_ALIGN const FIXP_STB RotVectorReal24[24]; +extern RAM_ALIGN const FIXP_STB RotVectorImag24[24]; +extern RAM_ALIGN const FIXP_STB RotVectorReal48[48]; +extern RAM_ALIGN const FIXP_STB RotVectorImag48[48]; +extern RAM_ALIGN const FIXP_STB RotVectorReal80[80]; +extern RAM_ALIGN const FIXP_STB RotVectorImag80[80]; +extern RAM_ALIGN const FIXP_STB RotVectorReal96[96]; +extern RAM_ALIGN const FIXP_STB RotVectorImag96[96]; +extern RAM_ALIGN const FIXP_STB RotVectorReal384[384]; +extern RAM_ALIGN const FIXP_STB RotVectorImag384[384]; +extern RAM_ALIGN const FIXP_STB RotVectorReal20[20]; +extern RAM_ALIGN const FIXP_STB RotVectorImag20[20]; +extern RAM_ALIGN const FIXP_STB RotVectorReal120[120]; +extern RAM_ALIGN const FIXP_STB RotVectorImag120[120]; + +/* Regular sine tables */ +extern RAM_ALIGN const FIXP_STP SineTable1024[]; +extern RAM_ALIGN const FIXP_STP SineTable512[]; +extern RAM_ALIGN const FIXP_STP SineTable480[]; +extern RAM_ALIGN const FIXP_STP SineTable384[]; +extern RAM_ALIGN const FIXP_STP SineTable80[]; +#ifdef INCLUDE_SineTable10 +extern RAM_ALIGN const FIXP_STP SineTable10[]; +#endif + +/* AAC-LC windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow1024[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow1024[]; +extern RAM_ALIGN const FIXP_WTP SineWindow128[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow128[]; + +extern RAM_ALIGN const FIXP_WTP SineWindow960[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow960[]; +extern RAM_ALIGN const FIXP_WTP SineWindow120[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow120[]; + +/* AAC-LD windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow512[]; +#define LowOverlapWindow512 SineWindow128 +extern RAM_ALIGN const FIXP_WTP SineWindow480[]; +#define LowOverlapWindow480 SineWindow120 + +/* USAC TCX Window */ +extern RAM_ALIGN const FIXP_WTP SineWindow256[256]; +extern RAM_ALIGN const FIXP_WTP SineWindow192[]; + +/* USAC 8/3 windows */ +extern RAM_ALIGN const FIXP_WTP SineWindow768[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow768[]; +extern RAM_ALIGN const FIXP_WTP SineWindow96[]; +extern RAM_ALIGN const FIXP_WTP KBDWindow96[]; + +/* DCT and others */ +extern RAM_ALIGN const FIXP_WTP SineWindow64[]; +extern RAM_ALIGN const FIXP_WTP SineWindow48[]; +extern RAM_ALIGN const FIXP_WTP SineWindow32[]; +extern RAM_ALIGN const FIXP_WTP SineWindow24[]; +extern RAM_ALIGN const FIXP_WTP SineWindow16[]; +extern RAM_ALIGN const FIXP_WTP SineWindow8[]; + +/** + * \brief Helper table for window slope mapping. You should prefer the usage of + * the function FDKgetWindowSlope(), this table is only made public for some + * optimized access inside dct.cpp. + */ +extern const FIXP_WTP *const windowSlopes[2][4][9]; + +/** + * \brief Window slope access helper. Obtain a window of given length and shape. + * \param length Length of the window slope. + * \param shape Shape index of the window slope. 0: sine window, 1: + * Kaiser-Bessel. Any other value is applied a mask of 1 to, mapping it to + * either 0 or 1. + * \param Pointer to window slope or NULL if the requested window slope is not + * available. + */ +const FIXP_WTP *FDKgetWindowSlope(int length, int shape); + +extern const FIXP_WTP sin_twiddle_L64[]; + +/* + * Filter coefficient type definition + */ + +#if defined(ARCH_PREFER_MULT_16x16) || defined(ARCH_PREFER_MULT_32x16) +#define QMF_COEFF_16BIT +#endif + +#define QMF_FILTER_PROTOTYPE_SIZE 640 +#define QMF_NO_POLY 5 + +#ifdef QMF_COEFF_16BIT +#define FIXP_PFT FIXP_SGL +#define FIXP_QTW FIXP_SGL +#define FX_DBL2FX_QTW(x) FX_DBL2FX_SGL(x) +#else +#define FIXP_PFT FIXP_DBL +#define FIXP_QTW FIXP_DBL + +#define FX_DBL2FX_QTW(x) (x) + +#endif + +#define QMF640_PFT_TABLE_SIZE (640 / 2 + QMF_NO_POLY) + +/* Resampling twiddles for QMF */ + +/* Not resampling twiddles */ +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin32[32]; +/* Adapted analysis post-twiddles for down-sampled HQ SBR */ +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos_downsamp32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin_downsamp32[32]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos64[64]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin64[64]; +extern RAM_ALIGN const FIXP_PFT + qmf_pfilt640[QMF640_PFT_TABLE_SIZE + QMF_NO_POLY]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt640_vector[640]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos40[40]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin40[40]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt400[]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt200[]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt120[]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos24[24]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin24[24]; +extern RAM_ALIGN const FIXP_PFT qmf_pfilt240[]; + +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_cos16[16]; +extern RAM_ALIGN const FIXP_QTW qmf_phaseshift_sin16[16]; + +#define QMF640_CLDFB_PFT_TABLE_SIZE (640) +#define QMF320_CLDFB_PFT_TABLE_SIZE (320) +#define QMF_CLDFB_PFT_SCALE 1 + +extern const FIXP_QTW qmf_phaseshift_cos32_cldfb_ana[32]; +extern const FIXP_QTW qmf_phaseshift_cos32_cldfb_syn[32]; +extern const FIXP_QTW qmf_phaseshift_sin32_cldfb[32]; + +extern const FIXP_QTW qmf_phaseshift_cos16_cldfb_ana[16]; +extern const FIXP_QTW qmf_phaseshift_cos16_cldfb_syn[16]; +extern const FIXP_QTW qmf_phaseshift_sin16_cldfb[16]; + +extern const FIXP_QTW qmf_phaseshift_cos8_cldfb_ana[8]; +extern const FIXP_QTW qmf_phaseshift_cos8_cldfb_syn[8]; +extern const FIXP_QTW qmf_phaseshift_sin8_cldfb[8]; + +extern const FIXP_QTW qmf_phaseshift_cos64_cldfb[64]; +extern const FIXP_QTW qmf_phaseshift_sin64_cldfb[64]; + +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_640[QMF640_CLDFB_PFT_TABLE_SIZE]; +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_320[QMF320_CLDFB_PFT_TABLE_SIZE]; +#define QMF160_CLDFB_PFT_TABLE_SIZE (160) +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_160[QMF160_CLDFB_PFT_TABLE_SIZE]; +#define QMF80_CLDFB_PFT_TABLE_SIZE (80) +extern RAM_ALIGN const FIXP_PFT qmf_cldfb_80[QMF80_CLDFB_PFT_TABLE_SIZE]; + +#define QMF320_MPSLDFB_PFT_TABLE_SIZE (320) +#define QMF640_MPSLDFB_PFT_TABLE_SIZE (640) +#define QMF_MPSLDFB_PFT_SCALE 1 + +extern const FIXP_PFT qmf_mpsldfb_320[QMF320_MPSLDFB_PFT_TABLE_SIZE]; +extern RAM_ALIGN const FIXP_PFT qmf_mpsldfb_640[QMF640_MPSLDFB_PFT_TABLE_SIZE]; + +/** + * Audio bitstream element specific syntax flags: + */ +#define AC_EL_GA_CCE 0x00000001 /*!< GA AAC coupling channel element (CCE) */ + +/* + * Raw Data Block list items. + */ +typedef enum { + element_instance_tag, + common_window, /* -> decision for link_sequence */ + global_gain, + ics_info, /* ics_reserved_bit, window_sequence, window_shape, max_sfb, + scale_factor_grouping, predictor_data_present, ltp_data_present, + ltp_data */ + max_sfb, + ms, /* ms_mask_present, ms_used */ + /*predictor_data_present,*/ /* part of ics_info */ + ltp_data_present, + ltp_data, + section_data, + scale_factor_data, + pulse, /* pulse_data_present, pulse_data */ + tns_data_present, + tns_data, + gain_control_data_present, + gain_control_data, + esc1_hcr, + esc2_rvlc, + spectral_data, + + scale_factor_data_usac, + core_mode, /* -> decision for link_sequence */ + common_tw, + lpd_channel_stream, + tw_data, + noise, + ac_spectral_data, + fac_data, + tns_active, /* introduced in MPEG-D usac CD */ + tns_data_present_usac, + common_max_sfb, + + coupled_elements, /* only for CCE parsing */ + gain_element_lists, /* only for CCE parsing */ + + /* Non data list items */ + adtscrc_start_reg1, + adtscrc_start_reg2, + adtscrc_end_reg1, + adtscrc_end_reg2, + drmcrc_start_reg, + drmcrc_end_reg, + next_channel, + next_channel_loop, + link_sequence, + end_of_sequence +} rbd_id_t; + +struct element_list { + const rbd_id_t *id; + const struct element_list *next[2]; +}; + +typedef struct element_list element_list_t; +/** + * \brief get elementary stream pieces list for given parameters. + * \param aot audio object type + * \param epConfig the epConfig value from the current Audio Specific Config + * \param nChannels amount of channels contained in the current element. + * \param layer the layer of the current element. + * \param elFlags element specific flags. + * \return element_list_t parser guidance structure. + */ +const element_list_t *getBitstreamElementList(AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, UCHAR nChannels, + UCHAR layer, UINT elFlags); + +typedef enum { + /* n.a. */ + FDK_FORMAT_1_0 = 1, /* mono */ + FDK_FORMAT_2_0 = 2, /* stereo */ + FDK_FORMAT_3_0_FC = 3, /* 3/0.0 */ + FDK_FORMAT_3_1_0 = 4, /* 3/1.0 */ + FDK_FORMAT_5_0 = 5, /* 3/2.0 */ + FDK_FORMAT_5_1 = 6, /* 5.1 */ + FDK_FORMAT_7_1_ALT = 7, /* 5/2.1 ALT */ + /* 8 n.a.*/ + FDK_FORMAT_3_0_RC = 9, /* 2/1.0 */ + FDK_FORMAT_2_2_0 = 10, /* 2/2.0 */ + FDK_FORMAT_6_1 = 11, /* 3/3.1 */ + FDK_FORMAT_7_1 = 12, /* 3/4.1 */ + FDK_FORMAT_22_2 = 13, /* 22.2 */ + FDK_FORMAT_5_2_1 = 14, /* 5/2.1*/ + FDK_FORMAT_5_5_2 = 15, /* 5/5.2 */ + FDK_FORMAT_9_1 = 16, /* 5/4.1 */ + FDK_FORMAT_6_5_1 = 17, /* 6/5.1 */ + FDK_FORMAT_6_7_1 = 18, /* 6/7.1 */ + FDK_FORMAT_5_6_1 = 19, /* 5/6.1 */ + FDK_FORMAT_7_6_1 = 20, /* 7/6.1 */ + FDK_FORMAT_IN_LISTOFCHANNELS = 21, + FDK_FORMAT_OUT_LISTOFCHANNELS = 22, + /* 20 formats + In & Out list of channels */ + FDK_NFORMATS = 23, + FDK_FORMAT_FAIL = -1 +} FDK_converter_formatid_t; + +extern const INT format_nchan[FDK_NFORMATS + 9 - 2]; + +#endif diff --git a/fdk-aac/libFDK/include/FDK_trigFcts.h b/fdk-aac/libFDK/include/FDK_trigFcts.h new file mode 100644 index 0000000..153ca4c --- /dev/null +++ b/fdk-aac/libFDK/include/FDK_trigFcts.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Haricharan Lakshman, Manuel Jander + + Description: Trigonometric functions fixed point fractional implementation. + +*******************************************************************************/ + +#if !defined(FDK_TRIGFCTS_H) +#define FDK_TRIGFCTS_H + +#include "common_fix.h" + +#include "FDK_tools_rom.h" + +/* Fixed point precision definitions */ +#define Q(format) ((FIXP_DBL)(((LONG)1) << (format))) + +#ifndef M_PI +#define M_PI (3.14159265358979323846f) +#endif + +/*! + * Inverse tangent function. + */ + +/* --- fixp_atan() ---- */ +#define Q_ATANINP (25) // Input in q25, Output in q30 +#define Q_ATANOUT (30) +#define ATI_SF ((DFRACT_BITS - 1) - Q_ATANINP) /* 6 */ +#define ATI_SCALE ((float)(1 << ATI_SF)) +#define ATO_SF ((DFRACT_BITS - 1) - Q_ATANOUT) /* 1 ] -pi/2 .. pi/2 [ */ +#define ATO_SCALE ((float)(1 << ATO_SF)) +/* --- fixp_atan2() --- */ +#define Q_ATAN2OUT (29) +#define AT2O_SF ((DFRACT_BITS - 1) - Q_ATAN2OUT) /* 2 ] -pi .. pi ] */ +#define AT2O_SCALE ((float)(1 << AT2O_SF)) +// -------------------- + +FIXP_DBL fixp_atan(FIXP_DBL x); +FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x); + +FIXP_DBL fixp_cos(FIXP_DBL x, int scale); +FIXP_DBL fixp_sin(FIXP_DBL x, int scale); + +#define FIXP_COS_SIN + +#include "FDK_tools_rom.h" + +#define SINETAB SineTable512 +#define LD 9 + +#ifndef FUNCTION_inline_fixp_cos_sin + +#define FUNCTION_inline_fixp_cos_sin + +/* + * Calculates coarse lookup index and sign for sine. + * Returns delta x residual. + */ +static inline FIXP_DBL fixp_sin_cos_residual_inline(FIXP_DBL x, int scale, + FIXP_DBL *sine, + FIXP_DBL *cosine) { + FIXP_DBL residual; + int s; + int shift = (31 - scale - LD - 1); + int ssign = 1; + int csign = 1; + + residual = fMult(x, FL2FXCONST_DBL(1.0 / M_PI)); + s = ((LONG)residual) >> shift; + + residual &= ((1 << shift) - 1); + residual = fMult(residual, FL2FXCONST_DBL(M_PI / 4.0)) << 2; + residual <<= scale; + + /* Sine sign symmetry */ + if (s & ((1 << LD) << 1)) { + ssign = -ssign; + } + /* Cosine sign symmetry */ + if ((s + (1 << LD)) & ((1 << LD) << 1)) { + csign = -csign; + } + + s = fAbs(s); + + s &= (((1 << LD) << 1) - 1); /* Modulo PI */ + + if (s > (1 << LD)) { + s = ((1 << LD) << 1) - s; + } + + { + LONG sl, cl; + /* Because of packed table */ + if (s > (1 << (LD - 1))) { + FIXP_STP tmp; + /* Cosine/Sine simetry for angles greater than PI/4 */ + s = (1 << LD) - s; + tmp = SINETAB[s]; + sl = (LONG)tmp.v.re; + cl = (LONG)tmp.v.im; + } else { + FIXP_STP tmp; + tmp = SINETAB[s]; + sl = (LONG)tmp.v.im; + cl = (LONG)tmp.v.re; + } + +#ifdef SINETABLE_16BIT + *sine = (FIXP_DBL)((sl * ssign) << (DFRACT_BITS - FRACT_BITS)); + *cosine = (FIXP_DBL)((cl * csign) << (DFRACT_BITS - FRACT_BITS)); +#else + /* scale down by 1 for overflow prevention. This is undone at the calling + * function. */ + *sine = (FIXP_DBL)(sl * ssign) >> 1; + *cosine = (FIXP_DBL)(cl * csign) >> 1; +#endif + } + + return residual; +} + +/** + * \brief Calculate cosine and sine value each of 2 angles different angle + * values. + * \param x1 first angle value + * \param x2 second angle value + * \param scale exponent of x1 and x2 + * \param out pointer to 4 FIXP_DBL locations, were the values cos(x1), sin(x1), + * cos(x2), sin(x2) will be stored into. + */ +static inline void inline_fixp_cos_sin(FIXP_DBL x1, FIXP_DBL x2, + const int scale, FIXP_DBL *out) { + FIXP_DBL residual, error0, error1, sine, cosine; + residual = fixp_sin_cos_residual_inline(x1, scale, &sine, &cosine); + error0 = fMultDiv2(sine, residual); + error1 = fMultDiv2(cosine, residual); + +#ifdef SINETABLE_16BIT + *out++ = cosine - (error0 << 1); + *out++ = sine + (error1 << 1); +#else + /* Undo downscaling by 1 which was done at fixp_sin_cos_residual_inline */ + *out++ = SATURATE_LEFT_SHIFT(cosine - (error0 << 1), 1, DFRACT_BITS); + *out++ = SATURATE_LEFT_SHIFT(sine + (error1 << 1), 1, DFRACT_BITS); +#endif + + residual = fixp_sin_cos_residual_inline(x2, scale, &sine, &cosine); + error0 = fMultDiv2(sine, residual); + error1 = fMultDiv2(cosine, residual); + +#ifdef SINETABLE_16BIT + *out++ = cosine - (error0 << 1); + *out++ = sine + (error1 << 1); +#else + *out++ = SATURATE_LEFT_SHIFT(cosine - (error0 << 1), 1, DFRACT_BITS); + *out++ = SATURATE_LEFT_SHIFT(sine + (error1 << 1), 1, DFRACT_BITS); +#endif +} +#endif + +#endif /* !defined(FDK_TRIGFCTS_H) */ diff --git a/fdk-aac/libFDK/include/abs.h b/fdk-aac/libFDK/include/abs.h new file mode 100644 index 0000000..0846c96 --- /dev/null +++ b/fdk-aac/libFDK/include/abs.h @@ -0,0 +1,136 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: fixed point abs definitions + +*******************************************************************************/ + +#if !defined(ABS_H) +#define ABS_H + +#if defined(__mips__) +#include "mips/abs_mips.h" + +#elif defined(__x86__) +#include "x86/abs_x86.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixabs_D) +inline FIXP_DBL fixabs_D(FIXP_DBL x) { + return ((x) > (FIXP_DBL)(0)) ? (x) : -(x); +} +#endif + +#if !defined(FUNCTION_fixabs_I) +inline INT fixabs_I(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } +#endif + +#if !defined(FUNCTION_fixabs_S) +inline FIXP_SGL fixabs_S(FIXP_SGL x) { + return ((x) > (FIXP_SGL)(0)) ? (x) : -(x); +} +#endif + +#endif /* ABS_H */ diff --git a/fdk-aac/libFDK/include/arm/clz_arm.h b/fdk-aac/libFDK/include/arm/clz_arm.h new file mode 100644 index 0000000..1c3e1fb --- /dev/null +++ b/fdk-aac/libFDK/include/arm/clz_arm.h @@ -0,0 +1,164 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_ARM_H) +#define CLZ_ARM_H + +#if defined(__arm__) + +#if defined(__GNUC__) +/* ARM gcc*/ + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_8__) +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D +#define FUNCTION_fixnormz_S +#define FUNCTION_fixnorm_S + +#ifdef FUNCTION_fixnormz_D +inline INT fixnormz_D(LONG value) { + INT result; +#if defined(__ARM_ARCH_8__) + asm("clz %w0, %w1 " : "=r"(result) : "r"(value)); +#else + asm("clz %0, %1 " : "=r"(result) : "r"(value)); +#endif + return result; +} +#endif /* #ifdef FUNCTION_fixnormz_D */ + +#ifdef FUNCTION_fixnorm_D +inline INT fixnorm_D(LONG value) { + if (!value) return 0; + if (value < 0) value = ~value; + return fixnormz_D(value) - 1; +} +#endif /* #ifdef FUNCTION_fixnorm_D */ + +#ifdef FUNCTION_fixnormz_S +inline INT fixnormz_S(SHORT value) { + INT result; + result = (LONG)(value << 16); + if (result == 0) + result = 16; + else + result = fixnormz_D(result); + return result; +} +#endif /* #ifdef FUNCTION_fixnormz_S */ + +#ifdef FUNCTION_fixnorm_S +inline INT fixnorm_S(SHORT value) { + LONG lvalue = (LONG)(value << 16); + if (!lvalue) return 0; + if (lvalue < 0) lvalue = ~lvalue; + return fixnormz_D(lvalue) - 1; +} +#endif /* #ifdef FUNCTION_fixnorm_S */ + +#endif + +#endif /* arm toolchain */ + +#endif /* __arm__ */ + +#endif /* !defined(CLZ_ARM_H) */ diff --git a/fdk-aac/libFDK/include/arm/cplx_mul_arm.h b/fdk-aac/libFDK/include/arm/cplx_mul_arm.h new file mode 100644 index 0000000..a448e33 --- /dev/null +++ b/fdk-aac/libFDK/include/arm/cplx_mul_arm.h @@ -0,0 +1,201 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_ARM_H) +#define CPLX_MUL_ARM_H + +#if defined(__arm__) && defined(__GNUC__) + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) || \ + defined(__ARM_ARCH_8__) +#define FUNCTION_cplxMultDiv2_32x16 +#define FUNCTION_cplxMultDiv2_32x16X2 +#endif + +#define FUNCTION_cplxMultDiv2_32x32X2 +#ifdef FUNCTION_cplxMultDiv2_32x32X2 +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + LONG tmp1, tmp2; + +#ifdef __ARM_ARCH_8__ + asm("smull %x0, %w2, %w4; \n" /* tmp1 = a_Re * b_Re */ + "smull %x1, %w2, %w5; \n" /* tmp2 = a_Re * b_Im */ + "smsubl %x0, %w3, %w5, %x0; \n" /* tmp1 -= a_Im * b_Im */ + "smaddl %x1, %w3, %w4, %x1; \n" /* tmp2 += a_Im * b_Re */ + "asr %x0, %x0, #32 \n" + "asr %x1, %x1, #32 \n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); +#elif defined(__ARM_ARCH_6__) + asm("smmul %0, %2, %4;\n" /* tmp1 = a_Re * b_Re */ + "smmls %0, %3, %5, %0;\n" /* tmp1 -= a_Im * b_Im */ + "smmul %1, %2, %5;\n" /* tmp2 = a_Re * b_Im */ + "smmla %1, %3, %4, %1;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); +#else + LONG discard; + asm("smull %2, %0, %7, %6;\n" /* tmp1 = -a_Im * b_Im */ + "smlal %2, %0, %3, %5;\n" /* tmp1 += a_Re * b_Re */ + "smull %2, %1, %3, %6;\n" /* tmp2 = a_Re * b_Im */ + "smlal %2, %1, %4, %5;\n" /* tmp2 += a_Im * b_Re */ + : "=&r"(tmp1), "=&r"(tmp2), "=&r"(discard) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im), "r"(-a_Im)); +#endif + *c_Re = tmp1; + *c_Im = tmp2; +} +#endif /* FUNCTION_cplxMultDiv2_32x32X2 */ + +#if defined(FUNCTION_cplxMultDiv2_32x16) +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, FIXP_SPK wpk) { +#ifdef __ARM_ARCH_8__ + FIXP_DBL b_Im = FX_SGL2FX_DBL(wpk.v.im); + FIXP_DBL b_Re = FX_SGL2FX_DBL(wpk.v.re); + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, b_Re, b_Im); +#else + LONG tmp1, tmp2; + const LONG w = wpk.w; + asm("smulwt %0, %3, %4;\n" + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" + "smulwt %1, %2, %4;\n" + "smlawb %1, %3, %4, %1;\n" + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(w)); + *c_Re = tmp1; + *c_Im = tmp2; +#endif +} +#endif /* FUNCTION_cplxMultDiv2_32x16 */ + +#ifdef FUNCTION_cplxMultDiv2_32x16X2 +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { +#ifdef __ARM_ARCH_8__ + FIXP_DBL b_re = FX_SGL2FX_DBL(b_Re); + FIXP_DBL b_im = FX_SGL2FX_DBL(b_Im); + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, b_re, b_im); +#else + LONG tmp1, tmp2; + + asm("smulwb %0, %3, %5;\n" /* %7 = -a_Im * b_Im */ + "rsb %1,%0,#0;\n" + "smlawb %0, %2, %4, %1;\n" /* tmp1 = a_Re * b_Re - a_Im * b_Im */ + "smulwb %1, %2, %5;\n" /* %7 = a_Re * b_Im */ + "smlawb %1, %3, %4, %1;\n" /* tmp2 = a_Im * b_Re + a_Re * b_Im */ + : "=&r"(tmp1), "=&r"(tmp2) + : "r"(a_Re), "r"(a_Im), "r"(b_Re), "r"(b_Im)); + + *c_Re = tmp1; + *c_Im = tmp2; +#endif +} +#endif /* FUNCTION_cplxMultDiv2_32x16X2 */ + +#endif + +#endif /* !defined(CPLX_MUL_ARM_H) */ diff --git a/fdk-aac/libFDK/include/arm/fixmadd_arm.h b/fdk-aac/libFDK/include/arm/fixmadd_arm.h new file mode 100644 index 0000000..1378660 --- /dev/null +++ b/fdk-aac/libFDK/include/arm/fixmadd_arm.h @@ -0,0 +1,220 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMADD_ARM_H) +#define FIXMADD_ARM_H + +#if defined(__arm__) + +/* ############################################################################# + */ +#if defined(__GNUC__) && defined(__arm__) +/* ############################################################################# + */ +/* ARM GNU GCC */ + +#ifdef __ARM_ARCH_8__ +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT64 result; + asm("smull %x0, %w1, %w2; \n" + "asr %x0, %x0, #32; \n" + "add %w0, %w3, %w0; \n" + : "=&r"(result) + : "r"(a), "r"(b), "r"(x)); + return (INT)result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ + +#define FUNCTION_fixmsubdiv2_DD +#ifdef FUNCTION_fixmsubdiv2_DD +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT64 result; + asm("smull %x0, %w1, %w2; \n" + "asr %x0, %x0, #32; \n" + "sub %w0, %w3, %w0; \n" + : "=&r"(result) + : "r"(a), "r"(b), "r"(x)); + return (INT)result; +} +#endif /* #ifdef FUNCTION_fixmsubdiv2_DD */ + +#elif defined(__ARM_ARCH_6__) +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm("smmla %0, %1, %2, %3;\n" : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ + +#define FUNCTION_fixmsubdiv2_DD +#ifdef FUNCTION_fixmsubdiv2_DD +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT result; + asm("smmls %0, %1, %2, %3;\n" : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmsubdiv2_DD */ + +#else +#define FUNCTION_fixmadddiv2_DD +#ifdef FUNCTION_fixmadddiv2_DD +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + INT discard = 0; + INT result = x; + asm("smlal %0, %1, %2, %3;\n" : "+r"(discard), "+r"(result) : "r"(a), "r"(b)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DD */ +#endif + +#if defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) + +#define FUNCTION_fixmadddiv2_DS +#ifdef FUNCTION_fixmadddiv2_DS +inline FIXP_DBL fixmadddiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { + INT result; + asm("smlawb %0, %1, %2, %3 " : "=r"(result) : "r"(a), "r"(b), "r"(x)); + return result; +} +#endif /* #ifdef FUNCTION_fixmadddiv2_DS */ + +#endif /* defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) */ + +#define FUNCTION_fixmadddiv2BitExact_DD +#ifdef FUNCTION_fixmadddiv2BitExact_DD +#define fixmadddiv2BitExact_DD(a, b, c) fixmadddiv2_DD(a, b, c) +#endif /* #ifdef FUNCTION_fixmadddiv2BitExact_DD */ + +#define FUNCTION_fixmsubdiv2BitExact_DD +#ifdef FUNCTION_fixmsubdiv2BitExact_DD +inline FIXP_DBL fixmsubdiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x - fixmuldiv2BitExact_DD(a, b); +} +#endif /* #ifdef FUNCTION_fixmsubdiv2BitExact_DD */ + +#define FUNCTION_fixmadddiv2BitExact_DS +#ifdef FUNCTION_fixmadddiv2BitExact_DS +#define fixmadddiv2BitExact_DS(a, b, c) fixmadddiv2_DS(a, b, c) +#endif /* #ifdef FUNCTION_fixmadddiv2BitExact_DS */ + +#define FUNCTION_fixmsubdiv2BitExact_DS +#ifdef FUNCTION_fixmsubdiv2BitExact_DS +inline FIXP_DBL fixmsubdiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { + return x - fixmuldiv2BitExact_DS(a, b); +} +#endif /* #ifdef FUNCTION_fixmsubdiv2BitExact_DS */ + +/* ############################################################################# + */ +#endif /* toolchain */ + /* ############################################################################# + */ + +#endif /* __arm__ */ + +#endif /* !defined(FIXMADD_ARM_H) */ diff --git a/fdk-aac/libFDK/include/arm/fixmul_arm.h b/fdk-aac/libFDK/include/arm/fixmul_arm.h new file mode 100644 index 0000000..077e5c6 --- /dev/null +++ b/fdk-aac/libFDK/include/arm/fixmul_arm.h @@ -0,0 +1,198 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_ARM_H) +#define FIXMUL_ARM_H + +#if defined(__arm__) + +#if defined(__GNUC__) && defined(__arm__) +/* ARM with GNU compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#ifdef FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) +#endif /* #ifdef FUNCTION_fixmuldiv2BitExact_DD */ + +#define FUNCTION_fixmulBitExact_DD +#ifdef FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) (fixmuldiv2BitExact_DD(a, b) << 1) +#endif /* #ifdef FUNCTION_fixmulBitExact_DD */ + +#define FUNCTION_fixmuldiv2BitExact_DS +#ifdef FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) +#endif /* #ifdef FUNCTION_fixmuldiv2BitExact_DS */ + +#define FUNCTION_fixmulBitExact_DS +#ifdef FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) +#endif /* #ifdef FUNCTION_fixmulBitExact_DS */ + +#ifdef FUNCTION_fixmuldiv2_DD +inline INT fixmuldiv2_DD(const INT a, const INT b) { + INT result; +#if defined(__ARM_ARCH_8__) + INT64 result64; + __asm__( + "smull %x0, %w1, %w2;\n" + "asr %x0, %x0, #32; " + : "=r"(result64) + : "r"(a), "r"(b)); + result = (INT)result64; +#elif defined(__ARM_ARCH_6__) || defined(__TARGET_ARCH_7E_M) + __asm__("smmul %0, %1, %2" : "=r"(result) : "r"(a), "r"(b)); +#else + INT discard; + __asm__("smull %0, %1, %2, %3" + : "=&r"(discard), "=r"(result) + : "r"(a), "r"(b)); +#endif + return result; +} +#endif /* #ifdef FUNCTION_fixmuldiv2_DD */ + +#if defined(__ARM_ARCH_8__) +#define FUNCTION_fixmuldiv2_SD +#ifdef FUNCTION_fixmuldiv2_SD +inline INT fixmuldiv2_SD(const SHORT a, const INT b) { + return fixmuldiv2_DD((INT)(a << 16), b); +} +#endif /* #ifdef FUNCTION_fixmuldiv2_SD */ +#elif defined(__ARM_ARCH_5TE__) || defined(__ARM_ARCH_6__) +#define FUNCTION_fixmuldiv2_SD +#ifdef FUNCTION_fixmuldiv2_SD +inline INT fixmuldiv2_SD(const SHORT a, const INT b) { + INT result; + __asm__("smulwb %0, %1, %2" : "=r"(result) : "r"(b), "r"(a)); + return result; +} +#endif /* #ifdef FUNCTION_fixmuldiv2_SD */ +#endif + +#define FUNCTION_fixmul_DD +#ifdef FUNCTION_fixmul_DD +#if defined(__ARM_ARCH_8__) +inline INT fixmul_DD(const INT a, const INT b) { + INT64 result64; + + __asm__( + "smull %x0, %w1, %w2;\n" + "asr %x0, %x0, #31; " + : "=r"(result64) + : "r"(a), "r"(b)); + return (INT)result64; +} +#else +inline INT fixmul_DD(const INT a, const INT b) { + return (fixmuldiv2_DD(a, b) << 1); +} +#endif /* __ARM_ARCH_8__ */ +#endif /* #ifdef FUNCTION_fixmul_DD */ + +#endif /* defined(__GNUC__) && defined(__arm__) */ + +#endif /* __arm__ */ + +#endif /* !defined(FIXMUL_ARM_H) */ diff --git a/fdk-aac/libFDK/include/arm/scale_arm.h b/fdk-aac/libFDK/include/arm/scale_arm.h new file mode 100644 index 0000000..0bf4f66 --- /dev/null +++ b/fdk-aac/libFDK/include/arm/scale_arm.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: ARM scaling operations + +*******************************************************************************/ + +#if !defined(SCALE_ARM_H) +#define SCALE_ARM_H + +#if defined(__GNUC__) /* GCC Compiler */ + +#if defined(__ARM_ARCH_6__) + +inline static INT shiftRightSat(INT src, int scale) { + INT result; + asm("ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src >> scale), "M"(SAMPLE_BITS)); + + return result; +} + +#define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) shiftRightSat(src, scale) + +inline static INT shiftLeftSat(INT src, int scale) { + INT result; + asm("ssat %0,%2,%0;\n" + + : "=&r"(result) + : "r"(src << scale), "M"(SAMPLE_BITS)); + + return result; +} + +#define SATURATE_INT_PCM_LEFT_SHIFT(src, scale) shiftLeftSat(src, scale) + +#endif /* __ARM_ARCH_6__ */ + +#endif /* compiler selection */ + +#define FUNCTION_scaleValueInPlace +#ifdef FUNCTION_scaleValueInPlace +inline void scaleValueInPlace(FIXP_DBL *value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + INT newscale; + if ((newscale = scalefactor) >= 0) + *value <<= newscale; + else + *value >>= -newscale; +} +#endif /* #ifdef FUNCTION_scaleValueInPlace */ + +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ((((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS - 1))) >> (scale)) > \ + (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? ((LONG)(src) >> (DFRACT_BITS - 1)) ^ (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) >> (scale)) + +#define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + (((LONG)(src) ^ ((LONG)(src) >> (DFRACT_BITS - 1))) > \ + ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ((LONG)(src) >> (DFRACT_BITS - 1)) ^ (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) << (scale)) + +#endif /* !defined(SCALE_ARM_H) */ diff --git a/fdk-aac/libFDK/include/arm/scramble_arm.h b/fdk-aac/libFDK/include/arm/scramble_arm.h new file mode 100644 index 0000000..a7cfe65 --- /dev/null +++ b/fdk-aac/libFDK/include/arm/scramble_arm.h @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: bitreversal of input data + +*******************************************************************************/ + +#if !defined(SCRAMBLE_ARM_H) +#define SCRAMBLE_ARM_H + +#if defined(FUNCTION_scramble) +#if defined(__GNUC__) + +#define FUNCTION_scramble + +#if defined(__ARM_ARCH_5TE__) +#define USE_LDRD_STRD /* LDRD requires 8 byte data alignment. */ +#endif + +inline void scramble(FIXP_DBL x[], INT n) { + FDK_ASSERT(!(((INT)x) & (ALIGNMENT_DEFAULT - 1))); + asm("mov r2, #1;\n" /* r2(m) = 1; */ + "sub r3, %1, #1;\n" /* r3 = n-1; */ + "mov r4, #0;\n" /* r4(j) = 0; */ + + "scramble_m_loop%=:\n" /* { */ + "mov r5, %1;\n" /* r5(k) = 1; */ + + "scramble_k_loop%=:\n" /* { */ + "mov r5, r5, lsr #1;\n" /* k >>= 1; */ + "eor r4, r4, r5;\n" /* j ^=k; */ + "ands r10, r4, r5;\n" /* r10 = r4 & r5; */ + "beq scramble_k_loop%=;\n" /* } while (r10 == 0); */ + + "cmp r4, r2;\n" /* if (r4 < r2) break; */ + "bcc scramble_m_loop_end%=;\n" + +#ifdef USE_LDRD_STRD + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldrd r10, [%0, r5];\n" /* r10 = x[r5], x7 = x[r5+1] */ + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldrd r8, [%0, r6];\n" /* r8 = x[r6], r9 = x[r6+1]; */ + "strd r10, [%0, r6];\n" /* x[r6,r6+1] = r10,r11; */ + "strd r8, [%0, r5];\n" /* x[r5,r5+1] = r8,r9; */ +#else + "mov r5, r2, lsl #3;\n" /* m(r5) = r2*4*2 */ + "ldr r10, [%0, r5];\n" + "mov r6, r4, lsl #3;\n" /* j(r6) = r4*4*2 */ + "ldr r11, [%0, r6];\n" + + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" + + "add r5, r5, #4;" + "ldr r10, [%0, r5];\n" + "add r6, r6, #4;" + "ldr r11, [%0, r6];\n" + "str r10, [%0, r6];\n" + "str r11, [%0, r5];\n" +#endif + "scramble_m_loop_end%=:\n" + "add r2, r2, #1;\n" /* r2++; */ + "cmp r2, r3;\n" + "bcc scramble_m_loop%=;\n" /* } while (r2(m) < r3(n-1)); */ + : + : "r"(x), "r"(n) +#ifdef USE_LDRD_STRD + : "r2", "r3", "r4", "r5", "r10", "r11", "r8", "r9", "r6"); +#else + : "r2", "r3", "r4", "r5", "r10", "r11", "r6"); +#endif +} +#else +/* Force C implementation if no assembler version available. */ +#undef FUNCTION_scramble +#endif /* Toolchain selection. */ + +#endif /* defined(FUNCTION_scramble) */ +#endif /* !defined(SCRAMBLE_ARM_H) */ diff --git a/fdk-aac/libFDK/include/autocorr2nd.h b/fdk-aac/libFDK/include/autocorr2nd.h new file mode 100644 index 0000000..e01989b --- /dev/null +++ b/fdk-aac/libFDK/include/autocorr2nd.h @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: fixed point abs definitions + +*******************************************************************************/ + +#ifndef AUTOCORR2ND_H +#define AUTOCORR2ND_H + +#include "common_fix.h" + +typedef struct { + FIXP_DBL r00r; + FIXP_DBL r11r; + FIXP_DBL r22r; + FIXP_DBL r01r; + FIXP_DBL r02r; + FIXP_DBL r12r; + FIXP_DBL r01i; + FIXP_DBL r02i; + FIXP_DBL r12i; + FIXP_DBL det; + int det_scale; +} ACORR_COEFS; + +#define LPC_ORDER 2 + +INT autoCorr2nd_real( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const int len /*!< Number of qmf slots */ +); + +INT autoCorr2nd_cplx( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of spectrum */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of spectrum */ + const int len /*!< Number of qmf slots */ +); + +#endif /* AUTOCORR2ND_H */ diff --git a/fdk-aac/libFDK/include/clz.h b/fdk-aac/libFDK/include/clz.h new file mode 100644 index 0000000..df75618 --- /dev/null +++ b/fdk-aac/libFDK/include/clz.h @@ -0,0 +1,205 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Marc Gayer + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_H) +#define CLZ_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +#if defined(__arm__) +#include "arm/clz_arm.h" + +#elif defined(__mips__) +#include "mips/clz_mips.h" + +#elif defined(__x86__) +#include "x86/clz_x86.h" + +#elif defined(__powerpc__) +#include "ppc/clz_ppc.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixnormz_S) +#ifdef FUNCTION_fixnormz_D +inline INT fixnormz_S(SHORT a) { + if (a < 0) { + return 0; + } + return fixnormz_D((INT)(a)) - 16; +} +#else +inline INT fixnormz_S(SHORT a) { + int leadingBits = 0; + a = ~a; + while (a & 0x8000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnormz_D) +inline INT fixnormz_D(LONG a) { + INT leadingBits = 0; + a = ~a; + while (a & 0x80000000) { + leadingBits++; + a <<= 1; + } + + return (leadingBits); +} +#endif + +/***************************************************************************** + + functionname: fixnorm_D + description: Count leading ones or zeros of operand val for dfract/LONG INT +values. Return this value minus 1. Return 0 if operand==0. +*****************************************************************************/ +#if !defined(FUNCTION_fixnorm_S) +#ifdef FUNCTION_fixnorm_D +inline INT fixnorm_S(FIXP_SGL val) { + if (val == (FIXP_SGL)0) { + return 0; + } + return fixnorm_D((INT)(val)) - 16; +} +#else +inline INT fixnorm_S(FIXP_SGL val) { + INT leadingBits = 0; + if (val != (FIXP_SGL)0) { + if (val < (FIXP_SGL)0) { + val = ~val; + } + leadingBits = fixnormz_S(val) - 1; + } + return (leadingBits); +} +#endif +#endif + +#if !defined(FUNCTION_fixnorm_D) +inline INT fixnorm_D(FIXP_DBL val) { + INT leadingBits = 0; + if (val != (FIXP_DBL)0) { + if (val < (FIXP_DBL)0) { + val = ~val; + } + leadingBits = fixnormz_D(val) - 1; + } + return (leadingBits); +} +#endif + +#endif /* CLZ_H */ diff --git a/fdk-aac/libFDK/include/common_fix.h b/fdk-aac/libFDK/include/common_fix.h new file mode 100644 index 0000000..7c08225 --- /dev/null +++ b/fdk-aac/libFDK/include/common_fix.h @@ -0,0 +1,449 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: Flexible fixpoint library configuration + +*******************************************************************************/ + +#ifndef COMMON_FIX_H +#define COMMON_FIX_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* ***** Start of former fix.h ****** */ + +/* Define bit sizes of integer fixpoint fractional data types */ +#define FRACT_BITS 16 /* single precision */ +#define DFRACT_BITS 32 /* double precision */ +#define ACCU_BITS 40 /* double precision plus overflow */ + +/* Fixpoint equivalent type fot PCM audio time domain data. */ +#if defined(SAMPLE_BITS) +#if (SAMPLE_BITS == DFRACT_BITS) +#define FIXP_PCM FIXP_DBL +#define MAXVAL_FIXP_PCM MAXVAL_DBL +#define MINVAL_FIXP_PCM MINVAL_DBL +#define FX_PCM2FX_DBL(x) ((FIXP_DBL)(x)) +#define FX_DBL2FX_PCM(x) ((INT_PCM)(x)) +#elif (SAMPLE_BITS == FRACT_BITS) +#define FIXP_PCM FIXP_SGL +#define MAXVAL_FIXP_PCM MAXVAL_SGL +#define MINVAL_FIXP_PCM MINVAL_SGL +#define FX_PCM2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) +#define FX_DBL2FX_PCM(x) FX_DBL2FX_SGL(x) +#else +#error SAMPLE_BITS different from FRACT_BITS or DFRACT_BITS not implemented! +#endif +#endif + +/* ****** End of former fix.h ****** */ + +#define SGL_MASK ((1UL << FRACT_BITS) - 1) /* 16bit: (2^16)-1 = 0xFFFF */ + +#define MAX_SHIFT_SGL \ + (FRACT_BITS - 1) /* maximum possible shift for FIXP_SGL values */ +#define MAX_SHIFT_DBL \ + (DFRACT_BITS - 1) /* maximum possible shift for FIXP_DBL values */ + +/* Scale factor from/to float/fixpoint values. DO NOT USE THESE VALUES AS + * SATURATION LIMITS !! */ +#define FRACT_FIX_SCALE ((INT64(1) << (FRACT_BITS - 1))) +#define DFRACT_FIX_SCALE ((INT64(1) << (DFRACT_BITS - 1))) + +/* Max and Min values for saturation purposes. DO NOT USE THESE VALUES AS SCALE + * VALUES !! */ +#define MAXVAL_SGL \ + ((signed)0x00007FFF) /* this has to be synchronized to FRACT_BITS */ +#define MINVAL_SGL \ + ((signed)0xFFFF8000) /* this has to be synchronized to FRACT_BITS */ +#define MAXVAL_DBL \ + ((signed)0x7FFFFFFF) /* this has to be synchronized to DFRACT_BITS */ +#define MINVAL_DBL \ + ((signed)0x80000000) /* this has to be synchronized to DFRACT_BITS */ + +#define FX_DBL2FXCONST_SGL(val) \ + ((((((val) >> (DFRACT_BITS - FRACT_BITS - 1)) + 1) > \ + (((LONG)1 << FRACT_BITS) - 1)) && \ + ((LONG)(val) > 0)) \ + ? (FIXP_SGL)(SHORT)(((LONG)1 << (FRACT_BITS - 1)) - 1) \ + : (FIXP_SGL)(SHORT)((((val) >> (DFRACT_BITS - FRACT_BITS - 1)) + 1) >> \ + 1)) + +#define shouldBeUnion union /* unions are possible */ + +typedef SHORT FIXP_SGL; +typedef LONG FIXP_DBL; + +/* macros for compile-time conversion of constant float values to fixedpoint */ +#define FL2FXCONST_SPC FL2FXCONST_DBL + +#define MINVAL_DBL_CONST MINVAL_DBL +#define MINVAL_SGL_CONST MINVAL_SGL + +#define FL2FXCONST_SGL(val) \ + (FIXP_SGL)( \ + ((val) >= 0) \ + ? ((((double)(val) * (FRACT_FIX_SCALE) + 0.5) >= \ + (double)(MAXVAL_SGL)) \ + ? (SHORT)(MAXVAL_SGL) \ + : (SHORT)((double)(val) * (double)(FRACT_FIX_SCALE) + 0.5)) \ + : ((((double)(val) * (FRACT_FIX_SCALE)-0.5) <= \ + (double)(MINVAL_SGL_CONST)) \ + ? (SHORT)(MINVAL_SGL_CONST) \ + : (SHORT)((double)(val) * (double)(FRACT_FIX_SCALE)-0.5))) + +#define FL2FXCONST_DBL(val) \ + (FIXP_DBL)( \ + ((val) >= 0) \ + ? ((((double)(val) * (DFRACT_FIX_SCALE) + 0.5) >= \ + (double)(MAXVAL_DBL)) \ + ? (LONG)(MAXVAL_DBL) \ + : (LONG)((double)(val) * (double)(DFRACT_FIX_SCALE) + 0.5)) \ + : ((((double)(val) * (DFRACT_FIX_SCALE)-0.5) <= \ + (double)(MINVAL_DBL_CONST)) \ + ? (LONG)(MINVAL_DBL_CONST) \ + : (LONG)((double)(val) * (double)(DFRACT_FIX_SCALE)-0.5))) + +/* macros for runtime conversion of float values to integer fixedpoint. NO + * OVERFLOW CHECK!!! */ +#define FL2FX_SPC FL2FX_DBL +#define FL2FX_SGL(val) \ + ((val) > 0.0f ? (SHORT)((val) * (float)(FRACT_FIX_SCALE) + 0.5f) \ + : (SHORT)((val) * (float)(FRACT_FIX_SCALE)-0.5f)) +#define FL2FX_DBL(val) \ + ((val) > 0.0f ? (LONG)((val) * (float)(DFRACT_FIX_SCALE) + 0.5f) \ + : (LONG)((val) * (float)(DFRACT_FIX_SCALE)-0.5f)) + +/* macros for runtime conversion of fixedpoint values to other fixedpoint. NO + * ROUNDING!!! */ +#define FX_ACC2FX_SGL(val) ((FIXP_SGL)((val) >> (ACCU_BITS - FRACT_BITS))) +#define FX_ACC2FX_DBL(val) ((FIXP_DBL)((val) >> (ACCU_BITS - DFRACT_BITS))) +#define FX_SGL2FX_ACC(val) ((FIXP_ACC)((LONG)(val) << (ACCU_BITS - FRACT_BITS))) +#define FX_SGL2FX_DBL(val) \ + ((FIXP_DBL)((LONG)(val) << (DFRACT_BITS - FRACT_BITS))) +#define FX_DBL2FX_SGL(val) ((FIXP_SGL)((val) >> (DFRACT_BITS - FRACT_BITS))) + +/* ############################################################# */ + +/* macros for runtime conversion of integer fixedpoint values to float. */ + +/* #define FX_DBL2FL(val) ((float)(pow(2.,-31.)*(float)val)) */ /* version #1 + */ +#define FX_DBL2FL(val) \ + ((float)((double)(val) / (double)DFRACT_FIX_SCALE)) /* version #2 - \ + identical to class \ + dfract cast from \ + dfract to float */ +#define FX_DBL2DOUBLE(val) (((double)(val) / (double)DFRACT_FIX_SCALE)) + +/* ############################################################# */ +#include "fixmul.h" + +FDK_INLINE LONG fMult(SHORT a, SHORT b) { return fixmul_SS(a, b); } +FDK_INLINE LONG fMult(SHORT a, LONG b) { return fixmul_SD(a, b); } +FDK_INLINE LONG fMult(LONG a, SHORT b) { return fixmul_DS(a, b); } +FDK_INLINE LONG fMult(LONG a, LONG b) { return fixmul_DD(a, b); } +FDK_INLINE LONG fPow2(LONG a) { return fixpow2_D(a); } +FDK_INLINE LONG fPow2(SHORT a) { return fixpow2_S(a); } + +FDK_INLINE LONG fMultDiv2(SHORT a, SHORT b) { return fixmuldiv2_SS(a, b); } +FDK_INLINE LONG fMultDiv2(SHORT a, LONG b) { return fixmuldiv2_SD(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, SHORT b) { return fixmuldiv2_DS(a, b); } +FDK_INLINE LONG fMultDiv2(LONG a, LONG b) { return fixmuldiv2_DD(a, b); } +FDK_INLINE LONG fPow2Div2(LONG a) { return fixpow2div2_D(a); } +FDK_INLINE LONG fPow2Div2(SHORT a) { return fixpow2div2_S(a); } + +FDK_INLINE LONG fMultDiv2BitExact(LONG a, LONG b) { + return fixmuldiv2BitExact_DD(a, b); +} +FDK_INLINE LONG fMultDiv2BitExact(SHORT a, LONG b) { + return fixmuldiv2BitExact_SD(a, b); +} +FDK_INLINE LONG fMultDiv2BitExact(LONG a, SHORT b) { + return fixmuldiv2BitExact_DS(a, b); +} +FDK_INLINE LONG fMultBitExact(LONG a, LONG b) { + return fixmulBitExact_DD(a, b); +} +FDK_INLINE LONG fMultBitExact(SHORT a, LONG b) { + return fixmulBitExact_SD(a, b); +} +FDK_INLINE LONG fMultBitExact(LONG a, SHORT b) { + return fixmulBitExact_DS(a, b); +} + +/* ******************************************************************************** + */ +#include "abs.h" + +FDK_INLINE FIXP_DBL fAbs(FIXP_DBL x) { return fixabs_D(x); } +FDK_INLINE FIXP_SGL fAbs(FIXP_SGL x) { return fixabs_S(x); } + +#if !defined(__LP64__) +FDK_INLINE INT fAbs(INT x) { return fixabs_I(x); } +#endif + + /* ******************************************************************************** + */ + +#include "clz.h" + +FDK_INLINE INT fNormz(INT64 x) { + INT clz = fixnormz_D((INT)(x >> 32)); + if (clz == 32) clz += fixnormz_D((INT)x); + return clz; +} +FDK_INLINE INT fNormz(FIXP_DBL x) { return fixnormz_D(x); } +FDK_INLINE INT fNormz(FIXP_SGL x) { return fixnormz_S(x); } +FDK_INLINE INT fNorm(FIXP_DBL x) { return fixnorm_D(x); } +FDK_INLINE INT fNorm(FIXP_SGL x) { return fixnorm_S(x); } + + /* ******************************************************************************** + */ + /* ******************************************************************************** + */ + /* ******************************************************************************** + */ + +#include "clz.h" +#define fixp_abs(x) fAbs(x) +#define fixMin(a, b) fMin(a, b) +#define fixMax(a, b) fMax(a, b) +#define CntLeadingZeros(x) fixnormz_D(x) +#define CountLeadingBits(x) fixnorm_D(x) + +#include "fixmadd.h" + +/* y = (x+0.5*a*b) */ +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadddiv2_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadddiv2_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadddiv2_DS(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmadddiv2_SS(x, a, b); +} + +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_DBL a) { + return fixpadddiv2_D(x, a); +} +FDK_INLINE FIXP_DBL fPow2AddDiv2(FIXP_DBL x, FIXP_SGL a) { + return fixpadddiv2_S(x, a); +} + +/* y = 2*(x+0.5*a*b) = (2x+a*b) */ +FDK_INLINE FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadd_DD(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadd_SD(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadd_DS(x, a, b); +} +inline FIXP_DBL fMultAdd(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmadd_SS(x, a, b); +} + +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_DBL a) { return fixpadd_D(x, a); } +inline FIXP_DBL fPow2Add(FIXP_DBL x, FIXP_SGL a) { return fixpadd_S(x, a); } + +/* y = (x-0.5*a*b) */ +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsubdiv2_DD(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsubdiv2_SD(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsubdiv2_DS(x, a, b); +} +inline FIXP_DBL fMultSubDiv2(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmsubdiv2_SS(x, a, b); +} + +/* y = 2*(x-0.5*a*b) = (2*x-a*b) */ +FDK_INLINE FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsub_DD(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsub_SD(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsub_DS(x, a, b); +} +inline FIXP_DBL fMultSub(FIXP_DBL x, FIXP_SGL a, FIXP_SGL b) { + return fixmsub_SS(x, a, b); +} + +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmadddiv2BitExact_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmadddiv2BitExact_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultAddDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmadddiv2BitExact_DS(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_DBL b) { + return fixmsubdiv2BitExact_DD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_SGL a, FIXP_DBL b) { + return fixmsubdiv2BitExact_SD(x, a, b); +} +FDK_INLINE FIXP_DBL fMultSubDiv2BitExact(FIXP_DBL x, FIXP_DBL a, FIXP_SGL b) { + return fixmsubdiv2BitExact_DS(x, a, b); +} + +#include "fixminmax.h" + +FDK_INLINE FIXP_DBL fMin(FIXP_DBL a, FIXP_DBL b) { return fixmin_D(a, b); } +FDK_INLINE FIXP_DBL fMax(FIXP_DBL a, FIXP_DBL b) { return fixmax_D(a, b); } + +FDK_INLINE FIXP_SGL fMin(FIXP_SGL a, FIXP_SGL b) { return fixmin_S(a, b); } +FDK_INLINE FIXP_SGL fMax(FIXP_SGL a, FIXP_SGL b) { return fixmax_S(a, b); } + +#if !defined(__LP64__) +FDK_INLINE INT fMax(INT a, INT b) { return fixmax_I(a, b); } +FDK_INLINE INT fMin(INT a, INT b) { return fixmin_I(a, b); } +#endif + +inline UINT fMax(UINT a, UINT b) { return fixmax_UI(a, b); } +inline UINT fMin(UINT a, UINT b) { return fixmin_UI(a, b); } + +inline UCHAR fMax(UCHAR a, UCHAR b) { + return (UCHAR)fixmax_UI((UINT)a, (UINT)b); +} +inline UCHAR fMin(UCHAR a, UCHAR b) { + return (UCHAR)fixmin_UI((UINT)a, (UINT)b); +} + +/* Complex data types */ +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_SGL re; + FIXP_SGL im; + } v; + /* word representation for memory move */ + LONG w; +} +FIXP_SPK; + +typedef shouldBeUnion { + /* vector representation for arithmetic */ + struct { + FIXP_DBL re; + FIXP_DBL im; + } v; + /* word representation for memory move */ + INT64 w; +} +FIXP_DPK; + +#include "fixmul.h" +#include "fixmadd.h" +#include "cplx_mul.h" +#include "fixpoint_math.h" + +#endif diff --git a/fdk-aac/libFDK/include/cplx_mul.h b/fdk-aac/libFDK/include/cplx_mul.h new file mode 100644 index 0000000..eb1afce --- /dev/null +++ b/fdk-aac/libFDK/include/cplx_mul.h @@ -0,0 +1,266 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_H) +#define CPLX_MUL_H + +#include "common_fix.h" + +#if defined(__arm__) || defined(_M_ARM) +#include "arm/cplx_mul_arm.h" + +#elif defined(__GNUC__) && defined(__mips__) && __mips_isa_rev < 6 +#include "mips/cplx_mul_mips.h" + +#endif /* #if defined all cores: bfin, arm, etc. */ + +/* ############################################################################# + */ + +/* Fallback generic implementations */ + +#if !defined(FUNCTION_cplxMultDiv2_32x16X2) +#define FUNCTION_cplxMultDiv2_32x16X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_16x16X2) +#define FUNCTION_cplxMultDiv2_16x16X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} + +inline void cplxMultDiv2(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = FX_DBL2FX_SGL(fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im)); + *c_Im = FX_DBL2FX_SGL(fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re)); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x16) +#define FUNCTION_cplxMultDiv2_32x16 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_16x16) +#define FUNCTION_cplxMultDiv2_16x16 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} + +inline void cplxMultDiv2(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x16X2) +#define FUNCTION_cplxMultSubDiv2_32x16X2 + +inline void cplxMultSubDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re -= fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im -= fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32X2) +#define FUNCTION_cplxMultDiv2_32x32X2 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re = fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im = fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMultDiv2_32x32) +#define FUNCTION_cplxMultDiv2_32x32 + +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DPK w) { + cplxMultDiv2(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMultSubDiv2_32x32X2) +#define FUNCTION_cplxMultSubDiv2_32x32X2 + +inline void cplxMultSubDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re -= fMultDiv2(a_Re, b_Re) - fMultDiv2(a_Im, b_Im); + *c_Im -= fMultDiv2(a_Re, b_Im) + fMultDiv2(a_Im, b_Re); +} +#endif + + /* ############################################################################# + */ + +#if !defined(FUNCTION_cplxMult_32x16X2) +#define FUNCTION_cplxMult_32x16X2 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = fMult(a_Re, b_Re) - fMult(a_Im, b_Im); + *c_Im = fMult(a_Re, b_Im) + fMult(a_Im, b_Re); +} +inline void cplxMult(FIXP_SGL *c_Re, FIXP_SGL *c_Im, const FIXP_SGL a_Re, + const FIXP_SGL a_Im, const FIXP_SGL b_Re, + const FIXP_SGL b_Im) { + *c_Re = FX_DBL2FX_SGL(fMult(a_Re, b_Re) - fMult(a_Im, b_Im)); + *c_Im = FX_DBL2FX_SGL(fMult(a_Re, b_Im) + fMult(a_Im, b_Re)); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x16) +#define FUNCTION_cplxMult_32x16 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_SPK w) { + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32X2) +#define FUNCTION_cplxMult_32x32X2 + +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DBL b_Re, + const FIXP_DBL b_Im) { + *c_Re = fMult(a_Re, b_Re) - fMult(a_Im, b_Im); + *c_Im = fMult(a_Re, b_Im) + fMult(a_Im, b_Re); +} +#endif + +#if !defined(FUNCTION_cplxMult_32x32) +#define FUNCTION_cplxMult_32x32 +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, const FIXP_DBL a_Re, + const FIXP_DBL a_Im, const FIXP_DPK w) { + cplxMult(c_Re, c_Im, a_Re, a_Im, w.v.re, w.v.im); +} +#endif + + /* ############################################################################# + */ + +#endif /* CPLX_MUL_H */ diff --git a/fdk-aac/libFDK/include/dct.h b/fdk-aac/libFDK/include/dct.h new file mode 100644 index 0000000..308afcb --- /dev/null +++ b/fdk-aac/libFDK/include/dct.h @@ -0,0 +1,171 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Library functions to calculate standard DCTs. This will most + likely be replaced by hand-optimized functions for the specific + target processor. + +*******************************************************************************/ + +#ifndef DCT_H +#define DCT_H + +#include "common_fix.h" + +void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle, + int *sin_step, int length); + +/** + * \brief Calculate DCT type II of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/(N-1)) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_II(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type III of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * Note that the factor 0.5 for the sum term x[0] is 1.0 instead of 0.5. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_III(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DST type III of given length. The DST III is + * calculated by a DCT III of mirrored input and sign-flipping of odd + * output coefficients. + * Note that the factor 0.5 for the sum term x[N-1] is 1.0 instead of + * 0.5. A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dst_III(FIXP_DBL *pDat, FIXP_DBL *tmp, int size, int *pDat_e); + +/** + * \brief Calculate DCT type IV of given length. The DCT IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dct_IV(FIXP_DBL *pDat, int size, int *pDat_e); + +/** + * \brief Calculate DST type IV of given length. The DST IV is + * calculated by a complex FFT, with some pre and post twiddeling. + * A factor of sqrt(2/N) is NOT applied. + * \param pDat pointer to input/output data (in place processing). + * \param size size of pDat. + * \param pDat_e pointer to an integer containing the exponent of the data + * referenced by pDat. The exponent is updated accordingly. + */ +void dst_IV(FIXP_DBL *pDat, int size, int *pDat_e); + +#endif diff --git a/fdk-aac/libFDK/include/fft.h b/fdk-aac/libFDK/include/fft.h new file mode 100644 index 0000000..d394046 --- /dev/null +++ b/fdk-aac/libFDK/include/fft.h @@ -0,0 +1,263 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, DSP Solutions + + Description: Fix point FFT + +*******************************************************************************/ + +#ifndef FFT_H +#define FFT_H + +#include "common_fix.h" + +/** + * \brief Perform an inplace complex valued FFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the + * input data, which is updated according to the FFT scale. + */ +void fft(int length, FIXP_DBL *pInput, INT *scalefactor); + +/** + * \brief Perform an inplace complex valued IFFT of length 2^n + * + * \param length Length of the FFT to be calculated. + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + * \param scalefactor Pointer to an INT, which contains the current scale of the + * input data, which is updated according to the IFFT scale. + */ +void ifft(int length, FIXP_DBL *pInput, INT *scalefactor); + +/* + * Frequently used and fixed short length FFTs. + */ + +#ifndef FUNCTION_fft_4 +/** + * \brief Perform an inplace complex valued FFT of length 4 + * + * \param pInput Input/Output data buffer. The input data must have at least 1 + * bit scale headroom. The values are interleaved, real/imag pairs. + */ +LNK_SECTION_CODE_L1 +static FDK_FORCEINLINE void fft_4(FIXP_DBL *x) { + FIXP_DBL a00, a10, a20, a30, tmp0, tmp1; + + a00 = (x[0] + x[4]) >> 1; /* Re A + Re B */ + a10 = (x[2] + x[6]) >> 1; /* Re C + Re D */ + a20 = (x[1] + x[5]) >> 1; /* Im A + Im B */ + a30 = (x[3] + x[7]) >> 1; /* Im C + Im D */ + + x[0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + + tmp0 = a00 - x[4]; /* Re A - Re B */ + tmp1 = a20 - x[5]; /* Im A - Im B */ + + x[4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a10 = a10 - x[6]; /* Re C - Re D */ + a30 = a30 - x[7]; /* Im C - Im D */ + + x[2] = tmp0 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[6] = tmp0 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[3] = tmp1 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[7] = tmp1 + a10; /* Im D' = Im A - Im B + Re C - Re D */ +} +#endif /* FUNCTION_fft_4 */ + +#ifndef FUNCTION_fft_8 +LNK_SECTION_CODE_L1 +static FDK_FORCEINLINE void fft_8(FIXP_DBL *x) { + FIXP_SPK w_PiFOURTH = {{FIXP_SGL(0x5A82), FIXP_SGL(0x5A82)}}; + + FIXP_DBL a00, a10, a20, a30; + FIXP_DBL y[16]; + + a00 = (x[0] + x[8]) >> 1; + a10 = x[4] + x[12]; + a20 = (x[1] + x[9]) >> 1; + a30 = x[5] + x[13]; + + y[0] = a00 + (a10 >> 1); + y[4] = a00 - (a10 >> 1); + y[1] = a20 + (a30 >> 1); + y[5] = a20 - (a30 >> 1); + + a00 = a00 - x[8]; + a10 = (a10 >> 1) - x[12]; + a20 = a20 - x[9]; + a30 = (a30 >> 1) - x[13]; + + y[2] = a00 + a30; + y[6] = a00 - a30; + y[3] = a20 - a10; + y[7] = a20 + a10; + + a00 = (x[2] + x[10]) >> 1; + a10 = x[6] + x[14]; + a20 = (x[3] + x[11]) >> 1; + a30 = x[7] + x[15]; + + y[8] = a00 + (a10 >> 1); + y[12] = a00 - (a10 >> 1); + y[9] = a20 + (a30 >> 1); + y[13] = a20 - (a30 >> 1); + + a00 = a00 - x[10]; + a10 = (a10 >> 1) - x[14]; + a20 = a20 - x[11]; + a30 = (a30 >> 1) - x[15]; + + y[10] = a00 + a30; + y[14] = a00 - a30; + y[11] = a20 - a10; + y[15] = a20 + a10; + + FIXP_DBL vr, vi, ur, ui; + + ur = y[0] >> 1; + ui = y[1] >> 1; + vr = y[8]; + vi = y[9]; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[8] = ur - (vr >> 1); + x[9] = ui - (vi >> 1); + + ur = y[4] >> 1; + ui = y[5] >> 1; + vi = y[12]; + vr = y[13]; + x[4] = ur + (vr >> 1); + x[5] = ui - (vi >> 1); + x[12] = ur - (vr >> 1); + x[13] = ui + (vi >> 1); + + ur = y[10]; + ui = y[11]; + + cplxMultDiv2(&vi, &vr, ui, ur, w_PiFOURTH); + + ur = y[2]; + ui = y[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[10] = (ur >> 1) - vr; + x[11] = (ui >> 1) - vi; + + ur = y[14]; + ui = y[15]; + + cplxMultDiv2(&vr, &vi, ui, ur, w_PiFOURTH); + + ur = y[6]; + ui = y[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) - vi; + x[14] = (ur >> 1) - vr; + x[15] = (ui >> 1) + vi; +} +#endif /* FUNCTION_fft_8 */ + +#endif diff --git a/fdk-aac/libFDK/include/fft_rad2.h b/fdk-aac/libFDK/include/fft_rad2.h new file mode 100644 index 0000000..b820b7d --- /dev/null +++ b/fdk-aac/libFDK/include/fft_rad2.h @@ -0,0 +1,121 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#ifndef FFT_RAD2_H +#define FFT_RAD2_H + +#include "common_fix.h" + +/** + * \brief Performe an inplace complex valued FFT of 2^n length + * + * \param x Input/Output data buffer. The input data must have at least 1 bit + * scale headroom. The values are interleaved, real/imag pairs. + * \param ldn log2 of FFT length + * \param trigdata Pointer to a sinetable of a length of at least (2^ldn)/2 sine + * values. + * \param trigDataSize length of the sinetable "trigdata". + */ +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize); + +#endif /* FFT_RAD2_H */ diff --git a/fdk-aac/libFDK/include/fixmadd.h b/fdk-aac/libFDK/include/fixmadd.h new file mode 100644 index 0000000..1672456 --- /dev/null +++ b/fdk-aac/libFDK/include/fixmadd.h @@ -0,0 +1,333 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMADD_H) +#define FIXMADD_H + +#include "FDK_archdef.h" +#include "machine_type.h" +#include "fixmul.h" + +#if defined(__arm__) +#include "arm/fixmadd_arm.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions. +************************************************************************** +**************************************************************************/ + +/* Divide by two versions. */ + +#if !defined(FUNCTION_fixmadddiv2_DD) +inline FIXP_DBL fixmadddiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return (x + fMultDiv2(a, b)); +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_SD) +inline FIXP_DBL fixmadddiv2_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2_DS + return fixmadddiv2_DS(x, b, a); +#else + return fixmadddiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_DS) +inline FIXP_DBL fixmadddiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2_SD + return fixmadddiv2_SD(x, b, a); +#else + return fixmadddiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmadddiv2_SS) +inline FIXP_DBL fixmadddiv2_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return x + fMultDiv2(a, b); +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DD) +inline FIXP_DBL fixmsubdiv2_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return (x - fMultDiv2(a, b)); +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SD) +inline FIXP_DBL fixmsubdiv2_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2_DS + return fixmsubdiv2_DS(x, b, a); +#else + return fixmsubdiv2_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_DS) +inline FIXP_DBL fixmsubdiv2_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2_SD + return fixmsubdiv2_SD(x, b, a); +#else + return fixmsubdiv2_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2_SS) +inline FIXP_DBL fixmsubdiv2_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return x - fMultDiv2(a, b); +} +#endif + +#if !defined(FUNCTION_fixmadddiv2BitExact_DD) +#define FUNCTION_fixmadddiv2BitExact_DD +inline FIXP_DBL fixmadddiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x + fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_SD) +#define FUNCTION_fixmadddiv2BitExact_SD +inline FIXP_DBL fixmadddiv2BitExact_SD(FIXP_DBL x, const FIXP_SGL a, + const FIXP_DBL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_DS + return fixmadddiv2BitExact_DS(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadddiv2BitExact_DS) +#define FUNCTION_fixmadddiv2BitExact_DS +inline FIXP_DBL fixmadddiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { +#ifdef FUNCTION_fixmadddiv2BitExact_SD + return fixmadddiv2BitExact_SD(x, b, a); +#else + return x + fMultDiv2BitExact(a, b); +#endif +} +#endif + +#if !defined(FUNCTION_fixmsubdiv2BitExact_DD) +#define FUNCTION_fixmsubdiv2BitExact_DD +inline FIXP_DBL fixmsubdiv2BitExact_DD(FIXP_DBL x, const FIXP_DBL a, + const FIXP_DBL b) { + return x - fMultDiv2BitExact(a, b); +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_SD) +#define FUNCTION_fixmsubdiv2BitExact_SD +inline FIXP_DBL fixmsubdiv2BitExact_SD(FIXP_DBL x, const FIXP_SGL a, + const FIXP_DBL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_DS + return fixmsubdiv2BitExact_DS(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsubdiv2BitExact_DS) +#define FUNCTION_fixmsubdiv2BitExact_DS +inline FIXP_DBL fixmsubdiv2BitExact_DS(FIXP_DBL x, const FIXP_DBL a, + const FIXP_SGL b) { +#ifdef FUNCTION_fixmsubdiv2BitExact_SD + return fixmsubdiv2BitExact_SD(x, b, a); +#else + return x - fMultDiv2BitExact(a, b); +#endif +} +#endif + + /* Normal versions */ + +#if !defined(FUNCTION_fixmadd_DD) +inline FIXP_DBL fixmadd_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return fixmadddiv2_DD(x, a, b) << 1; +} +#endif +#if !defined(FUNCTION_fixmadd_SD) +inline FIXP_DBL fixmadd_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmadd_DS + return fixmadd_DS(x, b, a); +#else + return fixmadd_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_DS) +inline FIXP_DBL fixmadd_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmadd_SD + return fixmadd_SD(x, b, a); +#else + return fixmadd_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmadd_SS) +inline FIXP_DBL fixmadd_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return (x + fMultDiv2(a, b)) << 1; +} +#endif + +#if !defined(FUNCTION_fixmsub_DD) +inline FIXP_DBL fixmsub_DD(FIXP_DBL x, const FIXP_DBL a, const FIXP_DBL b) { + return fixmsubdiv2_DD(x, a, b) << 1; +} +#endif +#if !defined(FUNCTION_fixmsub_SD) +inline FIXP_DBL fixmsub_SD(FIXP_DBL x, const FIXP_SGL a, const FIXP_DBL b) { +#ifdef FUNCTION_fixmsub_DS + return fixmsub_DS(x, b, a); +#else + return fixmsub_DD(x, FX_SGL2FX_DBL(a), b); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_DS) +inline FIXP_DBL fixmsub_DS(FIXP_DBL x, const FIXP_DBL a, const FIXP_SGL b) { +#ifdef FUNCTION_fixmsub_SD + return fixmsub_SD(x, b, a); +#else + return fixmsub_DD(x, a, FX_SGL2FX_DBL(b)); +#endif +} +#endif +#if !defined(FUNCTION_fixmsub_SS) +inline FIXP_DBL fixmsub_SS(FIXP_DBL x, const FIXP_SGL a, const FIXP_SGL b) { + return (x - fMultDiv2(a, b)) << 1; +} +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_D) +#ifdef FUNCTION_fixmadddiv2_DD +#define fixpadddiv2_D(x, a) fixmadddiv2_DD(x, a, a) +#else +inline INT fixpadddiv2_D(FIXP_DBL x, const FIXP_DBL a) { + return (x + fPow2Div2(a)); +} +#endif +#endif +#if !defined(FUNCTION_fixpow2add_D) +inline INT fixpadd_D(FIXP_DBL x, const FIXP_DBL a) { return (x + fPow2(a)); } +#endif + +#if !defined(FUNCTION_fixpow2adddiv2_S) +#ifdef FUNCTION_fixmadddiv2_SS +#define fixpadddiv2_S(x, a) fixmadddiv2_SS(x, a, a) +#else +inline INT fixpadddiv2_S(FIXP_DBL x, const FIXP_SGL a) { + return (x + fPow2Div2(a)); +} +#endif +#endif +#if !defined(FUNCTION_fixpow2add_S) +inline INT fixpadd_S(FIXP_DBL x, const FIXP_SGL a) { return (x + fPow2(a)); } +#endif + +#endif /* FIXMADD_H */ diff --git a/fdk-aac/libFDK/include/fixminmax.h b/fdk-aac/libFDK/include/fixminmax.h new file mode 100644 index 0000000..69ef35d --- /dev/null +++ b/fdk-aac/libFDK/include/fixminmax.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: min/max inline functions and defines + +*******************************************************************************/ + +#ifndef FIXMINMAX_H +#define FIXMINMAX_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +/* Inline Function to determine the smaller/bigger value of two values with same + * type. */ + +template +inline T fixmin(T a, T b) { + return (a < b ? a : b); +} + +template +inline T fixmax(T a, T b) { + return (a > b ? a : b); +} + +#define fixmax_D(a, b) fixmax(a, b) +#define fixmin_D(a, b) fixmin(a, b) +#define fixmax_S(a, b) fixmax(a, b) +#define fixmin_S(a, b) fixmin(a, b) +#define fixmax_I(a, b) fixmax(a, b) +#define fixmin_I(a, b) fixmin(a, b) +#define fixmax_UI(a, b) fixmax(a, b) +#define fixmin_UI(a, b) fixmin(a, b) + +#endif diff --git a/fdk-aac/libFDK/include/fixmul.h b/fdk-aac/libFDK/include/fixmul.h new file mode 100644 index 0000000..8eeb7ab --- /dev/null +++ b/fdk-aac/libFDK/include/fixmul.h @@ -0,0 +1,298 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Stefan Gewinner + + Description: fixed point multiplication + +*******************************************************************************/ + +#if !defined(FIXMUL_H) +#define FIXMUL_H + +#include "FDK_archdef.h" +#include "machine_type.h" + +#if defined(__arm__) +#include "arm/fixmul_arm.h" + +#elif defined(__mips__) +#include "mips/fixmul_mips.h" + +#elif defined(__x86__) +#include "x86/fixmul_x86.h" + +#elif defined(__powerpc__) +#include "ppc/fixmul_ppc.h" + +#endif /* all cores */ + +/************************************************************************* + ************************************************************************* + Software fallbacks for missing functions +************************************************************************** +**************************************************************************/ + +#if !defined(FUNCTION_fixmuldiv2_DD) +#define FUNCTION_fixmuldiv2_DD +inline LONG fixmuldiv2_DD(const LONG a, const LONG b) { + return (LONG)((((INT64)a) * b) >> 32); +} +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DD) +#define FUNCTION_fixmuldiv2BitExact_DD +inline LONG fixmuldiv2BitExact_DD(const LONG a, const LONG b) { + return (LONG)((((INT64)a) * b) >> 32); +} +#endif + +#if !defined(FUNCTION_fixmul_DD) +#define FUNCTION_fixmul_DD +inline LONG fixmul_DD(const LONG a, const LONG b) { + return fixmuldiv2_DD(a, b) << 1; +} +#endif + +#if !defined(FUNCTION_fixmulBitExact_DD) +#define FUNCTION_fixmulBitExact_DD +inline LONG fixmulBitExact_DD(const LONG a, const LONG b) { + return ((LONG)((((INT64)a) * b) >> 32)) << 1; +} +#endif + +#if !defined(FUNCTION_fixmuldiv2_SS) +#define FUNCTION_fixmuldiv2_SS +inline LONG fixmuldiv2_SS(const SHORT a, const SHORT b) { + return ((LONG)a * b); +} +#endif + +#if !defined(FUNCTION_fixmul_SS) +#define FUNCTION_fixmul_SS +inline LONG fixmul_SS(const SHORT a, const SHORT b) { return (a * b) << 1; } +#endif + +#if !defined(FUNCTION_fixmuldiv2_SD) +#define FUNCTION_fixmuldiv2_SD +inline LONG fixmuldiv2_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2_DS +{ + return fixmuldiv2_DS(b, a); +} +#else +{ + return fixmuldiv2_DD(FX_SGL2FX_DBL(a), b); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2_DS) +#define FUNCTION_fixmuldiv2_DS +inline LONG fixmuldiv2_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2_SD +{ + return fixmuldiv2_SD(b, a); +} +#else +{ + return fixmuldiv2_DD(a, FX_SGL2FX_DBL(b)); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_SD) +#define FUNCTION_fixmuldiv2BitExact_SD +inline LONG fixmuldiv2BitExact_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmuldiv2BitExact_DS +{ + return fixmuldiv2BitExact_DS(b, a); +} +#else +{ + return (LONG)((((INT64)a) * b) >> 16); +} +#endif +#endif + +#if !defined(FUNCTION_fixmuldiv2BitExact_DS) +#define FUNCTION_fixmuldiv2BitExact_DS +inline LONG fixmuldiv2BitExact_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmuldiv2BitExact_SD +{ + return fixmuldiv2BitExact_SD(b, a); +} +#else +{ + return (LONG)((((INT64)a) * b) >> 16); +} +#endif +#endif + +#if !defined(FUNCTION_fixmul_SD) +#define FUNCTION_fixmul_SD +inline LONG fixmul_SD(const SHORT a, const LONG b) { +#ifdef FUNCTION_fixmul_DS + return fixmul_DS(b, a); +#else + return fixmuldiv2_SD(a, b) << 1; +#endif +} +#endif + +#if !defined(FUNCTION_fixmul_DS) +#define FUNCTION_fixmul_DS +inline LONG fixmul_DS(const LONG a, const SHORT b) { +#ifdef FUNCTION_fixmul_SD + return fixmul_SD(b, a); +#else + return fixmuldiv2_DS(a, b) << 1; +#endif +} +#endif + +#if !defined(FUNCTION_fixmulBitExact_SD) +#define FUNCTION_fixmulBitExact_SD +inline LONG fixmulBitExact_SD(const SHORT a, const LONG b) +#ifdef FUNCTION_fixmulBitExact_DS +{ + return fixmulBitExact_DS(b, a); +} +#else +{ + return (LONG)(((((INT64)a) * b) >> 16) << 1); +} +#endif +#endif + +#if !defined(FUNCTION_fixmulBitExact_DS) +#define FUNCTION_fixmulBitExact_DS +inline LONG fixmulBitExact_DS(const LONG a, const SHORT b) +#ifdef FUNCTION_fixmulBitExact_SD +{ + return fixmulBitExact_SD(b, a); +} +#else +{ + return (LONG)(((((INT64)a) * b) >> 16) << 1); +} +#endif +#endif + +#if !defined(FUNCTION_fixpow2div2_D) +#define FUNCTION_fixpow2div2_D +inline LONG fixpow2div2_D(const LONG a) { return fixmuldiv2_DD(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_D) +#define FUNCTION_fixpow2_D +inline LONG fixpow2_D(const LONG a) { return fixpow2div2_D(a) << 1; } +#endif + +#if !defined(FUNCTION_fixpow2div2_S) +#define FUNCTION_fixpow2div2_S +inline LONG fixpow2div2_S(const SHORT a) { return fixmuldiv2_SS(a, a); } +#endif + +#if !defined(FUNCTION_fixpow2_S) +#define FUNCTION_fixpow2_S +inline LONG fixpow2_S(const SHORT a) { + LONG result = fixpow2div2_S(a) << 1; + return result ^ (result >> 31); +} +#endif + +#endif /* FIXMUL_H */ diff --git a/fdk-aac/libFDK/include/fixpoint_math.h b/fdk-aac/libFDK/include/fixpoint_math.h new file mode 100644 index 0000000..3805892 --- /dev/null +++ b/fdk-aac/libFDK/include/fixpoint_math.h @@ -0,0 +1,921 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Gayer + + Description: Fixed point specific mathematical functions + +*******************************************************************************/ + +#ifndef FIXPOINT_MATH_H +#define FIXPOINT_MATH_H + +#include "common_fix.h" +#include "scale.h" + +/* + * Data definitions + */ + +#define LD_DATA_SCALING (64.0f) +#define LD_DATA_SHIFT 6 /* pow(2, LD_DATA_SHIFT) = LD_DATA_SCALING */ + +#define MAX_LD_PRECISION 10 +#define LD_PRECISION 10 + +/* Taylor series coefficients for ln(1-x), centered at 0 (MacLaurin polynomial). + */ +#ifndef LDCOEFF_16BIT +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_DBL(-1.0), FL2FXCONST_DBL(-1.0 / 2.0), + FL2FXCONST_DBL(-1.0 / 3.0), FL2FXCONST_DBL(-1.0 / 4.0), + FL2FXCONST_DBL(-1.0 / 5.0), FL2FXCONST_DBL(-1.0 / 6.0), + FL2FXCONST_DBL(-1.0 / 7.0), FL2FXCONST_DBL(-1.0 / 8.0), + FL2FXCONST_DBL(-1.0 / 9.0), FL2FXCONST_DBL(-1.0 / 10.0)}; +#else /* LDCOEFF_16BIT */ +LNK_SECTION_CONSTDATA_L1 +static const FIXP_SGL ldCoeff[MAX_LD_PRECISION] = { + FL2FXCONST_SGL(-1.0), FL2FXCONST_SGL(-1.0 / 2.0), + FL2FXCONST_SGL(-1.0 / 3.0), FL2FXCONST_SGL(-1.0 / 4.0), + FL2FXCONST_SGL(-1.0 / 5.0), FL2FXCONST_SGL(-1.0 / 6.0), + FL2FXCONST_SGL(-1.0 / 7.0), FL2FXCONST_SGL(-1.0 / 8.0), + FL2FXCONST_SGL(-1.0 / 9.0), FL2FXCONST_SGL(-1.0 / 10.0)}; +#endif /* LDCOEFF_16BIT */ + +/***************************************************************************** + + functionname: invSqrtNorm2 + description: delivers 1/sqrt(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define SQRT_BITS 7 +#define SQRT_VALUES (128 + 2) +#define SQRT_BITS_MASK 0x7f +#define SQRT_FRACT_BITS_MASK 0x007FFFFF + +extern const FIXP_DBL invSqrtTab[SQRT_VALUES]; + +/* + * Hardware specific implementations + */ + +#if defined(__x86__) +#include "x86/fixpoint_math_x86.h" +#endif /* target architecture selector */ + +/* + * Fallback implementations + */ +#if !defined(FUNCTION_fIsLessThan) +/** + * \brief Compares two fixpoint values incl. scaling. + * \param a_m mantissa of the first input value. + * \param a_e exponent of the first input value. + * \param b_m mantissa of the second input value. + * \param b_e exponent of the second input value. + * \return non-zero if (a_m*2^a_e) < (b_m*2^b_e), 0 otherwise + */ +FDK_INLINE INT fIsLessThan(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e) { + if (a_e > b_e) { + return ((b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)) > a_m); + } else { + return ((a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) < b_m); + } +} + +FDK_INLINE INT fIsLessThan(FIXP_SGL a_m, INT a_e, FIXP_SGL b_m, INT b_e) { + if (a_e > b_e) { + return ((b_m >> fMin(a_e - b_e, FRACT_BITS - 1)) > a_m); + } else { + return ((a_m >> fMin(b_e - a_e, FRACT_BITS - 1)) < b_m); + } +} +#endif + +/** + * \brief deprecated. Use fLog2() instead. + */ +#define CalcLdData(op) fLog2(op, 0) + +void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT number); + +extern const UINT exp2_tab_long[32]; +extern const UINT exp2w_tab_long[32]; +extern const UINT exp2x_tab_long[32]; + +LNK_SECTION_CODE_L1 +FDK_INLINE FIXP_DBL CalcInvLdData(const FIXP_DBL x) { + int set_zero = (x < FL2FXCONST_DBL(-31.0 / 64.0)) ? 0 : 1; + int set_max = (x >= FL2FXCONST_DBL(31.0 / 64.0)) | (x == FL2FXCONST_DBL(0.0)); + + FIXP_SGL frac = (FIXP_SGL)((LONG)x & 0x3FF); + UINT index3 = (UINT)(LONG)(x >> 10) & 0x1F; + UINT index2 = (UINT)(LONG)(x >> 15) & 0x1F; + UINT index1 = (UINT)(LONG)(x >> 20) & 0x1F; + int exp = fMin(31, ((x > FL2FXCONST_DBL(0.0f)) ? (31 - (int)(x >> 25)) + : (int)(-(x >> 25)))); + + UINT lookup1 = exp2_tab_long[index1] * set_zero; + UINT lookup2 = exp2w_tab_long[index2]; + UINT lookup3 = exp2x_tab_long[index3]; + UINT lookup3f = + lookup3 + (UINT)(LONG)fMultDiv2((FIXP_DBL)(0x0016302F), (FIXP_SGL)frac); + + UINT lookup12 = (UINT)(LONG)fMult((FIXP_DBL)lookup1, (FIXP_DBL)lookup2); + UINT lookup = (UINT)(LONG)fMult((FIXP_DBL)lookup12, (FIXP_DBL)lookup3f); + + FIXP_DBL retVal = (lookup << 3) >> exp; + + if (set_max) { + retVal = (FIXP_DBL)MAXVAL_DBL; + } + + return retVal; +} + +void InitLdInt(); +FIXP_DBL CalcLdInt(INT i); + +extern const USHORT sqrt_tab[49]; + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x) { + UINT y = (INT)x; + UCHAR is_zero = (y == 0); + INT zeros = fixnormz_D(y) & 0x1e; + y <<= zeros; + UINT idx = (y >> 26) - 16; + USHORT frac = (y >> 10) & 0xffff; + USHORT nfrac = 0xffff ^ frac; + UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1]; + t = t >> (zeros >> 1); + return (is_zero ? 0 : t); +} + +inline FIXP_DBL sqrtFixp_lookup(FIXP_DBL x, INT *x_e) { + UINT y = (INT)x; + INT e; + + if (x == (FIXP_DBL)0) { + return x; + } + + /* Normalize */ + e = fixnormz_D(y); + y <<= e; + e = *x_e - e + 2; + + /* Correct odd exponent. */ + if (e & 1) { + y >>= 1; + e++; + } + /* Get square root */ + UINT idx = (y >> 26) - 16; + USHORT frac = (y >> 10) & 0xffff; + USHORT nfrac = 0xffff ^ frac; + UINT t = (UINT)nfrac * sqrt_tab[idx] + (UINT)frac * sqrt_tab[idx + 1]; + + /* Write back exponent */ + *x_e = e >> 1; + return (FIXP_DBL)(LONG)(t >> 1); +} + +void InitInvSqrtTab(); + +#ifndef FUNCTION_invSqrtNorm2 +/** + * \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 FDK_FORCEINLINE FIXP_DBL invSqrtNorm2(FIXP_DBL op, INT *shift) { + FIXP_DBL val = op; + FIXP_DBL reg1, reg2; + + if (val == FL2FXCONST_DBL(0.0)) { + *shift = 16; + return ((LONG)MAXVAL_DBL); /* maximum positive value */ + } + +#define INVSQRTNORM2_LINEAR_INTERPOLATE +#define INVSQRTNORM2_LINEAR_INTERPOLATE_HQ + + /* normalize input, calculate shift value */ + FDK_ASSERT(val > FL2FXCONST_DBL(0.0)); + *shift = fNormz(val) - 1; /* CountLeadingBits() is not necessary here since + test value is always > 0 */ + val <<= *shift; /* normalized input V */ + *shift += 2; /* bias for exponent */ + +#if defined(INVSQRTNORM2_LINEAR_INTERPOLATE) + INT index = + (INT)(val >> (DFRACT_BITS - 1 - (SQRT_BITS + 1))) & SQRT_BITS_MASK; + FIXP_DBL Fract = + (FIXP_DBL)(((INT)val & SQRT_FRACT_BITS_MASK) << (SQRT_BITS + 1)); + FIXP_DBL diff = invSqrtTab[index + 1] - invSqrtTab[index]; + reg1 = invSqrtTab[index] + (fMultDiv2(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 != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + Fract = fMultDiv2(Fract, (FIXP_DBL)((ULONG)0x80000000 - (ULONG)Fract)) << 1; + diff = diff - (invSqrtTab[index + 2] - invSqrtTab[index + 1]); + reg1 = fMultAddDiv2(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 = (FIXP_DBL)0x5A827999; + /* FL2FXCONST_DBL(0.707106781186547524400844362104849f);*/ /* 1/sqrt(2); + */ + reg1 = fMultDiv2(reg1, reg2) << 2; + } + + *shift = *shift >> 1; + + return (reg1); +} +#endif /* FUNCTION_invSqrtNorm2 */ + +#ifndef FUNCTION_sqrtFixp +static FDK_FORCEINLINE FIXP_DBL sqrtFixp(FIXP_DBL op) { + INT tmp_exp = 0; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp); + + FDK_ASSERT(tmp_exp > 0); + return ((FIXP_DBL)(fMultDiv2((op << (tmp_exp - 1)), tmp_inv) << 2)); +} +#endif /* FUNCTION_sqrtFixp */ + +#ifndef FUNCTION_invFixp +/** + * \brief calculate 1.0/op + * \param op mantissa of the input value. + * \return mantissa of the result with implicit exponent of 31 + * \exceptions are provided for op=0,1 setting max. positive value + */ +static inline FIXP_DBL invFixp(FIXP_DBL op) { + if ((op == (FIXP_DBL)0x00000000) || (op == (FIXP_DBL)0x00000001)) { + return ((LONG)MAXVAL_DBL); + } + INT tmp_exp; + FIXP_DBL tmp_inv = invSqrtNorm2(op, &tmp_exp); + FDK_ASSERT((31 - (2 * tmp_exp + 1)) >= 0); + int shift = 31 - (2 * tmp_exp + 1); + tmp_inv = fPow2Div2(tmp_inv); + if (shift) { + tmp_inv = ((tmp_inv >> (shift - 1)) + (FIXP_DBL)1) >> 1; + } + return tmp_inv; +} + +/** + * \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 + */ +static inline FIXP_DBL invFixp(FIXP_DBL op_m, int *op_e) { + if ((op_m == (FIXP_DBL)0x00000000) || (op_m == (FIXP_DBL)0x00000001)) { + *op_e = 31 - *op_e; + return ((LONG)MAXVAL_DBL); + } + + INT tmp_exp; + FIXP_DBL tmp_inv = invSqrtNorm2(op_m, &tmp_exp); + + *op_e = (tmp_exp << 1) - *op_e + 1; + return fPow2Div2(tmp_inv); +} +#endif /* FUNCTION_invFixp */ + +#ifndef FUNCTION_schur_div + +/** + * \brief Divide two FIXP_DBL values with given precision. + * \param num dividend + * \param denum divisor + * \param count amount of significant bits of the result (starting to the MSB) + * \return num/divisor + */ + +FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count); + +#endif /* FUNCTION_schur_div */ + +FIXP_DBL mul_dbl_sgl_rnd(const FIXP_DBL op1, const FIXP_SGL op2); + +#ifndef FUNCTION_fMultNorm +/** + * \brief multiply two values with normalization, thus max precision. + * Author: Robert Weidner + * + * \param f1 first factor + * \param f2 second factor + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return mantissa of the product f1*f2 + */ +FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e); + +/** + * \brief Multiply 2 values using maximum precision. The exponent of the result + * is 0. + * \param f1_m mantissa of factor 1 + * \param f2_m mantissa of factor 2 + * \return mantissa of the result with exponent equal to 0 + */ +inline FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2) { + FIXP_DBL m; + INT e; + + m = fMultNorm(f1, f2, &e); + + m = scaleValueSaturate(m, e); + + return m; +} + +/** + * \brief Multiply 2 values with exponent and use given exponent for the + * mantissa of the result. + * \param f1_m mantissa of factor 1 + * \param f1_e exponent of factor 1 + * \param f2_m mantissa of factor 2 + * \param f2_e exponent of factor 2 + * \param result_e exponent for the returned mantissa of the result + * \return mantissa of the result with exponent equal to result_e + */ +inline FIXP_DBL fMultNorm(FIXP_DBL f1_m, INT f1_e, FIXP_DBL f2_m, INT f2_e, + INT result_e) { + FIXP_DBL m; + INT e; + + m = fMultNorm(f1_m, f2_m, &e); + + m = scaleValueSaturate(m, e + f1_e + f2_e - result_e); + + return m; +} +#endif /* FUNCTION_fMultNorm */ + +#ifndef FUNCTION_fMultI +/** + * \brief Multiplies a fractional value and a integer value and performs + * rounding to nearest + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultI(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT)-DFRACT_BITS) { + m = m >> ((-m_e) - 1); + mi = (m + (FIXP_DBL)1) >> 1; + } else { + mi = (FIXP_DBL)0; + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultI */ + +#ifndef FUNCTION_fMultIfloor +/** + * \brief Multiplies a fractional value and a integer value and performs floor + * rounding + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultIfloor(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT)-DFRACT_BITS) { + mi = m >> (-m_e); + } else { + mi = (FIXP_DBL)0; + if (m < (FIXP_DBL)0) { + mi = (FIXP_DBL)-1; + } + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultIfloor */ + +#ifndef FUNCTION_fMultIceil +/** + * \brief Multiplies a fractional value and a integer value and performs ceil + * rounding + * \param a fractional value + * \param b integer value + * \return integer value + */ +inline INT fMultIceil(FIXP_DBL a, INT b) { + FIXP_DBL m, mi; + INT m_e; + + m = fMultNorm(a, (FIXP_DBL)b, &m_e); + + if (m_e < (INT)0) { + if (m_e > (INT)-DFRACT_BITS) { + mi = (m >> (-m_e)); + if ((LONG)m & ((1 << (-m_e)) - 1)) { + mi = mi + (FIXP_DBL)1; + } + } else { + mi = (FIXP_DBL)1; + if (m < (FIXP_DBL)0) { + mi = (FIXP_DBL)0; + } + } + } else { + mi = scaleValueSaturate(m, m_e); + } + + return ((INT)mi); +} +#endif /* FUNCTION_fMultIceil */ + +#ifndef FUNCTION_fDivNorm +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return num/denum with exponent = *result_e + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom, INT *result_e); + +/** + * \brief Divide 2 positive FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom); + +/** + * \brief Divide 2 signed FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \param result_e pointer to an INT where the exponent of the result is stored + * into + * \return num/denum with exponent = *result_e + */ +FIXP_DBL fDivNormSigned(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e); + +/** + * \brief Divide 2 signed FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denominator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNormSigned(FIXP_DBL num, FIXP_DBL denom); +#endif /* FUNCTION_fDivNorm */ + +/** + * \brief Adjust mantissa to exponent -1 + * \param a_m mantissa of value to be adjusted + * \param pA_e pointer to the exponen of a_m + * \return adjusted mantissa + */ +inline FIXP_DBL fAdjust(FIXP_DBL a_m, INT *pA_e) { + INT shift; + + shift = fNorm(a_m) - 1; + *pA_e -= shift; + + return scaleValue(a_m, shift); +} + +#ifndef FUNCTION_fAddNorm +/** + * \brief Add two values with normalization + * \param a_m mantissa of first summand + * \param a_e exponent of first summand + * \param a_m mantissa of second summand + * \param a_e exponent of second summand + * \param pResult_e pointer to where the exponent of the result will be stored + * to. + * \return mantissa of result + */ +inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e, + INT *pResult_e) { + INT result_e; + FIXP_DBL result_m; + + /* If one of the summands is zero, return the other. + This is necessary for the summation of a very small number to zero */ + if (a_m == (FIXP_DBL)0) { + *pResult_e = b_e; + return b_m; + } + if (b_m == (FIXP_DBL)0) { + *pResult_e = a_e; + return a_m; + } + + a_m = fAdjust(a_m, &a_e); + b_m = fAdjust(b_m, &b_e); + + if (a_e > b_e) { + result_m = a_m + (b_m >> fMin(a_e - b_e, DFRACT_BITS - 1)); + result_e = a_e; + } else { + result_m = (a_m >> fMin(b_e - a_e, DFRACT_BITS - 1)) + b_m; + result_e = b_e; + } + + *pResult_e = result_e; + return result_m; +} + +inline FIXP_DBL fAddNorm(FIXP_DBL a_m, INT a_e, FIXP_DBL b_m, INT b_e, + INT result_e) { + FIXP_DBL result_m; + + a_m = scaleValue(a_m, a_e - result_e); + b_m = scaleValue(b_m, b_e - result_e); + + result_m = a_m + b_m; + + return result_m; +} +#endif /* FUNCTION_fAddNorm */ + +/** + * \brief Divide 2 FIXP_DBL values with normalization of input values. + * \param num numerator + * \param denum denomintator + * \return num/denum with exponent = 0 + */ +FIXP_DBL fDivNormHighPrec(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e); + +#ifndef FUNCTION_fPow +/** + * \brief return 2 ^ (exp_m * 2^exp_e) + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e); + +/** + * \brief return 2 ^ (exp_m * 2^exp_e). This version returns only the mantissa + * with implicit exponent of zero. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e); + +/** + * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). + * This saves the need to compute log2() of constant values (when x is a + * constant). + * \param baseLd_m mantissa of log2() of x. + * \param baseLd_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e); + +/** + * \brief return x ^ (exp_m * 2^exp_e), where log2(x) = baseLd_m * 2^(baseLd_e). + * This saves the need to compute log2() of constant values (when x is a + * constant). This version does not return an exponent, which is + * implicitly 0. + * \param baseLd_m mantissa of log2() of x. + * \param baseLd_e exponent of log2() of x. + * \param exp_m mantissa of the exponent to 2.0f + * \param exp_e exponent of the exponent to 2.0f + * \return mantissa of the result + */ +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e); + +/** + * \brief return (base_m * 2^base_e) ^ (exp * 2^exp_e). Use fLdPow() instead + * whenever possible. + * \param base_m mantissa of the base. + * \param base_e exponent of the base. + * \param exp_m mantissa of power to be calculated of the base. + * \param exp_e exponent of power to be calculated of the base. + * \param result_e pointer to a INT where the exponent of the result will be + * stored into. + * \return mantissa of the result. + */ +FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e); + +/** + * \brief return (base_m * 2^base_e) ^ N + * \param base_m mantissa of the base + * \param base_e exponent of the base + * \param N power to be calculated of the base + * \param result_e pointer to a INT where the exponent of the result will be + * stored into + * \return mantissa of the result + */ +FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT N, INT *result_e); +#endif /* #ifndef FUNCTION_fPow */ + +#ifndef FUNCTION_fLog2 +/** + * \brief Calculate log(argument)/log(2) (logarithm with base 2). deprecated. + * Use fLog2() instead. + * \param arg mantissa of the argument + * \param arg_e exponent of the argument + * \param result_e pointer to an INT to store the exponent of the result + * \return the mantissa of the result. + * \param + */ +FIXP_DBL CalcLog2(FIXP_DBL arg, INT arg_e, INT *result_e); + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \param pointer to an INT where the exponent of the result is returned into. + * \return mantissa of the result. + */ +FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e, INT *result_e) { + FIXP_DBL result_m; + + /* Short cut for zero and negative numbers. */ + if (x_m <= FL2FXCONST_DBL(0.0f)) { + *result_e = DFRACT_BITS - 1; + return FL2FXCONST_DBL(-1.0f); + } + + /* Calculate log2() */ + { + FIXP_DBL x2_m; + + /* Move input value x_m * 2^x_e toward 1.0, where the taylor approximation + of the function log(1-x) centered at 0 is most accurate. */ + { + INT b_norm; + + b_norm = fNormz(x_m) - 1; + x2_m = x_m << b_norm; + x_e = x_e - b_norm; + } + + /* map x from log(x) domain to log(1-x) domain. */ + x2_m = -(x2_m + FL2FXCONST_DBL(-1.0)); + + /* Taylor polynomial approximation of ln(1-x) */ + { + FIXP_DBL px2_m; + result_m = FL2FXCONST_DBL(0.0); + px2_m = x2_m; + for (int i = 0; i < LD_PRECISION; i++) { + result_m = fMultAddDiv2(result_m, ldCoeff[i], px2_m); + px2_m = fMult(px2_m, x2_m); + } + } + /* Multiply result with 1/ln(2) = 1.0 + 0.442695040888 (get log2(x) from + * ln(x) result). */ + result_m = + fMultAddDiv2(result_m, result_m, + FL2FXCONST_DBL(2.0 * 0.4426950408889634073599246810019)); + + /* Add exponent part. log2(x_m * 2^x_e) = log2(x_m) + x_e */ + if (x_e != 0) { + int enorm; + + enorm = DFRACT_BITS - fNorm((FIXP_DBL)x_e); + /* The -1 in the right shift of result_m compensates the fMultDiv2() above + * in the taylor polynomial evaluation loop.*/ + result_m = (result_m >> (enorm - 1)) + + ((FIXP_DBL)x_e << (DFRACT_BITS - 1 - enorm)); + + *result_e = enorm; + } else { + /* 1 compensates the fMultDiv2() above in the taylor polynomial evaluation + * loop.*/ + *result_e = 1; + } + } + + return result_m; +} + +/** + * \brief calculate logarithm of base 2 of x_m * 2^(x_e) + * \param x_m mantissa of the input value. + * \param x_e exponent of the input value. + * \return mantissa of the result with implicit exponent of LD_DATA_SHIFT. + */ +FDK_INLINE FIXP_DBL fLog2(FIXP_DBL x_m, INT x_e) { + if (x_m <= FL2FXCONST_DBL(0.0f)) { + x_m = FL2FXCONST_DBL(-1.0f); + } else { + INT result_e; + x_m = fLog2(x_m, x_e, &result_e); + x_m = scaleValue(x_m, result_e - LD_DATA_SHIFT); + } + return x_m; +} + +#endif /* FUNCTION_fLog2 */ + +#ifndef FUNCTION_fAddSaturate +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_SGL fAddSaturate(const FIXP_SGL a, const FIXP_SGL b) { + LONG sum; + + sum = (LONG)(SHORT)a + (LONG)(SHORT)b; + sum = fMax(fMin((INT)sum, (INT)MAXVAL_SGL), (INT)MINVAL_SGL); + return (FIXP_SGL)(SHORT)sum; +} + +/** + * \brief Add with saturation of the result. + * \param a first summand + * \param b second summand + * \return saturated sum of a and b. + */ +inline FIXP_DBL fAddSaturate(const FIXP_DBL a, const FIXP_DBL b) { + LONG sum; + + sum = (LONG)(a >> 1) + (LONG)(b >> 1); + sum = fMax(fMin((INT)sum, (INT)(MAXVAL_DBL >> 1)), (INT)(MINVAL_DBL >> 1)); + return (FIXP_DBL)(LONG)(sum << 1); +} +#endif /* FUNCTION_fAddSaturate */ + +INT fixp_floorToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_floor(FIXP_DBL f_inp, INT sf); + +INT fixp_ceilToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_ceil(FIXP_DBL f_inp, INT sf); + +INT fixp_truncateToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_truncate(FIXP_DBL f_inp, INT sf); + +INT fixp_roundToInt(FIXP_DBL f_inp, INT sf); +FIXP_DBL fixp_round(FIXP_DBL f_inp, INT sf); + +/***************************************************************************** + + array for 1/n, n=1..80 + +****************************************************************************/ + +extern const FIXP_DBL invCount[80]; + +LNK_SECTION_INITCODE +inline void InitInvInt(void) {} + +/** + * \brief Calculate the value of 1/i where i is a integer value. It supports + * input values from 1 upto (80-1). + * \param intValue Integer input value. + * \param FIXP_DBL representation of 1/intValue + */ +inline FIXP_DBL GetInvInt(int intValue) { + return invCount[fMin(fMax(intValue, 0), 80 - 1)]; +} + +#endif /* FIXPOINT_MATH_H */ diff --git a/fdk-aac/libFDK/include/huff_nodes.h b/fdk-aac/libFDK/include/huff_nodes.h new file mode 100644 index 0000000..0dda5d3 --- /dev/null +++ b/fdk-aac/libFDK/include/huff_nodes.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: MPEG-D SAC/USAC/SAOC Huffman Part0 Tables + +*******************************************************************************/ + +#ifndef HUFF_NODES_H +#define HUFF_NODES_H + +#include "genericStds.h" + +typedef struct { + SHORT nodeTab[39][2]; + +} HUFF_RES_NODES; + +/* 1D Nodes */ +typedef struct { + SHORT nodeTab[30][2]; + +} HUFF_CLD_NOD_1D; + +typedef struct { + SHORT nodeTab[7][2]; + +} HUFF_ICC_NOD_1D; + +typedef struct { + SHORT nodeTab[50][2]; + +} HUFF_CPC_NOD_1D; + +typedef struct { + SHORT nodeTab[15][2]; + +} HUFF_OLD_NOD_1D; + +typedef struct { + SHORT nodeTab[63][2]; + +} HUFF_NRG_NOD_1D; + +/* 2D Nodes */ +typedef struct { + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + SHORT lav9[99][2]; + +} HUFF_CLD_NOD_2D; + +typedef struct { + SHORT lav1[3][2]; + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + +} HUFF_ICC_NOD_2D; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav6[48][2]; + SHORT lav9[99][2]; + SHORT lav12[168][2]; + +} HUFF_OLD_NOD_2D; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + SHORT lav9[99][2]; + +} HUFF_NRG_NOD_2D_df; + +typedef struct { + SHORT lav3[15][2]; + SHORT lav6[48][2]; + SHORT lav9[99][2]; + SHORT lav12[168][2]; + +} HUFF_NRG_NOD_2D_dt; + +typedef struct { + HUFF_NRG_NOD_2D_df df[2]; + HUFF_NRG_NOD_2D_dt dt[2]; + HUFF_NRG_NOD_2D_df dp[2]; + +} HUFF_NRG_NOD_2D; + +/* Complete bs Parameter Nodes */ +typedef struct { + const HUFF_CLD_NOD_1D *h1D[3]; + const HUFF_CLD_NOD_2D *h2D[3][2]; + +} HUFF_CLD_NODES; + +typedef struct { + const HUFF_ICC_NOD_1D *h1D[3]; + const HUFF_ICC_NOD_2D *h2D[3][2]; + +} HUFF_ICC_NODES; + +typedef struct { + const HUFF_OLD_NOD_1D *h1D[3]; + const HUFF_OLD_NOD_2D *h2D[3][2]; + +} HUFF_OLD_NODES; + +typedef struct { + const HUFF_NRG_NOD_1D *h1D[3]; + const HUFF_NRG_NOD_2D *h2D; + +} HUFF_NRG_NODES; + +/* parameter instance */ +typedef struct { + SHORT cld[30][2]; + SHORT icc[7][2]; + SHORT ipd[7][2]; + SHORT old[15][2]; + SHORT nrg[63][2]; +} HUFF_PT0_NODES; + +typedef struct { + SHORT nodeTab[3][2]; + +} HUFF_LAV_NODES; + +/* USAC specific */ +typedef struct { + SHORT nodeTab[7][2]; + +} HUFF_IPD_NOD_1D; + +typedef struct { + SHORT lav1[3][2]; + SHORT lav3[15][2]; + SHORT lav5[35][2]; + SHORT lav7[63][2]; + +} HUFF_IPD_NOD_2D; + +typedef struct { + HUFF_IPD_NOD_1D h1D[3]; + HUFF_IPD_NOD_2D h2D[3][2]; + +} HUFF_IPD_NODES; + +/* non-lossy coding decoder */ +extern const HUFF_PT0_NODES FDK_huffPart0Nodes; +extern const HUFF_LAV_NODES FDK_huffLavIdxNodes; + +extern const HUFF_ICC_NODES FDK_huffICCNodes; +extern const HUFF_CLD_NODES FDK_huffCLDNodes; +extern const HUFF_RES_NODES FDK_huffReshapeNodes; + +extern const HUFF_OLD_NODES huffOLDNodes; + +extern const HUFF_IPD_NODES FDK_huffIPDNodes; + +#endif /* HUFF_NODES_H */ diff --git a/fdk-aac/libFDK/include/mdct.h b/fdk-aac/libFDK/include/mdct.h new file mode 100644 index 0000000..1382374 --- /dev/null +++ b/fdk-aac/libFDK/include/mdct.h @@ -0,0 +1,253 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander, Josef Hoepfl, Youliy Ninov, Daniel Hagel + + Description: MDCT/MDST routines + +*******************************************************************************/ + +#ifndef MDCT_H +#define MDCT_H + +#include "common_fix.h" + +#define MDCT_OUT_HEADROOM 2 /* Output additional headroom */ +#define PCM_OUT_BITS SAMPLE_BITS +#define PCM_OUT_HEADROOM 8 /* Must have the same values as DMXH_HEADROOM */ + +#define MDCT_OUTPUT_SCALE (-MDCT_OUT_HEADROOM + (DFRACT_BITS - SAMPLE_BITS)) +/* Refer to "Output word length" in ISO/IEC 14496-3:2008(E) 23.2.3.6 */ +#define MDCT_OUTPUT_GAIN 16 + +#if (MDCT_OUTPUT_SCALE >= 0) +#define IMDCT_SCALE(x) SATURATE_RIGHT_SHIFT(x, MDCT_OUTPUT_SCALE, PCM_OUT_BITS) +#else +#define IMDCT_SCALE(x) SATURATE_LEFT_SHIFT(x, -MDCT_OUTPUT_SCALE, PCM_OUT_BITS) +#endif +#define IMDCT_SCALE_DBL(x) (FIXP_DBL)(x) +#define IMDCT_SCALE_DBL_LSH1(x) SATURATE_LEFT_SHIFT_ALT((x), 1, DFRACT_BITS) + +#define MLT_FLAG_CURR_ALIAS_SYMMETRY 1 + +typedef enum { + BLOCK_LONG = 0, /* normal long block */ + BLOCK_START, /* long start block */ + BLOCK_SHORT, /* 8 short blocks sequence */ + BLOCK_STOP /* long stop block*/ +} BLOCK_TYPE; + +typedef enum { SHAPE_SINE = 0, SHAPE_KBD, SHAPE_LOL } WINDOW_SHAPE; + +/** + * \brief MDCT persistent data + */ +typedef struct { + union { + FIXP_DBL *freq; + FIXP_DBL *time; + } overlap; /**< Pointer to overlap memory */ + + const FIXP_WTP *prev_wrs; /**< pointer to previous right window slope */ + int prev_tl; /**< previous transform length */ + int prev_nr; /**< previous right window offset */ + int prev_fr; /**< previous right window slope length */ + int ov_offset; /**< overlap time data fill level */ + int ov_size; /**< Overlap buffer size in words */ + + int prevAliasSymmetry; + int prevPrevAliasSymmetry; + + FIXP_DBL *pFacZir; + FIXP_DBL *pAsymOvlp; /**< pointer to asymmetric overlap (used for stereo LPD + transition) */ +} mdct_t; + +typedef mdct_t *H_MDCT; + +/** + * \brief Initialize as valid MDCT handle + * + * \param hMdct handle of an allocated MDCT handle. + * \param overlap pointer to FIXP_DBL overlap buffer. + * \param overlapBufferSize size in FIXP_DBLs of the given overlap buffer. + */ +void mdct_init(H_MDCT hMdct, FIXP_DBL *overlap, INT overlapBufferSize); + +/** + * \brief perform MDCT transform (time domain to frequency domain) with given + * parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param pTimeData pointer to input time domain signal + * \param noInSamples number of input samples + * \param mdctData pointer to where the resulting MDCT spectrum will be stored + * into. + * \param nSpec number of spectra + * \param pMdctData_e pointer to the input data exponent. Updated accordingly on + * return for output data. + * \return number of input samples processed. + */ +INT mdct_block(H_MDCT hMdct, const INT_PCM *pTimeData, const INT noInSamples, + FIXP_DBL *RESTRICT mdctData, const INT nSpec, const INT tl, + const FIXP_WTP *pRightWindowPart, const INT fr, + SHORT *pMdctData_e); + +/** + * \brief add/multiply 2/N transform gain and MPEG4 part 3 defined output gain + * (see definition of MDCT_OUTPUT_GAIN) to given mantissa factor and exponent. + * \param pGain pointer to the mantissa of a gain factor to be applied to IMDCT + * data. + * \param pExponent pointer to the exponent of a gain factor to be applied to + * IMDCT data. + * \param tl length of the IMDCT where the gain *pGain * (2 ^ *pExponent) will + * be applied to. + */ +void imdct_gain(FIXP_DBL *pGain, int *pExponent, int tl); + +/** + * \brief drain buffered output samples into given buffer. Changes the MDCT + * state. + */ +INT imdct_drain(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamplesRoom); + +/** + * \brief Copy overlap time domain data to given buffer. Does not change the + * MDCT state. + * \return number of actually copied samples (ov + nr). + */ +INT imdct_copy_ov_and_nr(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamples); + +/** + * \brief Adapt MDCT parameters for non-matching window slopes. + * \param hMdct handle of an allocated MDCT handle. + * \param pfl pointer to left overlap window side length. + * \param pnl pointer to length of the left n part of the window. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param noOutSamples desired number of output samples. + */ +void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl, + const FIXP_WTP *wls, int noOutSamples); + +/** + * \brief perform several inverse MLT transforms (frequency domain to time + * domain) with given parameters. + * + * \param hMdct handle of an allocated MDCT handle. + * \param output pointer to where the output time domain signal will be stored + * into. + * \param spectrum pointer to the input MDCT spectra. + * \param scalefactors exponents of the input spectrum. + * \param nSpec number of MDCT spectrums. + * \param noOutSamples desired number of output samples. + * \param tl transform length. + * \param wls pointer to the left side overlap window coefficients. + * \param fl left overlap window side length. + * \param wrs pointer to the right side overlap window coefficients of all + * individual IMDCTs. + * \param fr right overlap window side length of all individual IMDCTs. + * \param gain factor to apply to output samples (if != 0). + * \param flags flags controlling the type of transform + * \return number of output samples returned. + */ +INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, + const SHORT scalefactor[], const INT nSpec, + const INT noOutSamples, const INT tl, const FIXP_WTP *wls, + INT fl, const FIXP_WTP *wrs, const INT fr, FIXP_DBL gain, + int flags); + +#endif /* MDCT_H */ diff --git a/fdk-aac/libFDK/include/mips/abs_mips.h b/fdk-aac/libFDK/include/mips/abs_mips.h new file mode 100644 index 0000000..dbb2063 --- /dev/null +++ b/fdk-aac/libFDK/include/mips/abs_mips.h @@ -0,0 +1,125 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(ABS_MIPS_H) +#define ABS_MIPS_H + +#if defined(__mips__) + +#if defined(__GNUC__) && defined(__mips__) + +#if defined(__mips_dsp) +#define FUNCTION_fixabs_D +#define FUNCTION_fixabs_I +#define FUNCTION_fixabs_S +inline FIXP_DBL fixabs_D(FIXP_DBL x) { return __builtin_mips_absq_s_w(x); } +inline FIXP_SGL fixabs_S(FIXP_SGL x) { + return ((x) > (FIXP_SGL)(0)) ? (x) : -(x); +} +inline INT fixabs_I(INT x) { return __builtin_mips_absq_s_w(x); } +#endif /* __mips_dsp */ + +#endif /* defined(__GNUC__) && defined(__mips__) */ + +#endif /*__mips__ */ + +#endif /* !defined(ABS_MIPS_H) */ diff --git a/fdk-aac/libFDK/include/mips/clz_mips.h b/fdk-aac/libFDK/include/mips/clz_mips.h new file mode 100644 index 0000000..748f6c2 --- /dev/null +++ b/fdk-aac/libFDK/include/mips/clz_mips.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CLZ_MIPS_H) +#define CLZ_MIPS_H + +#if defined(__mips__) + +#if defined(__mips__) && (__GNUC__ == 2) && (mips >= 32) + +#define FUNCTION_fixnormz_D +inline INT fixnormz_D(LONG value) { + INT result; + __asm__("clz %0,%1" : "=d"(result) : "d"(value)); + + return result; +} + +#elif defined(__mips__) && (__GNUC__ == 3) && (__mips >= 32) + +#define FUNCTION_fixnormz_D +INT inline fixnormz_D(LONG value) { + INT result; + __asm__("clz %[result], %[value]" + : [result] "=r"(result) + : [value] "r"(value)); + + return result; +} + +#endif + +#endif /* __mips__ */ + +#endif /* !defined(CLZ_MIPS_H) */ diff --git a/fdk-aac/libFDK/include/mips/cplx_mul_mips.h b/fdk-aac/libFDK/include/mips/cplx_mul_mips.h new file mode 100644 index 0000000..4ade3e5 --- /dev/null +++ b/fdk-aac/libFDK/include/mips/cplx_mul_mips.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(CPLX_MUL_MIPS_H) +#define CPLX_MUL_MIPS_H + +#if defined(__GNUC__) && defined(__mips__) + +//#define FUNCTION_cplxMultDiv2_32x16 +//#define FUNCTION_cplxMultDiv2_32x16X2 +#define FUNCTION_cplxMultDiv2_32x32X2 +//#define FUNCTION_cplxMult_32x16 +//#define FUNCTION_cplxMult_32x16X2 +#define FUNCTION_cplxMult_32x32X2 + +#if defined(FUNCTION_cplxMultDiv2_32x32X2) +inline void cplxMultDiv2(FIXP_DBL *c_Re, FIXP_DBL *c_Im, FIXP_DBL a_Re, + FIXP_DBL a_Im, FIXP_DBL b_Re, FIXP_DBL b_Im) { + *c_Re = (((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32; + *c_Im = (((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32; +} +#endif + +#if defined(FUNCTION_cplxMult_32x32X2) +inline void cplxMult(FIXP_DBL *c_Re, FIXP_DBL *c_Im, FIXP_DBL a_Re, + FIXP_DBL a_Im, FIXP_DBL b_Re, FIXP_DBL b_Im) { + *c_Re = ((((long long)a_Re * (long long)b_Re) - ((long long)a_Im * (long long)b_Im))>>32)<<1; + *c_Im = ((((long long)a_Re * (long long)b_Im) + ((long long)a_Im * (long long)b_Re))>>32)<<1; +} +#endif + +#endif /* defined(__GNUC__) && defined(__mips__) */ + +#endif /* !defined(CPLX_MUL_MIPS_H) */ diff --git a/fdk-aac/libFDK/include/mips/fixmul_mips.h b/fdk-aac/libFDK/include/mips/fixmul_mips.h new file mode 100644 index 0000000..06cf530 --- /dev/null +++ b/fdk-aac/libFDK/include/mips/fixmul_mips.h @@ -0,0 +1,130 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_MIPS_H) +#define FIXMUL_MIPS_H + +#if defined(__mips__) + +#if (__GNUC__) && defined(__mips__) +/* MIPS GCC based compiler */ + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) + +inline INT fixmuldiv2_DD(const INT a, const INT b) { + INT result; + + result = ((long long)a * b) >> 32; + + return result; +} + +#endif /* (__GNUC__) && defined(__mips__) */ + +#endif /* __mips__ */ + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD fixmul_DD +#endif /* !defined(FIXMUL_MIPS_H) */ diff --git a/fdk-aac/libFDK/include/mips/scale_mips.h b/fdk-aac/libFDK/include/mips/scale_mips.h new file mode 100644 index 0000000..3c141fc --- /dev/null +++ b/fdk-aac/libFDK/include/mips/scale_mips.h @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCALE_MIPS_H +#define SCALE_MIPS_H + +#if defined(__mips_dsp) + +/*! + * + * \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} + * \return scaled and saturated value + * + * This macro scales src value right or left and applies saturation to + * (2^dBits)-1 maxima output. + */ +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + (__builtin_mips_shll_s_w((src) >> (scale), (DFRACT_BITS - (dBits))) >> \ + (DFRACT_BITS - (dBits))) + +#endif /*__mips_dsp */ + +#endif /* SCALE_MIPS_H */ diff --git a/fdk-aac/libFDK/include/mips/scramble_mips.h b/fdk-aac/libFDK/include/mips/scramble_mips.h new file mode 100644 index 0000000..08c2e6d --- /dev/null +++ b/fdk-aac/libFDK/include/mips/scramble_mips.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCRAMBLE_MIPS_H +#define SCRAMBLE_MIPS_H + +#define FUNCTION_scramble + +#if defined(FUNCTION_scramble) +inline void scramble(FIXP_DBL *x, INT n) { + INT m, j; + int ldn = 1; + do { + ldn++; + } while ((1 << ldn) < n); + + for (m = 1, j = 0; m < n - 1; m++) { + j = __builtin_mips_bitrev(m) >> (16 - ldn); + + if (j > m) { + FIXP_DBL tmp; + tmp = x[2 * m]; + x[2 * m] = x[2 * j]; + x[2 * j] = tmp; + + tmp = x[2 * m + 1]; + x[2 * m + 1] = x[2 * j + 1]; + x[2 * j + 1] = tmp; + } + } +} +#endif + +#endif /* SCRAMBLE_MIPS_H */ diff --git a/fdk-aac/libFDK/include/nlc_dec.h b/fdk-aac/libFDK/include/nlc_dec.h new file mode 100644 index 0000000..cca97f1 --- /dev/null +++ b/fdk-aac/libFDK/include/nlc_dec.h @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: SAC/SAOC Dec Noiseless Coding + +*******************************************************************************/ + +#ifndef NLC_DEC_H +#define NLC_DEC_H + +#include "FDK_bitstream.h" +#include "huff_nodes.h" +#include "common_fix.h" + +typedef enum { + + SAC_DECODER, + SAOC_DECODER, + USAC_DECODER + +} DECODER_TYPE; + +typedef enum { + t_CLD, + t_ICC, + t_IPD, + t_OLD, + t_IOC, + t_NRG, + t_DCLD, + t_DMG, + t_PDG + +} DATA_TYPE; + +typedef enum { + + BACKWARDS = 0x0, + FORWARDS = 0x1 + +} DIRECTION; + +typedef enum { + + DIFF_FREQ = 0x0, + DIFF_TIME = 0x1 + +} DIFF_TYPE; + +typedef enum { + + HUFF_1D = 0x0, + HUFF_2D = 0x1 + +} CODING_SCHEME; + +typedef enum { + + FREQ_PAIR = 0x0, + TIME_PAIR = 0x1 + +} PAIRING; + +#ifndef HUFFDEC_PARAMS +#define HUFFDEC_PARMS + +#define PAIR_SHIFT 4 +#define PAIR_MASK 0xf + +#define MAX_ENTRIES 168 +#define HANDLE_HUFF_NODE const SHORT(*)[MAX_ENTRIES][2] + +#endif /* HUFFDECPARAMS */ + +#define HUFFDEC_OK 0 +#define HUFFDEC_NOTOK (-1) + +typedef int ERROR_t; + +ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm, + SCHAR *aaOutData1, SCHAR *aaOutData2, SCHAR *aHistory, + DATA_TYPE data_type, int startBand, int dataBands, + int pair_flag, int coarse_flag, + int allowDiffTimeBack_flag); + +/* needed for GES- & STP-tool */ +ERROR_t huff_dec_reshape(HANDLE_FDK_BITSTREAM strm, int *out_data, int num_val); + +extern ERROR_t sym_restoreIPD(HANDLE_FDK_BITSTREAM strm, int lav, + SCHAR data[2]); + +#endif diff --git a/fdk-aac/libFDK/include/ppc/clz_ppc.h b/fdk-aac/libFDK/include/ppc/clz_ppc.h new file mode 100644 index 0000000..bfd23c6 --- /dev/null +++ b/fdk-aac/libFDK/include/ppc/clz_ppc.h @@ -0,0 +1,102 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixnormz_D + +inline INT fixnormz_D(LONG value) +{ + INT result; + __asm__ ("cntlzw %0, %1" : "=r" (result) : "r" (value)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/fdk-aac/libFDK/include/ppc/fixmul_ppc.h b/fdk-aac/libFDK/include/ppc/fixmul_ppc.h new file mode 100644 index 0000000..9e2745c --- /dev/null +++ b/fdk-aac/libFDK/include/ppc/fixmul_ppc.h @@ -0,0 +1,115 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2013 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/*************************** Fraunhofer IIS FDK Tools ********************** + + Author(s): + Description: fixed point intrinsics + +******************************************************************************/ + +#if defined(__powerpc__) && (defined(__GNUC__) || defined(__xlC__)) + +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a,b) fixmuldiv2_DD(a,b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a,b) fixmul_DD(a,b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a,b) fixmuldiv2_DS(a,b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a,b) fixmul_DS(a,b) + + +inline INT fixmuldiv2_DD (const INT a, const INT b) +{ + INT result; + __asm__ ("mulhw %0, %1, %2" : "=r" (result) : "r" (a), "r" (b)); + return result; +} + +#endif /* __powerpc__ && (__GNUC__ || __xlC__) */ diff --git a/fdk-aac/libFDK/include/qmf.h b/fdk-aac/libFDK/include/qmf.h new file mode 100644 index 0000000..609c6f1 --- /dev/null +++ b/fdk-aac/libFDK/include/qmf.h @@ -0,0 +1,301 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file qmf.h + \brief Complex qmf analysis/synthesis + \author Markus Werner + +*/ + +#ifndef QMF_H +#define QMF_H + +#include "common_fix.h" +#include "FDK_tools_rom.h" +#include "dct.h" + +#define FIXP_QAS FIXP_PCM +#define QAS_BITS SAMPLE_BITS + +#define FIXP_QSS FIXP_DBL +#define QSS_BITS DFRACT_BITS + +/* Flags for QMF intialization */ +/* Low Power mode flag */ +#define QMF_FLAG_LP 1 +/* Filter is not symmetric. This flag is set internally in the QMF + * initialization as required. */ +/* DO NOT PASS THIS FLAG TO qmfInitAnalysisFilterBank or + * qmfInitSynthesisFilterBank */ +#define QMF_FLAG_NONSYMMETRIC 2 +/* Complex Low Delay Filter Bank (or std symmetric filter bank) */ +#define QMF_FLAG_CLDFB 4 +/* Flag indicating that the states should be kept. */ +#define QMF_FLAG_KEEP_STATES 8 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder */ +#define QMF_FLAG_MPSLDFB 16 +/* Complex Low Delay Filter Bank used in MPEG Surround Encoder allows a + * optimized calculation of the modulation in qmfForwardModulationHQ() */ +#define QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION 32 +/* Flag to indicate HE-AAC down-sampled SBR mode (decoder) -> adapt analysis + * post twiddling */ +#define QMF_FLAG_DOWNSAMPLED 64 + +#define QMF_MAX_SYNTHESIS_BANDS (64) + +/*! + * \brief Algorithmic scaling in sbrForwardModulation() + * + * The scaling in sbrForwardModulation() is caused by: + * + * \li 1 R_SHIFT in sbrForwardModulation() + * \li 5/6 R_SHIFT in dct3() if using 32/64 Bands + * \li 1 omitted gain of 2.0 in qmfForwardModulation() + */ +#define ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK 7 + +/*! + * \brief Algorithmic scaling in cplxSynthesisQmfFiltering() + * + * The scaling in cplxSynthesisQmfFiltering() is caused by: + * + * \li 5/6 R_SHIFT in dct2() if using 32/64 Bands + * \li 1 omitted gain of 2.0 in qmfInverseModulation() + * \li -6 division by 64 in synthesis filterbank + * \li x bits external influence + */ +#define ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK 1 + +typedef struct { + int lb_scale; /*!< Scale of low band area */ + int ov_lb_scale; /*!< Scale of adjusted overlap low band area */ + int hb_scale; /*!< Scale of high band area */ + int ov_hb_scale; /*!< Scale of adjusted overlap high band area */ +} QMF_SCALE_FACTOR; + +struct QMF_FILTER_BANK { + const FIXP_PFT *p_filter; /*!< Pointer to filter coefficients */ + + void *FilterStates; /*!< Pointer to buffer of filter states + FIXP_PCM in analyse and + FIXP_DBL in synthesis filter */ + int FilterSize; /*!< Size of prototype filter. */ + const FIXP_QTW *t_cos; /*!< Modulation tables. */ + const FIXP_QTW *t_sin; + int filterScale; /*!< filter scale */ + + int no_channels; /*!< Total number of channels (subbands) */ + int no_col; /*!< Number of time slots */ + int lsb; /*!< Top of low subbands */ + int usb; /*!< Top of high subbands */ + + int synScalefactor; /*!< Scale factor of synthesis qmf (syn only) */ + int outScalefactor; /*!< Scale factor of output data (syn only) */ + FIXP_DBL outGain_m; /*!< Mantissa of gain output data (syn only) (init with + 0x80000000 to ignore) */ + int outGain_e; /*!< Exponent of gain output data (syn only) */ + + UINT flags; /*!< flags */ + UCHAR p_stride; /*!< Stride Factor of polyphase filters */ +}; + +typedef struct QMF_FILTER_BANK *HANDLE_QMF_FILTER_BANK; + +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const LONG *timeIn, /*!< Time signal */ + const int timeIn_e, /*!< Exponent of audio data */ + const int stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); + +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const INT_PCM *timeIn, /*!< Time signal */ + const int timeIn_e, /*!< Exponent of audio data */ + const int stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +); + +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Pointer to real subband slots */ + FIXP_DBL **QmfBufferImag, /*!< Pointer to imag subband slots */ + const QMF_SCALE_FACTOR *scaleFactor, /*!< Scale factors of QMF data */ + const int ov_len, /*!< Length of band overlap */ + INT_PCM *timeOut, /*!< Time signal */ + const INT stride, /*!< Stride factor of audio data */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer. It must be + aligned */ +); + +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QAS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ + +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const LONG *timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporary working buffer */ +); + +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const INT_PCM *timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +); +int qmfInitSynthesisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< QMF Handle */ + FIXP_QSS *pFilterStates, /*!< Pointer to filter state buffer */ + int noCols, /*!< Number of time slots */ + int lsb, /*!< Number of lower bands */ + int usb, /*!< Number of upper bands */ + int no_channels, /*!< Number of critically sampled bands */ + int flags); /*!< Flags */ + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, INT_PCM *timeOut, + const int timeOut_e, FIXP_DBL *pWorkBuffer); + +void qmfChangeOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ +); + +int qmfGetOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf /*!< Handle of Qmf Synthesis Bank */ +); + +void qmfChangeOutGain( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ + int outputGainScale /*!< New gain for output data (exponent) */ +); +void qmfSynPrototypeFirSlot( + HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM *RESTRICT timeOut, /*!< Time domain data */ + const int timeOut_e); + +#endif /*ifndef QMF_H */ diff --git a/fdk-aac/libFDK/include/qmf_pcm.h b/fdk-aac/libFDK/include/qmf_pcm.h new file mode 100644 index 0000000..f24e0cd --- /dev/null +++ b/fdk-aac/libFDK/include/qmf_pcm.h @@ -0,0 +1,405 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander + + Description: QMF filterbank + +*******************************************************************************/ + +#ifndef QMF_PCM_H +#define QMF_PCM_H + +/* + All Synthesis functions dependent on datatype INT_PCM_QMFOUT + Should only be included by qmf.cpp, but not compiled separately, please + exclude compilation from project, if done otherwise. Is optional included + twice to duplicate all functions with two different pre-definitions, as: + #define INT_PCM_QMFOUT LONG + and ... + #define INT_PCM_QMFOUT SHORT + needed to run QMF synthesis in both 16bit and 32bit sample output format. +*/ + +#define QSSCALE (0) +#define FX_DBL2FX_QSS(x) (x) +#define FX_QSS2FX_DBL(x) (x) + +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +/* static */ +#ifndef FUNCTION_qmfSynPrototypeFirSlot +void qmfSynPrototypeFirSlot( +#else +void qmfSynPrototypeFirSlot_fallback( +#endif + HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ + int stride) { + FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - + qmf->outGain_e; + + p_flt = + p_Filter + p_stride * QMF_NO_POLY; /* 5th of 330 */ + p_fltm = p_Filter + (qmf->FilterSize / 2) - + p_stride * QMF_NO_POLY; /* 5 + (320 - 2*5) = 315th of 330 */ + + FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); + + FIXP_DBL rnd_val = 0; + + if (scale > 0) { + if (scale < (DFRACT_BITS - 1)) + rnd_val = FIXP_DBL(1 << (scale - 1)); + else + scale = (DFRACT_BITS - 1); + } else { + scale = fMax(scale, -(DFRACT_BITS - 1)); + } + + for (j = no_channels - 1; j >= 0; j--) { + FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ + FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ + { + INT_PCM_QMFOUT tmp; + FIXP_DBL Are = fMultAddDiv2(FX_QSS2FX_DBL(sta[0]), p_fltm[0], real); + + /* This PCM formatting performs: + - multiplication with 16-bit gain, if not -1.0f + - rounding, if shift right is applied + - apply shift left (or right) with saturation to 32 (or 16) bits + - store output with --stride in 32 (or 16) bit format + */ + if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ + { + Are = fMult(Are, gain); + } + if (scale >= 0) { + FDK_ASSERT( + Are <= + (Are + rnd_val)); /* Round-addition must not overflow, might be + equal for rnd_val=0 */ + tmp = (INT_PCM_QMFOUT)( + SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); + } else { + tmp = (INT_PCM_QMFOUT)( + SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); + } + + { timeOut[(j)*stride] = tmp; } + } + + sta[0] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[1]), p_flt[4], imag)); + sta[1] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[2]), p_fltm[1], real)); + sta[2] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[3]), p_flt[3], imag)); + sta[3] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[4]), p_fltm[2], real)); + sta[4] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[5]), p_flt[2], imag)); + sta[5] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[6]), p_fltm[3], real)); + sta[6] = FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[7]), p_flt[1], imag)); + sta[7] = + FX_DBL2FX_QSS(fMultAddDiv2(FX_QSS2FX_DBL(sta[8]), p_fltm[4], real)); + sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); + p_flt += (p_stride * QMF_NO_POLY); + p_fltm -= (p_stride * QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } +} + +#ifndef FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Synthesis Prototype Filtering on a single slot of input data. + + The filter takes 2 * qmf->no_channels of input data and + generates qmf->no_channels time domain output samples. +*/ +static void qmfSynPrototypeFirSlot_NonSymmetric( + HANDLE_QMF_FILTER_BANK qmf, + FIXP_DBL *RESTRICT realSlot, /*!< Input: Pointer to real Slot */ + FIXP_DBL *RESTRICT imagSlot, /*!< Input: Pointer to imag Slot */ + INT_PCM_QMFOUT *RESTRICT timeOut, /*!< Time domain data */ + int stride) { + FIXP_QSS *FilterStates = (FIXP_QSS *)qmf->FilterStates; + int no_channels = qmf->no_channels; + const FIXP_PFT *p_Filter = qmf->p_filter; + int p_stride = qmf->p_stride; + int j; + FIXP_QSS *RESTRICT sta = FilterStates; + const FIXP_PFT *RESTRICT p_flt, *RESTRICT p_fltm; + int scale = (DFRACT_BITS - SAMPLE_BITS_QMFOUT) - 1 - qmf->outScalefactor - + qmf->outGain_e; + + p_flt = p_Filter; /*!< Pointer to first half of filter coefficients */ + p_fltm = + &p_flt[qmf->FilterSize / 2]; /* at index 320, overall 640 coefficients */ + + FIXP_SGL gain = FX_DBL2FX_SGL(qmf->outGain_m); + + FIXP_DBL rnd_val = (FIXP_DBL)0; + + if (scale > 0) { + if (scale < (DFRACT_BITS - 1)) + rnd_val = FIXP_DBL(1 << (scale - 1)); + else + scale = (DFRACT_BITS - 1); + } else { + scale = fMax(scale, -(DFRACT_BITS - 1)); + } + + for (j = no_channels - 1; j >= 0; j--) { + FIXP_DBL imag = imagSlot[j]; /* no_channels-1 .. 0 */ + FIXP_DBL real = realSlot[j]; /* no_channels-1 .. 0 */ + { + INT_PCM_QMFOUT tmp; + FIXP_DBL Are = sta[0] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[4], real)); + + /* This PCM formatting performs: + - multiplication with 16-bit gain, if not -1.0f + - rounding, if shift right is applied + - apply shift left (or right) with saturation to 32 (or 16) bits + - store output with --stride in 32 (or 16) bit format + */ + if (gain != (FIXP_SGL)(-32768)) /* -1.0f */ + { + Are = fMult(Are, gain); + } + if (scale > 0) { + FDK_ASSERT(Are < + (Are + rnd_val)); /* Round-addition must not overflow */ + tmp = (INT_PCM_QMFOUT)( + SATURATE_RIGHT_SHIFT(Are + rnd_val, scale, SAMPLE_BITS_QMFOUT)); + } else { + tmp = (INT_PCM_QMFOUT)( + SATURATE_LEFT_SHIFT(Are, -scale, SAMPLE_BITS_QMFOUT)); + } + timeOut[j * stride] = tmp; + } + + sta[0] = sta[1] + FX_DBL2FX_QSS(fMultDiv2(p_flt[4], imag)); + sta[1] = sta[2] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[3], real)); + sta[2] = sta[3] + FX_DBL2FX_QSS(fMultDiv2(p_flt[3], imag)); + + sta[3] = sta[4] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[2], real)); + sta[4] = sta[5] + FX_DBL2FX_QSS(fMultDiv2(p_flt[2], imag)); + sta[5] = sta[6] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[1], real)); + sta[6] = sta[7] + FX_DBL2FX_QSS(fMultDiv2(p_flt[1], imag)); + + sta[7] = sta[8] + FX_DBL2FX_QSS(fMultDiv2(p_fltm[0], real)); + sta[8] = FX_DBL2FX_QSS(fMultDiv2(p_flt[0], imag)); + + p_flt += (p_stride * QMF_NO_POLY); + p_fltm += (p_stride * QMF_NO_POLY); + sta += 9; // = (2*QMF_NO_POLY-1); + } +} +#endif /* FUNCTION_qmfSynPrototypeFirSlot_NonSymmetric */ + +void qmfSynthesisFilteringSlot(HANDLE_QMF_FILTER_BANK synQmf, + const FIXP_DBL *realSlot, + const FIXP_DBL *imagSlot, + const int scaleFactorLowBand, + const int scaleFactorHighBand, + INT_PCM_QMFOUT *timeOut, const int stride, + FIXP_DBL *pWorkBuffer) { + if (!(synQmf->flags & QMF_FLAG_LP)) + qmfInverseModulationHQ(synQmf, realSlot, imagSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + else { + if (synQmf->flags & QMF_FLAG_CLDFB) { + qmfInverseModulationLP_odd(synQmf, realSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + } else { + qmfInverseModulationLP_even(synQmf, realSlot, scaleFactorLowBand, + scaleFactorHighBand, pWorkBuffer); + } + } + + if (synQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfSynPrototypeFirSlot_NonSymmetric(synQmf, pWorkBuffer, + pWorkBuffer + synQmf->no_channels, + timeOut, stride); + } else { + qmfSynPrototypeFirSlot(synQmf, pWorkBuffer, + pWorkBuffer + synQmf->no_channels, timeOut, stride); + } +} + +/*! + * + * \brief Perform complex-valued subband synthesis of the + * low band and the high band and store the + * time domain data in timeOut + * + * First step: Calculate the proper scaling factor of current + * spectral data in qmfReal/qmfImag, old spectral data in the overlap + * range and filter states. + * + * Second step: Perform Frequency-to-Time mapping with inverse + * Modulation slot-wise. + * + * Third step: Perform FIR-filter slot-wise. To save space for filter + * states, the MAC operations are executed directly on the filter states + * instead of accumulating several products in the accumulator. The + * buffer shift at the end of the function should be replaced by a + * modulo operation, which is available on some DSPs. + * + * Last step: Copy the upper part of the spectral data to the overlap buffer. + * + * The qmf coefficient table is symmetric. The symmetry is exploited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. If the #define #QMFTABLE_FULL is set, + * coefficient addressing works on the full table size. The code will be + * slightly faster and slightly more compact. + * + * Workbuffer requirement: 2 x sizeof(**QmfBufferReal) * synQmf->no_channels + * The workbuffer must be aligned + */ +void qmfSynthesisFiltering( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL **QmfBufferReal, /*!< Low and High band, real */ + FIXP_DBL **QmfBufferImag, /*!< Low and High band, imag */ + const QMF_SCALE_FACTOR *scaleFactor, + const INT ov_len, /*!< split Slot of overlap and actual slots */ + INT_PCM_QMFOUT *timeOut, /*!< Pointer to output */ + const INT stride, /*!< stride factor of output */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int L = synQmf->no_channels; + int scaleFactorHighBand; + int scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + + FDK_ASSERT(synQmf->no_channels >= synQmf->lsb); + FDK_ASSERT(synQmf->no_channels >= synQmf->usb); + + /* adapt scaling */ + scaleFactorHighBand = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->hb_scale - synQmf->filterScale; + scaleFactorLowBand_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->ov_lb_scale - synQmf->filterScale; + scaleFactorLowBand_no_ov = -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - + scaleFactor->lb_scale - synQmf->filterScale; + + for (i = 0; i < synQmf->no_col; i++) /* ----- no_col loop ----- */ + { + const FIXP_DBL *QmfBufferImagSlot = NULL; + + int scaleFactorLowBand = + (i < ov_len) ? scaleFactorLowBand_ov : scaleFactorLowBand_no_ov; + + if (!(synQmf->flags & QMF_FLAG_LP)) QmfBufferImagSlot = QmfBufferImag[i]; + + qmfSynthesisFilteringSlot(synQmf, QmfBufferReal[i], QmfBufferImagSlot, + scaleFactorLowBand, scaleFactorHighBand, + timeOut + (i * L * stride), stride, pWorkBuffer); + } /* no_col loop i */ +} +#endif /* QMF_PCM_H */ diff --git a/fdk-aac/libFDK/include/scale.h b/fdk-aac/libFDK/include/scale.h new file mode 100644 index 0000000..30fa089 --- /dev/null +++ b/fdk-aac/libFDK/include/scale.h @@ -0,0 +1,298 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Scaling operations + +*******************************************************************************/ + +#ifndef SCALE_H +#define SCALE_H + +#include "common_fix.h" +#include "genericStds.h" +#include "fixminmax.h" + +#define SCALE_INLINE + +#if defined(__arm__) +#include "arm/scale_arm.h" + +#elif defined(__mips__) +#include "mips/scale_mips.h" + +#endif + +void scaleValues(FIXP_SGL *vector, INT len, INT scalefactor); +void scaleValues(FIXP_DBL *vector, INT len, INT scalefactor); +void scaleValues(FIXP_DBL *dst, const FIXP_DBL *src, INT len, INT scalefactor); +#if (SAMPLE_BITS == 16) +void scaleValues(FIXP_PCM *dst, const FIXP_DBL *src, INT len, INT scalefactor); +#endif +void scaleValues(FIXP_PCM *dst, const FIXP_SGL *src, INT len, INT scalefactor); +void scaleCplxValues(FIXP_DBL *r_dst, FIXP_DBL *i_dst, const FIXP_DBL *r_src, + const FIXP_DBL *i_src, INT len, INT scalefactor); +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor); +void scaleValuesSaturate(FIXP_DBL *vector, INT len, INT scalefactor); +void scaleValuesSaturate(FIXP_DBL *dst, FIXP_DBL *src, INT len, + INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *dst, FIXP_DBL *src, INT len, + INT scalefactor); +void scaleValuesSaturate(INT_PCM *dst, FIXP_DBL *src, INT len, INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *vector, INT len, INT scalefactor); +void scaleValuesSaturate(FIXP_SGL *dst, FIXP_SGL *src, INT len, + INT scalefactor); +void scaleValuesSaturate(INT_PCM *dst, INT_PCM *src, INT len, INT scalefactor); +INT getScalefactorShort(const SHORT *vector, INT len); +INT getScalefactorPCM(const INT_PCM *vector, INT len, INT stride); +INT getScalefactor(const FIXP_DBL *vector, INT len); +INT getScalefactor(const FIXP_SGL *vector, INT len); + +#ifndef FUNCTION_scaleValue +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * + * \return Scaled input + * + */ +#define FUNCTION_scaleValue +inline FIXP_DBL scaleValue(const FIXP_DBL value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + if (scalefactor > 0) + return (value << scalefactor); + else + return (value >> (-scalefactor)); +} +inline FIXP_SGL scaleValue(const FIXP_SGL value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + if (scalefactor > 0) + return (value << scalefactor); + else + return (value >> (-scalefactor)); +} +#endif + +#ifndef FUNCTION_scaleValueSaturate +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ + * \param value The value to be scaled. + * \param the shift amount + * \return \f$ value * 2^scalefactor \f$ + * + */ +#define FUNCTION_scaleValueSaturate +inline FIXP_DBL scaleValueSaturate(const FIXP_DBL value, + INT scalefactor /* in range -31 ... +31 */ +) { + int headroom = fixnormz_D( + (INT)value ^ (INT)((value >> 31))); /* headroom in range 1...32 */ + if (scalefactor >= 0) { + /* shift left: saturate in case of headroom less/equal scalefactor */ + if (headroom <= scalefactor) { + if (value > (FIXP_DBL)0) + return (FIXP_DBL)MAXVAL_DBL; /* 0x7FFF.FFFF */ + else + return (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1; /* 0x8000.0001 */ + } else { + return fMax((value << scalefactor), (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1); + } + } else { + scalefactor = -scalefactor; + /* shift right: clear in case of 32-headroom greater/equal -scalefactor */ + if ((DFRACT_BITS - headroom) <= scalefactor) { + return (FIXP_DBL)0; + } else { + return fMax((value >> scalefactor), (FIXP_DBL)MINVAL_DBL + (FIXP_DBL)1); + } + } +} +#endif + +#ifndef FUNCTION_scaleValueInPlace +/*! + * + * \brief Multiply input by \f$ 2^{scalefactor} \f$ in place + * + * \return void + * + */ +#define FUNCTION_scaleValueInPlace +inline void scaleValueInPlace(FIXP_DBL *value, /*!< Value */ + INT scalefactor /*!< Scalefactor */ +) { + INT newscale; + /* Note: The assignment inside the if conditional allows combining a load with + * the compare to zero (on ARM and maybe others) */ + if ((newscale = (scalefactor)) >= 0) { + *(value) <<= newscale; + } else { + *(value) >>= -newscale; + } +} +#endif + + /*! + * + * \brief Scale input value by 2^{scale} and saturate output to 2^{dBits-1} + * \return scaled and saturated value + * + * This macro scales src value right or left and applies saturation to + * (2^dBits)-1 maxima output. + */ + +#ifndef SATURATE_RIGHT_SHIFT +#define SATURATE_RIGHT_SHIFT(src, scale, dBits) \ + ((((LONG)(src) >> (scale)) > (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : (((LONG)(src) >> (scale)) < ~((LONG)(((1U) << ((dBits)-1)) - 1))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 1)) \ + : ((LONG)(src) >> (scale))) +#endif + +#ifndef SATURATE_LEFT_SHIFT +#define SATURATE_LEFT_SHIFT(src, scale, dBits) \ + (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) < ~((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 1)) \ + : ((LONG)(src) << (scale))) +#endif + +#ifndef SATURATE_SHIFT +#define SATURATE_SHIFT(src, scale, dBits) \ + (((scale) < 0) ? SATURATE_LEFT_SHIFT((src), -(scale), (dBits)) \ + : SATURATE_RIGHT_SHIFT((src), (scale), (dBits))) +#endif + +/* + * Alternative shift and saturate left, saturates to -0.99999 instead of -1.0000 + * to avoid problems when inverting the sign of the result. + */ +#ifndef SATURATE_LEFT_SHIFT_ALT +#define SATURATE_LEFT_SHIFT_ALT(src, scale, dBits) \ + (((LONG)(src) > ((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : ((LONG)(src) <= ~((LONG)(((1U) << ((dBits)-1)) - 1) >> (scale))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 2)) \ + : ((LONG)(src) << (scale))) +#endif + +#ifndef SATURATE_RIGHT_SHIFT_ALT +#define SATURATE_RIGHT_SHIFT_ALT(src, scale, dBits) \ + ((((LONG)(src) >> (scale)) > (LONG)(((1U) << ((dBits)-1)) - 1)) \ + ? (LONG)(((1U) << ((dBits)-1)) - 1) \ + : (((LONG)(src) >> (scale)) < ~((LONG)(((1U) << ((dBits)-1)) - 2))) \ + ? ~((LONG)(((1U) << ((dBits)-1)) - 2)) \ + : ((LONG)(src) >> (scale))) +#endif + +#ifndef SATURATE_INT_PCM_RIGHT_SHIFT +#define SATURATE_INT_PCM_RIGHT_SHIFT(src, scale) \ + SATURATE_RIGHT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#ifndef SATURATE_INT_PCM_LEFT_SHIFT +#define SATURATE_INT_PCM_LEFT_SHIFT(src, scale) \ + SATURATE_LEFT_SHIFT(src, scale, SAMPLE_BITS) +#endif + +#endif /* #ifndef SCALE_H */ diff --git a/fdk-aac/libFDK/include/scramble.h b/fdk-aac/libFDK/include/scramble.h new file mode 100644 index 0000000..f07ebed --- /dev/null +++ b/fdk-aac/libFDK/include/scramble.h @@ -0,0 +1,153 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef SCRAMBLE_H +#define SCRAMBLE_H + +#include "common_fix.h" + +#if defined(__arm__) +#include "arm/scramble_arm.h" + +#elif defined(__mips__) && defined(__mips_dsp) +#include "mips/scramble_mips.h" + +#endif + +/***************************************************************************** + + functionname: scramble + description: bitreversal of input data + returns: + input: + output: + +*****************************************************************************/ +#if !defined(FUNCTION_scramble) + +/* default scramble functionality */ +inline void scramble(FIXP_DBL *x, INT length) { + INT m, k, j; + FDK_ASSERT(!(((INT)(INT64)x) & (ALIGNMENT_DEFAULT - 1))); + C_ALLOC_ALIGNED_CHECK(x); + + for (m = 1, j = 0; m < length - 1; m++) { + { + for (k = length >> 1; (!((j ^= k) & k)); k >>= 1) + ; + } + + if (j > m) { + FIXP_DBL tmp; + tmp = x[2 * m]; + x[2 * m] = x[2 * j]; + x[2 * j] = tmp; + + tmp = x[2 * m + 1]; + x[2 * m + 1] = x[2 * j + 1]; + x[2 * j + 1] = tmp; + } + } +} +#endif /* !defined(FUNCTION_scramble) */ + +#endif /* SCRAMBLE_H */ diff --git a/fdk-aac/libFDK/include/x86/abs_x86.h b/fdk-aac/libFDK/include/x86/abs_x86.h new file mode 100644 index 0000000..efd6433 --- /dev/null +++ b/fdk-aac/libFDK/include/x86/abs_x86.h @@ -0,0 +1,123 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(ABS_X86_H) +#define ABS_X86_H + +#if defined(__x86__) + +#if defined(__x86_64__) + +inline INT fixabs_D(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } +inline INT fixabs_S(INT x) { return ((x) > (INT)(0)) ? (x) : -(x); } + +#define fixabs_I(x) fixabs_D(x) + +#define FUNCTION_fixabs_S +#define FUNCTION_fixabs_D +#define FUNCTION_fixabs_I + +#endif /* __x86_64__ */ + +#endif /*__x86__ */ + +#endif /* !defined(ABS_X86_H) */ diff --git a/fdk-aac/libFDK/include/x86/clz_x86.h b/fdk-aac/libFDK/include/x86/clz_x86.h new file mode 100644 index 0000000..badca29 --- /dev/null +++ b/fdk-aac/libFDK/include/x86/clz_x86.h @@ -0,0 +1,165 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: x86 version of count leading zero / bits + +*******************************************************************************/ + +#if !defined(CLZ_X86_H) +#define CLZ_X86_H + +#if defined(__GNUC__) && (defined(__x86__) || defined(__x86_64__)) + +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D + +inline INT fixnormz_D(LONG value) { + INT result; + + if (value != 0) { + result = __builtin_clz(value); + } else { + result = 32; + } + return result; +} + +inline INT fixnorm_D(LONG value) { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; +} + +#elif (_MSC_VER > 1200) && (defined(_M_IX86) || defined(_M_X64)) + +#include + +#define FUNCTION_fixnormz_D +#define FUNCTION_fixnorm_D + +inline INT fixnormz_D(LONG value) { + unsigned long result = 0; + unsigned char err; + err = _BitScanReverse(&result, value); + if (err) { + return 31 - result; + } else { + return 32; + } +} + +inline INT fixnorm_D(LONG value) { + INT result; + if (value == 0) { + return 0; + } + if (value < 0) { + value = ~value; + } + result = fixnormz_D(value); + return result - 1; +} + +#endif /* toolchain */ +#endif /* !defined(CLZ_X86_H) */ diff --git a/fdk-aac/libFDK/include/x86/fixmul_x86.h b/fdk-aac/libFDK/include/x86/fixmul_x86.h new file mode 100644 index 0000000..84e6316 --- /dev/null +++ b/fdk-aac/libFDK/include/x86/fixmul_x86.h @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: fixed point intrinsics + +*******************************************************************************/ + +#if !defined(FIXMUL_X86_H) +#define FIXMUL_X86_H + +#if defined(__x86__) + +#if defined(_MSC_VER) && defined(_M_IX86) +/* Intel x86 */ + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) fixmul_DD(a, b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) + +inline INT fixmul_DD(INT a, const INT b) { + __asm + { + mov eax, a + imul b + shl edx, 1 + mov a, edx + } + return a; +} + +inline INT fixmuldiv2_DD(INT a, const INT b) { + __asm + { + mov eax, a + imul b + mov a, edx + } + return a; +} + +/* ############################################################################# + */ +#elif (defined(__GNUC__) || defined(__gnu_linux__)) && defined(__x86__) + +#define FUNCTION_fixmul_DD +#define FUNCTION_fixmuldiv2_DD + +#define FUNCTION_fixmuldiv2BitExact_DD +#define fixmuldiv2BitExact_DD(a, b) fixmuldiv2_DD(a, b) + +#define FUNCTION_fixmulBitExact_DD +#define fixmulBitExact_DD(a, b) fixmul_DD(a, b) + +#define FUNCTION_fixmuldiv2BitExact_DS +#define fixmuldiv2BitExact_DS(a, b) fixmuldiv2_DS(a, b) + +#define FUNCTION_fixmulBitExact_DS +#define fixmulBitExact_DS(a, b) fixmul_DS(a, b) + +inline INT fixmul_DD(INT a, const INT b) { + INT result; + + asm("imul %2;\n" + "shl $1, %0;\n" + : "=d"(result), "+a"(a) + : "r"(b)); + + return result; +} + +inline INT fixmuldiv2_DD(INT a, const INT b) { + INT result; + + asm("imul %2;" : "=d"(result), "+a"(a) : "r"(b)); + + return result; +} + +#endif /* (defined(__GNUC__)||defined(__gnu_linux__)) && defined(__x86__) */ + +#endif /* __x86__ */ + +#endif /* !defined(FIXMUL_X86_H) */ diff --git a/fdk-aac/libFDK/include/x86/fixpoint_math_x86.h b/fdk-aac/libFDK/include/x86/fixpoint_math_x86.h new file mode 100644 index 0000000..d81fb26 --- /dev/null +++ b/fdk-aac/libFDK/include/x86/fixpoint_math_x86.h @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: Fixed point specific mathematical functions for x86 + +*******************************************************************************/ + +#if !defined(FIXPOINT_MATH_X86_H) +#define FIXPOINT_MATH_X86_H + +#define FUNCTION_sqrtFixp + +#include + +#ifdef FUNCTION_sqrtFixp +static inline FIXP_DBL sqrtFixp(const FIXP_DBL op) { + FIXP_DBL result; + /* result = + * (FIXP_DBL)(INT)(sqrt((double)(INT)op)*46340.950011841578559133736114903); + */ + result = (FIXP_DBL)(INT)(sqrt((float)(INT)op) * 46340.9492f); + FDK_ASSERT(result >= (FIXP_DBL)0); + return result; +} +#endif /* FUNCTION_sqrtFixp */ + +#include + +#define FUNCTION_invSqrtNorm2 +/** + * \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 + */ +#ifdef FUNCTION_invSqrtNorm2 +inline FIXP_DBL invSqrtNorm2(FIXP_DBL op_m, INT *result_e) { + float result; + if (op_m == (FIXP_DBL)0) { + *result_e = 16; + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / sqrt(0.5f * (float)(INT)op_m)); + result = (float)ldexp(frexpf(result, result_e), DFRACT_BITS - 1); + *result_e += 15; + + FDK_ASSERT(result >= 0); + return (FIXP_DBL)(INT)result; +} +#endif /* FUNCTION_invSqrtNorm2 */ + +#define FUNCTION_invFixp +/** + * \brief calculate 1.0/op + * \param op mantissa of the input value. + * \return mantissa of the result with implizit exponent of 31 + */ +#ifdef FUNCTION_invFixp +inline FIXP_DBL invFixp(FIXP_DBL op) { + float result; + INT result_e; + if ((op == (FIXP_DBL)0) || (op == (FIXP_DBL)1)) { + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / (float)(INT)op); + result = frexpf(result, &result_e); + result = ldexpf(result, 31 + result_e); + + return (FIXP_DBL)(INT)result; +} + +/** + * \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 + */ +inline FIXP_DBL invFixp(FIXP_DBL op_m, int *op_e) { + float result; + INT result_e; + if ((op_m == (FIXP_DBL)0x00000000) || (op_m == (FIXP_DBL)0x00000001)) { + *op_e = 31 - *op_e; + return ((LONG)0x7fffffff); + } + result = (float)(1.0 / (float)(INT)op_m); + result = ldexpf(frexpf(result, &result_e), DFRACT_BITS - 1); + *op_e = result_e - *op_e + 31; + return (FIXP_DBL)(INT)result; +} +#endif /* FUNCTION_invFixp */ + +#define FUNCTION_schur_div +/** + * \brief Divide two FIXP_DBL values with given precision. + * \param num dividend + * \param denum divisor + * \param count amount of significant bits of the result (starting to the MSB) + * \return num/divisor + */ +#ifdef FUNCTION_schur_div +inline FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) { + (void)count; + /* same asserts than for fallback implementation */ + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denum > (FIXP_DBL)0); + FDK_ASSERT(num <= denum); + + return (num == denum) ? (FIXP_DBL)MAXVAL_DBL + : (FIXP_DBL)(INT)(((INT64)(INT)num << 31) / (INT)denum); +} +#endif /* FUNCTION_schur_div */ +#endif /* !defined(FIXPOINT_MATH_X86_H) */ diff --git a/fdk-aac/libFDK/src/FDK_bitbuffer.cpp b/fdk-aac/libFDK/src/FDK_bitbuffer.cpp new file mode 100644 index 0000000..98905ea --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_bitbuffer.cpp @@ -0,0 +1,489 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: common bitbuffer read/write routines + +*******************************************************************************/ + +#include "FDK_bitbuffer.h" + +#include "genericStds.h" +#include "common_fix.h" +#include "fixminmax.h" + +const UINT BitMask[32 + 1] = { + 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, + 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, + 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, + 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, + 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, + 0x3fffffff, 0x7fffffff, 0xffffffff}; + +void FDK_CreateBitBuffer(HANDLE_FDK_BITBUF *hBitBuf, UCHAR *pBuffer, + UINT bufSize) { + FDK_InitBitBuffer(*hBitBuf, pBuffer, bufSize, 0); + + FDKmemclear((*hBitBuf)->Buffer, bufSize * sizeof(UCHAR)); +} + +void FDK_DeleteBitBuffer(HANDLE_FDK_BITBUF hBitBuf) { ; } + +void FDK_InitBitBuffer(HANDLE_FDK_BITBUF hBitBuf, UCHAR *pBuffer, UINT bufSize, + UINT validBits) { + hBitBuf->ValidBits = validBits; + hBitBuf->ReadOffset = 0; + hBitBuf->WriteOffset = 0; + hBitBuf->BitNdx = 0; + + hBitBuf->Buffer = pBuffer; + hBitBuf->bufSize = bufSize; + hBitBuf->bufBits = (bufSize << 3); + /*assure bufsize (2^n) */ + FDK_ASSERT(hBitBuf->ValidBits <= hBitBuf->bufBits); + FDK_ASSERT((bufSize > 0) && (bufSize <= MAX_BUFSIZE_BYTES)); + { + UINT x = 0, n = bufSize; + for (x = 0; n > 0; x++, n >>= 1) { + } + if (bufSize != ((UINT)1 << (x - 1))) { + FDK_ASSERT(0); + } + } +} + +void FDK_ResetBitBuffer(HANDLE_FDK_BITBUF hBitBuf) { + hBitBuf->ValidBits = 0; + hBitBuf->ReadOffset = 0; + hBitBuf->WriteOffset = 0; + hBitBuf->BitNdx = 0; +} + +#ifndef FUNCTION_FDK_get +INT FDK_get(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x07; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits -= numberOfBits; + + UINT byteMask = hBitBuf->bufSize - 1; + + UINT tx = (hBitBuf->Buffer[byteOffset & byteMask] << 24) | + (hBitBuf->Buffer[(byteOffset + 1) & byteMask] << 16) | + (hBitBuf->Buffer[(byteOffset + 2) & byteMask] << 8) | + hBitBuf->Buffer[(byteOffset + 3) & byteMask]; + + if (bitOffset) { + tx <<= bitOffset; + tx |= hBitBuf->Buffer[(byteOffset + 4) & byteMask] >> (8 - bitOffset); + } + + return (tx >> (32 - numberOfBits)); +} +#endif /* #ifndef FUNCTION_FDK_get */ + +#ifndef FUNCTION_FDK_get32 +INT FDK_get32(HANDLE_FDK_BITBUF hBitBuf) { + UINT BitNdx = hBitBuf->BitNdx + 32; + hBitBuf->BitNdx = BitNdx & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits = (UINT)((INT)hBitBuf->ValidBits - (INT)32); + + UINT byteOffset = (BitNdx - 1) >> 3; + if (BitNdx <= hBitBuf->bufBits) { + UINT cache = (hBitBuf->Buffer[(byteOffset - 3)] << 24) | + (hBitBuf->Buffer[(byteOffset - 2)] << 16) | + (hBitBuf->Buffer[(byteOffset - 1)] << 8) | + hBitBuf->Buffer[(byteOffset - 0)]; + + if ((BitNdx = (BitNdx & 7)) != 0) { + cache = (cache >> (8 - BitNdx)) | + ((UINT)hBitBuf->Buffer[byteOffset - 4] << (24 + BitNdx)); + } + return (cache); + } else { + UINT byte_mask = hBitBuf->bufSize - 1; + UINT cache = (hBitBuf->Buffer[(byteOffset - 3) & byte_mask] << 24) | + (hBitBuf->Buffer[(byteOffset - 2) & byte_mask] << 16) | + (hBitBuf->Buffer[(byteOffset - 1) & byte_mask] << 8) | + hBitBuf->Buffer[(byteOffset - 0) & byte_mask]; + + if ((BitNdx = (BitNdx & 7)) != 0) { + cache = (cache >> (8 - BitNdx)) | + ((UINT)hBitBuf->Buffer[(byteOffset - 4) & byte_mask] + << (24 + BitNdx)); + } + return (cache); + } +} +#endif + +INT FDK_getBwd(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x07; + UINT byteMask = hBitBuf->bufSize - 1; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits += numberOfBits; + + UINT tx = hBitBuf->Buffer[(byteOffset - 3) & byteMask] << 24 | + hBitBuf->Buffer[(byteOffset - 2) & byteMask] << 16 | + hBitBuf->Buffer[(byteOffset - 1) & byteMask] << 8 | + hBitBuf->Buffer[byteOffset & byteMask]; + UINT txa = 0x0; + + tx >>= (8 - bitOffset); + + if (bitOffset && numberOfBits > 24) { + tx |= hBitBuf->Buffer[(byteOffset - 4) & byteMask] << (24 + bitOffset); + } + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + txa |= (tx & bitMaskR) << (31 - (i << 1)); + txa |= (tx & bitMaskL) >> (31 - (i << 1)); + } + + return (txa >> (32 - numberOfBits)); +} + +void FDK_put(HANDLE_FDK_BITBUF hBitBuf, UINT value, const UINT numberOfBits) { + if (numberOfBits != 0) { + UINT byteOffset0 = hBitBuf->BitNdx >> 3; + UINT bitOffset = hBitBuf->BitNdx & 0x7; + + hBitBuf->BitNdx = (hBitBuf->BitNdx + numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits += numberOfBits; + + UINT byteMask = hBitBuf->bufSize - 1; + + UINT byteOffset1 = (byteOffset0 + 1) & byteMask; + UINT byteOffset2 = (byteOffset0 + 2) & byteMask; + UINT byteOffset3 = (byteOffset0 + 3) & byteMask; + + // Create tmp containing free bits at the left border followed by bits to + // write, LSB's are cleared, if available Create mask to apply upon all + // buffer bytes + UINT tmp = (value << (32 - numberOfBits)) >> bitOffset; + UINT mask = ~((BitMask[numberOfBits] << (32 - numberOfBits)) >> bitOffset); + + // read all 4 bytes from buffer and create a 32-bit cache + UINT cache = (((UINT)hBitBuf->Buffer[byteOffset0]) << 24) | + (((UINT)hBitBuf->Buffer[byteOffset1]) << 16) | + (((UINT)hBitBuf->Buffer[byteOffset2]) << 8) | + (((UINT)hBitBuf->Buffer[byteOffset3]) << 0); + + cache = (cache & mask) | tmp; + hBitBuf->Buffer[byteOffset0] = (UCHAR)(cache >> 24); + hBitBuf->Buffer[byteOffset1] = (UCHAR)(cache >> 16); + hBitBuf->Buffer[byteOffset2] = (UCHAR)(cache >> 8); + hBitBuf->Buffer[byteOffset3] = (UCHAR)(cache >> 0); + + if ((bitOffset + numberOfBits) > 32) { + UINT byteOffset4 = (byteOffset0 + 4) & byteMask; + // remaining bits: in range 1..7 + // replace MSBits of next byte in buffer by LSBits of "value" + int bits = (bitOffset + numberOfBits) & 7; + cache = + (UINT)hBitBuf->Buffer[byteOffset4] & (~(BitMask[bits] << (8 - bits))); + cache |= value << (8 - bits); + hBitBuf->Buffer[byteOffset4] = (UCHAR)cache; + } + } +} + +void FDK_putBwd(HANDLE_FDK_BITBUF hBitBuf, UINT value, + const UINT numberOfBits) { + UINT byteOffset = hBitBuf->BitNdx >> 3; + UINT bitOffset = 7 - (hBitBuf->BitNdx & 0x07); + UINT byteMask = hBitBuf->bufSize - 1; + + UINT mask = ~(BitMask[numberOfBits] << bitOffset); + UINT tmp = 0x0000; + int i; + + hBitBuf->BitNdx = (hBitBuf->BitNdx - numberOfBits) & (hBitBuf->bufBits - 1); + hBitBuf->ValidBits -= numberOfBits; + + /* in place turn around */ + for (i = 0; i < 16; i++) { + UINT bitMaskR = 0x00000001 << i; + UINT bitMaskL = 0x80000000 >> i; + + tmp |= (value & bitMaskR) << (31 - (i << 1)); + tmp |= (value & bitMaskL) >> (31 - (i << 1)); + } + value = tmp; + tmp = value >> (32 - numberOfBits) << bitOffset; + + hBitBuf->Buffer[byteOffset & byteMask] = + (hBitBuf->Buffer[byteOffset & byteMask] & (mask)) | (UCHAR)(tmp); + hBitBuf->Buffer[(byteOffset - 1) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 1) & byteMask] & (mask >> 8)) | + (UCHAR)(tmp >> 8); + hBitBuf->Buffer[(byteOffset - 2) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 2) & byteMask] & (mask >> 16)) | + (UCHAR)(tmp >> 16); + hBitBuf->Buffer[(byteOffset - 3) & byteMask] = + (hBitBuf->Buffer[(byteOffset - 3) & byteMask] & (mask >> 24)) | + (UCHAR)(tmp >> 24); + + if ((bitOffset + numberOfBits) > 32) { + hBitBuf->Buffer[(byteOffset - 4) & byteMask] = + (UCHAR)(value >> (64 - numberOfBits - bitOffset)) | + (hBitBuf->Buffer[(byteOffset - 4) & byteMask] & + ~(BitMask[bitOffset] >> (32 - numberOfBits))); + } +} + +#ifndef FUNCTION_FDK_pushBack +void FDK_pushBack(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, + UCHAR config) { + hBitBuf->ValidBits = + (config == 0) ? (UINT)((INT)hBitBuf->ValidBits + (INT)numberOfBits) + : ((UINT)((INT)hBitBuf->ValidBits - (INT)numberOfBits)); + hBitBuf->BitNdx = ((UINT)((INT)hBitBuf->BitNdx - (INT)numberOfBits)) & + (hBitBuf->bufBits - 1); +} +#endif + +void FDK_pushForward(HANDLE_FDK_BITBUF hBitBuf, const UINT numberOfBits, + UCHAR config) { + hBitBuf->ValidBits = + (config == 0) ? ((UINT)((INT)hBitBuf->ValidBits - (INT)numberOfBits)) + : (UINT)((INT)hBitBuf->ValidBits + (INT)numberOfBits); + hBitBuf->BitNdx = + (UINT)((INT)hBitBuf->BitNdx + (INT)numberOfBits) & (hBitBuf->bufBits - 1); +} + +#ifndef FUNCTION_FDK_getValidBits +UINT FDK_getValidBits(HANDLE_FDK_BITBUF hBitBuf) { return hBitBuf->ValidBits; } +#endif /* #ifndef FUNCTION_FDK_getValidBits */ + +INT FDK_getFreeBits(HANDLE_FDK_BITBUF hBitBuf) { + return (hBitBuf->bufBits - hBitBuf->ValidBits); +} + +void FDK_Feed(HANDLE_FDK_BITBUF hBitBuf, const UCHAR *RESTRICT inputBuffer, + const UINT bufferSize, UINT *bytesValid) { + inputBuffer = &inputBuffer[bufferSize - *bytesValid]; + + UINT bTotal = 0; + + UINT bToRead = (hBitBuf->bufBits - hBitBuf->ValidBits) >> 3; + UINT noOfBytes = + fMin(bToRead, + *bytesValid); //(bToRead < *bytesValid) ? bToRead : *bytesValid ; + + while (noOfBytes > 0) { + /* split read to buffer size */ + bToRead = hBitBuf->bufSize - hBitBuf->ReadOffset; + bToRead = fMin(bToRead, + noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes ; + + /* copy 'bToRead' bytes from 'ptr' to inputbuffer */ + FDKmemcpy(&hBitBuf->Buffer[hBitBuf->ReadOffset], inputBuffer, + bToRead * sizeof(UCHAR)); + + /* add noOfBits to number of valid bits in buffer */ + hBitBuf->ValidBits += bToRead << 3; + bTotal += bToRead; + inputBuffer += bToRead; + + hBitBuf->ReadOffset = + (hBitBuf->ReadOffset + bToRead) & (hBitBuf->bufSize - 1); + noOfBytes -= bToRead; + } + + *bytesValid -= bTotal; +} + +void CopyAlignedBlock(HANDLE_FDK_BITBUF h_BitBufSrc, UCHAR *RESTRICT dstBuffer, + UINT bToRead) { + UINT byteOffset = h_BitBufSrc->BitNdx >> 3; + const UINT byteMask = h_BitBufSrc->bufSize - 1; + + UCHAR *RESTRICT pBBB = h_BitBufSrc->Buffer; + for (UINT i = 0; i < bToRead; i++) { + dstBuffer[i] = pBBB[(byteOffset + i) & byteMask]; + } + + bToRead <<= 3; + + h_BitBufSrc->BitNdx = + (h_BitBufSrc->BitNdx + bToRead) & (h_BitBufSrc->bufBits - 1); + h_BitBufSrc->ValidBits -= bToRead; +} + +void FDK_Copy(HANDLE_FDK_BITBUF h_BitBufDst, HANDLE_FDK_BITBUF h_BitBufSrc, + UINT *bytesValid) { + INT bTotal = 0; + + /* limit noOfBytes to valid bytes in src buffer and available bytes in dst + * buffer */ + UINT bToRead = h_BitBufSrc->ValidBits >> 3; + UINT noOfBytes = + fMin(bToRead, + *bytesValid); //(*bytesValid < bToRead) ? *bytesValid : bToRead ; + bToRead = FDK_getFreeBits(h_BitBufDst); + noOfBytes = + fMin(bToRead, noOfBytes); //(bToRead < noOfBytes) ? bToRead : noOfBytes; + + while (noOfBytes > 0) { + /* Split Read to buffer size */ + bToRead = h_BitBufDst->bufSize - h_BitBufDst->ReadOffset; + bToRead = fMin(noOfBytes, + bToRead); //(noOfBytes < bToRead) ? noOfBytes : bToRead ; + + /* copy 'bToRead' bytes from buffer to buffer */ + if (!(h_BitBufSrc->BitNdx & 0x07)) { + CopyAlignedBlock(h_BitBufSrc, + h_BitBufDst->Buffer + h_BitBufDst->ReadOffset, bToRead); + } else { + for (UINT i = 0; i < bToRead; i++) { + h_BitBufDst->Buffer[h_BitBufDst->ReadOffset + i] = + (UCHAR)FDK_get(h_BitBufSrc, 8); + } + } + + /* add noOfBits to number of valid bits in buffer */ + h_BitBufDst->ValidBits += bToRead << 3; + bTotal += bToRead; + + h_BitBufDst->ReadOffset = + (h_BitBufDst->ReadOffset + bToRead) & (h_BitBufDst->bufSize - 1); + noOfBytes -= bToRead; + } + + *bytesValid -= bTotal; +} + +void FDK_Fetch(HANDLE_FDK_BITBUF hBitBuf, UCHAR *outBuf, UINT *writeBytes) { + UCHAR *RESTRICT outputBuffer = outBuf; + UINT bTotal = 0; + + UINT bToWrite = (hBitBuf->ValidBits) >> 3; + UINT noOfBytes = + fMin(bToWrite, + *writeBytes); //(bToWrite < *writeBytes) ? bToWrite : *writeBytes ; + + while (noOfBytes > 0) { + /* split write to buffer size */ + bToWrite = hBitBuf->bufSize - hBitBuf->WriteOffset; + bToWrite = fMin( + bToWrite, noOfBytes); //(bToWrite < noOfBytes) ? bToWrite : noOfBytes ; + + /* copy 'bToWrite' bytes from bitbuffer to outputbuffer */ + FDKmemcpy(outputBuffer, &hBitBuf->Buffer[hBitBuf->WriteOffset], + bToWrite * sizeof(UCHAR)); + + /* sub noOfBits from number of valid bits in buffer */ + hBitBuf->ValidBits -= bToWrite << 3; + bTotal += bToWrite; + outputBuffer += bToWrite; + + hBitBuf->WriteOffset = + (hBitBuf->WriteOffset + bToWrite) & (hBitBuf->bufSize - 1); + noOfBytes -= bToWrite; + } + + *writeBytes = bTotal; +} diff --git a/fdk-aac/libFDK/src/FDK_core.cpp b/fdk-aac/libFDK/src/FDK_core.cpp new file mode 100644 index 0000000..75ea8a2 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_core.cpp @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: FDK tools versioning support + +*******************************************************************************/ + +#include "FDK_core.h" + +/* FDK tools library info */ +#define FDK_TOOLS_LIB_VL0 3 +#define FDK_TOOLS_LIB_VL1 0 +#define FDK_TOOLS_LIB_VL2 0 +#define FDK_TOOLS_LIB_TITLE "FDK Tools" +#ifdef __ANDROID__ +#define FDK_TOOLS_LIB_BUILD_DATE "" +#define FDK_TOOLS_LIB_BUILD_TIME "" +#else +#define FDK_TOOLS_LIB_BUILD_DATE __DATE__ +#define FDK_TOOLS_LIB_BUILD_TIME __TIME__ +#endif + +int FDK_toolsGetLibInfo(LIB_INFO *info) { + UINT v; + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + i = FDKlibInfo_lookup(info, FDK_TOOLS); + if (i < 0) return -1; + + info += i; + + v = LIB_VERSION(FDK_TOOLS_LIB_VL0, FDK_TOOLS_LIB_VL1, FDK_TOOLS_LIB_VL2); + + FDKsprintf(info->versionStr, "%d.%d.%d", ((v >> 24) & 0xff), + ((v >> 16) & 0xff), ((v >> 8) & 0xff)); + + info->module_id = FDK_TOOLS; + info->version = v; + info->build_date = FDK_TOOLS_LIB_BUILD_DATE; + info->build_time = FDK_TOOLS_LIB_BUILD_TIME; + info->title = FDK_TOOLS_LIB_TITLE; + info->flags = 1; + + return 0; +} diff --git a/fdk-aac/libFDK/src/FDK_crc.cpp b/fdk-aac/libFDK/src/FDK_crc.cpp new file mode 100644 index 0000000..ecbddb1 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_crc.cpp @@ -0,0 +1,526 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: CRC calculation + +*******************************************************************************/ + +#include "FDK_crc.h" + +/*---------------- constants -----------------------*/ + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^15 + x^2 + x^0. + */ +static const USHORT crcLookup_16_15_2_0[256] = { + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, + 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, + 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, 0x0050, 0x8055, 0x805f, + 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, + 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, + 0x00ee, 0x00e4, 0x80e1, 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, + 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, + 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, + 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, + 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, 0x0140, 0x8145, 0x814f, + 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, + 0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, + 0x813d, 0x8137, 0x0132, 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, + 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, + 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, + 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, + 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, 0x83f3, 0x03f6, 0x03fc, + 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, + 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, + 0x038e, 0x0384, 0x8381, 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, + 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, + 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, + 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, + 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, 0x0220, 0x8225, 0x822f, + 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, + 0x0208, 0x820d, 0x8207, 0x0202}; + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^12 + x^5 + x^0. + */ +static const USHORT crcLookup_16_12_5_0[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, + 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, + 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, + 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, + 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, + 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, + 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, + 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, + 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, + 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, + 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, + 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, + 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, + 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, + 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, + 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, + 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, + 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, + 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, + 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, + 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, + 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, + 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, + 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, + 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, + 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, + 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0. + */ +static const USHORT crcLookup_16_14_13_12_11_5_3_2_0[256] = +{ + 0x0000, 0x782f, 0xf05e, 0x8871, 0x9893, 0xe0bc, 0x68cd, 0x10e2, + 0x4909, 0x3126, 0xb957, 0xc178, 0xd19a, 0xa9b5, 0x21c4, 0x59eb, + 0x9212, 0xea3d, 0x624c, 0x1a63, 0x0a81, 0x72ae, 0xfadf, 0x82f0, + 0xdb1b, 0xa334, 0x2b45, 0x536a, 0x4388, 0x3ba7, 0xb3d6, 0xcbf9, + 0x5c0b, 0x2424, 0xac55, 0xd47a, 0xc498, 0xbcb7, 0x34c6, 0x4ce9, + 0x1502, 0x6d2d, 0xe55c, 0x9d73, 0x8d91, 0xf5be, 0x7dcf, 0x05e0, + 0xce19, 0xb636, 0x3e47, 0x4668, 0x568a, 0x2ea5, 0xa6d4, 0xdefb, + 0x8710, 0xff3f, 0x774e, 0x0f61, 0x1f83, 0x67ac, 0xefdd, 0x97f2, + 0xb816, 0xc039, 0x4848, 0x3067, 0x2085, 0x58aa, 0xd0db, 0xa8f4, + 0xf11f, 0x8930, 0x0141, 0x796e, 0x698c, 0x11a3, 0x99d2, 0xe1fd, + 0x2a04, 0x522b, 0xda5a, 0xa275, 0xb297, 0xcab8, 0x42c9, 0x3ae6, + 0x630d, 0x1b22, 0x9353, 0xeb7c, 0xfb9e, 0x83b1, 0x0bc0, 0x73ef, + 0xe41d, 0x9c32, 0x1443, 0x6c6c, 0x7c8e, 0x04a1, 0x8cd0, 0xf4ff, + 0xad14, 0xd53b, 0x5d4a, 0x2565, 0x3587, 0x4da8, 0xc5d9, 0xbdf6, + 0x760f, 0x0e20, 0x8651, 0xfe7e, 0xee9c, 0x96b3, 0x1ec2, 0x66ed, + 0x3f06, 0x4729, 0xcf58, 0xb777, 0xa795, 0xdfba, 0x57cb, 0x2fe4, + 0x0803, 0x702c, 0xf85d, 0x8072, 0x9090, 0xe8bf, 0x60ce, 0x18e1, + 0x410a, 0x3925, 0xb154, 0xc97b, 0xd999, 0xa1b6, 0x29c7, 0x51e8, + 0x9a11, 0xe23e, 0x6a4f, 0x1260, 0x0282, 0x7aad, 0xf2dc, 0x8af3, + 0xd318, 0xab37, 0x2346, 0x5b69, 0x4b8b, 0x33a4, 0xbbd5, 0xc3fa, + 0x5408, 0x2c27, 0xa456, 0xdc79, 0xcc9b, 0xb4b4, 0x3cc5, 0x44ea, + 0x1d01, 0x652e, 0xed5f, 0x9570, 0x8592, 0xfdbd, 0x75cc, 0x0de3, + 0xc61a, 0xbe35, 0x3644, 0x4e6b, 0x5e89, 0x26a6, 0xaed7, 0xd6f8, + 0x8f13, 0xf73c, 0x7f4d, 0x0762, 0x1780, 0x6faf, 0xe7de, 0x9ff1, + 0xb015, 0xc83a, 0x404b, 0x3864, 0x2886, 0x50a9, 0xd8d8, 0xa0f7, + 0xf91c, 0x8133, 0x0942, 0x716d, 0x618f, 0x19a0, 0x91d1, 0xe9fe, + 0x2207, 0x5a28, 0xd259, 0xaa76, 0xba94, 0xc2bb, 0x4aca, 0x32e5, + 0x6b0e, 0x1321, 0x9b50, 0xe37f, 0xf39d, 0x8bb2, 0x03c3, 0x7bec, + 0xec1e, 0x9431, 0x1c40, 0x646f, 0x748d, 0x0ca2, 0x84d3, 0xfcfc, + 0xa517, 0xdd38, 0x5549, 0x2d66, 0x3d84, 0x45ab, 0xcdda, 0xb5f5, + 0x7e0c, 0x0623, 0x8e52, 0xf67d, 0xe69f, 0x9eb0, 0x16c1, 0x6eee, + 0x3705, 0x4f2a, 0xc75b, 0xbf74, 0xaf96, 0xd7b9, 0x5fc8, 0x27e7, +}; + +/** + * \brief This table defines precalculated lookup tables for crc polynom x^16 + * + x^15 + x^5 + x^0. + */ +static const USHORT crcLookup_16_15_5_0[256] = { + 0x0000, 0x8021, 0x8063, 0x0042, 0x80e7, 0x00c6, 0x0084, 0x80a5, 0x81ef, + 0x01ce, 0x018c, 0x81ad, 0x0108, 0x8129, 0x816b, 0x014a, 0x83ff, 0x03de, + 0x039c, 0x83bd, 0x0318, 0x8339, 0x837b, 0x035a, 0x0210, 0x8231, 0x8273, + 0x0252, 0x82f7, 0x02d6, 0x0294, 0x82b5, 0x87df, 0x07fe, 0x07bc, 0x879d, + 0x0738, 0x8719, 0x875b, 0x077a, 0x0630, 0x8611, 0x8653, 0x0672, 0x86d7, + 0x06f6, 0x06b4, 0x8695, 0x0420, 0x8401, 0x8443, 0x0462, 0x84c7, 0x04e6, + 0x04a4, 0x8485, 0x85cf, 0x05ee, 0x05ac, 0x858d, 0x0528, 0x8509, 0x854b, + 0x056a, 0x8f9f, 0x0fbe, 0x0ffc, 0x8fdd, 0x0f78, 0x8f59, 0x8f1b, 0x0f3a, + 0x0e70, 0x8e51, 0x8e13, 0x0e32, 0x8e97, 0x0eb6, 0x0ef4, 0x8ed5, 0x0c60, + 0x8c41, 0x8c03, 0x0c22, 0x8c87, 0x0ca6, 0x0ce4, 0x8cc5, 0x8d8f, 0x0dae, + 0x0dec, 0x8dcd, 0x0d68, 0x8d49, 0x8d0b, 0x0d2a, 0x0840, 0x8861, 0x8823, + 0x0802, 0x88a7, 0x0886, 0x08c4, 0x88e5, 0x89af, 0x098e, 0x09cc, 0x89ed, + 0x0948, 0x8969, 0x892b, 0x090a, 0x8bbf, 0x0b9e, 0x0bdc, 0x8bfd, 0x0b58, + 0x8b79, 0x8b3b, 0x0b1a, 0x0a50, 0x8a71, 0x8a33, 0x0a12, 0x8ab7, 0x0a96, + 0x0ad4, 0x8af5, 0x9f1f, 0x1f3e, 0x1f7c, 0x9f5d, 0x1ff8, 0x9fd9, 0x9f9b, + 0x1fba, 0x1ef0, 0x9ed1, 0x9e93, 0x1eb2, 0x9e17, 0x1e36, 0x1e74, 0x9e55, + 0x1ce0, 0x9cc1, 0x9c83, 0x1ca2, 0x9c07, 0x1c26, 0x1c64, 0x9c45, 0x9d0f, + 0x1d2e, 0x1d6c, 0x9d4d, 0x1de8, 0x9dc9, 0x9d8b, 0x1daa, 0x18c0, 0x98e1, + 0x98a3, 0x1882, 0x9827, 0x1806, 0x1844, 0x9865, 0x992f, 0x190e, 0x194c, + 0x996d, 0x19c8, 0x99e9, 0x99ab, 0x198a, 0x9b3f, 0x1b1e, 0x1b5c, 0x9b7d, + 0x1bd8, 0x9bf9, 0x9bbb, 0x1b9a, 0x1ad0, 0x9af1, 0x9ab3, 0x1a92, 0x9a37, + 0x1a16, 0x1a54, 0x9a75, 0x1080, 0x90a1, 0x90e3, 0x10c2, 0x9067, 0x1046, + 0x1004, 0x9025, 0x916f, 0x114e, 0x110c, 0x912d, 0x1188, 0x91a9, 0x91eb, + 0x11ca, 0x937f, 0x135e, 0x131c, 0x933d, 0x1398, 0x93b9, 0x93fb, 0x13da, + 0x1290, 0x92b1, 0x92f3, 0x12d2, 0x9277, 0x1256, 0x1214, 0x9235, 0x975f, + 0x177e, 0x173c, 0x971d, 0x17b8, 0x9799, 0x97db, 0x17fa, 0x16b0, 0x9691, + 0x96d3, 0x16f2, 0x9657, 0x1676, 0x1634, 0x9615, 0x14a0, 0x9481, 0x94c3, + 0x14e2, 0x9447, 0x1466, 0x1424, 0x9405, 0x954f, 0x156e, 0x152c, 0x950d, + 0x15a8, 0x9589, 0x95cb, 0x15ea, +}; + +/*--------------- function declarations --------------------*/ + +static inline INT calcCrc_Bits(USHORT *const pCrc, USHORT crcMask, + USHORT crcPoly, HANDLE_FDK_BITSTREAM hBs, + INT nBits); + +static inline INT calcCrc_Bytes(USHORT *const pCrc, const USHORT *pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, INT nBytes); + +static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, + const INT reg); + +/*------------- function definitions ----------------*/ + +void FDKcrcInit(HANDLE_FDK_CRCINFO hCrcInfo, const UINT crcPoly, + const UINT crcStartValue, const UINT crcLen) { + /* crc polynom example: + DAB+ FireCode: + x^16 + x^14 + x^13 + x^12 + x^11 + x^5 + x^3 + x^2 + x^0 + (1) 0111 1000 0010 1101 -> 0x782d + + x^16 + x^15 + x^5 + x^0 (1) 1000 0000 0010 0001 -> 0x8021 + x^16 + x^15 + x^2 + x^0 (1) 1000 0000 0000 0101 -> 0x8005 + x^16 + x^12 + x^5 + x^0 (1) 0001 0000 0010 0001 -> 0x1021 + x^8 + x^4 + x^3 + x^2 + x^0 (1) 0001 1101 -> 0x001d */ + + hCrcInfo->crcLen = crcLen; + hCrcInfo->crcPoly = crcPoly; + hCrcInfo->startValue = crcStartValue; + hCrcInfo->crcMask = (crcLen) ? (1 << (crcLen - 1)) : 0; + + FDKcrcReset(hCrcInfo); + + hCrcInfo->pCrcLookup = + 0; /* Preset 0 for "crcLen" != 16 or unknown 16-bit polynoms "crcPoly" */ + + if (hCrcInfo->crcLen == 16) { + switch (crcPoly) { + case 0x8021: + hCrcInfo->pCrcLookup = crcLookup_16_15_5_0; + break; + case 0x8005: + hCrcInfo->pCrcLookup = crcLookup_16_15_2_0; + break; + case 0x1021: + hCrcInfo->pCrcLookup = crcLookup_16_12_5_0; + break; + case 0x782d: + hCrcInfo->pCrcLookup = crcLookup_16_14_13_12_11_5_3_2_0; + break; + case 0x001d: + default: + /* no lookup table */ + break; + } + } +} + +void FDKcrcReset(HANDLE_FDK_CRCINFO hCrcInfo) { + int i; + + hCrcInfo->crcValue = hCrcInfo->startValue; + + for (i = 0; i < MAX_CRC_REGS; i++) { + hCrcInfo->crcRegData[i].isActive = 0; + } + hCrcInfo->regStart = 0; + hCrcInfo->regStop = 0; +} + +INT FDKcrcStartReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT mBits) { + int reg = hCrcInfo->regStart; + + FDK_ASSERT(hCrcInfo->crcRegData[reg].isActive == 0); + hCrcInfo->crcRegData[reg].isActive = 1; + hCrcInfo->crcRegData[reg].maxBits = mBits; + hCrcInfo->crcRegData[reg].validBits = (INT)FDKgetValidBits(hBs); + hCrcInfo->crcRegData[reg].bitBufCntBits = 0; + + hCrcInfo->regStart = (hCrcInfo->regStart + 1) % MAX_CRC_REGS; + + return (reg); +} + +INT FDKcrcEndReg(HANDLE_FDK_CRCINFO hCrcInfo, const HANDLE_FDK_BITSTREAM hBs, + const INT reg) { + FDK_ASSERT((reg == (INT)hCrcInfo->regStop) && + (hCrcInfo->crcRegData[reg].isActive == 1)); + + if (hBs->ConfigCache == BS_WRITER) { + hCrcInfo->crcRegData[reg].bitBufCntBits = + (INT)FDKgetValidBits(hBs) - hCrcInfo->crcRegData[reg].validBits; + } else { + hCrcInfo->crcRegData[reg].bitBufCntBits = + hCrcInfo->crcRegData[reg].validBits - (INT)FDKgetValidBits(hBs); + } + + if (hCrcInfo->crcRegData[reg].maxBits == 0) { + hCrcInfo->crcRegData[reg].maxBits = hCrcInfo->crcRegData[reg].bitBufCntBits; + } + + crcCalc(hCrcInfo, hBs, reg); + + hCrcInfo->crcRegData[reg].isActive = 0; + hCrcInfo->regStop = (hCrcInfo->regStop + 1) % MAX_CRC_REGS; + + return 0; +} + +USHORT FDKcrcGetCRC(const HANDLE_FDK_CRCINFO hCrcInfo) { + return (hCrcInfo->crcValue & (((hCrcInfo->crcMask - 1) << 1) + 1)); +} + +/** + * \brief Calculate crc bits. + * + * Calculate crc starting at current bitstream postion over nBits. + * + * \param pCrc Pointer to an outlying allocated crc info + * structure. + * \param crcMask CrcMask in use. + * \param crcPoly Crc polynom in use. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bits. + * + * \return Number of processed bits. + */ +static inline INT calcCrc_Bits(USHORT *const pCrc, USHORT crcMask, + USHORT crcPoly, HANDLE_FDK_BITSTREAM hBs, + INT nBits) { + int i; + USHORT crc = *pCrc; /* get crc value */ + + if (hBs != NULL) { + for (i = 0; (i < nBits); i++) { + USHORT tmp = FDKreadBit(hBs); // process single bit + tmp ^= ((crc & crcMask) ? 1 : 0); + if (tmp != 0) tmp = crcPoly; + crc <<= 1; + crc ^= tmp; + } + } else { + for (i = 0; (i < nBits); i++) { + USHORT tmp = (crc & crcMask) ? crcPoly : 0; // process single bit + crc <<= 1; + crc ^= tmp; + } + } + *pCrc = crc; /* update crc value */ + + return nBits; +} + +/** + * \brief Calculate crc bytes. + * + * Calculate crc starting at current bitstream postion over nBytes. + * + * \param pCrc Pointer to an outlying allocated crc info + * structure. + * \param pCrcLookup Pointer to lookup table used for fast crc + * calculation. + * \param hBs Handle to current bit buffer structure. + * \param nBits Number of processing bytes. + * + * \return Number of processed bits. + */ + +static inline INT calcCrc_Bytes(USHORT *const pCrc, const USHORT *pCrcLookup, + HANDLE_FDK_BITSTREAM hBs, INT nBytes) { + int i; + USHORT crc = *pCrc; /* get crc value */ + + if (hBs != NULL) { + ULONG data; + INT bits; + for (i = 0; i < (nBytes >> 2); i++) { + data = (ULONG)FDKreadBits(hBs, 32); + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 24))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 16))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 8))) & 0xFF]; + crc = + (crc << 8) ^ pCrcLookup[((crc >> 8) ^ ((USHORT)(data >> 0))) & 0xFF]; + } + bits = (nBytes & 3) << 3; + if (bits > 0) { + data = (ULONG)FDKreadBits(hBs, bits); + for (bits -= 8; bits >= 0; bits -= 8) + crc = (crc << 8) ^ + pCrcLookup[((crc >> 8) ^ (USHORT)(data >> bits)) & 0xFF]; + } + } else { + for (i = 0; i < nBytes; i++) { + crc = (crc << 8) ^ pCrcLookup[(crc >> 8) & 0xFF]; + } + } + + *pCrc = crc; /* update crc value */ + //fprintf(stderr, "\n\n crc[%d]=%04x\n", i, crc); + + return (nBytes); +} + +/** + * \brief Calculate crc. + * + * Calculate crc. Lenght depends on mBits parameter in FDKcrcStartReg() + * configuration. + * + * \param hCrcInfo Pointer to an outlying allocated crc info + * structure. + * \param hBs Pointer to current bit buffer structure. + * \param reg Crc region ID. + * + * \return Number of processed bits. + */ +static void crcCalc(HANDLE_FDK_CRCINFO hCrcInfo, HANDLE_FDK_BITSTREAM hBs, + const INT reg) { + USHORT crc = hCrcInfo->crcValue; + CCrcRegData *rD = &hCrcInfo->crcRegData[reg]; + FDK_BITSTREAM bsReader; + + if (hBs->ConfigCache == BS_READER) { + bsReader = *hBs; + FDKpushBiDirectional(&bsReader, + -(rD->validBits - (INT)FDKgetValidBits(&bsReader))); + } else { + FDKinitBitStream(&bsReader, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, + hBs->hBitBuf.ValidBits, BS_READER); + FDKpushBiDirectional(&bsReader, rD->validBits); + } + + int bits, rBits; + rBits = (rD->maxBits >= 0) ? rD->maxBits : -rD->maxBits; /* ramaining bits */ + if ((rD->maxBits > 0) && ((rD->bitBufCntBits >> 3 << 3) < rBits)) { + bits = rD->bitBufCntBits; + } else { + bits = rBits; + } + + int words = bits >> 3; /* processing bytes */ + int mBits = bits & 0x7; /* modulo bits */ + + if (hCrcInfo->pCrcLookup) { + rBits -= (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, &bsReader, words) << 3); + } else { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, + words << 3); + } + + /* remaining valid bits*/ + if (mBits != 0) { + rBits -= calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, &bsReader, + mBits); + } + + if (rBits != 0) { + /* zero bytes */ + if ((hCrcInfo->pCrcLookup) && (rBits > 8)) { + rBits -= + (calcCrc_Bytes(&crc, hCrcInfo->pCrcLookup, NULL, rBits >> 3) << 3); + } + /* remaining zero bits */ + if (rBits != 0) { + calcCrc_Bits(&crc, hCrcInfo->crcMask, hCrcInfo->crcPoly, NULL, rBits); + } + } + + //fprintf(stderr, "\n\n crc=%04x\n", crc); + hCrcInfo->crcValue = crc; +} diff --git a/fdk-aac/libFDK/src/FDK_decorrelate.cpp b/fdk-aac/libFDK/src/FDK_decorrelate.cpp new file mode 100644 index 0000000..c5de79a --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_decorrelate.cpp @@ -0,0 +1,1746 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Decorrelator + +*******************************************************************************/ + +#include "FDK_decorrelate.h" + +#define PC_NUM_BANDS (8) +#define PC_NUM_HYB_BANDS (PC_NUM_BANDS - 3 + 10) + +#define DUCK_ALPHA (0.8f) +#define DUCK_GAMMA (1.5f) +#define ABS_THR (1e-9f * 32768 * 32768) +#define ABS_THR_FDK ((FIXP_DBL)1) + +#define DECORR_ZERO_PADDING 0 + +#define DECORR_FILTER_ORDER_BAND_0_MPS (20) +#define DECORR_FILTER_ORDER_BAND_1_MPS (15) +#define DECORR_FILTER_ORDER_BAND_2_MPS (6) +#define DECORR_FILTER_ORDER_BAND_3_MPS (3) + +#define DECORR_FILTER_ORDER_BAND_0_USAC (10) +#define DECORR_FILTER_ORDER_BAND_1_USAC (8) +#define DECORR_FILTER_ORDER_BAND_2_USAC (3) +#define DECORR_FILTER_ORDER_BAND_3_USAC (2) + +#define DECORR_FILTER_ORDER_BAND_0_LD (0) +#define DECORR_FILTER_ORDER_BAND_1_LD (DECORR_FILTER_ORDER_BAND_1_MPS) +#define DECORR_FILTER_ORDER_BAND_2_LD (DECORR_FILTER_ORDER_BAND_2_MPS) +#define DECORR_FILTER_ORDER_BAND_3_LD (DECORR_FILTER_ORDER_BAND_3_MPS) + +#define MAX_DECORR_SEED_MPS \ + (5) /* 4 is worst case for 7272 mode for low power */ + /* 5 is worst case for 7271 and 7272 mode for high quality */ +#define MAX_DECORR_SEED_USAC (1) +#define MAX_DECORR_SEED_LD (4) + +#define DECORR_FILTER_ORDER_PS (12) +#define NUM_DECORR_CONFIGS \ + (3) /* different configs defined by bsDecorrConfig bitstream field */ + +/* REV_bandOffset_... tables map (hybrid) bands to the corresponding reverb + bands. Within each reverb band the same processing is applied. Instead of QMF + split frequencies the corresponding hybrid band offsets are stored directly + */ +static const UCHAR REV_bandOffset_MPS_HQ[NUM_DECORR_CONFIGS][(4)] = { + {8, 21, 30, 71}, {8, 56, 71, 71}, {0, 21, 71, 71}}; +/* REV_bandOffset_USAC[] are equivalent to REV_bandOffset_MPS_HQ */ +static const UCHAR REV_bandOffset_PS_HQ[(4)] = {30, 42, 71, 71}; +static const UCHAR REV_bandOffset_PS_LP[(4)] = {14, 42, 71, 71}; +static const UCHAR REV_bandOffset_LD[NUM_DECORR_CONFIGS][(4)] = { + {0, 14, 23, 64}, {0, 49, 64, 64}, {0, 14, 64, 64}}; + +/* REV_delay_... tables define the number of delay elements within each reverb + * band */ +/* REV_filterOrder_... tables define the filter order within each reverb band */ +static const UCHAR REV_delay_MPS[(4)] = {8, 7, 2, 1}; +static const SCHAR REV_filterOrder_MPS[(4)] = { + DECORR_FILTER_ORDER_BAND_0_MPS, DECORR_FILTER_ORDER_BAND_1_MPS, + DECORR_FILTER_ORDER_BAND_2_MPS, DECORR_FILTER_ORDER_BAND_3_MPS}; +static const UCHAR REV_delay_PS_HQ[(4)] = {2, 14, 1, 0}; +static const UCHAR REV_delay_PS_LP[(4)] = {8, 14, 1, 0}; +static const SCHAR REV_filterOrder_PS[(4)] = {DECORR_FILTER_ORDER_PS, -1, -1, + -1}; +static const UCHAR REV_delay_USAC[(4)] = {11, 10, 5, 2}; +static const SCHAR REV_filterOrder_USAC[(4)] = { + DECORR_FILTER_ORDER_BAND_0_USAC, DECORR_FILTER_ORDER_BAND_1_USAC, + DECORR_FILTER_ORDER_BAND_2_USAC, DECORR_FILTER_ORDER_BAND_3_USAC}; + +/* REV_filtType_... tables define the type of processing (filtering with + different properties or pure delay) done in each reverb band. This is mapped + to specialized routines. */ +static const REVBAND_FILT_TYPE REV_filtType_MPS[(4)] = { + COMMON_REAL, COMMON_REAL, COMMON_REAL, COMMON_REAL}; + +static const REVBAND_FILT_TYPE REV_filtType_PS[(4)] = {INDEP_CPLX_PS, DELAY, + DELAY, NOT_EXIST}; + +/* initialization values of ring buffer offsets for the 3 concatenated allpass + * filters (PS type decorrelator). */ +static const UCHAR stateBufferOffsetInit[(3)] = {0, 6, 14}; + +static const REVBAND_FILT_TYPE REV_filtType_LD[(4)] = { + NOT_EXIST, COMMON_REAL, COMMON_REAL, COMMON_REAL}; + +/*** mapping of hybrid bands to processing (/parameter?) bands ***/ +/* table for PS decorr running in legacy PS decoder. */ +static const UCHAR kernels_20_to_71_PS[(71) + 1] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 14, + 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}; + +/*** mapping of processing (/parameter?) bands to hybrid bands ***/ +/* table for PS decorr running in legacy PS decoder. */ +static const UCHAR kernels_20_to_71_offset_PS[(20) + 1] = { + 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static const UCHAR kernels_28_to_71[(71) + 1] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, 23, 23, + 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, + 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; + +static const UCHAR kernels_28_to_71_offset[(28) + 1] = { + 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 21, 23, 25, 27, 30, 33, 37, 42, 48, 55, 71}; + +/* LD-MPS defined in SAOC standart (mapping qmf -> param bands)*/ +static const UCHAR kernels_23_to_64[(64) + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, + 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 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, 22, 22, 22, 22, 22, 22, 22, +}; + +static const UCHAR kernels_23_to_64_offset[(23) + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 14, 16, 18, 20, 23, 26, 30, 35, 41, 48, 64}; + +static inline int SpatialDecGetProcessingBand(int hybridBand, + const UCHAR *tab) { + return tab[hybridBand]; +} + +/* helper inline function */ +static inline int SpatialDecGetQmfBand(int paramBand, const UCHAR *tab) { + return (int)tab[paramBand]; +} + +#define DUCKER_MAX_NRG_SCALE (24) +#define DUCKER_HEADROOM_BITS (3) + +#define FILTER_SF (2) + +#ifdef ARCH_PREFER_MULT_32x32 +#define FIXP_DUCK_GAIN FIXP_DBL +#define FX_DBL2FX_DUCK_GAIN +#define FL2FXCONST_DUCK FL2FXCONST_DBL +#else +#define FIXP_DUCK_GAIN FIXP_SGL +#define FX_DBL2FX_DUCK_GAIN FX_DBL2FX_SGL +#define FL2FXCONST_DUCK FL2FXCONST_SGL +#endif +#define PS_DUCK_PEAK_DECAY_FACTOR (0.765928338364649f) +#define PS_DUCK_FILTER_COEFF (0.25f) +#define DUCK_ALPHA_FDK FL2FXCONST_DUCK(DUCK_ALPHA) +#define DUCK_ONE_MINUS_ALPHA_X4_FDK FL2FXCONST_DUCK(4.0f * (1.0f - DUCK_ALPHA)) +#define DUCK_GAMMA_FDK FL2FXCONST_DUCK(DUCK_GAMMA / 2) +#define PS_DUCK_PEAK_DECAY_FACTOR_FDK FL2FXCONST_DUCK(PS_DUCK_PEAK_DECAY_FACTOR) +#define PS_DUCK_FILTER_COEFF_FDK FL2FXCONST_DUCK(PS_DUCK_FILTER_COEFF) +RAM_ALIGN +const FIXP_STP DecorrPsCoeffsCplx[][4] = { + {STCP(0x5d6940eb, 0x5783153e), STCP(0xadcd41a8, 0x0e0373ed), + STCP(0xbad41f3e, 0x14fba045), STCP(0xc1eb6694, 0x0883227d)}, + {STCP(0x5d6940eb, 0xa87ceac2), STCP(0xadcd41a8, 0xf1fc8c13), + STCP(0xbad41f3e, 0xeb045fbb), STCP(0xc1eb6694, 0xf77cdd83)}, + {STCP(0xaec24162, 0x62e9d75b), STCP(0xb7169316, 0x28751048), + STCP(0xd224c0cc, 0x37e05050), STCP(0xc680864f, 0x18e88cba)}, + {STCP(0xaec24162, 0x9d1628a5), STCP(0xb7169316, 0xd78aefb8), + STCP(0xd224c0cc, 0xc81fafb0), STCP(0xc680864f, 0xe7177346)}, + {STCP(0x98012341, 0x4aa00ed1), STCP(0xc89ca1b2, 0xc1ab6bff), + STCP(0xf8ea394e, 0xb8106bf4), STCP(0xcf542d73, 0xd888b99b)}, + {STCP(0x43b137b3, 0x6ca2ca40), STCP(0xe0649cc4, 0xb2d69cca), + STCP(0x22130c21, 0xc0405382), STCP(0xdbbf8fba, 0xcce3c7cc)}, + {STCP(0x28fc4d71, 0x86bd3b87), STCP(0x09ccfeb9, 0xad319baf), + STCP(0x46e51f02, 0xf1e5ea55), STCP(0xf30d5e34, 0xc2b0e335)}, + {STCP(0xc798f756, 0x72e73c7d), STCP(0x3b6c3c1e, 0xc580dc72), + STCP(0x2828a6ba, 0x3c1a14fb), STCP(0x14b733bb, 0xc4dcaae1)}, + {STCP(0x46dcadd3, 0x956795c7), STCP(0x52f32fae, 0xf78048cd), + STCP(0xd7d75946, 0x3c1a14fb), STCP(0x306017cb, 0xd82c0a75)}, + {STCP(0xabe197de, 0x607a675e), STCP(0x460cef6e, 0x2d3b264e), + STCP(0xb91ae0fe, 0xf1e5ea55), STCP(0x3e03e5e0, 0xf706590e)}, + {STCP(0xb1b4f509, 0x9abcaf5f), STCP(0xfeb0b4be, 0x535fb8ba), + STCP(0x1ba96f8e, 0xbd37e6d8), STCP(0x30f6dbbb, 0x271a0743)}, + {STCP(0xce75b52a, 0x89f9be61), STCP(0xb26e4dda, 0x101054c5), + STCP(0x1a475d2e, 0x3f714b19), STCP(0xf491f154, 0x3a6baf46)}, + {STCP(0xee8fdfcb, 0x813181fa), STCP(0xe11e1a00, 0xbb9a6039), + STCP(0xc3e582f5, 0xe71ab533), STCP(0xc9eb35e2, 0x0ffd212a)}, + {STCP(0x0fd7d92f, 0x80fbf975), STCP(0x38adccbc, 0xd571bbf4), + STCP(0x38c3aefc, 0xe87cc794), STCP(0xdafe8c3d, 0xd9b16100)}, + {STCP(0x300d9e10, 0x895cc359), STCP(0x32b9843e, 0x2b52adcc), + STCP(0xe9ded9f4, 0x356ce0ed), STCP(0x0fdd5ca3, 0xd072932e)}, + {STCP(0x4d03b4f8, 0x99c2dec3), STCP(0xe2bc8d94, 0x3744e195), + STCP(0xeb40ec55, 0xcde9ed22), STCP(0x2e67e231, 0xf893470b)}, + {STCP(0x64c4deb3, 0xb112790f), STCP(0xc7b32682, 0xf099172d), + STCP(0x2ebf44cf, 0x135d014a), STCP(0x1a2bacd5, 0x23334254)}, + {STCP(0x75b5f9aa, 0xcdb81e14), STCP(0x028d9bb1, 0xc9dc45b9), + STCP(0xd497893f, 0x11faeee9), STCP(0xee40ff71, 0x24a91b85)}, + {STCP(0x7eb1cd81, 0xedc3feec), STCP(0x31491897, 0xf765f6d8), + STCP(0x1098dc89, 0xd7ee574e), STCP(0xda6b816d, 0x011f35cf)}, + {STCP(0x7f1cde01, 0x0f0b7727), STCP(0x118ce49d, 0x2a5ecda4), + STCP(0x0f36ca28, 0x24badaa3), STCP(0xef2908a4, 0xe1ee3743)}, + {STCP(0x76efee25, 0x2f4e8c3a), STCP(0xdde3be2a, 0x17f92215), + STCP(0xde9bf36c, 0xf22b4839), STCP(0x1128fc0c, 0xe5c95f5a)}, + {STCP(0x66b87d65, 0x4c5ede42), STCP(0xe43f351a, 0xe6bf22dc), + STCP(0x1e0d3e85, 0xf38d5a9a), STCP(0x1c0f44a3, 0x02c92fe3)}, + {STCP(0x4f8f36b7, 0x6445680f), STCP(0x10867ea2, 0xe3072740), + STCP(0xf4ef6cfa, 0x1ab67076), STCP(0x09562a8a, 0x1742bb8b)}, + {STCP(0x3304f6ec, 0x7564812a), STCP(0x1be4f1a8, 0x0894d75a), + STCP(0xf6517f5b, 0xe8a05d98), STCP(0xf1bb0053, 0x10a78853)}, + {STCP(0x1307b2c5, 0x7e93d532), STCP(0xfe098e27, 0x18f02a58), + STCP(0x1408d459, 0x084c6e44), STCP(0xedafe5bd, 0xfbc15b2e)}, + {STCP(0xf1c111cd, 0x7f346c97), STCP(0xeb5ca6a0, 0x02efee93), + STCP(0xef4df9b6, 0x06ea5be4), STCP(0xfc149289, 0xf0d53ce4)}, + {STCP(0xd1710001, 0x773b6beb), STCP(0xfa1aeb8c, 0xf06655ff), + STCP(0x05884983, 0xf2a4c7c5), STCP(0x094f13df, 0xf79c01bf)}, + {STCP(0xb446be0b, 0x6732cfca), STCP(0x0a743752, 0xf9220dfa), + STCP(0x04263722, 0x0a046a2c), STCP(0x08ced80b, 0x0347e9c2)}, + {STCP(0x9c3b1202, 0x503018a5), STCP(0x05fcf01a, 0x05cd8529), + STCP(0xf95263e2, 0xfd3bdb3f), STCP(0x00c68cf9, 0x0637cb7f)}, + {STCP(0x8aee2710, 0x33c187ec), STCP(0xfdd253f8, 0x038e09b9), + STCP(0x0356ce0f, 0xfe9ded9f), STCP(0xfd6c3054, 0x01c8060a)}}; + +const FIXP_DECORR DecorrNumeratorReal0_USAC + [MAX_DECORR_SEED_USAC][DECORR_FILTER_ORDER_BAND_0_USAC + 1] = { + {DECORR(0x05bf4880), DECORR(0x08321c00), DECORR(0xe9315ee0), + DECORR(0x07d9dd20), DECORR(0x02224994), DECORR(0x0009d200), + DECORR(0xf8a29358), DECORR(0xf4e310d0), DECORR(0xef901fc0), + DECORR(0xebda0460), DECORR(0x40000000)}}; + +const FIXP_DECORR DecorrNumeratorReal1_USAC + [MAX_DECORR_SEED_USAC][DECORR_FILTER_ORDER_BAND_1_USAC + 1] = { + {DECORR(0xf82f8378), DECORR(0xfef588c2), DECORR(0x02eddbd8), + DECORR(0x041c2450), DECORR(0xf7edcd60), DECORR(0x07e29310), + DECORR(0xfa4ece48), DECORR(0xed9f8a20), DECORR(0x40000000)}}; + +/* identical to MPS coeffs for reverb band 3: DecorrNumeratorReal3[0] */ +const FIXP_DECORR + DecorrNumeratorReal2_USAC[MAX_DECORR_SEED_USAC] + [DECORR_FILTER_ORDER_BAND_2_USAC + 1] = { + {DECORR(0x0248e8a8), DECORR(0xfde95838), + DECORR(0x084823c0), DECORR(0x40000000)}}; + +const FIXP_DECORR + DecorrNumeratorReal3_USAC[MAX_DECORR_SEED_USAC] + [DECORR_FILTER_ORDER_BAND_3_USAC + 1] = { + {DECORR(0xff2b020c), DECORR(0x02393830), + DECORR(0x40000000)}}; + +/* const FIXP_DECORR DecorrNumeratorReal0_LD[MAX_DECORR_SEED_LD][] does not + * exist */ + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal1_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_1_LD + 1] = { + { + DECORR(0xf310cb29), + DECORR(0x1932d745), + DECORR(0x0cc2d917), + DECORR(0xddde064e), + DECORR(0xf234a626), + DECORR(0x198551a6), + DECORR(0x17141b6a), + DECORR(0xf298803d), + DECORR(0xef98be92), + DECORR(0x09ea1706), + DECORR(0x28fbdff4), + DECORR(0x1a869eb9), + DECORR(0xdeefe147), + DECORR(0xcde2adda), + DECORR(0x13ddc619), + DECORR(0x40000000), + }, + { + DECORR(0x041d7dbf), + DECORR(0x01b7309c), + DECORR(0xfb599834), + DECORR(0x092fc5ed), + DECORR(0xf2fd7c25), + DECORR(0xdd51e2eb), + DECORR(0xf62fe72b), + DECORR(0x0b15d588), + DECORR(0xf1f091a7), + DECORR(0xed1bbbfe), + DECORR(0x03526899), + DECORR(0x180cb256), + DECORR(0xecf1433d), + DECORR(0xf626ab95), + DECORR(0x197dd27e), + DECORR(0x40000000), + }, + { + DECORR(0x157a786c), + DECORR(0x0028c98c), + DECORR(0xf5eff57b), + DECORR(0x11f7d04f), + DECORR(0xf390d28d), + DECORR(0x18947081), + DECORR(0xe5dc2319), + DECORR(0xf4cc0235), + DECORR(0x2394d47f), + DECORR(0xe069230e), + DECORR(0x03a1a773), + DECORR(0xfbc9b092), + DECORR(0x15a0173b), + DECORR(0x0e9ecdf0), + DECORR(0xd309b2c7), + DECORR(0x40000000), + }, + { + DECORR(0xe0ce703b), + DECORR(0xe508b672), + DECORR(0xef362398), + DECORR(0xffe788ef), + DECORR(0x2fda3749), + DECORR(0x4671c0c6), + DECORR(0x3c003494), + DECORR(0x2387707c), + DECORR(0xd2107d2e), + DECORR(0xb3e47e08), + DECORR(0xacd0abca), + DECORR(0xc70791df), + DECORR(0x0b586e85), + DECORR(0x2f11cda7), + DECORR(0x3a4a210b), + DECORR(0x40000000), + }, +}; + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal2_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_2_LD + 1 + + DECORR_ZERO_PADDING] = { + { + DECORR(0xffb4a234), + DECORR(0x01ac71a2), + DECORR(0xf2bca010), + DECORR(0xfe3d7593), + DECORR(0x093e9976), + DECORR(0xf2c5f3f5), + DECORR(0x40000000), + }, + { + DECORR(0xe303afb8), + DECORR(0xcd70c2bb), + DECORR(0xf1e2ad7e), + DECORR(0x0c8ffbe2), + DECORR(0x21f80abf), + DECORR(0x3d08410c), + DECORR(0x40000000), + }, + { + DECORR(0xe26809d5), + DECORR(0x0efbcfa4), + DECORR(0x210c1a97), + DECORR(0xfe60af4e), + DECORR(0xeda01a51), + DECORR(0x00faf468), + DECORR(0x40000000), + }, + { + DECORR(0x1edc5d64), + DECORR(0xe5b2e35c), + DECORR(0xe94b1c45), + DECORR(0x30a6f1e1), + DECORR(0xf04e52de), + DECORR(0xe30de45a), + DECORR(0x40000000), + }, +}; + +RAM_ALIGN +const FIXP_DECORR DecorrNumeratorReal3_LD[MAX_DECORR_SEED_LD] + [DECORR_FILTER_ORDER_BAND_3_LD + 1] = { + { + DECORR(0x0248e8a7), + DECORR(0xfde9583b), + DECORR(0x084823bb), + DECORR(0x40000000), + }, + { + DECORR(0x1db22d0e), + DECORR(0xfc773992), + DECORR(0x0e819a74), + DECORR(0x40000000), + }, + { + DECORR(0x0fcb923a), + DECORR(0x0154b7ff), + DECORR(0xe70cb647), + DECORR(0x40000000), + }, + { + DECORR(0xe39f559b), + DECORR(0xe06dd6ca), + DECORR(0x19f71f71), + DECORR(0x40000000), + }, +}; + +FIXP_DBL *getAddrDirectSignalMaxVal(HANDLE_DECORR_DEC self) { + return &(self->ducker.maxValDirectData); +} + +static INT DecorrFilterInit(DECORR_FILTER_INSTANCE *const self, + FIXP_MPS *pStateBufferCplx, + FIXP_DBL *pDelayBufferCplx, INT *offsetStateBuffer, + INT *offsetDelayBuffer, INT const decorr_seed, + INT const reverb_band, INT const useFractDelay, + INT const noSampleDelay, INT const filterOrder, + FDK_DECORR_TYPE const decorrType) { + INT errorCode = 0; + switch (decorrType) { + case DECORR_USAC: + if (useFractDelay) { + return 1; + } else { + FDK_ASSERT(decorr_seed == 0); + + switch (reverb_band) { + case 0: + self->numeratorReal = DecorrNumeratorReal0_USAC[decorr_seed]; + break; + case 1: + self->numeratorReal = DecorrNumeratorReal1_USAC[decorr_seed]; + break; + case 2: + self->numeratorReal = DecorrNumeratorReal2_USAC[decorr_seed]; + break; + case 3: + self->numeratorReal = DecorrNumeratorReal3_USAC[decorr_seed]; + break; + } + } + break; + case DECORR_LD: + FDK_ASSERT(decorr_seed < MAX_DECORR_SEED_LD); + switch (reverb_band) { + case 0: + self->numeratorReal = NULL; + break; + case 1: + self->numeratorReal = DecorrNumeratorReal1_LD[decorr_seed]; + break; + case 2: + self->numeratorReal = DecorrNumeratorReal2_LD[decorr_seed]; + break; + case 3: + self->numeratorReal = DecorrNumeratorReal3_LD[decorr_seed]; + break; + } + break; + default: + return 1; + } + + self->stateCplx = pStateBufferCplx + (*offsetStateBuffer); + *offsetStateBuffer += 2 * filterOrder; + self->DelayBufferCplx = pDelayBufferCplx + (*offsetDelayBuffer); + *offsetDelayBuffer += 2 * noSampleDelay; + + return errorCode; +} + +/******************************************************************************* +*******************************************************************************/ +static INT DecorrFilterInitPS(DECORR_FILTER_INSTANCE *const self, + FIXP_MPS *pStateBufferCplx, + FIXP_DBL *pDelayBufferCplx, + INT *offsetStateBuffer, INT *offsetDelayBuffer, + INT const hybridBand, INT const reverbBand, + INT const noSampleDelay) { + INT errorCode = 0; + + if (reverbBand == 0) { + self->coeffsPacked = DecorrPsCoeffsCplx[hybridBand]; + + self->stateCplx = pStateBufferCplx + (*offsetStateBuffer); + *offsetStateBuffer += 2 * DECORR_FILTER_ORDER_PS; + } + + self->DelayBufferCplx = pDelayBufferCplx + (*offsetDelayBuffer); + *offsetDelayBuffer += 2 * noSampleDelay; + + return errorCode; +} + +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyPASS(DECORR_FILTER_INSTANCE const filter[], + FIXP_DBL *dataRealIn, FIXP_DBL *dataImagIn, + FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, + INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex) { + INT i; + INT offset = 2 * reverbBandNoSampleDelay; + FIXP_MPS *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; + + /* Memory for the delayline has been allocated in a consecutive order, so we + can address from filter to filter with a constant length. + Be aware that real and imaginary part of the delayline are stored in + interleaved order. + */ + if (dataImagIn == NULL) { + for (i = start; i < stop; i++) { + FIXP_DBL tmp; + + tmp = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + dataRealOut[i] = tmp; + pDelayBuffer += offset; + } + } else { + if ((i = stop - start) != 0) { + dataRealIn += start; + dataImagIn += start; + dataRealOut += start; + dataImagOut += start; +#ifdef FUNCTION_DecorrFilterApplyPASS_func1 + DecorrFilterApplyPASS_func1(i, dataRealIn, dataImagIn, dataRealOut, + dataImagOut, pDelayBuffer, offset); +#else + do { + FIXP_DBL delay_re, delay_im, real, imag; + + real = *dataRealIn++; + imag = *dataImagIn++; + delay_re = pDelayBuffer[0]; + delay_im = pDelayBuffer[1]; + pDelayBuffer[0] = real; + pDelayBuffer[1] = imag; + *dataRealOut++ = delay_re; + *dataImagOut++ = delay_im; + pDelayBuffer += offset; + } while (--i != 0); +#endif + } + } + + return (INT)0; +} + +#ifndef FUNCTION_DecorrFilterApplyREAL +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyREAL(DECORR_FILTER_INSTANCE const filter[], + FIXP_DBL *dataRealIn, FIXP_DBL *dataImagIn, + FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, INT reverbFilterOrder, + INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex) { + INT i, j; + FIXP_DBL xReal, xImag, yReal, yImag; + + const FIXP_DECORR *pFilter = filter[start].numeratorReal; + + INT offsetDelayBuffer = (2 * reverbBandNoSampleDelay) - 1; + FIXP_MPS *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; + + INT offsetStates = 2 * reverbFilterOrder; + FIXP_DBL *pStates = filter[start].stateCplx; + + /* Memory for the delayline has been allocated in a consecutive order, so we + can address from filter to filter with a constant length. The same is valid + for the states. + Be aware that real and imaginary part of the delayline and the states are + stored in interleaved order. + All filter in a reverb band have the same filter coefficients. + Exploit symmetry: numeratorReal[i] = + denominatorReal[reverbFilterLength-1-i] Do not accumulate the highest + states which are always zero. + */ + if (reverbFilterOrder == 2) { + FIXP_DECORR nFilt0L, nFilt0H; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt0H); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt0H); + pStates[2] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[3] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else if (reverbFilterOrder == 3) { + FIXP_DECORR nFilt0L, nFilt0H, nFilt1L; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + nFilt1L = pFilter[2]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt1L); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt1L); + pStates[2] = + pStates[4] + fMultDiv2(xReal, nFilt1L) - fMultDiv2(yReal, nFilt0H); + pStates[3] = + pStates[5] + fMultDiv2(xImag, nFilt1L) - fMultDiv2(yImag, nFilt0H); + pStates[4] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[5] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else if (reverbFilterOrder == 6) { + FIXP_DECORR nFilt0L, nFilt0H, nFilt1L, nFilt1H, nFilt2L, nFilt2H; + + nFilt0L = pFilter[0]; + nFilt0H = pFilter[1]; + nFilt1L = pFilter[2]; + nFilt1H = pFilter[3]; + nFilt2L = pFilter[4]; + nFilt2H = pFilter[5]; + + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << FILTER_SF; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << FILTER_SF; + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + pStates[0] = + pStates[2] + fMultDiv2(xReal, nFilt0H) - fMultDiv2(yReal, nFilt2H); + pStates[1] = + pStates[3] + fMultDiv2(xImag, nFilt0H) - fMultDiv2(yImag, nFilt2H); + pStates[2] = + pStates[4] + fMultDiv2(xReal, nFilt1L) - fMultDiv2(yReal, nFilt2L); + pStates[3] = + pStates[5] + fMultDiv2(xImag, nFilt1L) - fMultDiv2(yImag, nFilt2L); + pStates[4] = + pStates[6] + fMultDiv2(xReal, nFilt1H) - fMultDiv2(yReal, nFilt1H); + pStates[5] = + pStates[7] + fMultDiv2(xImag, nFilt1H) - fMultDiv2(yImag, nFilt1H); + pStates[6] = + pStates[8] + fMultDiv2(xReal, nFilt2L) - fMultDiv2(yReal, nFilt1L); + pStates[7] = + pStates[9] + fMultDiv2(xImag, nFilt2L) - fMultDiv2(yImag, nFilt1L); + pStates[8] = + pStates[10] + fMultDiv2(xReal, nFilt2H) - fMultDiv2(yReal, nFilt0H); + pStates[9] = + pStates[11] + fMultDiv2(xImag, nFilt2H) - fMultDiv2(yImag, nFilt0H); + pStates[10] = (xReal >> FILTER_SF) - fMultDiv2(yReal, nFilt0L); + pStates[11] = (xImag >> FILTER_SF) - fMultDiv2(yImag, nFilt0L); + pStates += offsetStates; + } + } else { + FIXP_DECORR nFilt0L, nFilt0H; + for (i = start; i < stop; i++) { + xReal = *pDelayBuffer; + *pDelayBuffer = dataRealIn[i]; + pDelayBuffer++; + + xImag = *pDelayBuffer; + *pDelayBuffer = dataImagIn[i]; + pDelayBuffer += offsetDelayBuffer; + + nFilt0L = pFilter[0]; + yReal = (pStates[0] + fMultDiv2(xReal, nFilt0L)) << 2; + yImag = (pStates[1] + fMultDiv2(xImag, nFilt0L)) << 2; + dataRealOut[i] = yReal; + dataImagOut[i] = yImag; + + for (j = 1; j < reverbFilterOrder; j++) { + nFilt0L = pFilter[j]; + nFilt0H = pFilter[reverbFilterOrder - j]; + pStates[2 * j - 2] = pStates[2 * j] + fMultDiv2(xReal, nFilt0L) - + fMultDiv2(yReal, nFilt0H); + pStates[2 * j - 1] = pStates[2 * j + 1] + fMultDiv2(xImag, nFilt0L) - + fMultDiv2(yImag, nFilt0H); + } + nFilt0L = pFilter[j]; + nFilt0H = pFilter[reverbFilterOrder - j]; + pStates[2 * j - 2] = + fMultDiv2(xReal, nFilt0L) - fMultDiv2(yReal, nFilt0H); + pStates[2 * j - 1] = + fMultDiv2(xImag, nFilt0L) - fMultDiv2(yImag, nFilt0H); + + pStates += offsetStates; + } + } + + return (INT)0; +} +#endif /* #ifndef FUNCTION_DecorrFilterApplyREAL */ + +#ifndef FUNCTION_DecorrFilterApplyCPLX_PS +LNK_SECTION_CODE_L1 +static INT DecorrFilterApplyCPLX_PS( + DECORR_FILTER_INSTANCE const filter[], FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, FIXP_DBL *dataImagOut, + INT start, INT stop, INT reverbFilterOrder, INT reverbBandNoSampleDelay, + INT reverbBandDelayBufferIndex, UCHAR *stateBufferOffset) { + /* r = real, j = imaginary */ + FIXP_DBL r_data_a, j_data_a, r_data_b, j_data_b, r_stage_mult, j_stage_mult; + FIXP_STP rj_coeff; + + /* get pointer to current position in input delay buffer of filter with + * starting-index */ + FIXP_DBL *pDelayBuffer = + &filter[start].DelayBufferCplx[reverbBandDelayBufferIndex]; /* increases + by 2 every + other call + of this + function */ + /* determine the increment for this pointer to get to the correct position in + * the delay buffer of the next filter */ + INT offsetDelayBuffer = (2 * reverbBandNoSampleDelay) - 1; + + /* pointer to current position in state buffer */ + FIXP_DBL *pStates = filter[start].stateCplx; + INT pStatesIncrement = 2 * reverbFilterOrder; + + /* stateBufferOffset-pointers */ + FIXP_DBL *pStateBufferOffset0 = pStates + stateBufferOffset[0]; + FIXP_DBL *pStateBufferOffset1 = pStates + stateBufferOffset[1]; + FIXP_DBL *pStateBufferOffset2 = pStates + stateBufferOffset[2]; + + /* traverse all hybrid-bands inbetween start- and stop-index */ + for (int i = start; i < stop; i++) { + /* 1. input delay (real/imaginary values interleaved) */ + + /* load delayed real input value */ + r_data_a = *pDelayBuffer; + /* store incoming real data value to delay buffer and increment pointer */ + *pDelayBuffer++ = dataRealIn[i]; + + /* load delayed imaginary input value */ + j_data_a = *pDelayBuffer; + /* store incoming imaginary data value to delay buffer */ + *pDelayBuffer = dataImagIn[i]; + /* increase delay buffer by offset */ + pDelayBuffer += offsetDelayBuffer; + + /* 2. Phi(k)-stage */ + + /* create pointer to coefficient table (real and imaginary coefficients + * interleaved) */ + const FIXP_STP *pCoeffs = filter[i].coeffsPacked; + + /* the first two entries of the coefficient table are the + * Phi(k)-multiplicants */ + rj_coeff = *pCoeffs++; + /* multiply value from input delay buffer by looked-up values */ + cplxMultDiv2(&r_data_b, &j_data_b, r_data_a, j_data_a, rj_coeff); + + /* 3. process all three filter stages */ + + /* stage 0 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_b, j_data_b, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_a = r_stage_mult + pStateBufferOffset0[0]; + j_data_a = j_stage_mult + pStateBufferOffset0[1]; + + /* negate r_data_a to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_a, j_data_a, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_b + (r_stage_mult << 1); + j_stage_mult = j_data_b - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset0[0] = r_stage_mult; + pStateBufferOffset0[1] = j_stage_mult; + pStateBufferOffset0 += pStatesIncrement; + + /* stage 1 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_a, j_data_a, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_b = r_stage_mult + pStateBufferOffset1[0]; + j_data_b = j_stage_mult + pStateBufferOffset1[1]; + + /* negate r_data_b to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_b, j_data_b, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_a + (r_stage_mult << 1); + j_stage_mult = j_data_a - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset1[0] = r_stage_mult; + pStateBufferOffset1[1] = j_stage_mult; + pStateBufferOffset1 += pStatesIncrement; + + /* stage 2 */ + + /* get coefficients from lookup table */ + rj_coeff = *pCoeffs++; + + /* multiply output of last stage by coefficient */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, r_data_b, j_data_b, rj_coeff); + r_stage_mult <<= 1; + j_stage_mult <<= 1; + + /* read and add value from state buffer (this is the input for the next + * stage) */ + r_data_a = r_stage_mult + pStateBufferOffset2[0]; + j_data_a = j_stage_mult + pStateBufferOffset2[1]; + + /* negate r_data_a to perform multiplication with complex conjugate of + * rj_coeff */ + cplxMultDiv2(&r_stage_mult, &j_stage_mult, -r_data_a, j_data_a, rj_coeff); + + /* add stage input to shifted result */ + r_stage_mult = r_data_b + (r_stage_mult << 1); + j_stage_mult = j_data_b - (j_stage_mult << 1); + + /* store result to state buffer */ + pStateBufferOffset2[0] = r_stage_mult; + pStateBufferOffset2[1] = j_stage_mult; + pStateBufferOffset2 += pStatesIncrement; + + /* write filter output */ + dataRealOut[i] = r_data_a << 1; + dataImagOut[i] = j_data_a << 1; + + } /* end of band/filter loop (outer loop) */ + + /* update stateBufferOffset with respect to ring buffer boundaries */ + if (stateBufferOffset[0] == 4) + stateBufferOffset[0] = 0; + else + stateBufferOffset[0] += 2; + + if (stateBufferOffset[1] == 12) + stateBufferOffset[1] = 6; + else + stateBufferOffset[1] += 2; + + if (stateBufferOffset[2] == 22) + stateBufferOffset[2] = 14; + else + stateBufferOffset[2] += 2; + + return (INT)0; +} + +#endif /* FUNCTION_DecorrFilterApplyCPLX_PS */ + +/******************************************************************************* +*******************************************************************************/ +static INT DuckerInit(DUCKER_INSTANCE *const self, int const hybridBands, + int partiallyComplex, const FDK_DUCKER_TYPE duckerType, + const int nParamBands, int initStatesFlag) { + INT errorCode = 0; + + if (self) { + switch (nParamBands) { + case (20): + FDK_ASSERT(hybridBands == 71); + self->mapHybBands2ProcBands = kernels_20_to_71_PS; + self->mapProcBands2HybBands = kernels_20_to_71_offset_PS; + self->parameterBands = (20); + break; + case (28): + + self->mapHybBands2ProcBands = kernels_28_to_71; + self->mapProcBands2HybBands = kernels_28_to_71_offset; + self->parameterBands = (28); + break; + case (23): + FDK_ASSERT(hybridBands == 64 || hybridBands == 32); + self->mapHybBands2ProcBands = kernels_23_to_64; + self->mapProcBands2HybBands = kernels_23_to_64_offset; + self->parameterBands = (23); + break; + default: + return 1; + } + self->qs_next = &self->mapProcBands2HybBands[1]; + + self->maxValDirectData = FL2FXCONST_DBL(-1.0f); + self->maxValReverbData = FL2FXCONST_DBL(-1.0f); + self->scaleDirectNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->scaleReverbNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->scaleSmoothDirRevNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->headroomSmoothDirRevNrg = 2 * DUCKER_MAX_NRG_SCALE; + self->hybridBands = hybridBands; + self->partiallyComplex = partiallyComplex; + + if (initStatesFlag && (duckerType == DUCKER_PS)) { + int pb; + for (pb = 0; pb < self->parameterBands; pb++) { + self->SmoothDirRevNrg[pb] = (FIXP_MPS)0; + } + } + } else + errorCode = 1; + + return errorCode; +} + + /******************************************************************************* + *******************************************************************************/ + +#ifndef FUNCTION_DuckerCalcEnergy +static INT DuckerCalcEnergy(DUCKER_INSTANCE *const self, + FIXP_DBL const inputReal[(71)], + FIXP_DBL const inputImag[(71)], + FIXP_DBL energy[(28)], FIXP_DBL inputMaxVal, + SCHAR *nrgScale, int mode, /* 1:(ps) 0:(else) */ + int startHybBand) { + INT err = 0; + int qs, maxHybBand; + int maxHybridBand = self->hybridBands - 1; + + maxHybBand = maxHybridBand; + + FDKmemclear(energy, (28) * sizeof(FIXP_DBL)); + + if (mode == 1) { + int pb; + int clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(-1.0f); + + if (maxVal == FL2FXCONST_DBL(-1.0f)) { +#ifdef FUNCTION_DuckerCalcEnergy_func2 + maxVal = DuckerCalcEnergy_func2(inputReal, inputImag, startHybBand, + maxHybBand, maxHybridBand); +#else + FIXP_DBL localMaxVal = FL2FXCONST_DBL(0.0f); + for (qs = startHybBand; qs <= maxHybBand; qs++) { + localMaxVal |= fAbs(inputReal[qs]); + localMaxVal |= fAbs(inputImag[qs]); + } + for (; qs <= maxHybridBand; qs++) { + localMaxVal |= fAbs(inputReal[qs]); + } + maxVal = localMaxVal; +#endif + } + + clz = fixMax(0, CntLeadingZeros(maxVal) - DUCKER_HEADROOM_BITS); + clz = fixMin(clz, DUCKER_MAX_NRG_SCALE); + *nrgScale = (SCHAR)clz << 1; + + /* Initialize pb since it would stay uninitialized for the case startHybBand + * > maxHybBand. */ + pb = SpatialDecGetProcessingBand(maxHybBand, self->mapHybBands2ProcBands); + for (qs = startHybBand; qs <= maxHybBand; qs++) { + pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = + fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) + + fPow2Div2(inputImag[qs] << clz)); + } + pb++; + + for (; pb <= SpatialDecGetProcessingBand(maxHybridBand, + self->mapHybBands2ProcBands); + pb++) { + FDK_ASSERT(pb != SpatialDecGetProcessingBand( + qs - 1, self->mapHybBands2ProcBands)); + int qs_next; + FIXP_DBL nrg = 0; + qs_next = (int)self->qs_next[pb]; + for (; qs < qs_next; qs++) { + nrg = fAddSaturate(nrg, fPow2Div2(inputReal[qs] << clz)); + } + energy[pb] = nrg; + } + } else { + int clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(-1.0f); + + maxVal = inputMaxVal; + + if (maxVal == FL2FXCONST_DBL(-1.0f)) { +#ifdef FUNCTION_DuckerCalcEnergy_func2 + maxVal = DuckerCalcEnergy_func2(inputReal, inputImag, startHybBand, + maxHybBand, maxHybridBand); +#else + FIXP_DBL localMaxVal = FL2FXCONST_DBL(0.0f); + for (qs = startHybBand; qs <= maxHybBand; qs++) { + localMaxVal |= fAbs(inputReal[qs]); + localMaxVal |= fAbs(inputImag[qs]); + } + for (; qs <= maxHybridBand; qs++) { + localMaxVal |= fAbs(inputReal[qs]); + } + maxVal = localMaxVal; +#endif + } + + clz = fixMax(0, CntLeadingZeros(maxVal) - DUCKER_HEADROOM_BITS); + clz = fixMin(clz, DUCKER_MAX_NRG_SCALE); + *nrgScale = (SCHAR)clz << 1; + +#ifdef FUNCTION_DuckerCalcEnergy_func4 + DuckerCalcEnergy_func4(inputReal, inputImag, energy, + self->mapHybBands2ProcBands, clz, startHybBand, + maxHybBand, maxHybridBand); +#else + for (qs = startHybBand; qs <= maxHybBand; qs++) { + int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = + fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz) + + fPow2Div2(inputImag[qs] << clz)); + } + + for (; qs <= maxHybridBand; qs++) { + int pb = SpatialDecGetProcessingBand(qs, self->mapHybBands2ProcBands); + energy[pb] = fAddSaturate(energy[pb], fPow2Div2(inputReal[qs] << clz)); + } +#endif /* FUNCTION_DuckerCalcEnergy_func4 */ + } + + { + /* Catch overflows which have been observed in erred bitstreams to avoid + * assertion failures later. */ + int pb; + for (pb = 0; pb < (28); pb++) { + energy[pb] = (FIXP_DBL)((LONG)energy[pb] & (LONG)MAXVAL_DBL); + } + } + return err; +} +#endif /* #ifndef FUNCTION_DuckerCalcEnergy */ + +LNK_SECTION_CODE_L1 +static INT DuckerApply(DUCKER_INSTANCE *const self, + FIXP_DBL const directNrg[(28)], + FIXP_DBL outputReal[(71)], FIXP_DBL outputImag[(71)], + int startHybBand) { + INT err = 0; + int qs = startHybBand; + int qs_next = 0; + int pb = 0; + int startParamBand = 0; + int hybBands; + int hybridBands = self->hybridBands; + + C_ALLOC_SCRATCH_START(reverbNrg, FIXP_DBL, (28)); + + FIXP_DBL *smoothDirRevNrg = &self->SmoothDirRevNrg[0]; + FIXP_DUCK_GAIN duckGain = 0; + + int doScaleNrg = 0; + int scaleDirectNrg = 0; + int scaleReverbNrg = 0; + int scaleSmoothDirRevNrg = 0; + FIXP_DBL maxDirRevNrg = FL2FXCONST_DBL(0.0); + + hybBands = hybridBands; + + startParamBand = + SpatialDecGetProcessingBand(startHybBand, self->mapHybBands2ProcBands); + + DuckerCalcEnergy(self, outputReal, outputImag, reverbNrg, + self->maxValReverbData, &(self->scaleReverbNrg), 0, + startHybBand); + + if ((self->scaleDirectNrg != self->scaleReverbNrg) || + (self->scaleDirectNrg != self->scaleSmoothDirRevNrg) || + (self->headroomSmoothDirRevNrg == 0)) { + int scale; + + scale = fixMin(self->scaleDirectNrg, self->scaleSmoothDirRevNrg + + self->headroomSmoothDirRevNrg - 1); + scale = fixMin(scale, self->scaleReverbNrg); + + scaleDirectNrg = fMax(fMin(self->scaleDirectNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleReverbNrg = fMax(fMin(self->scaleReverbNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleSmoothDirRevNrg = + fMax(fMin(self->scaleSmoothDirRevNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + + self->scaleSmoothDirRevNrg = (SCHAR)scale; + + doScaleNrg = 1; + } + for (pb = startParamBand; pb < self->parameterBands; pb++) { + FIXP_DBL tmp1; + FIXP_DBL tmp2; + INT s; + + /* smoothDirRevNrg[2*pb ] = fMult(smoothDirRevNrg[2*pb ],DUCK_ALPHA_FDK) + + fMultDiv2(directNrg[pb],DUCK_ONE_MINUS_ALPHA_X4_FDK); + smoothDirRevNrg[2*pb+1] = fMult(smoothDirRevNrg[2*pb+1],DUCK_ALPHA_FDK) + + fMultDiv2(reverbNrg[pb],DUCK_ONE_MINUS_ALPHA_X4_FDK); tmp1 = + fMult(smoothDirRevNrg[2*pb],DUCK_GAMMA_FDK); tmp2 = + smoothDirRevNrg[2*pb+1] >> 1; + */ + tmp1 = smoothDirRevNrg[2 * pb + 0]; + tmp2 = smoothDirRevNrg[2 * pb + 1]; + tmp1 = fMult(tmp1, DUCK_ALPHA_FDK); + tmp2 = fMult(tmp2, DUCK_ALPHA_FDK); + + if (doScaleNrg) { + int scaleSmoothDirRevNrg_asExponent = -scaleSmoothDirRevNrg; + + tmp1 = scaleValue(tmp1, scaleSmoothDirRevNrg_asExponent); + tmp2 = scaleValue(tmp2, scaleSmoothDirRevNrg_asExponent); + tmp1 = fMultAddDiv2(tmp1, scaleValue(directNrg[pb], -scaleDirectNrg), + DUCK_ONE_MINUS_ALPHA_X4_FDK); + tmp2 = fMultAddDiv2(tmp2, scaleValue(reverbNrg[pb], -scaleReverbNrg), + DUCK_ONE_MINUS_ALPHA_X4_FDK); + } else { + tmp1 = fMultAddDiv2(tmp1, directNrg[pb], DUCK_ONE_MINUS_ALPHA_X4_FDK); + tmp2 = fMultAddDiv2(tmp2, reverbNrg[pb], DUCK_ONE_MINUS_ALPHA_X4_FDK); + } + + smoothDirRevNrg[2 * pb] = tmp1; + smoothDirRevNrg[2 * pb + 1] = tmp2; + + maxDirRevNrg |= fAbs(tmp1); + maxDirRevNrg |= fAbs(tmp2); + + tmp1 = fMult(tmp1, DUCK_GAMMA_FDK); + tmp2 = tmp2 >> 1; + + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + if (tmp2 > tmp1) { /* true for about 20% */ + /* gain smaller than 1.0 */ + tmp1 = sqrtFixp(tmp1); + tmp2 = invSqrtNorm2(tmp2, &s); + duckGain = FX_DBL2FX_DUCK_GAIN(fMultDiv2(tmp1, tmp2) << s); + } else { /* true for about 80 % */ + tmp2 = smoothDirRevNrg[2 * pb] >> 1; + tmp1 = fMult(smoothDirRevNrg[2 * pb + 1], DUCK_GAMMA_FDK); + if (tmp2 > tmp1) { /* true for about 20% */ + if (tmp1 <= (tmp2 >> 2)) { + /* limit gain to 2.0 */ + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + outputReal[qs] = outputReal[qs] << 1; + outputImag[qs] = outputImag[qs] << 1; + } + } else { + for (; qs < qs_next; qs++) { + outputReal[qs] = outputReal[qs] << 1; + } + } + /* skip general gain*output section */ + continue; + } else { + /* gain from 1.0 to 2.0 */ + tmp2 = sqrtFixp(tmp2 >> 2); + tmp1 = invSqrtNorm2(tmp1, &s); + duckGain = FX_DBL2FX_DUCK_GAIN(fMult(tmp1, tmp2) << s); + } + } else { /* true for about 60% */ + /* gain = 1.0; output does not change; update qs index */ + qs = qs_next; + continue; + } + } + +#ifdef FUNCTION_DuckerApply_func1 + qs = DuckerApply_func1(qs, hybBands, qs_next, outputReal, outputImag, + duckGain); +#else + /* general gain*output section */ + if (qs < hybBands) { /* true for about 39% */ + for (; qs < qs_next; qs++) { /* runs about 2 times */ + outputReal[qs] = fMultDiv2(outputReal[qs], duckGain) << 2; + outputImag[qs] = fMultDiv2(outputImag[qs], duckGain) << 2; + } + } else { + for (; qs < qs_next; qs++) { + outputReal[qs] = fMultDiv2(outputReal[qs], duckGain) << 2; + } + } +#endif + } /* pb */ + + self->headroomSmoothDirRevNrg = + (SCHAR)fixMax(0, CntLeadingZeros(maxDirRevNrg) - 1); + + C_ALLOC_SCRATCH_END(reverbNrg, FIXP_DBL, (28)); + + return err; +} + +LNK_SECTION_CODE_L1 +static INT DuckerApplyPS(DUCKER_INSTANCE *const self, + FIXP_DBL const directNrg[(28)], + FIXP_DBL outputReal[(71)], FIXP_DBL outputImag[(71)], + int startHybBand) { + int qs = startHybBand; + int pb = 0; + int startParamBand = + SpatialDecGetProcessingBand(startHybBand, self->mapHybBands2ProcBands); + int hybBands; + + int doScaleNrg = 0; + int scaleDirectNrg = 0; + int scaleSmoothDirRevNrg = 0; + FIXP_DBL maxDirRevNrg = FL2FXCONST_DBL(0.0); + + if ((self->scaleDirectNrg != self->scaleSmoothDirRevNrg) || + (self->headroomSmoothDirRevNrg == 0)) { + int scale; + + scale = fixMin(self->scaleDirectNrg, self->scaleSmoothDirRevNrg + + self->headroomSmoothDirRevNrg - 2); + + scaleDirectNrg = fMax(fMin(self->scaleDirectNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + scaleSmoothDirRevNrg = + fMax(fMin(self->scaleSmoothDirRevNrg - scale, (DFRACT_BITS - 1)), + -(DFRACT_BITS - 1)); + + self->scaleSmoothDirRevNrg = (SCHAR)scale; + + doScaleNrg = 1; + } + + hybBands = self->hybridBands; + + FDK_ASSERT((self->parameterBands == (28)) || (self->parameterBands == (20))); + for (pb = startParamBand; pb < self->parameterBands; pb++) { + FIXP_DBL directNrg2 = directNrg[pb]; + + if (doScaleNrg) { + directNrg2 = scaleValue(directNrg2, -scaleDirectNrg); + self->peakDiff[pb] = + scaleValue(self->peakDiff[pb], -scaleSmoothDirRevNrg); + self->peakDecay[pb] = + scaleValue(self->peakDecay[pb], -scaleSmoothDirRevNrg); + self->SmoothDirRevNrg[pb] = + scaleValue(self->SmoothDirRevNrg[pb], -scaleSmoothDirRevNrg); + } + self->peakDecay[pb] = fixMax( + directNrg2, fMult(self->peakDecay[pb], PS_DUCK_PEAK_DECAY_FACTOR_FDK)); + self->peakDiff[pb] = + self->peakDiff[pb] + + fMult(PS_DUCK_FILTER_COEFF_FDK, + (self->peakDecay[pb] - directNrg2 - self->peakDiff[pb])); + self->SmoothDirRevNrg[pb] = + fixMax(self->SmoothDirRevNrg[pb] + + fMult(PS_DUCK_FILTER_COEFF_FDK, + (directNrg2 - self->SmoothDirRevNrg[pb])), + FL2FXCONST_DBL(0)); + + maxDirRevNrg |= fAbs(self->peakDiff[pb]); + maxDirRevNrg |= fAbs(self->SmoothDirRevNrg[pb]); + + if ((self->peakDiff[pb] == FL2FXCONST_DBL(0)) && + (self->SmoothDirRevNrg[pb] == FL2FXCONST_DBL(0))) { + int qs_next; + + qs = fMax(qs, SpatialDecGetQmfBand(pb, self->mapProcBands2HybBands)); + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + FIXP_DBL *pOutputReal = &outputReal[qs]; + FIXP_DBL *pOutputImag = &outputImag[qs]; + + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + *pOutputReal++ = FL2FXCONST_DBL(0); + *pOutputImag++ = FL2FXCONST_DBL(0); + } + } else { + for (; qs < qs_next; qs++) { + *pOutputReal++ = FL2FXCONST_DBL(0); + } + } + } else if (self->peakDiff[pb] != FL2FXCONST_DBL(0)) { + FIXP_DBL multiplication = + fMult(FL2FXCONST_DUCK(0.75f), self->peakDiff[pb]); + if (multiplication > (self->SmoothDirRevNrg[pb] >> 1)) { + FIXP_DBL num, denom, duckGain; + int scale, qs_next; + + /* implement x/y as (sqrt(x)*invSqrt(y))^2 */ + num = sqrtFixp(self->SmoothDirRevNrg[pb] >> 1); + denom = self->peakDiff[pb] + + FL2FXCONST_DBL(ABS_THR / (32768.0f * 32768.0f * 128.0f * 1.5f)); + denom = invSqrtNorm2(denom, &scale); + + /* duck output whether duckGain != 1.f */ + qs = fMax(qs, SpatialDecGetQmfBand(pb, self->mapProcBands2HybBands)); + qs_next = fMin((int)self->qs_next[pb], self->hybridBands); + + duckGain = fMult(num, denom); + duckGain = fPow2Div2(duckGain << scale); + duckGain = fMultDiv2(FL2FXCONST_DUCK(2.f / 3.f), duckGain) << 3; + + FIXP_DBL *pOutputReal = &outputReal[qs]; + FIXP_DBL *pOutputImag = &outputImag[qs]; + + if (qs < hybBands) { + for (; qs < qs_next; qs++) { + *pOutputReal = fMult(*pOutputReal, duckGain); + pOutputReal++; /* don't move in front of "=" above, because then the + fract class treats it differently and provides + wrong argument to fMult() (seen on win32/msvc8) */ + *pOutputImag = fMult(*pOutputImag, duckGain); + pOutputImag++; + } + } else { + for (; qs < qs_next; qs++) { + *pOutputReal = fMult(*pOutputReal, duckGain); + pOutputReal++; + } + } + } + } + } /* pb */ + + self->headroomSmoothDirRevNrg = + (SCHAR)fixMax(0, CntLeadingZeros(maxDirRevNrg) - 1); + + return 0; +} + +INT FDKdecorrelateOpen(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *bufferCplx, + const INT bufLen) { + HANDLE_DECORR_DEC self = hDecorrDec; + + if (bufLen < (2 * ((825) + (373)))) return 1; + + /* assign all memory to stateBufferCplx. It is reassigned during + * FDKdecorrelateInit() */ + self->stateBufferCplx = bufferCplx; + self->L_stateBufferCplx = 0; + + self->delayBufferCplx = NULL; + self->L_delayBufferCplx = 0; + + return 0; +} + +static int distributeBuffer(HANDLE_DECORR_DEC self, const int L_stateBuf, + const int L_delayBuf) { + /* factor 2 because of complex values */ + if ((2 * ((825) + (373))) < 2 * (L_stateBuf + L_delayBuf)) { + return 1; + } + + self->L_stateBufferCplx = 2 * L_stateBuf; + self->delayBufferCplx = self->stateBufferCplx + 2 * L_stateBuf; + self->L_delayBufferCplx = 2 * L_delayBuf; + + return 0; +} +INT FDKdecorrelateInit(HANDLE_DECORR_DEC hDecorrDec, const INT nrHybBands, + const FDK_DECORR_TYPE decorrType, + const FDK_DUCKER_TYPE duckerType, const INT decorrConfig, + const INT seed, const INT partiallyComplex, + const INT useFractDelay, const INT isLegacyPS, + const INT initStatesFlag) { + INT errorCode = 0; + int i, rb, i_start; + int nParamBands = 28; + + INT offsetStateBuffer = 0; + INT offsetDelayBuffer = 0; + + const UCHAR *REV_bandOffset; + + const SCHAR *REV_filterOrder; + + hDecorrDec->partiallyComplex = partiallyComplex; + hDecorrDec->numbins = nrHybBands; + + switch (decorrType) { + case DECORR_PS: + /* ignore decorrConfig, seed */ + if (partiallyComplex) { + hDecorrDec->REV_bandOffset = REV_bandOffset_PS_LP; + hDecorrDec->REV_delay = REV_delay_PS_LP; + errorCode = distributeBuffer(hDecorrDec, (168), (533)); + } else { + hDecorrDec->REV_bandOffset = REV_bandOffset_PS_HQ; + hDecorrDec->REV_delay = REV_delay_PS_HQ; + errorCode = distributeBuffer(hDecorrDec, (360), (257)); + } + hDecorrDec->REV_filterOrder = REV_filterOrder_PS; + hDecorrDec->REV_filtType = REV_filtType_PS; + + /* Initialize ring buffer offsets for PS specific filter implementation. + */ + for (i = 0; i < (3); i++) + hDecorrDec->stateBufferOffset[i] = stateBufferOffsetInit[i]; + + break; + case DECORR_USAC: + if (partiallyComplex) return 1; + if (seed != 0) return 1; + hDecorrDec->REV_bandOffset = + REV_bandOffset_MPS_HQ[decorrConfig]; /* reverb band layout is + inherited from MPS standard */ + hDecorrDec->REV_filterOrder = REV_filterOrder_USAC; + hDecorrDec->REV_delay = REV_delay_USAC; + if (useFractDelay) { + return 1; /* not yet supported */ + } else { + hDecorrDec->REV_filtType = REV_filtType_MPS; /* the filter types are + inherited from MPS + standard */ + } + /* bsDecorrConfig == 1 is worst case */ + errorCode = distributeBuffer(hDecorrDec, (509), (643)); + break; + case DECORR_LD: + if (partiallyComplex) return 1; + if (useFractDelay) return 1; + if (decorrConfig > 2) return 1; + if (seed > (MAX_DECORR_SEED_LD - 1)) return 1; + if (!(nrHybBands == 64 || nrHybBands == 32)) + return 1; /* actually just qmf bands and no hybrid bands */ + hDecorrDec->REV_bandOffset = REV_bandOffset_LD[decorrConfig]; + hDecorrDec->REV_filterOrder = REV_filterOrder_MPS; /* the filter orders + are inherited from + MPS standard */ + hDecorrDec->REV_delay = + REV_delay_MPS; /* the delays in each reverb band are inherited from + MPS standard */ + hDecorrDec->REV_filtType = REV_filtType_LD; + errorCode = distributeBuffer(hDecorrDec, (825), (373)); + break; + default: + return 1; + } + + if (errorCode) { + return errorCode; + } + + if (initStatesFlag) { + FDKmemclear( + hDecorrDec->stateBufferCplx, + hDecorrDec->L_stateBufferCplx * sizeof(*hDecorrDec->stateBufferCplx)); + FDKmemclear( + hDecorrDec->delayBufferCplx, + hDecorrDec->L_delayBufferCplx * sizeof(*hDecorrDec->delayBufferCplx)); + FDKmemclear(hDecorrDec->reverbBandDelayBufferIndex, + sizeof(hDecorrDec->reverbBandDelayBufferIndex)); + } + + REV_bandOffset = hDecorrDec->REV_bandOffset; + + REV_filterOrder = hDecorrDec->REV_filterOrder; + + i_start = 0; + for (rb = 0; rb < (4); rb++) { + int i_stop; + + i_stop = REV_bandOffset[rb]; + + if (i_stop <= i_start) { + continue; + } + + for (i = i_start; i < i_stop; i++) { + switch (decorrType) { + case DECORR_PS: + errorCode = DecorrFilterInitPS( + &hDecorrDec->Filter[i], hDecorrDec->stateBufferCplx, + hDecorrDec->delayBufferCplx, &offsetStateBuffer, + &offsetDelayBuffer, i, rb, hDecorrDec->REV_delay[rb]); + break; + default: + errorCode = DecorrFilterInit( + &hDecorrDec->Filter[i], hDecorrDec->stateBufferCplx, + hDecorrDec->delayBufferCplx, &offsetStateBuffer, + &offsetDelayBuffer, seed, rb, useFractDelay, + hDecorrDec->REV_delay[rb], REV_filterOrder[rb], decorrType); + break; + } + } + + i_start = i_stop; + } /* loop over reverbBands */ + + if (!(offsetStateBuffer <= hDecorrDec->L_stateBufferCplx) || + !(offsetDelayBuffer <= hDecorrDec->L_delayBufferCplx)) { + return errorCode = 1; + } + + if (duckerType == DUCKER_AUTOMATIC) { + /* Choose correct ducker type according to standards: */ + switch (decorrType) { + case DECORR_PS: + hDecorrDec->ducker.duckerType = DUCKER_PS; + if (isLegacyPS) { + nParamBands = (20); + } else { + nParamBands = (28); + } + break; + case DECORR_USAC: + hDecorrDec->ducker.duckerType = DUCKER_MPS; + nParamBands = (28); + break; + case DECORR_LD: + hDecorrDec->ducker.duckerType = DUCKER_MPS; + nParamBands = (23); + break; + default: + return 1; + } + } + + errorCode = DuckerInit( + &hDecorrDec->ducker, hDecorrDec->numbins, hDecorrDec->partiallyComplex, + hDecorrDec->ducker.duckerType, nParamBands, initStatesFlag); + + return errorCode; +} + +INT FDKdecorrelateClose(HANDLE_DECORR_DEC hDecorrDec) { + INT err = 0; + + if (hDecorrDec == NULL) { + return 1; + } + + hDecorrDec->stateBufferCplx = NULL; + hDecorrDec->L_stateBufferCplx = 0; + hDecorrDec->delayBufferCplx = NULL; + hDecorrDec->L_delayBufferCplx = 0; + + return err; +} + +LNK_SECTION_CODE_L1 +INT FDKdecorrelateApply(HANDLE_DECORR_DEC hDecorrDec, FIXP_DBL *dataRealIn, + FIXP_DBL *dataImagIn, FIXP_DBL *dataRealOut, + FIXP_DBL *dataImagOut, const INT startHybBand) { + HANDLE_DECORR_DEC self = hDecorrDec; + INT err = 0; + INT rb, stop, start; + + if (self != NULL) { + int nHybBands = 0; + /* copy new samples */ + nHybBands = self->numbins; + + FIXP_DBL directNrg[(28)]; + + DuckerCalcEnergy( + &self->ducker, dataRealIn, dataImagIn, directNrg, + self->ducker.maxValDirectData, &(self->ducker.scaleDirectNrg), + (self->ducker.duckerType == DUCKER_PS) ? 1 : 0, startHybBand); + + /* complex-valued hybrid bands */ + for (stop = 0, rb = 0; rb < (4); rb++) { + start = fMax(stop, startHybBand); + stop = fMin(self->REV_bandOffset[rb], (UCHAR)nHybBands); + + if (start < stop) { + switch (hDecorrDec->REV_filtType[rb]) { + case DELAY: + err = DecorrFilterApplyPASS(&self->Filter[0], dataRealIn, + dataImagIn, dataRealOut, dataImagOut, + start, stop, self->REV_delay[rb], + self->reverbBandDelayBufferIndex[rb]); + break; + case INDEP_CPLX_PS: + err = DecorrFilterApplyCPLX_PS( + &self->Filter[0], dataRealIn, dataImagIn, dataRealOut, + dataImagOut, start, stop, self->REV_filterOrder[rb], + self->REV_delay[rb], self->reverbBandDelayBufferIndex[rb], + self->stateBufferOffset); + break; + case COMMON_REAL: + err = DecorrFilterApplyREAL( + &self->Filter[0], dataRealIn, dataImagIn, dataRealOut, + dataImagOut, start, stop, self->REV_filterOrder[rb], + self->REV_delay[rb], self->reverbBandDelayBufferIndex[rb]); + break; + default: + err = 1; + break; + } + if (err != 0) { + goto bail; + } + } /* if start < stop */ + } /* loop over reverb bands */ + + for (rb = 0; rb < (4); rb++) { + self->reverbBandDelayBufferIndex[rb] += 2; + if (self->reverbBandDelayBufferIndex[rb] >= 2 * self->REV_delay[rb]) + self->reverbBandDelayBufferIndex[rb] = 0; + } + + switch (self->ducker.duckerType) { + case DUCKER_PS: + err = DuckerApplyPS(&self->ducker, directNrg, dataRealOut, dataImagOut, + startHybBand); + if (err != 0) goto bail; + break; + default: + err = DuckerApply(&self->ducker, directNrg, dataRealOut, dataImagOut, + startHybBand); + if (err != 0) goto bail; + break; + } + } + +bail: + return err; +} diff --git a/fdk-aac/libFDK/src/FDK_hybrid.cpp b/fdk-aac/libFDK/src/FDK_hybrid.cpp new file mode 100644 index 0000000..b661f82 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_hybrid.cpp @@ -0,0 +1,813 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser + + Description: FDK Tools Hybrid Filterbank + +*******************************************************************************/ + +#include "FDK_hybrid.h" + +#include "fft.h" + +/*--------------- defines -----------------------------*/ +#define FFT_IDX_R(a) (2 * a) +#define FFT_IDX_I(a) (2 * a + 1) + +#define HYB_COEF8_0 (0.00746082949812f) +#define HYB_COEF8_1 (0.02270420949825f) +#define HYB_COEF8_2 (0.04546865930473f) +#define HYB_COEF8_3 (0.07266113929591f) +#define HYB_COEF8_4 (0.09885108575264f) +#define HYB_COEF8_5 (0.11793710567217f) +#define HYB_COEF8_6 (0.12500000000000f) +#define HYB_COEF8_7 (HYB_COEF8_5) +#define HYB_COEF8_8 (HYB_COEF8_4) +#define HYB_COEF8_9 (HYB_COEF8_3) +#define HYB_COEF8_10 (HYB_COEF8_2) +#define HYB_COEF8_11 (HYB_COEF8_1) +#define HYB_COEF8_12 (HYB_COEF8_0) + +/*--------------- structure definitions ---------------*/ + +#if defined(ARCH_PREFER_MULT_32x16) +#define FIXP_HTB FIXP_SGL /* SGL data type. */ +#define FIXP_HTP FIXP_SPK /* Packed SGL data type. */ +#define HTC(a) (FX_DBL2FXCONST_SGL(a)) /* Cast to SGL */ +#define FL2FXCONST_HTB FL2FXCONST_SGL +#else +#define FIXP_HTB FIXP_DBL /* SGL data type. */ +#define FIXP_HTP FIXP_DPK /* Packed DBL data type. */ +#define HTC(a) ((FIXP_DBL)(LONG)(a)) /* Cast to DBL */ +#define FL2FXCONST_HTB FL2FXCONST_DBL +#endif + +#define HTCP(real, imag) \ + { \ + { HTC(real), HTC(imag) } \ + } /* How to arrange the packed values. */ + +struct FDK_HYBRID_SETUP { + UCHAR nrQmfBands; /*!< Number of QMF bands to be converted to hybrid. */ + UCHAR nHybBands[3]; /*!< Number of Hybrid bands generated by nrQmfBands. */ + SCHAR kHybrid[3]; /*!< Filter configuration of each QMF band. */ + UCHAR protoLen; /*!< Prototype filter length. */ + UCHAR filterDelay; /*!< Delay caused by hybrid filter. */ + const INT + *pReadIdxTable; /*!< Helper table to access input data ringbuffer. */ +}; + +/*--------------- constants ---------------------------*/ +static const INT ringbuffIdxTab[2 * 13] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12}; + +static const FDK_HYBRID_SETUP setup_3_16 = {3, {8, 4, 4}, {8, 4, 4}, + 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_12 = {3, {8, 2, 2}, {8, 2, 2}, + 13, (13 - 1) / 2, ringbuffIdxTab}; +static const FDK_HYBRID_SETUP setup_3_10 = {3, {6, 2, 2}, {-8, -2, 2}, + 13, (13 - 1) / 2, ringbuffIdxTab}; + +static const FIXP_HTP HybFilterCoef8[] = { + HTCP(0x10000000, 0x00000000), HTCP(0x0df26407, 0xfa391882), + HTCP(0xff532109, 0x00acdef7), HTCP(0x08f26d36, 0xf70d92ca), + HTCP(0xfee34b5f, 0x02af570f), HTCP(0x038f276e, 0xf7684793), + HTCP(0x00000000, 0x05d1eac2), HTCP(0x00000000, 0x05d1eac2), + HTCP(0x038f276e, 0x0897b86d), HTCP(0xfee34b5f, 0xfd50a8f1), + HTCP(0x08f26d36, 0x08f26d36), HTCP(0xff532109, 0xff532109), + HTCP(0x0df26407, 0x05c6e77e)}; + +static const FIXP_HTB HybFilterCoef2[3] = {FL2FXCONST_HTB(0.01899487526049f), + FL2FXCONST_HTB(-0.07293139167538f), + FL2FXCONST_HTB(0.30596630545168f)}; + +static const FIXP_HTB HybFilterCoef4[13] = {FL2FXCONST_HTB(-0.00305151927305f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.25f), + FL2FXCONST_HTB(0.21227807049160f), + FL2FXCONST_HTB(0.12542448210445f), + FL2FXCONST_HTB(0.04318924038756f), + FL2FXCONST_HTB(0.0f), + FL2FXCONST_HTB(-0.00794862316203f), + FL2FXCONST_HTB(-0.00305151927305f)}; + +/*--------------- function declarations ---------------*/ +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig); + +/*--------------- function definitions ----------------*/ + +INT FDKhybridAnalysisOpen(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + FIXP_DBL *const pLFmemory, const UINT LFmemorySize, + FIXP_DBL *const pHFmemory, const UINT HFmemorySize) { + INT err = 0; + + /* Save pointer to extern memory. */ + hAnalysisHybFilter->pLFmemory = pLFmemory; + hAnalysisHybFilter->LFmemorySize = LFmemorySize; + + hAnalysisHybFilter->pHFmemory = pHFmemory; + hAnalysisHybFilter->HFmemorySize = HFmemorySize; + + return err; +} + +INT FDKhybridAnalysisInit(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands, const INT initStatesFlag) { + int k; + INT err = 0; + FIXP_DBL *pMem = NULL; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } + + /* Initialize handle. */ + hAnalysisHybFilter->pSetup = setup; + if (initStatesFlag) { + hAnalysisHybFilter->bufferLFpos = setup->protoLen - 1; + hAnalysisHybFilter->bufferHFpos = 0; + } + hAnalysisHybFilter->nrBands = qmfBands; + hAnalysisHybFilter->cplxBands = cplxBands; + hAnalysisHybFilter->hfMode = 0; + + /* Check available memory. */ + if (((2 * setup->nrQmfBands * setup->protoLen * sizeof(FIXP_DBL)) > + hAnalysisHybFilter->LFmemorySize)) { + err = -2; + goto bail; + } + if (hAnalysisHybFilter->HFmemorySize != 0) { + if (((setup->filterDelay * + ((qmfBands - setup->nrQmfBands) + (cplxBands - setup->nrQmfBands)) * + sizeof(FIXP_DBL)) > hAnalysisHybFilter->HFmemorySize)) { + err = -3; + goto bail; + } + } + + /* Distribute LF memory. */ + pMem = hAnalysisHybFilter->pLFmemory; + for (k = 0; k < setup->nrQmfBands; k++) { + hAnalysisHybFilter->bufferLFReal[k] = pMem; + pMem += setup->protoLen; + hAnalysisHybFilter->bufferLFImag[k] = pMem; + pMem += setup->protoLen; + } + + /* Distribute HF memory. */ + if (hAnalysisHybFilter->HFmemorySize != 0) { + pMem = hAnalysisHybFilter->pHFmemory; + for (k = 0; k < setup->filterDelay; k++) { + hAnalysisHybFilter->bufferHFReal[k] = pMem; + pMem += (qmfBands - setup->nrQmfBands); + hAnalysisHybFilter->bufferHFImag[k] = pMem; + pMem += (cplxBands - setup->nrQmfBands); + } + } + + if (initStatesFlag) { + /* Clear LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + FDKmemclear(hAnalysisHybFilter->bufferLFReal[k], + setup->protoLen * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferLFImag[k], + setup->protoLen * sizeof(FIXP_DBL)); + } + + if (hAnalysisHybFilter->HFmemorySize != 0) { + if (qmfBands > setup->nrQmfBands) { + /* Clear HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + FDKmemclear(hAnalysisHybFilter->bufferHFReal[k], + (qmfBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + FDKmemclear(hAnalysisHybFilter->bufferHFImag[k], + (cplxBands - setup->nrQmfBands) * sizeof(FIXP_DBL)); + } + } + } + } + +bail: + return err; +} + +INT FDKhybridAnalysisScaleStates(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const INT scalingValue) { + INT err = 0; + + if (hAnalysisHybFilter == NULL) { + err = 1; /* invalid handle */ + } else { + int k; + HANDLE_FDK_HYBRID_SETUP setup = hAnalysisHybFilter->pSetup; + + /* Scale LF buffer */ + for (k = 0; k < setup->nrQmfBands; k++) { + scaleValues(hAnalysisHybFilter->bufferLFReal[k], setup->protoLen, + scalingValue); + scaleValues(hAnalysisHybFilter->bufferLFImag[k], setup->protoLen, + scalingValue); + } + if (hAnalysisHybFilter->nrBands > setup->nrQmfBands) { + /* Scale HF buffer */ + for (k = 0; k < setup->filterDelay; k++) { + scaleValues(hAnalysisHybFilter->bufferHFReal[k], + (hAnalysisHybFilter->nrBands - setup->nrQmfBands), + scalingValue); + scaleValues(hAnalysisHybFilter->bufferHFImag[k], + (hAnalysisHybFilter->cplxBands - setup->nrQmfBands), + scalingValue); + } + } + } + return err; +} + +INT FDKhybridAnalysisApply(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter, + const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + FIXP_DBL *const pHybridReal, + FIXP_DBL *const pHybridImag) { + int k, hybOffset = 0; + INT err = 0; + const int nrQmfBandsLF = + hAnalysisHybFilter->pSetup + ->nrQmfBands; /* number of QMF bands to be converted to hybrid */ + + const int writIndex = hAnalysisHybFilter->bufferLFpos; + int readIndex = hAnalysisHybFilter->bufferLFpos; + + if (++readIndex >= hAnalysisHybFilter->pSetup->protoLen) readIndex = 0; + const INT *pBufferLFreadIdx = + &hAnalysisHybFilter->pSetup->pReadIdxTable[readIndex]; + + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + /* New input sample. */ + hAnalysisHybFilter->bufferLFReal[k][writIndex] = pQmfReal[k]; + hAnalysisHybFilter->bufferLFImag[k][writIndex] = pQmfImag[k]; + + /* Perform hybrid filtering. */ + err |= + kChannelFiltering(hAnalysisHybFilter->bufferLFReal[k], + hAnalysisHybFilter->bufferLFImag[k], pBufferLFreadIdx, + pHybridReal + hybOffset, pHybridImag + hybOffset, + hAnalysisHybFilter->pSetup->kHybrid[k]); + + hybOffset += hAnalysisHybFilter->pSetup->nHybBands[k]; + } + + hAnalysisHybFilter->bufferLFpos = + readIndex; /* Index where to write next input sample. */ + + if (hAnalysisHybFilter->nrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + if (hAnalysisHybFilter->hfMode != 0) { + /* HF delay compensation was applied outside. */ + FDKmemcpy( + pHybridReal + hybOffset, &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } else { + FDK_ASSERT(hAnalysisHybFilter->HFmemorySize != 0); + /* HF delay compensation, filterlength/2. */ + FDKmemcpy( + pHybridReal + hybOffset, + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + pHybridImag + hybOffset, + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + FDKmemcpy( + hAnalysisHybFilter->bufferHFReal[hAnalysisHybFilter->bufferHFpos], + &pQmfReal[nrQmfBandsLF], + (hAnalysisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + hAnalysisHybFilter->bufferHFImag[hAnalysisHybFilter->bufferHFpos], + &pQmfImag[nrQmfBandsLF], + (hAnalysisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + + if (++hAnalysisHybFilter->bufferHFpos >= + hAnalysisHybFilter->pSetup->filterDelay) + hAnalysisHybFilter->bufferHFpos = 0; + } + } /* process HF part*/ + + return err; +} + +INT FDKhybridAnalysisClose(HANDLE_FDK_ANA_HYB_FILTER hAnalysisHybFilter) { + INT err = 0; + + if (hAnalysisHybFilter != NULL) { + hAnalysisHybFilter->pLFmemory = NULL; + hAnalysisHybFilter->pHFmemory = NULL; + hAnalysisHybFilter->LFmemorySize = 0; + hAnalysisHybFilter->HFmemorySize = 0; + } + + return err; +} + +INT FDKhybridSynthesisInit(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FDK_HYBRID_MODE mode, const INT qmfBands, + const INT cplxBands) { + INT err = 0; + HANDLE_FDK_HYBRID_SETUP setup = NULL; + + switch (mode) { + case THREE_TO_TEN: + setup = &setup_3_10; + break; + case THREE_TO_TWELVE: + setup = &setup_3_12; + break; + case THREE_TO_SIXTEEN: + setup = &setup_3_16; + break; + default: + err = -1; + goto bail; + } + + hSynthesisHybFilter->pSetup = setup; + hSynthesisHybFilter->nrBands = qmfBands; + hSynthesisHybFilter->cplxBands = cplxBands; + +bail: + return err; +} + +void FDKhybridSynthesisApply(HANDLE_FDK_SYN_HYB_FILTER hSynthesisHybFilter, + const FIXP_DBL *const pHybridReal, + const FIXP_DBL *const pHybridImag, + FIXP_DBL *const pQmfReal, + FIXP_DBL *const pQmfImag) { + int k, n, hybOffset = 0; + const INT nrQmfBandsLF = hSynthesisHybFilter->pSetup->nrQmfBands; + + /* + * LF buffer. + */ + for (k = 0; k < nrQmfBandsLF; k++) { + const int nHybBands = hSynthesisHybFilter->pSetup->nHybBands[k]; + + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); + + /* Perform hybrid filtering. */ + for (n = 0; n < nHybBands; n++) { + accu1 += pHybridReal[hybOffset + n]; + accu2 += pHybridImag[hybOffset + n]; + } + pQmfReal[k] = accu1; + pQmfImag[k] = accu2; + + hybOffset += nHybBands; + } + + if (hSynthesisHybFilter->nrBands > nrQmfBandsLF) { + /* + * HF buffer. + */ + FDKmemcpy(&pQmfReal[nrQmfBandsLF], &pHybridReal[hybOffset], + (hSynthesisHybFilter->nrBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + FDKmemcpy( + &pQmfImag[nrQmfBandsLF], &pHybridImag[hybOffset], + (hSynthesisHybFilter->cplxBands - nrQmfBandsLF) * sizeof(FIXP_DBL)); + } + + return; +} + +static void dualChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + FIXP_DBL r1, r6; + FIXP_DBL i1, i6; + + const FIXP_HTB f0 = HybFilterCoef2[0]; /* corresponds to p1 and p11 */ + const FIXP_HTB f1 = HybFilterCoef2[1]; /* corresponds to p3 and p9 */ + const FIXP_HTB f2 = HybFilterCoef2[2]; /* corresponds to p5 and p7 */ + + /* symmetric filter coefficients */ + r1 = fMultDiv2(f0, pQmfReal[pReadIdx[1]]) + + fMultDiv2(f0, pQmfReal[pReadIdx[11]]); + i1 = fMultDiv2(f0, pQmfImag[pReadIdx[1]]) + + fMultDiv2(f0, pQmfImag[pReadIdx[11]]); + r1 += fMultDiv2(f1, pQmfReal[pReadIdx[3]]) + + fMultDiv2(f1, pQmfReal[pReadIdx[9]]); + i1 += fMultDiv2(f1, pQmfImag[pReadIdx[3]]) + + fMultDiv2(f1, pQmfImag[pReadIdx[9]]); + r1 += fMultDiv2(f2, pQmfReal[pReadIdx[5]]) + + fMultDiv2(f2, pQmfReal[pReadIdx[7]]); + i1 += fMultDiv2(f2, pQmfImag[pReadIdx[5]]) + + fMultDiv2(f2, pQmfImag[pReadIdx[7]]); + + r6 = pQmfReal[pReadIdx[6]] >> 2; + i6 = pQmfImag[pReadIdx[6]] >> 2; + + FDK_ASSERT((invert == 0) || (invert == 1)); + mHybridReal[0 + invert] = (r6 + r1) << 1; + mHybridImag[0 + invert] = (i6 + i1) << 1; + + mHybridReal[1 - invert] = (r6 - r1) << 1; + mHybridImag[1 - invert] = (i6 - i1) << 1; +} + +static void fourChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTB *p = HybFilterCoef4; + + FIXP_DBL fft[8]; + + static const FIXP_DBL cr[13] = { + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f)}; + static const FIXP_DBL ci[13] = { + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(-1.f), FL2FXCONST_DBL(-0.70710678118655f), + FL2FXCONST_DBL(0.f), FL2FXCONST_DBL(0.70710678118655f), + FL2FXCONST_DBL(1.f)}; + + /* FIR filter. */ + /* pre twiddeling with pre-twiddling coefficients c[n] */ + /* multiplication with filter coefficients p[n] */ + /* hint: (a + ib)*(c + id) = (a*c - b*d) + i(a*d + b*c) */ + /* write to fft coefficient n' */ + fft[FFT_IDX_R(0)] = + (fMult(p[10], (fMultSub(fMultDiv2(cr[2], pQmfReal[pReadIdx[2]]), ci[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultSub(fMultDiv2(cr[6], pQmfReal[pReadIdx[6]]), ci[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultSub(fMultDiv2(cr[10], pQmfReal[pReadIdx[10]]), ci[10], + pQmfImag[pReadIdx[10]])))); + fft[FFT_IDX_I(0)] = + (fMult(p[10], (fMultAdd(fMultDiv2(ci[2], pQmfReal[pReadIdx[2]]), cr[2], + pQmfImag[pReadIdx[2]]))) + + fMult(p[6], (fMultAdd(fMultDiv2(ci[6], pQmfReal[pReadIdx[6]]), cr[6], + pQmfImag[pReadIdx[6]]))) + + fMult(p[2], (fMultAdd(fMultDiv2(ci[10], pQmfReal[pReadIdx[10]]), cr[10], + pQmfImag[pReadIdx[10]])))); + + /* twiddle dee dum */ + fft[FFT_IDX_R(1)] = + (fMult(p[9], (fMultSub(fMultDiv2(cr[3], pQmfReal[pReadIdx[3]]), ci[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultSub(fMultDiv2(cr[7], pQmfReal[pReadIdx[7]]), ci[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultSub(fMultDiv2(cr[11], pQmfReal[pReadIdx[11]]), ci[11], + pQmfImag[pReadIdx[11]])))); + fft[FFT_IDX_I(1)] = + (fMult(p[9], (fMultAdd(fMultDiv2(ci[3], pQmfReal[pReadIdx[3]]), cr[3], + pQmfImag[pReadIdx[3]]))) + + fMult(p[5], (fMultAdd(fMultDiv2(ci[7], pQmfReal[pReadIdx[7]]), cr[7], + pQmfImag[pReadIdx[7]]))) + + fMult(p[1], (fMultAdd(fMultDiv2(ci[11], pQmfReal[pReadIdx[11]]), cr[11], + pQmfImag[pReadIdx[11]])))); + + /* twiddle dee dee */ + fft[FFT_IDX_R(2)] = + (fMult(p[12], (fMultSub(fMultDiv2(cr[0], pQmfReal[pReadIdx[0]]), ci[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultSub(fMultDiv2(cr[4], pQmfReal[pReadIdx[4]]), ci[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultSub(fMultDiv2(cr[8], pQmfReal[pReadIdx[8]]), ci[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultSub(fMultDiv2(cr[12], pQmfReal[pReadIdx[12]]), ci[12], + pQmfImag[pReadIdx[12]])))); + fft[FFT_IDX_I(2)] = + (fMult(p[12], (fMultAdd(fMultDiv2(ci[0], pQmfReal[pReadIdx[0]]), cr[0], + pQmfImag[pReadIdx[0]]))) + + fMult(p[8], (fMultAdd(fMultDiv2(ci[4], pQmfReal[pReadIdx[4]]), cr[4], + pQmfImag[pReadIdx[4]]))) + + fMult(p[4], (fMultAdd(fMultDiv2(ci[8], pQmfReal[pReadIdx[8]]), cr[8], + pQmfImag[pReadIdx[8]]))) + + fMult(p[0], (fMultAdd(fMultDiv2(ci[12], pQmfReal[pReadIdx[12]]), cr[12], + pQmfImag[pReadIdx[12]])))); + + fft[FFT_IDX_R(3)] = + (fMult(p[11], (fMultSub(fMultDiv2(cr[1], pQmfReal[pReadIdx[1]]), ci[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultSub(fMultDiv2(cr[5], pQmfReal[pReadIdx[5]]), ci[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultSub(fMultDiv2(cr[9], pQmfReal[pReadIdx[9]]), ci[9], + pQmfImag[pReadIdx[9]])))); + fft[FFT_IDX_I(3)] = + (fMult(p[11], (fMultAdd(fMultDiv2(ci[1], pQmfReal[pReadIdx[1]]), cr[1], + pQmfImag[pReadIdx[1]]))) + + fMult(p[7], (fMultAdd(fMultDiv2(ci[5], pQmfReal[pReadIdx[5]]), cr[5], + pQmfImag[pReadIdx[5]]))) + + fMult(p[3], (fMultAdd(fMultDiv2(ci[9], pQmfReal[pReadIdx[9]]), cr[9], + pQmfImag[pReadIdx[9]])))); + + /* fft modulation */ + /* here: fast manual fft modulation for a fft of length M=4 */ + /* fft_4{x[n]} = x[0]*exp(-i*2*pi/4*m*0) + x[1]*exp(-i*2*pi/4*m*1) + + x[2]*exp(-i*2*pi/4*m*2) + x[3]*exp(-i*2*pi/4*m*3) */ + + /* + fft bin m=0: + X[0, n] = x[0] + x[1] + x[2] + x[3] + */ + mHybridReal[0] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] + + fft[FFT_IDX_R(3)]; + mHybridImag[0] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] + + fft[FFT_IDX_I(3)]; + + /* + fft bin m=1: + X[1, n] = x[0] - i*x[1] - x[2] + i*x[3] + */ + mHybridReal[1] = fft[FFT_IDX_R(0)] + fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] - + fft[FFT_IDX_I(3)]; + mHybridImag[1] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] + + fft[FFT_IDX_R(3)]; + + /* + fft bin m=2: + X[2, n] = x[0] - x[1] + x[2] - x[3] + */ + mHybridReal[2] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_R(1)] + fft[FFT_IDX_R(2)] - + fft[FFT_IDX_R(3)]; + mHybridImag[2] = fft[FFT_IDX_I(0)] - fft[FFT_IDX_I(1)] + fft[FFT_IDX_I(2)] - + fft[FFT_IDX_I(3)]; + + /* + fft bin m=3: + X[3, n] = x[0] + j*x[1] - x[2] - j*x[3] + */ + mHybridReal[3] = fft[FFT_IDX_R(0)] - fft[FFT_IDX_I(1)] - fft[FFT_IDX_R(2)] + + fft[FFT_IDX_I(3)]; + mHybridImag[3] = fft[FFT_IDX_I(0)] + fft[FFT_IDX_R(1)] - fft[FFT_IDX_I(2)] - + fft[FFT_IDX_R(3)]; +} + +static void eightChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const INT invert) { + const FIXP_HTP *p = HybFilterCoef8; + INT k, sc; + + FIXP_DBL mfft[16 + ALIGNMENT_DEFAULT]; + FIXP_DBL *pfft = (FIXP_DBL *)ALIGN_PTR(mfft); + + FIXP_DBL accu1, accu2, accu3, accu4; + + /* pre twiddeling */ + pfft[FFT_IDX_R(0)] = + pQmfReal[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfReal[pReadIdx[6]]); */ + pfft[FFT_IDX_I(0)] = + pQmfImag[pReadIdx[6]] >> + (3 + 1); /* fMultDiv2(p[0].v.re, pQmfImag[pReadIdx[6]]); */ + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[7]], pQmfImag[pReadIdx[7]], + p[1]); + pfft[FFT_IDX_R(1)] = accu1; + pfft[FFT_IDX_I(1)] = accu2; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[0]], pQmfImag[pReadIdx[0]], + p[2]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[8]], pQmfImag[pReadIdx[8]], + p[3]); + pfft[FFT_IDX_R(2)] = accu1 + accu3; + pfft[FFT_IDX_I(2)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[1]], pQmfImag[pReadIdx[1]], + p[4]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[9]], pQmfImag[pReadIdx[9]], + p[5]); + pfft[FFT_IDX_R(3)] = accu1 + accu3; + pfft[FFT_IDX_I(3)] = accu2 + accu4; + + pfft[FFT_IDX_R(4)] = fMultDiv2(pQmfImag[pReadIdx[10]], p[7].v.im) - + fMultDiv2(pQmfImag[pReadIdx[2]], p[6].v.im); + pfft[FFT_IDX_I(4)] = fMultDiv2(pQmfReal[pReadIdx[2]], p[6].v.im) - + fMultDiv2(pQmfReal[pReadIdx[10]], p[7].v.im); + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[3]], pQmfImag[pReadIdx[3]], + p[8]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[11]], pQmfImag[pReadIdx[11]], + p[9]); + pfft[FFT_IDX_R(5)] = accu1 + accu3; + pfft[FFT_IDX_I(5)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[4]], pQmfImag[pReadIdx[4]], + p[10]); + cplxMultDiv2(&accu3, &accu4, pQmfReal[pReadIdx[12]], pQmfImag[pReadIdx[12]], + p[11]); + pfft[FFT_IDX_R(6)] = accu1 + accu3; + pfft[FFT_IDX_I(6)] = accu2 + accu4; + + cplxMultDiv2(&accu1, &accu2, pQmfReal[pReadIdx[5]], pQmfImag[pReadIdx[5]], + p[12]); + pfft[FFT_IDX_R(7)] = accu1; + pfft[FFT_IDX_I(7)] = accu2; + + /* fft modulation */ + fft_8(pfft); + sc = 1 + 2; + + if (invert) { + mHybridReal[0] = pfft[FFT_IDX_R(7)] << sc; + mHybridImag[0] = pfft[FFT_IDX_I(7)] << sc; + mHybridReal[1] = pfft[FFT_IDX_R(0)] << sc; + mHybridImag[1] = pfft[FFT_IDX_I(0)] << sc; + + mHybridReal[2] = pfft[FFT_IDX_R(6)] << sc; + mHybridImag[2] = pfft[FFT_IDX_I(6)] << sc; + mHybridReal[3] = pfft[FFT_IDX_R(1)] << sc; + mHybridImag[3] = pfft[FFT_IDX_I(1)] << sc; + + mHybridReal[4] = pfft[FFT_IDX_R(2)] << sc; + mHybridReal[4] += pfft[FFT_IDX_R(5)] << sc; + mHybridImag[4] = pfft[FFT_IDX_I(2)] << sc; + mHybridImag[4] += pfft[FFT_IDX_I(5)] << sc; + + mHybridReal[5] = pfft[FFT_IDX_R(3)] << sc; + mHybridReal[5] += pfft[FFT_IDX_R(4)] << sc; + mHybridImag[5] = pfft[FFT_IDX_I(3)] << sc; + mHybridImag[5] += pfft[FFT_IDX_I(4)] << sc; + } else { + for (k = 0; k < 8; k++) { + mHybridReal[k] = pfft[FFT_IDX_R(k)] << sc; + mHybridImag[k] = pfft[FFT_IDX_I(k)] << sc; + } + } +} + +static INT kChannelFiltering(const FIXP_DBL *const pQmfReal, + const FIXP_DBL *const pQmfImag, + const INT *const pReadIdx, + FIXP_DBL *const mHybridReal, + FIXP_DBL *const mHybridImag, + const SCHAR hybridConfig) { + INT err = 0; + + switch (hybridConfig) { + case 2: + case -2: + dualChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 4: + case -4: + fourChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + case 8: + case -8: + eightChannelFiltering(pQmfReal, pQmfImag, pReadIdx, mHybridReal, + mHybridImag, (hybridConfig < 0) ? 1 : 0); + break; + default: + err = -1; + } + + return err; +} diff --git a/fdk-aac/libFDK/src/FDK_lpc.cpp b/fdk-aac/libFDK/src/FDK_lpc.cpp new file mode 100644 index 0000000..7d7e691 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_lpc.cpp @@ -0,0 +1,487 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Manuel Jander + + Description: LPC related functions + +*******************************************************************************/ + +#include "FDK_lpc.h" + +/* Internal scaling of LPC synthesis to avoid overflow of filte states. + This depends on the LPC order, because the LPC order defines the amount + of MAC operations. */ +static SCHAR order_ld[LPC_MAX_ORDER] = { + /* Assume that Synthesis filter output does not clip and filter + accu does change no more than 1.0 for each iteration. + ceil(0.5*log((1:24))/log(2)) */ + 0, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3}; + +/* IIRLattice */ +#ifndef FUNCTION_CLpc_SynthesisLattice_SGL +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_SGL *coeff, + const int order, FIXP_DBL *state) { + int i, j; + FIXP_DBL *pSignal; + int shift; + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(order > 0); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* + tmp = x(k) - K(M)*g(M); + for m=M-1:-1:1 + tmp = tmp - K(m) * g(m); + g(m+1) = g(m) + K(m) * tmp; + endfor + g(1) = tmp; + + y(k) = tmp; + */ + + shift = -order_ld[order - 1]; + + for (i = signal_size; i != 0; i--) { + FIXP_DBL *pState = state + order - 1; + const FIXP_SGL *pCoeff = coeff + order - 1; + FIXP_DBL tmp; + + tmp = scaleValue(*pSignal, shift + signal_e) - + fMultDiv2(*pCoeff--, *pState--); + for (j = order - 1; j != 0; j--) { + tmp = fMultSubDiv2(tmp, pCoeff[0], pState[0]); + pState[1] = pState[0] + (fMultDiv2(*pCoeff--, tmp) << 2); + pState--; + } + + *pSignal = scaleValueSaturate(tmp, -shift - signal_e_out); + + /* exponent of state[] is -1 */ + pState[1] = tmp << 1; + pSignal += inc; + } +} +#endif + +#ifndef FUNCTION_CLpc_SynthesisLattice_DBL +void CLpc_SynthesisLattice(FIXP_DBL *signal, const int signal_size, + const int signal_e, const int signal_e_out, + const int inc, const FIXP_DBL *coeff, + const int order, FIXP_DBL *state) { + int i, j; + FIXP_DBL *pSignal; + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(order > 0); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + FDK_ASSERT(signal_size > 0); + for (i = signal_size; i != 0; i--) { + FIXP_DBL *pState = state + order - 1; + const FIXP_DBL *pCoeff = coeff + order - 1; + FIXP_DBL tmp, accu; + + accu = + fMultSubDiv2(scaleValue(*pSignal, signal_e - 1), *pCoeff--, *pState--); + tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + for (j = order - 1; j != 0; j--) { + accu = fMultSubDiv2(tmp >> 1, pCoeff[0], pState[0]); + tmp = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + accu = fMultAddDiv2(pState[0] >> 1, *pCoeff--, tmp); + pState[1] = SATURATE_LEFT_SHIFT_ALT(accu, 1, DFRACT_BITS); + + pState--; + } + + *pSignal = scaleValue(tmp, -signal_e_out); + + /* exponent of state[] is 0 */ + pState[1] = tmp; + pSignal += inc; + } +} + +#endif + +/* LPC_SYNTHESIS_IIR version */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC_TNS *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex) { + int i, j; + FIXP_DBL *pSignal; + int stateIndex = *pStateIndex; + + FIXP_LPC_TNS coeff[2 * LPC_MAX_ORDER]; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC_TNS)); + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(stateIndex < order); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */ + + for (i = 0; i < signal_size; i++) { + FIXP_DBL x; + const FIXP_LPC_TNS *pCoeff = coeff + order - stateIndex; + + x = scaleValue(*pSignal, -(lpcCoeff_e + 1)); + for (j = 0; j < order; j++) { + x -= fMultDiv2(state[j], pCoeff[j]); + } + x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS); + + /* Update states */ + stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1); + state[stateIndex] = x; + + *pSignal = scaleValue(x, signal_e); + pSignal += inc; + } + + *pStateIndex = stateIndex; +} +/* default version */ +void CLpc_Synthesis(FIXP_DBL *signal, const int signal_size, const int signal_e, + const int inc, const FIXP_LPC *lpcCoeff_m, + const int lpcCoeff_e, const int order, FIXP_DBL *state, + int *pStateIndex) { + int i, j; + FIXP_DBL *pSignal; + int stateIndex = *pStateIndex; + + FIXP_LPC coeff[2 * LPC_MAX_ORDER]; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC)); + + FDK_ASSERT(order <= LPC_MAX_ORDER); + FDK_ASSERT(stateIndex < order); + + if (inc == -1) + pSignal = &signal[signal_size - 1]; + else + pSignal = &signal[0]; + + /* y(n) = x(n) - lpc[1]*y(n-1) - ... - lpc[order]*y(n-order) */ + + for (i = 0; i < signal_size; i++) { + FIXP_DBL x; + const FIXP_LPC *pCoeff = coeff + order - stateIndex; + + x = scaleValue(*pSignal, -(lpcCoeff_e + 1)); + for (j = 0; j < order; j++) { + x -= fMultDiv2(state[j], pCoeff[j]); + } + x = SATURATE_SHIFT(x, -lpcCoeff_e - 1, DFRACT_BITS); + + /* Update states */ + stateIndex = ((stateIndex - 1) < 0) ? (order - 1) : (stateIndex - 1); + state[stateIndex] = x; + + *pSignal = scaleValue(x, signal_e); + pSignal += inc; + } + + *pStateIndex = stateIndex; +} + +/* FIR */ +void CLpc_Analysis(FIXP_DBL *RESTRICT signal, const int signal_size, + const FIXP_LPC lpcCoeff_m[], const int lpcCoeff_e, + const int order, FIXP_DBL *RESTRICT filtState, + int *filtStateIndex) { + int stateIndex; + INT i, j, shift = lpcCoeff_e + 1; /* +1, because fMultDiv2 */ + FIXP_DBL tmp; + + if (order <= 0) { + return; + } + if (filtStateIndex != NULL) { + stateIndex = *filtStateIndex; + } else { + stateIndex = 0; + } + + /* keep filter coefficients twice and save memory copy operation in + modulo state buffer */ + FIXP_LPC coeff[2 * LPC_MAX_ORDER]; + FIXP_LPC *pCoeff; + FDKmemcpy(&coeff[0], lpcCoeff_m, order * sizeof(FIXP_LPC)); + FDKmemcpy(&coeff[order], lpcCoeff_m, order * sizeof(FIXP_LPC)); + + /* + # Analysis filter, obtain residual. + for k = 0:BL-1 + err(i-BL+k) = a * inputSignal(i-BL+k:-1:i-BL-M+k); + endfor + */ + + FDK_ASSERT(shift >= 0); + + for (j = 0; j < signal_size; j++) { + pCoeff = &coeff[(order - stateIndex)]; + + tmp = signal[j] >> shift; + for (i = 0; i < order; i++) { + tmp = fMultAddDiv2(tmp, pCoeff[i], filtState[i]); + } + + stateIndex = + ((stateIndex - 1) < 0) ? (stateIndex - 1 + order) : (stateIndex - 1); + filtState[stateIndex] = signal[j]; + + signal[j] = tmp << shift; + } + + if (filtStateIndex != NULL) { + *filtStateIndex = stateIndex; + } +} + +/* For the LPC_SYNTHESIS_IIR version */ +INT CLpc_ParcorToLpc(const FIXP_LPC_TNS reflCoeff[], FIXP_LPC_TNS LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]) { + INT i, j; + INT shiftval, + par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */ + FIXP_DBL maxVal = (FIXP_DBL)0; + + workBuffer[0] = FX_LPC_TNS2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal; + for (i = 1; i < numOfCoeff; i++) { + for (j = 0; j < i / 2; j++) { + FIXP_DBL tmp1, tmp2; + + tmp1 = workBuffer[j]; + tmp2 = workBuffer[i - 1 - j]; + workBuffer[j] += fMult(reflCoeff[i], tmp2); + workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1); + } + if (i & 1) { + workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]); + } + + workBuffer[i] = FX_LPC_TNS2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal; + } + + /* calculate exponent */ + for (i = 0; i < numOfCoeff; i++) { + maxVal = fMax(maxVal, fAbs(workBuffer[i])); + } + + shiftval = fMin(fNorm(maxVal), par2LpcShiftVal); + + for (i = 0; i < numOfCoeff; i++) { + LpcCoeff[i] = FX_DBL2FX_LPC_TNS(workBuffer[i] << shiftval); + } + + return (par2LpcShiftVal - shiftval); +} +/* Default version */ +INT CLpc_ParcorToLpc(const FIXP_LPC reflCoeff[], FIXP_LPC LpcCoeff[], + INT numOfCoeff, FIXP_DBL workBuffer[]) { + INT i, j; + INT shiftval, + par2LpcShiftVal = 6; /* 6 should be enough, bec. max(numOfCoeff) = 20 */ + FIXP_DBL maxVal = (FIXP_DBL)0; + + workBuffer[0] = FX_LPC2FX_DBL(reflCoeff[0]) >> par2LpcShiftVal; + for (i = 1; i < numOfCoeff; i++) { + for (j = 0; j < i / 2; j++) { + FIXP_DBL tmp1, tmp2; + + tmp1 = workBuffer[j]; + tmp2 = workBuffer[i - 1 - j]; + workBuffer[j] += fMult(reflCoeff[i], tmp2); + workBuffer[i - 1 - j] += fMult(reflCoeff[i], tmp1); + } + if (i & 1) { + workBuffer[j] += fMult(reflCoeff[i], workBuffer[j]); + } + + workBuffer[i] = FX_LPC2FX_DBL(reflCoeff[i]) >> par2LpcShiftVal; + } + + /* calculate exponent */ + for (i = 0; i < numOfCoeff; i++) { + maxVal = fMax(maxVal, fAbs(workBuffer[i])); + } + + shiftval = fMin(fNorm(maxVal), par2LpcShiftVal); + + for (i = 0; i < numOfCoeff; i++) { + LpcCoeff[i] = FX_DBL2FX_LPC(workBuffer[i] << shiftval); + } + + return (par2LpcShiftVal - shiftval); +} + +void CLpc_AutoToParcor(FIXP_DBL acorr[], const int acorr_e, + FIXP_LPC reflCoeff[], const int numOfCoeff, + FIXP_DBL *pPredictionGain_m, INT *pPredictionGain_e) { + INT i, j, scale = 0; + FIXP_DBL parcorWorkBuffer[LPC_MAX_ORDER]; + + FIXP_DBL *workBuffer = parcorWorkBuffer; + FIXP_DBL autoCorr_0 = acorr[0]; + + FDKmemclear(reflCoeff, numOfCoeff * sizeof(FIXP_LPC)); + + if (autoCorr_0 == FL2FXCONST_DBL(0.0)) { + if (pPredictionGain_m != NULL) { + *pPredictionGain_m = FL2FXCONST_DBL(0.5f); + *pPredictionGain_e = 1; + } + return; + } + + FDKmemcpy(workBuffer, acorr + 1, numOfCoeff * sizeof(FIXP_DBL)); + for (i = 0; i < numOfCoeff; i++) { + LONG sign = ((LONG)workBuffer[0] >> (DFRACT_BITS - 1)); + FIXP_DBL tmp = (FIXP_DBL)((LONG)workBuffer[0] ^ sign); + + /* Check preconditions for division function: num<=denum */ + /* For 1st iteration acorr[0] cannot be 0, it is checked before loop */ + /* Due to exor operation with "sign", num(=tmp) is greater/equal 0 */ + if (acorr[0] < tmp) break; + + /* tmp = div(num, denum, 16) */ + tmp = (FIXP_DBL)((LONG)schur_div(tmp, acorr[0], FRACT_BITS) ^ (~sign)); + + reflCoeff[i] = FX_DBL2FX_LPC(tmp); + + for (j = numOfCoeff - i - 1; j >= 0; j--) { + FIXP_DBL accu1 = fMult(tmp, acorr[j]); + FIXP_DBL accu2 = fMult(tmp, workBuffer[j]); + workBuffer[j] += accu1; + acorr[j] += accu2; + } + /* Check preconditions for division function: denum (=acorr[0]) > 0 */ + if (acorr[0] == (FIXP_DBL)0) break; + + workBuffer++; + } + + if (pPredictionGain_m != NULL) { + if (acorr[0] > (FIXP_DBL)0) { + /* prediction gain = signal power / error (residual) power */ + *pPredictionGain_m = fDivNormSigned(autoCorr_0, acorr[0], &scale); + *pPredictionGain_e = scale; + } else { + *pPredictionGain_m = (FIXP_DBL)0; + *pPredictionGain_e = 0; + } + } +} diff --git a/fdk-aac/libFDK/src/FDK_matrixCalloc.cpp b/fdk-aac/libFDK/src/FDK_matrixCalloc.cpp new file mode 100644 index 0000000..5d5c521 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_matrixCalloc.cpp @@ -0,0 +1,315 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: matrix memory allocation + +*******************************************************************************/ + +#include "FDK_matrixCalloc.h" + +#include "genericStds.h" + +void *fdkCallocMatrix1D_aligned(UINT dim1, UINT size) { + return FDKaalloc(dim1 * size, ALIGNMENT_DEFAULT); +} + +void *fdkCallocMatrix1D_int(UINT dim, UINT size, MEMORY_SECTION s) { + return FDKcalloc_L(dim, size, s); +} + +void *fdkCallocMatrix1D_int_aligned(UINT dim, UINT size, MEMORY_SECTION s) { + return FDKaalloc_L(dim * size, ALIGNMENT_DEFAULT, s); +} + +void fdkFreeMatrix1D(void *p) { + if (p != NULL) { + FDKfree_L(p); + } +} + +void fdkFreeMatrix1D_aligned(void *p) { + if (p != NULL) { + FDKafree_L(p); + } +} + +void *fdkCallocMatrix1D(UINT dim1, UINT size) { return FDKcalloc(dim1, size); } + +/* 2D */ +void **fdkCallocMatrix2D(UINT dim1, UINT dim2, UINT size) { + void **p1; + UINT i; + char *p2; + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D(dim1, sizeof(void *))) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D(dim1 * dim2, size)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void **fdkCallocMatrix2D_aligned(UINT dim1, UINT dim2, UINT size) { + void **p1; + UINT i; + char *p2; + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D(dim1, sizeof(void *))) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_aligned(dim1 * dim2, size)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void fdkFreeMatrix2D(void **p) { + if (!p) return; + fdkFreeMatrix1D(p[0]); + fdkFreeMatrix1D(p); +} + +void fdkFreeMatrix2D_aligned(void **p) { + if (!p) return; + fdkFreeMatrix1D_aligned(p[0]); + fdkFreeMatrix1D(p); +} + +void **fdkCallocMatrix2D_int(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s) { + void **p1; + UINT i; + char *p2; + + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D_int(dim1, sizeof(void *), s)) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_int(dim1 * dim2, size, s)) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +void **fdkCallocMatrix2D_int_aligned(UINT dim1, UINT dim2, UINT size, + MEMORY_SECTION s) { + void **p1; + UINT i; + char *p2; + + if (!dim1 || !dim2) return NULL; + if ((p1 = (void **)fdkCallocMatrix1D_int(dim1, sizeof(void *), s)) == NULL) { + goto bail; + } + if ((p2 = (char *)fdkCallocMatrix1D_int_aligned(dim1 * dim2, size, s)) == + NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + p2 += dim2 * size; + } +bail: + return p1; +} + +/* 3D */ +void ***fdkCallocMatrix3D(UINT dim1, UINT dim2, UINT dim3, UINT size) { + void ***p1; + UINT i, j; + void **p2; + char *p3; + + if (!dim1 || !dim2 || !dim3) return NULL; + if ((p1 = (void ***)fdkCallocMatrix1D(dim1, sizeof(void **))) == NULL) { + goto bail; + } + if ((p2 = (void **)fdkCallocMatrix1D(dim1 * dim2, sizeof(void *))) == NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + p1[0] = p2; + if ((p3 = (char *)fdkCallocMatrix1D(dim1 * dim2 * dim3, size)) == NULL) { + fdkFreeMatrix1D(p1); + fdkFreeMatrix1D(p2); + p1 = NULL; + p2 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + for (j = 0; j < dim2; j++) { + p2[j] = p3; + p3 += dim3 * size; + } + p2 += dim2; + } +bail: + return p1; +} + +void fdkFreeMatrix3D(void ***p) { + if (!p) return; + if (p[0] != NULL) fdkFreeMatrix1D(p[0][0]); + fdkFreeMatrix1D(p[0]); + fdkFreeMatrix1D(p); +} + +void ***fdkCallocMatrix3D_int(UINT dim1, UINT dim2, UINT dim3, UINT size, + MEMORY_SECTION s) { + void ***p1; + UINT i, j; + void **p2; + char *p3; + + if (!dim1 || !dim2 || !dim3) return NULL; + if ((p1 = (void ***)fdkCallocMatrix1D_int(dim1, sizeof(void **), s)) == + NULL) { + goto bail; + } + if ((p2 = (void **)fdkCallocMatrix1D_int(dim1 * dim2, sizeof(void *), s)) == + NULL) { + fdkFreeMatrix1D(p1); + p1 = NULL; + goto bail; + } + p1[0] = p2; + if ((p3 = (char *)fdkCallocMatrix1D_int(dim1 * dim2 * dim3, size, s)) == + NULL) { + fdkFreeMatrix1D(p1); + fdkFreeMatrix1D(p2); + p1 = NULL; + p2 = NULL; + goto bail; + } + for (i = 0; i < dim1; i++) { + p1[i] = p2; + for (j = 0; j < dim2; j++) { + p2[j] = p3; + p3 += dim3 * size; + } + p2 += dim2; + } +bail: + return p1; +} diff --git a/fdk-aac/libFDK/src/FDK_qmf_domain.cpp b/fdk-aac/libFDK/src/FDK_qmf_domain.cpp new file mode 100644 index 0000000..3245deb --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_qmf_domain.cpp @@ -0,0 +1,1018 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Matthias Hildenbrand + + Description: Module to efficiently handle QMF data for multiple channels and + to share the data between e.g. SBR and MPS + +*******************************************************************************/ + +#include "FDK_qmf_domain.h" + +#include "common_fix.h" + +#define WORKBUFFER1_TAG 0 +#define WORKBUFFER2_TAG 1 + +#define WORKBUFFER3_TAG 4 +#define WORKBUFFER4_TAG 5 +#define WORKBUFFER5_TAG 6 +#define WORKBUFFER6_TAG 7 + +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore1, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L1, WORKBUFFER1_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore2, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER2_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore3, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER3_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore4, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER4_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore5, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER5_TAG) +C_ALLOC_MEM_OVERLAY(QmfWorkBufferCore6, FIXP_DBL, QMF_WB_SECTION_SIZE, + SECT_DATA_L2, WORKBUFFER6_TAG) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(AnaQmfStates, FIXP_QAS, 10 * QMF_DOMAIN_MAX_ANALYSIS_QMF_BANDS, + ((8) + (1))) + +/*! Synthesis states buffer.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(SynQmfStates, FIXP_QSS, 9 * QMF_DOMAIN_MAX_SYNTHESIS_QMF_BANDS, + ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal, FIXP_DBL *, + QMF_DOMAIN_MAX_TIMESLOTS + QMF_DOMAIN_MAX_OV_TIMESLOTS, + ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag, FIXP_DBL *, + QMF_DOMAIN_MAX_TIMESLOTS + QMF_DOMAIN_MAX_OV_TIMESLOTS, + ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer, FIXP_DBL, + 2 * QMF_DOMAIN_MAX_OV_TIMESLOTS * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(AnaQmfStates16, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_16, + ((8) + (1))) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(AnaQmfStates24, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_24, + ((8) + (1))) + +/*! Analysis states buffer.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(AnaQmfStates32, FIXP_QAS, 10 * QMF_DOMAIN_ANALYSIS_QMF_BANDS_32, + ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal16, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_16 + QMF_DOMAIN_OV_TIMESLOTS_16, ((8) + (1))) + +/*! Pointer to real qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsReal32, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_32 + QMF_DOMAIN_OV_TIMESLOTS_32, ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag16, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_16 + QMF_DOMAIN_OV_TIMESLOTS_16, ((8) + (1))) + +/*! Pointer to imaginary qmf data for each time slot.
+ Dimension: #((8) + (1)) */ +C_ALLOC_MEM2(QmfSlotsImag32, FIXP_DBL *, + QMF_DOMAIN_TIMESLOTS_32 + QMF_DOMAIN_OV_TIMESLOTS_32, ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer16, FIXP_DBL, + 2 * QMF_DOMAIN_OV_TIMESLOTS_16 * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +/*! QMF overlap buffer.
+ Dimension: #((8) + (1)) */ +C_AALLOC_MEM2(QmfOverlapBuffer32, FIXP_DBL, + 2 * QMF_DOMAIN_OV_TIMESLOTS_32 * QMF_DOMAIN_MAX_QMF_PROC_BANDS, + ((8) + (1))) + +static int FDK_QmfDomain_FreePersistentMemory(HANDLE_FDK_QMF_DOMAIN qd) { + int err = 0; + int ch; + + for (ch = 0; ch < ((8) + (1)); ch++) { + if (qd->QmfDomainIn[ch].pAnaQmfStates) { + if (qd->globalConf.nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_16) { + FreeAnaQmfStates16(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else if (qd->globalConf.nBandsAnalysis == + QMF_DOMAIN_ANALYSIS_QMF_BANDS_24) { + FreeAnaQmfStates24(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else if (qd->globalConf.nBandsAnalysis == + QMF_DOMAIN_ANALYSIS_QMF_BANDS_32) { + FreeAnaQmfStates32(&qd->QmfDomainIn[ch].pAnaQmfStates); + } else { + FreeAnaQmfStates(&qd->QmfDomainIn[ch].pAnaQmfStates); + } + } + + if (qd->QmfDomainIn[ch].pOverlapBuffer) { + if (qd->globalConf.nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_16) { + FreeQmfOverlapBuffer16(&qd->QmfDomainIn[ch].pOverlapBuffer); + } else if (qd->globalConf.nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_32) { + FreeQmfOverlapBuffer32(&qd->QmfDomainIn[ch].pOverlapBuffer); + } else { + FreeQmfOverlapBuffer(&qd->QmfDomainIn[ch].pOverlapBuffer); + } + } + + if (qd->QmfDomainIn[ch].hQmfSlotsReal) { + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + FreeQmfSlotsReal16(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } else if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + FreeQmfSlotsReal32(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } else { + FreeQmfSlotsReal(&qd->QmfDomainIn[ch].hQmfSlotsReal); + } + } + + if (qd->QmfDomainIn[ch].hQmfSlotsImag) { + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + FreeQmfSlotsImag16(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } + if (qd->globalConf.nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + FreeQmfSlotsImag32(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } else { + FreeQmfSlotsImag(&qd->QmfDomainIn[ch].hQmfSlotsImag); + } + } + } + + for (ch = 0; ch < ((8) + (1)); ch++) { + if (qd->QmfDomainOut[ch].pSynQmfStates) { + FreeSynQmfStates(&qd->QmfDomainOut[ch].pSynQmfStates); + } + } + + return err; +} + +static int FDK_QmfDomain_AllocatePersistentMemory(HANDLE_FDK_QMF_DOMAIN qd) { + int err = 0; + int ch; + HANDLE_FDK_QMF_DOMAIN_GC gc = &qd->globalConf; + + if ((gc->nInputChannels > ((8) + (1))) || (gc->nOutputChannels > ((8) + (1)))) + return err = 1; + for (ch = 0; ch < gc->nInputChannels; ch++) { + int size; + + size = gc->nBandsAnalysis * 10; + if (size > 0) { + if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_16) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates16(ch))) + goto bail; + } + } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_24) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates24(ch))) + goto bail; + } + } else if (gc->nBandsAnalysis == QMF_DOMAIN_ANALYSIS_QMF_BANDS_32) { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].pAnaQmfStates == NULL) { + if (NULL == (qd->QmfDomainIn[ch].pAnaQmfStates = GetAnaQmfStates(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].pAnaQmfStates = NULL; + } + + size = gc->nQmfOvTimeSlots + gc->nQmfTimeSlots; + if (size > 0) { + if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_16) { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal16(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag16(ch))) + goto bail; + } + } else if (gc->nQmfTimeSlots == QMF_DOMAIN_TIMESLOTS_32) { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal32(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].hQmfSlotsReal == NULL) { + if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsReal = GetQmfSlotsReal(ch))) + goto bail; + } + if (qd->QmfDomainIn[ch].hQmfSlotsImag == NULL) { + if (NULL == (qd->QmfDomainIn[ch].hQmfSlotsImag = GetQmfSlotsImag(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].hQmfSlotsReal = NULL; + qd->QmfDomainIn[ch].hQmfSlotsImag = NULL; + } + + size = gc->nQmfOvTimeSlots * gc->nQmfProcBands * CMPLX_MOD; + if (size > 0) { + if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_16) { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer16(ch))) + goto bail; + } + } else if (gc->nQmfOvTimeSlots == QMF_DOMAIN_OV_TIMESLOTS_32) { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer32(ch))) + goto bail; + } + } else { + if (qd->QmfDomainIn[ch].pOverlapBuffer == NULL) { + if (NULL == + (qd->QmfDomainIn[ch].pOverlapBuffer = GetQmfOverlapBuffer(ch))) + goto bail; + } + } + } else { + qd->QmfDomainIn[ch].pOverlapBuffer = NULL; + } + } + + for (ch = 0; ch < gc->nOutputChannels; ch++) { + int size = gc->nBandsSynthesis * 9; + if (size > 0) { + if (qd->QmfDomainOut[ch].pSynQmfStates == NULL) { + if (NULL == (qd->QmfDomainOut[ch].pSynQmfStates = GetSynQmfStates(ch))) + goto bail; + } + } else { + qd->QmfDomainOut[ch].pSynQmfStates = NULL; + } + } + + return err; + +bail: + FDK_QmfDomain_FreePersistentMemory(qd); + return -1; +} + +QMF_DOMAIN_ERROR FDK_QmfDomain_ClearPersistentMemory( + HANDLE_FDK_QMF_DOMAIN hqd) { + QMF_DOMAIN_ERROR err = QMF_DOMAIN_OK; + int ch, size; + if (hqd) { + HANDLE_FDK_QMF_DOMAIN_GC gc = &hqd->globalConf; + + size = gc->nQmfOvTimeSlots * gc->nQmfProcBands * CMPLX_MOD; + for (ch = 0; ch < gc->nInputChannels; ch++) { + if (hqd->QmfDomainIn[ch].pOverlapBuffer) { + FDKmemclear(hqd->QmfDomainIn[ch].pOverlapBuffer, + size * sizeof(FIXP_DBL)); + } + } + if (FDK_QmfDomain_InitFilterBank(hqd, 0)) { + err = QMF_DOMAIN_INIT_ERROR; + } + } else { + err = QMF_DOMAIN_INIT_ERROR; + } + return err; +} + +/* + FDK_getWorkBuffer + + Parameters: + + pWorkBuffer i: array of pointers which point to different workbuffer + sections workBufferOffset i: offset in the workbuffer to the requested + memory memSize i: size of requested memory + + Function: + + The functions returns the address to the requested memory in the workbuffer. + + The overall workbuffer is divided into several sections. There are + QMF_MAX_WB_SECTIONS sections of size QMF_WB_SECTION_SIZE. The function + selects the workbuffer section with the help of the workBufferOffset and than + it verifies whether the requested amount of memory fits into the selected + workbuffer section. + + Returns: + + address to workbuffer +*/ +static FIXP_DBL *FDK_getWorkBuffer(FIXP_DBL **pWorkBuffer, + USHORT workBufferOffset, + USHORT workBufferSectSize, USHORT memSize) { + int idx1; + int idx2; + FIXP_DBL *pwb; + + /* a section must be a multiple of the number of processing bands (currently + * always 64) */ + FDK_ASSERT((workBufferSectSize % 64) == 0); + + /* calculate offset within the section */ + idx2 = workBufferOffset % workBufferSectSize; + /* calculate section number */ + idx1 = (workBufferOffset - idx2) / workBufferSectSize; + /* maximum sectionnumber is QMF_MAX_WB_SECTIONS */ + FDK_ASSERT(idx1 < QMF_MAX_WB_SECTIONS); + + /* check, whether workbuffer is available */ + FDK_ASSERT(pWorkBuffer[idx1] != NULL); + + /* check, whether buffer fits into selected section */ + FDK_ASSERT((idx2 + memSize) <= workBufferSectSize); + + /* get requested address to workbuffer */ + pwb = &pWorkBuffer[idx1][idx2]; + + return pwb; +} + +static int FDK_QmfDomain_FeedWorkBuffer(HANDLE_FDK_QMF_DOMAIN qd, int ch, + FIXP_DBL **pWorkBuffer, + USHORT workBufferOffset, + USHORT workBufferSectSize, int size) { + int err = 0; + int mem_needed; + + mem_needed = qd->QmfDomainIn[ch].workBuf_nBands * + qd->QmfDomainIn[ch].workBuf_nTimeSlots * CMPLX_MOD; + if (mem_needed > size) { + return (err = 1); + } + qd->QmfDomainIn[ch].pWorkBuffer = pWorkBuffer; + qd->QmfDomainIn[ch].workBufferOffset = workBufferOffset; + qd->QmfDomainIn[ch].workBufferSectSize = workBufferSectSize; + + return err; +} + +int FDK_QmfDomain_IsInitialized(const HANDLE_FDK_QMF_DOMAIN qd) { + FDK_ASSERT(qd != NULL); + return ((qd->QmfDomainIn[0].pAnaQmfStates == NULL) && + (qd->QmfDomainOut[0].pSynQmfStates == NULL)) + ? 0 + : 1; +} + +int FDK_QmfDomain_InitFilterBank(HANDLE_FDK_QMF_DOMAIN qd, UINT extra_flags) { + FDK_ASSERT(qd != NULL); + int err = 0; + int ch, ts; + HANDLE_FDK_QMF_DOMAIN_GC gc = &qd->globalConf; + int noCols = gc->nQmfTimeSlots; + int lsb = gc->nBandsAnalysis; + int usb = fMin((INT)gc->nBandsSynthesis, 64); + int nProcBands = gc->nQmfProcBands; + FDK_ASSERT(nProcBands % ALIGNMENT_DEFAULT == 0); + + if (extra_flags & QMF_FLAG_MPSLDFB) { + gc->flags &= ~QMF_FLAG_CLDFB; + gc->flags |= QMF_FLAG_MPSLDFB; + } + for (ch = 0; ch < gc->nInputChannels; ch++) { + /* distribute memory to slots array */ + FIXP_DBL *ptrOv = + qd->QmfDomainIn[ch].pOverlapBuffer; /* persistent memory for overlap */ + if ((ptrOv == NULL) && (gc->nQmfOvTimeSlots != 0)) { + err = 1; + return err; + } + /* This assumes the workbuffer defined for ch0 is the big one being used to + * hold one full frame of QMF data. */ + FIXP_DBL **ptr = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .pWorkBuffer; /* non-persistent workbuffer */ + USHORT workBufferOffset = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .workBufferOffset; + USHORT workBufferSectSize = + qd->QmfDomainIn[fMin(ch, fMax((INT)gc->nQmfProcChannels - 1, 0))] + .workBufferSectSize; + + if ((ptr == NULL) && (gc->nQmfTimeSlots != 0)) { + err = 1; + return err; + } + + qd->QmfDomainIn[ch].pGlobalConf = gc; + for (ts = 0; ts < gc->nQmfOvTimeSlots; ts++) { + qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = ptrOv; + ptrOv += nProcBands; + qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = ptrOv; + ptrOv += nProcBands; + } + for (; ts < (gc->nQmfOvTimeSlots + gc->nQmfTimeSlots); ts++) { + qd->QmfDomainIn[ch].hQmfSlotsReal[ts] = FDK_getWorkBuffer( + ptr, workBufferOffset, workBufferSectSize, nProcBands); + workBufferOffset += nProcBands; + qd->QmfDomainIn[ch].hQmfSlotsImag[ts] = FDK_getWorkBuffer( + ptr, workBufferOffset, workBufferSectSize, nProcBands); + workBufferOffset += nProcBands; + } + err |= qmfInitAnalysisFilterBank( + &qd->QmfDomainIn[ch].fb, qd->QmfDomainIn[ch].pAnaQmfStates, noCols, + (qd->QmfDomainIn[ch].fb.lsb == 0) ? lsb : qd->QmfDomainIn[ch].fb.lsb, + (qd->QmfDomainIn[ch].fb.usb == 0) ? usb : qd->QmfDomainIn[ch].fb.usb, + gc->nBandsAnalysis, gc->flags | extra_flags); + } + + for (ch = 0; ch < gc->nOutputChannels; ch++) { + FIXP_DBL outGain_m = qd->QmfDomainOut[ch].fb.outGain_m; + int outGain_e = qd->QmfDomainOut[ch].fb.outGain_e; + int outScale = qmfGetOutScalefactor(&qd->QmfDomainOut[ch].fb); + err |= qmfInitSynthesisFilterBank( + &qd->QmfDomainOut[ch].fb, qd->QmfDomainOut[ch].pSynQmfStates, noCols, + (qd->QmfDomainOut[ch].fb.lsb == 0) ? lsb : qd->QmfDomainOut[ch].fb.lsb, + (qd->QmfDomainOut[ch].fb.usb == 0) ? usb : qd->QmfDomainOut[ch].fb.usb, + gc->nBandsSynthesis, gc->flags | extra_flags); + if (outGain_m != (FIXP_DBL)0) { + qmfChangeOutGain(&qd->QmfDomainOut[ch].fb, outGain_m, outGain_e); + } + if (outScale) { + qmfChangeOutScalefactor(&qd->QmfDomainOut[ch].fb, outScale); + } + } + + return err; +} + +void FDK_QmfDomain_SaveOverlap(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, int offset) { + FDK_ASSERT(qd_ch != NULL); + int ts; + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + int ovSlots = gc->nQmfOvTimeSlots; + int nCols = gc->nQmfTimeSlots; + int nProcBands = gc->nQmfProcBands; + FIXP_DBL **qmfReal = qd_ch->hQmfSlotsReal; + FIXP_DBL **qmfImag = qd_ch->hQmfSlotsImag; + QMF_SCALE_FACTOR *pScaling = &qd_ch->scaling; + + /* for high part it would be enough to save only used part of overlap area */ + if (qmfImag != NULL) { + for (ts = offset; ts < ovSlots; ts++) { + FDKmemcpy(qmfReal[ts], qmfReal[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + FDKmemcpy(qmfImag[ts], qmfImag[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + } + } else { + for (ts = 0; ts < ovSlots; ts++) { + FDKmemcpy(qmfReal[ts], qmfReal[nCols + ts], + sizeof(FIXP_DBL) * nProcBands); + } + } + pScaling->ov_lb_scale = pScaling->lb_scale; +} + + /* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15 - (s)) +#define EXP2SCALE(e) (15 - (e)) + +void FDK_QmfDomain_GetSlot(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, const int ts, + const int start_band, const int stop_band, + FIXP_DBL *pQmfOutReal, FIXP_DBL *pQmfOutImag, + const int exp_out) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(pQmfOutReal != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + const FIXP_DBL *real = qd_ch->hQmfSlotsReal[ts]; + const FIXP_DBL *imag = qd_ch->hQmfSlotsImag[ts]; + const int ovSlots = gc->nQmfOvTimeSlots; + const int exp_lb = SCALE2EXP((ts < ovSlots) ? qd_ch->scaling.ov_lb_scale + : qd_ch->scaling.lb_scale); + const int exp_hb = SCALE2EXP(qd_ch->scaling.hb_scale); + const int lsb = qd_ch->fb.lsb; + const int usb = qd_ch->fb.usb; + int b = start_band; + int lb_sf, hb_sf; + + int target_exp = + ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + qd_ch->fb.filterScale; + + FDK_ASSERT(ts < (gc->nQmfTimeSlots + gc->nQmfOvTimeSlots)); + FDK_ASSERT(start_band >= 0); + FDK_ASSERT(stop_band <= gc->nQmfProcBands); + + if (qd_ch->fb.no_channels == 24) { + target_exp -= 1; + } + + /* Limit scaling factors to maximum negative value to avoid faulty behaviour + due to right-shifts. Corresponding asserts were observed during robustness + testing. + */ + lb_sf = fMax(exp_lb - target_exp - exp_out, -31); + FDK_ASSERT(lb_sf < 32); + hb_sf = fMax(exp_hb - target_exp - exp_out, -31); + FDK_ASSERT(hb_sf < 32); + + if (pQmfOutImag == NULL) { + for (; b < fMin(lsb, stop_band); b++) { + pQmfOutReal[b] = scaleValue(real[b], lb_sf); + } + for (; b < fMin(usb, stop_band); b++) { + pQmfOutReal[b] = scaleValue(real[b], hb_sf); + } + for (; b < stop_band; b++) { + pQmfOutReal[b] = (FIXP_DBL)0; + } + } else { + FDK_ASSERT(imag != NULL); + for (; b < fMin(lsb, stop_band); b++) { + pQmfOutReal[b] = scaleValue(real[b], lb_sf); + pQmfOutImag[b] = scaleValue(imag[b], lb_sf); + } + for (; b < fMin(usb, stop_band); b++) { + pQmfOutReal[b] = scaleValue(real[b], hb_sf); + pQmfOutImag[b] = scaleValue(imag[b], hb_sf); + } + for (; b < stop_band; b++) { + pQmfOutReal[b] = (FIXP_DBL)0; + pQmfOutImag[b] = (FIXP_DBL)0; + } + } +} + +void FDK_QmfDomain_GetWorkBuffer(const HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + const int ts, FIXP_DBL **ppQmfReal, + FIXP_DBL **ppQmfImag) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(ppQmfReal != NULL); + FDK_ASSERT(ppQmfImag != NULL); + const int bands = qd_ch->workBuf_nBands; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + FDK_ASSERT(bands > 0); + FDK_ASSERT(ts < qd_ch->workBuf_nTimeSlots); + + *ppQmfReal = FDK_getWorkBuffer( + pWorkBuf, workBufferOffset + (ts * CMPLX_MOD + 0) * bands, + workBufferSectSize, bands); + *ppQmfImag = FDK_getWorkBuffer( + pWorkBuf, workBufferOffset + (ts * CMPLX_MOD + 1) * bands, + workBufferSectSize, bands); +} + +void FDK_QmfDomain_WorkBuffer2ProcChannel( + const HANDLE_FDK_QMF_DOMAIN_IN qd_ch) { + FDK_ASSERT(qd_ch != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + if (FDK_getWorkBuffer(pWorkBuf, workBufferOffset, workBufferSectSize, + qd_ch->workBuf_nBands) == + qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots]) { + /* work buffer is part of processing channel => nothing to do */ + return; + } else { + /* copy parked new QMF data to processing channel */ + const int bands = qd_ch->workBuf_nBands; + const int slots = qd_ch->workBuf_nTimeSlots; + int ts; + for (ts = 0; ts < slots; ts++) { + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); // parkBuf_to_anaMatrix + workBufferOffset += bands; + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); + workBufferOffset += bands; + } + } +} + +void FDK_QmfDomain_QmfData2HBE(HANDLE_FDK_QMF_DOMAIN_IN qd_ch, + FIXP_DBL **ppQmfReal, FIXP_DBL **ppQmfImag) { + FDK_ASSERT(qd_ch != NULL); + FDK_ASSERT(ppQmfReal != NULL); + FDK_ASSERT(ppQmfImag != NULL); + HANDLE_FDK_QMF_DOMAIN_GC gc = qd_ch->pGlobalConf; + FIXP_DBL **pWorkBuf = qd_ch->pWorkBuffer; + USHORT workBufferOffset = qd_ch->workBufferOffset; + USHORT workBufferSectSize = qd_ch->workBufferSectSize; + + if (FDK_getWorkBuffer(pWorkBuf, workBufferOffset, workBufferSectSize, + qd_ch->workBuf_nBands) == + qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots]) { // left channel (anaMatrix) + int ts; + const int bands = gc->nBandsAnalysis; + const int slots = qd_ch->workBuf_nTimeSlots; + FDK_ASSERT(bands <= 64); + for (ts = 0; ts < slots; ts++) { + /* copy current data of processing channel */ + FIXP_DBL tmp[64]; // one slot + /* real */ + FDKmemcpy(tmp, qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], + sizeof(FIXP_DBL) * bands); // anaMatrix_to_tmp + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], ppQmfReal[ts], + sizeof(FIXP_DBL) * bands); // HBE_to_anaMatrix + FDKmemcpy(ppQmfReal[ts], tmp, sizeof(FIXP_DBL) * bands); // tmp_to_HBE + /* imag */ + FDKmemcpy(tmp, qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], + sizeof(FIXP_DBL) * bands); + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], ppQmfImag[ts], + sizeof(FIXP_DBL) * bands); + FDKmemcpy(ppQmfImag[ts], tmp, sizeof(FIXP_DBL) * bands); + } + } else { // right channel (parkBuf) + const int bands = qd_ch->workBuf_nBands; + const int slots = qd_ch->workBuf_nTimeSlots; + int ts; + FDK_ASSERT(qd_ch->workBuf_nBands == gc->nBandsAnalysis); + for (ts = 0; ts < slots; ts++) { + /* copy HBE QMF data buffer to processing channel */ + FDKmemcpy(qd_ch->hQmfSlotsReal[gc->nQmfOvTimeSlots + ts], ppQmfReal[ts], + sizeof(FIXP_DBL) * bands); // HBE_to_anaMatrix + FDKmemcpy(qd_ch->hQmfSlotsImag[gc->nQmfOvTimeSlots + ts], ppQmfImag[ts], + sizeof(FIXP_DBL) * bands); + /* copy parked new QMF data to HBE QMF data buffer */ + FDKmemcpy(ppQmfReal[ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); // parkBuf_to_HBE + workBufferOffset += bands; + FDKmemcpy(ppQmfImag[ts], + FDK_getWorkBuffer(pWorkBuf, workBufferOffset, + workBufferSectSize, bands), + sizeof(FIXP_DBL) * bands); + workBufferOffset += bands; + } + } +} + +void FDK_QmfDomain_ClearRequested(HANDLE_FDK_QMF_DOMAIN_GC hgc) { + hgc->qmfDomainExplicitConfig = 0; + hgc->flags_requested = 0; + hgc->nInputChannels_requested = 0; + hgc->nOutputChannels_requested = 0; + hgc->parkChannel_requested = 0; + hgc->nBandsAnalysis_requested = 0; + hgc->nBandsSynthesis_requested = 0; + hgc->nQmfTimeSlots_requested = 0; + hgc->nQmfOvTimeSlots_requested = 0; + hgc->nQmfProcBands_requested = 0; + hgc->nQmfProcChannels_requested = 0; +} + +static void FDK_QmfDomain_ClearConfigured(HANDLE_FDK_QMF_DOMAIN_GC hgc) { + hgc->flags = 0; + hgc->nInputChannels = 0; + hgc->nOutputChannels = 0; + hgc->parkChannel = 0; + hgc->nBandsAnalysis = 0; + hgc->nBandsSynthesis = 0; + hgc->nQmfTimeSlots = 0; + hgc->nQmfOvTimeSlots = 0; + hgc->nQmfProcBands = 0; + hgc->nQmfProcChannels = 0; +} + +static void FDK_QmfDomain_ClearFilterBank(HANDLE_FDK_QMF_DOMAIN hqd) { + int ch; + + for (ch = 0; ch < ((8) + (1)); ch++) { + FDKmemclear(&hqd->QmfDomainIn[ch].fb, sizeof(hqd->QmfDomainIn[ch].fb)); + } + + for (ch = 0; ch < ((8) + (1)); ch++) { + FDKmemclear(&hqd->QmfDomainOut[ch].fb, sizeof(hqd->QmfDomainIn[ch].fb)); + } +} + +QMF_DOMAIN_ERROR FDK_QmfDomain_Configure(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_ASSERT(hqd != NULL); + QMF_DOMAIN_ERROR err = QMF_DOMAIN_OK; + int i, size_main, size, size_temp = 0; + + HANDLE_FDK_QMF_DOMAIN_GC hgc = &hqd->globalConf; + FIXP_DBL **pWorkBuffer = hgc->pWorkBuffer; + + int hasChanged = 0; + + if ((hgc->nQmfProcChannels_requested > 0) && + (hgc->nQmfProcBands_requested != 64)) { + return QMF_DOMAIN_INIT_ERROR; + } + if (hgc->nBandsAnalysis_requested > hgc->nQmfProcBands_requested) { + /* In general the output of the qmf analysis is written to QMF memory slots + which size is defined by nQmfProcBands. nBandsSynthesis may be larger + than nQmfProcBands. This is e.g. the case if the QMF based resampler is + used. + */ + return QMF_DOMAIN_INIT_ERROR; + } + + /* 1. adjust change of processing channels by comparison of current and + * requested parameters */ + if ((hgc->nQmfProcChannels != hgc->nQmfProcChannels_requested) || + (hgc->nQmfProcBands != hgc->nQmfProcBands_requested) || + (hgc->nQmfTimeSlots != hgc->nQmfTimeSlots_requested)) { + for (i = 0; i < hgc->nQmfProcChannels_requested; i++) { + hqd->QmfDomainIn[i].workBuf_nBands = hgc->nQmfProcBands_requested; + hgc->nQmfProcBands = hgc->nQmfProcBands_requested; + + hqd->QmfDomainIn[i].workBuf_nTimeSlots = hgc->nQmfTimeSlots_requested; + } + + hgc->nQmfProcChannels = + hgc->nQmfProcChannels_requested; /* keep highest value encountered so + far as allocated */ + + hasChanged = 1; + } + + /* 2. reallocate persistent memory if necessary (analysis state-buffers, + * timeslot-pointer-array, overlap-buffers, synthesis state-buffers) */ + if ((hgc->nInputChannels != hgc->nInputChannels_requested) || + (hgc->nBandsAnalysis != hgc->nBandsAnalysis_requested) || + (hgc->nQmfTimeSlots != hgc->nQmfTimeSlots_requested) || + (hgc->nQmfOvTimeSlots != hgc->nQmfOvTimeSlots_requested) || + (hgc->nOutputChannels != hgc->nOutputChannels_requested) || + (hgc->nBandsSynthesis != hgc->nBandsSynthesis_requested) || + (hgc->parkChannel != hgc->parkChannel_requested)) { + hgc->nInputChannels = hgc->nInputChannels_requested; + hgc->nBandsAnalysis = hgc->nBandsAnalysis_requested; + hgc->nQmfTimeSlots = hgc->nQmfTimeSlots_requested; + hgc->nQmfOvTimeSlots = hgc->nQmfOvTimeSlots_requested; + hgc->nOutputChannels = hgc->nOutputChannels_requested; + hgc->nBandsSynthesis = hgc->nBandsSynthesis_requested; + hgc->parkChannel = hgc->parkChannel_requested; + + if (FDK_QmfDomain_AllocatePersistentMemory(hqd)) { + err = QMF_DOMAIN_OUT_OF_MEMORY; + goto bail; + } + + /* 3. set request-flag for downsampled SBR */ + if ((hgc->nBandsAnalysis == 32) && (hgc->nBandsSynthesis == 32) && + !(hgc->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + hgc->flags_requested |= QMF_FLAG_DOWNSAMPLED; + } + + hasChanged = 1; + } + + /* 4. initialize tables and buffer for QMF-resampler */ + + /* 5. set requested flags */ + if (hgc->flags != hgc->flags_requested) { + if ((hgc->flags_requested & QMF_FLAG_MPSLDFB) && + (hgc->flags_requested & QMF_FLAG_CLDFB)) { + hgc->flags_requested &= ~QMF_FLAG_CLDFB; + } + hgc->flags = hgc->flags_requested; + hasChanged = 1; + } + + if (hasChanged) { + /* 6. recalculate and check size of required workbuffer-space */ + + if (hgc->parkChannel && (hqd->globalConf.nQmfProcChannels == 1)) { + /* configure temp QMF buffer for parking right channel MPS212 output, + * (USAC stereoConfigIndex 3 only) */ + hqd->QmfDomainIn[1].workBuf_nBands = hqd->globalConf.nBandsAnalysis; + hqd->QmfDomainIn[1].workBuf_nTimeSlots = hqd->globalConf.nQmfTimeSlots; + size_temp = hqd->QmfDomainIn[1].workBuf_nBands * + hqd->QmfDomainIn[1].workBuf_nTimeSlots * CMPLX_MOD; + } + + size_main = hqd->QmfDomainIn[0].workBuf_nBands * + hqd->QmfDomainIn[0].workBuf_nTimeSlots * CMPLX_MOD; + + size = size_main * hgc->nQmfProcChannels + size_temp; + + if (size > (QMF_MAX_WB_SECTIONS * QMF_WB_SECTION_SIZE)) { + err = QMF_DOMAIN_OUT_OF_MEMORY; + goto bail; + } + + /* 7. allocate additional workbuffer if necessary */ + if ((size > 0 /* *QMF_WB_SECTION_SIZE */) && (pWorkBuffer[0] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[0] = GetQmfWorkBufferCore6(); + } + + if ((size > 1 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[1] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[1] = GetQmfWorkBufferCore1(); + } + + if ((size > 2 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[2] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[2] = GetQmfWorkBufferCore3(); + } + + if ((size > 3 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[3] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[3] = GetQmfWorkBufferCore4(); + } + + if ((size > 4 * QMF_WB_SECTION_SIZE) && (pWorkBuffer[4] == NULL)) { + /* get work buffer of size QMF_WB_SECTION_SIZE */ + pWorkBuffer[4] = GetQmfWorkBufferCore5(); + } + + /* 8. distribute workbuffer over processing channels */ + for (i = 0; i < hgc->nQmfProcChannels; i++) { + FDK_QmfDomain_FeedWorkBuffer(hqd, i, pWorkBuffer, size_main * i, + QMF_WB_SECTION_SIZE, size_main); + } + if (hgc->parkChannel) { + for (; i < hgc->nInputChannels; i++) { + FDK_QmfDomain_FeedWorkBuffer(hqd, 1, pWorkBuffer, + size_main * hgc->nQmfProcChannels, + QMF_WB_SECTION_SIZE, size_temp); + } + } + + /* 9. (re-)init filterbank */ + for (i = 0; i < hgc->nOutputChannels; i++) { + if ((hqd->QmfDomainOut[i].fb.lsb == 0) && + (hqd->QmfDomainOut[i].fb.usb == 0)) { + /* Although lsb and usb are set in the SBR module, they are initialized + * at this point due to the case of using MPS without SBR. */ + hqd->QmfDomainOut[i].fb.lsb = hgc->nBandsAnalysis_requested; + hqd->QmfDomainOut[i].fb.usb = + fMin((INT)hgc->nBandsSynthesis_requested, 64); + } + } + if (FDK_QmfDomain_InitFilterBank(hqd, 0)) { + err = QMF_DOMAIN_INIT_ERROR; + } + } + +bail: + if (err) { + FDK_QmfDomain_FreeMem(hqd); + } + return err; +} + +static void FDK_QmfDomain_FreeWorkBuffer(HANDLE_FDK_QMF_DOMAIN hqd) { + FIXP_DBL **pWorkBuffer = hqd->globalConf.pWorkBuffer; + + if (pWorkBuffer[0]) FreeQmfWorkBufferCore6(&pWorkBuffer[0]); + if (pWorkBuffer[1]) FreeQmfWorkBufferCore1(&pWorkBuffer[1]); + if (pWorkBuffer[2]) FreeQmfWorkBufferCore3(&pWorkBuffer[2]); + if (pWorkBuffer[3]) FreeQmfWorkBufferCore4(&pWorkBuffer[3]); + if (pWorkBuffer[4]) FreeQmfWorkBufferCore5(&pWorkBuffer[4]); +} + +void FDK_QmfDomain_FreeMem(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_QmfDomain_FreeWorkBuffer(hqd); + + FDK_QmfDomain_FreePersistentMemory(hqd); + + FDK_QmfDomain_ClearFilterBank(hqd); + + FDK_QmfDomain_ClearConfigured(&hqd->globalConf); + + FDK_QmfDomain_ClearRequested(&hqd->globalConf); +} + +void FDK_QmfDomain_Close(HANDLE_FDK_QMF_DOMAIN hqd) { + FDK_QmfDomain_FreeWorkBuffer(hqd); + + FDK_QmfDomain_FreePersistentMemory(hqd); +} diff --git a/fdk-aac/libFDK/src/FDK_tools_rom.cpp b/fdk-aac/libFDK/src/FDK_tools_rom.cpp new file mode 100644 index 0000000..e9e1206 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_tools_rom.cpp @@ -0,0 +1,7274 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Oliver Moser + + Description: ROM tables used by FDK tools + +*******************************************************************************/ + +#include "FDK_tools_rom.h" + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable80[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7ff9af04, 0x02835b5a), + STCP(0x7fe6bcb0, 0x05067734), STCP(0x7fc72ae2, 0x07891418), + STCP(0x7f9afcb9, 0x0a0af299), STCP(0x7f62368f, 0x0c8bd35e), + STCP(0x7f1cde01, 0x0f0b7727), STCP(0x7ecaf9e5, 0x11899ed3), + STCP(0x7e6c9251, 0x14060b68), STCP(0x7e01b096, 0x16807e15), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d06aa16, 0x1b6e7b7a), + STCP(0x7c769e18, 0x1de189a6), STCP(0x7bda497d, 0x2051a4dd), + STCP(0x7b31bbb2, 0x22be8f87), STCP(0x7a7d055b, 0x25280c5e), + STCP(0x79bc384d, 0x278dde6e), STCP(0x78ef678f, 0x29efc925), + STCP(0x7816a759, 0x2c4d9050), STCP(0x77320d0d, 0x2ea6f827), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x7545a5a0, 0x334bbcde), + STCP(0x743e0918, 0x3596a46c), STCP(0x732af3a7, 0x37dc420c), + STCP(0x720c8075, 0x3a1c5c57), STCP(0x70e2cbc6, 0x3c56ba70), + STCP(0x6fadf2fc, 0x3e8b240e), STCP(0x6e6e1492, 0x40b9617d), + STCP(0x6d23501b, 0x42e13ba4), STCP(0x6bcdc639, 0x45027c0c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6902ea1d, 0x4930590f), + STCP(0x678dde6e, 0x4b3c8c12), STCP(0x660e9a6a, 0x4d415234), + STCP(0x648543e4, 0x4f3e7875), STCP(0x62f201ac, 0x5133cc94), + STCP(0x6154fb91, 0x53211d18), STCP(0x5fae5a55, 0x55063951), + STCP(0x5dfe47ad, 0x56e2f15d), STCP(0x5c44ee40, 0x58b71632), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable384[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffb9d1, 0x00860a79), + STCP(0x7ffee744, 0x010c1460), STCP(0x7ffd885a, 0x01921d20), + STCP(0x7ffb9d15, 0x02182427), STCP(0x7ff92577, 0x029e28e2), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff2913a, 0x03aa292a), + STCP(0x7fee74a2, 0x0430238f), STCP(0x7fe9cbc0, 0x04b6195d), + STCP(0x7fe49698, 0x053c0a01), STCP(0x7fded530, 0x05c1f4e7), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd1adb9, 0x06cdb72f), + STCP(0x7fca47b9, 0x07538d6b), STCP(0x7fc25596, 0x07d95b9e), + STCP(0x7fb9d759, 0x085f2137), STCP(0x7fb0cd0a, 0x08e4dda0), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9d1461, 0x09f0389f), + STCP(0x7f92661d, 0x0a75d60e), STCP(0x7f872bf3, 0x0afb6805), + STCP(0x7f7b65ef, 0x0b80edf1), STCP(0x7f6f141f, 0x0c066740), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f54cd4f, 0x0d1131ba), + STCP(0x7f46d86c, 0x0d9681c2), STCP(0x7f3857f6, 0x0e1bc2e4), + STCP(0x7f294bfd, 0x0ea0f48c), STCP(0x7f19b491, 0x0f26162a), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7ef8e3a6, 0x103026fe), + STCP(0x7ee7aa4c, 0x10b5150f), STCP(0x7ed5e5c6, 0x1139f0cf), + STCP(0x7ec3962a, 0x11beb9aa), STCP(0x7eb0bb8a, 0x12436f10), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e896595, 0x134c9d34), + STCP(0x7e74ea6a, 0x13d114d0), STCP(0x7e5fe493, 0x145576b1), + STCP(0x7e4a5426, 0x14d9c245), STCP(0x7e34393b, 0x155df6fc), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e06644c, 0x1666198d), + STCP(0x7deeaa7a, 0x16ea0646), STCP(0x7dd6668f, 0x176dd9de), + STCP(0x7dbd98a4, 0x17f193c5), STCP(0x7da440d6, 0x1875336a), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d6ff3fe, 0x197c21ad), + STCP(0x7d54ff2e, 0x19ff6f2a), STCP(0x7d3980ec, 0x1a82a026), + STCP(0x7d1d7958, 0x1b05b40f), STCP(0x7d00e88f, 0x1b88aa55), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7cc62bdf, 0x1c8e3bbe), + STCP(0x7ca80038, 0x1d10d5c2), STCP(0x7c894bde, 0x1d934fe5), + STCP(0x7c6a0ef2, 0x1e15a99a), STCP(0x7c4a4996, 0x1e97e251), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c09261d, 0x1f9bee8a), + STCP(0x7be7c847, 0x201dc0ef), STCP(0x7bc5e290, 0x209f701c), + STCP(0x7ba3751d, 0x2120fb83), STCP(0x7b808015, 0x21a26295), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b38ffde, 0x22a4c185), + STCP(0x7b1474fd, 0x2325b847), STCP(0x7aef6323, 0x23a6887f), + STCP(0x7ac9ca7a, 0x2427319d), STCP(0x7aa3ab29, 0x24a7b317), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a55d93a, 0x25a83ce6), + STCP(0x7a2e26f2, 0x26284422), STCP(0x7a05eead, 0x26a82186), + STCP(0x79dd3098, 0x2727d486), STCP(0x79b3ece0, 0x27a75c95), + STCP(0x798a23b1, 0x2826b928), STCP(0x795fd53a, 0x28a5e9b4), + STCP(0x793501a9, 0x2924edac), STCP(0x7909a92d, 0x29a3c485), + STCP(0x78ddcbf5, 0x2a226db5), STCP(0x78b16a32, 0x2aa0e8b0), + STCP(0x78848414, 0x2b1f34eb), STCP(0x785719cc, 0x2b9d51dd), + STCP(0x78292b8d, 0x2c1b3efb), STCP(0x77fab989, 0x2c98fbba), + STCP(0x77cbc3f2, 0x2d168792), STCP(0x779c4afc, 0x2d93e1f8), + STCP(0x776c4edb, 0x2e110a62), STCP(0x773bcfc4, 0x2e8e0048), + STCP(0x770acdec, 0x2f0ac320), STCP(0x76d94989, 0x2f875262), + STCP(0x76a742d1, 0x3003ad85), STCP(0x7674b9fa, 0x307fd401), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x760e22d1, 0x317780e2), + STCP(0x75da14ef, 0x31f30638), STCP(0x75a585cf, 0x326e54c7), + STCP(0x757075ac, 0x32e96c09), STCP(0x753ae4c0, 0x33644b76), + STCP(0x7504d345, 0x33def287), STCP(0x74ce4177, 0x345960b7), + STCP(0x74972f92, 0x34d3957e), STCP(0x745f9dd1, 0x354d9057), + STCP(0x74278c72, 0x35c750bc), STCP(0x73eefbb3, 0x3640d627), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x737c5d0b, 0x37332dfd), + STCP(0x73424fa0, 0x37abff5d), STCP(0x7307c3d0, 0x382493b0), + STCP(0x72ccb9db, 0x389cea72), STCP(0x72913201, 0x3915031f), + STCP(0x72552c85, 0x398cdd32), STCP(0x7218a9a7, 0x3a04782a), + STCP(0x71dba9ab, 0x3a7bd382), STCP(0x719e2cd2, 0x3af2eeb7), + STCP(0x71603361, 0x3b69c947), STCP(0x7121bd9c, 0x3be062b0), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70a35e25, 0x3cccd004), + STCP(0x706374ff, 0x3d42a2ec), STCP(0x7023109a, 0x3db832a6), + STCP(0x6fe2313c, 0x3e2d7eb1), STCP(0x6fa0d72c, 0x3ea2868c), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f1cb416, 0x3f8bc7b4), + STCP(0x6ed9eba1, 0x40000000), STCP(0x6e96a99d, 0x4073f21d), + STCP(0x6e52ee52, 0x40e79d8c), STCP(0x6e0eba0c, 0x415b01ce), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d84e7b7, 0x4240f2d1), + STCP(0x6d3f4a40, 0x42b37e96), STCP(0x6cf934fc, 0x4325c135), + STCP(0x6cb2a837, 0x4397ba32), STCP(0x6c6ba43e, 0x44096910), + STCP(0x6c242960, 0x447acd50), STCP(0x6bdc37eb, 0x44ebe679), + STCP(0x6b93d02e, 0x455cb40c), STCP(0x6b4af279, 0x45cd358f), + STCP(0x6b019f1a, 0x463d6a87), STCP(0x6ab7d663, 0x46ad5278), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a22e630, 0x478c395a), + STCP(0x69d7bf57, 0x47fb3757), STCP(0x698c246c, 0x4869e665), + STCP(0x694015c3, 0x48d84609), STCP(0x68f393ae, 0x494655cc), + STCP(0x68a69e81, 0x49b41533), STCP(0x68593691, 0x4a2183c8), + STCP(0x680b5c33, 0x4a8ea111), STCP(0x67bd0fbd, 0x4afb6c98), + STCP(0x676e5183, 0x4b67e5e4), STCP(0x671f21dc, 0x4bd40c80), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x667f6fa5, 0x4cab5fc9), + STCP(0x662eedc3, 0x4d168b8b), STCP(0x65ddfbd3, 0x4d8162c4), + STCP(0x658c9a2d, 0x4debe4fe), STCP(0x653ac92b, 0x4e5611c5), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x6495da79, 0x4f296928), + STCP(0x6442bd7e, 0x4f9292dc), STCP(0x63ef3290, 0x4ffb654d), + STCP(0x639b3a0b, 0x5063e008), STCP(0x6346d44b, 0x50cc029c), + STCP(0x62f201ac, 0x5133cc94), STCP(0x629cc28c, 0x519b3d80), + STCP(0x62471749, 0x520254ef), STCP(0x61f1003f, 0x5269126e), + STCP(0x619a7dce, 0x52cf758f), STCP(0x61439053, 0x53357ddf), + STCP(0x60ec3830, 0x539b2af0), STCP(0x609475c3, 0x54007c51), + STCP(0x603c496c, 0x54657194), STCP(0x5fe3b38d, 0x54ca0a4b), + STCP(0x5f8ab487, 0x552e4605), STCP(0x5f314cba, 0x55922457), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e7d4458, 0x5658c709), + STCP(0x5e22a487, 0x56bb8a90), STCP(0x5dc79d7c, 0x571deefa), + STCP(0x5d6c2f99, 0x577ff3da), STCP(0x5d105b44, 0x57e198c7), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c5780d3, 0x58a3c118), + STCP(0x5bfa7b82, 0x590443a7), STCP(0x5b9d1154, 0x59646498), + STCP(0x5b3f42ae, 0x59c42381), STCP(0x5ae10ff9, 0x5a237ffa), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable480[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable512[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7fffd886, 0x006487e3), + STCP(0x7fff6216, 0x00c90f88), STCP(0x7ffe9cb2, 0x012d96b1), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffc250f, 0x01f6a297), + STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff871a2, 0x02bfa9a4), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff38274, 0x0388a9ea), + STCP(0x7ff09478, 0x03ed26e6), STCP(0x7fed5791, 0x0451a177), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe5f108, 0x051a8e5c), + STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdd4eec, 0x05e36ea9), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd37153, 0x06ac406f), + STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fc85854, 0x077501be), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbc040a, 0x083db0a7), + STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fae7495, 0x09064b3a), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7f9faa15, 0x09cecf89), + STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f8fa4b0, 0x0a973ba5), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f7e648c, 0x0b5f8d9f), + STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f6be9d4, 0x0c27c389), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5834b7, 0x0cefdb76), + STCP(0x7f4de451, 0x0d53db92), STCP(0x7f434563, 0x0db7d376), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f2d1c0e, 0x0e7fa99e), + STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f15b8ee, 0x0f475bff), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7efd1c3c, 0x100ee8ad), + STCP(0x7ef05860, 0x1072a048), STCP(0x7ee34636, 0x10d64dbd), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ec8371a, 0x119d8941), + STCP(0x7eba3a39, 0x120116d5), STCP(0x7eabef2c, 0x1264994e), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e8e6eb2, 0x132b7bf9), + STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e6fb5f4, 0x13f22f58), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e4fc53e, 0x14b8b17f), + STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e2e9cdf, 0x157f0086), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e0c3d29, 0x16451a83), + STCP(0x7dfa98a8, 0x16a81305), STCP(0x7de8a670, 0x170afd8d), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dc3d90d, 0x17d0a7bc), + STCP(0x7db0fdf8, 0x183366e9), STCP(0x7d9dd55a, 0x18961728), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d769bb5, 0x195b49ea), + STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d4e2c7f, 0x1a203e1b), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d24881b, 0x1ae4f1d6), + STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7cf9aef0, 0x1ba96335), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7ccda169, 0x1c6d9053), + STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7ca05ff1, 0x1d31774d), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c71eaf9, 0x1df5163f), + STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4242f2, 0x1eb86b46), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c116853, 0x1f7b7481), + STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bdf5b94, 0x203e300d), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bac1d31, 0x21009c0c), + STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b77ada8, 0x21c2b69c), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b420d7a, 0x22847de0), + STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b0b3d2c, 0x2345eff8), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ad33d45, 0x24070b08), + STCP(0x7ab6cba4, 0x24677758), STCP(0x7a9a0e50, 0x24c7cd33), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a5fb0d8, 0x2588349d), + STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a24256f, 0x26483f6c), + STCP(0x7a05eead, 0x26a82186), STCP(0x79e76ca7, 0x2707ebc7), + STCP(0x79c89f6e, 0x27679df4), STCP(0x79a98715, 0x27c737d3), + STCP(0x798a23b1, 0x2826b928), STCP(0x796a7554, 0x288621b9), + STCP(0x794a7c12, 0x28e5714b), STCP(0x792a37fe, 0x2944a7a2), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78e8cfb2, 0x2a02c7b8), + STCP(0x78c7aba2, 0x2a61b101), STCP(0x78a63d11, 0x2ac08026), + STCP(0x78848414, 0x2b1f34eb), STCP(0x786280bf, 0x2b7dcf17), + STCP(0x78403329, 0x2bdc4e6f), STCP(0x781d9b65, 0x2c3ab2b9), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77d78daa, 0x2cf72939), + STCP(0x77b417df, 0x2d553afc), STCP(0x7790583e, 0x2db330c7), + STCP(0x776c4edb, 0x2e110a62), STCP(0x7747fbce, 0x2e6ec792), + STCP(0x77235f2d, 0x2ecc681e), STCP(0x76fe790e, 0x2f29ebcc), + STCP(0x76d94989, 0x2f875262), STCP(0x76b3d0b4, 0x2fe49ba7), + STCP(0x768e0ea6, 0x3041c761), STCP(0x76680376, 0x309ed556), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x761b1211, 0x3158970e), + STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75ccfd42, 0x3211df04), + STCP(0x75a585cf, 0x326e54c7), STCP(0x757dc5ca, 0x32caab6f), + STCP(0x7555bd4c, 0x3326e2c3), STCP(0x752d6c6c, 0x3382fa88), + STCP(0x7504d345, 0x33def287), STCP(0x74dbf1ef, 0x343aca87), + STCP(0x74b2c884, 0x34968250), STCP(0x7489571c, 0x34f219a8), + STCP(0x745f9dd1, 0x354d9057), STCP(0x74359cbd, 0x35a8e625), + STCP(0x740b53fb, 0x36041ad9), STCP(0x73e0c3a3, 0x365f2e3b), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x738acc9e, 0x3714f02a), + STCP(0x735f6626, 0x376f9e46), STCP(0x7333b883, 0x37ca2a30), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72db8828, 0x387eda8e), + STCP(0x72af05a7, 0x38d8fe93), STCP(0x72823c67, 0x3932ff87), + STCP(0x72552c85, 0x398cdd32), STCP(0x7227d61c, 0x39e6975e), + STCP(0x71fa3949, 0x3a402dd2), STCP(0x71cc5626, 0x3a99a057), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x716fbd68, 0x3b4c18ba), + STCP(0x71410805, 0x3ba51e29), STCP(0x71120cc5, 0x3bfdfecd), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70b34525, 0x3caf50da), + STCP(0x708378ff, 0x3d07c1d6), STCP(0x70536771, 0x3d600d2c), + STCP(0x7023109a, 0x3db832a6), STCP(0x6ff27497, 0x3e10320d), + STCP(0x6fc19385, 0x3e680b2c), STCP(0x6f906d84, 0x3ebfbdcd), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f2d532c, 0x3f6eaeb8), + STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ec92683, 0x401d0321), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e63e87f, 0x40cab958), + STCP(0x6e30e34a, 0x4121589b), STCP(0x6dfd9a1c, 0x4177cfb1), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6d963c54, 0x42244481), + STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d2dd027, 0x42d0161e), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cc45698, 0x437b42e1), + STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c59d0a9, 0x4425c923), + STCP(0x6c242960, 0x447acd50), STCP(0x6bee3f62, 0x44cfa740), + STCP(0x6bb812d1, 0x452456bd), STCP(0x6b81a3cd, 0x4578db93), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b13fef5, 0x4621647d), + STCP(0x6adcc964, 0x46756828), STCP(0x6aa551e9, 0x46c9405c), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a359db9, 0x47706d93), + STCP(0x69fd614a, 0x47c3c22f), STCP(0x69c4e37a, 0x4816ea86), + STCP(0x698c246c, 0x4869e665), STCP(0x69532442, 0x48bcb599), + STCP(0x6919e320, 0x490f57ee), STCP(0x68e06129, 0x4961cd33), + STCP(0x68a69e81, 0x49b41533), STCP(0x686c9b4b, 0x4a062fbd), + STCP(0x683257ab, 0x4a581c9e), STCP(0x67f7d3c5, 0x4aa9dba2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x67820bb7, 0x4b4ccf4d), + STCP(0x6746c7d8, 0x4b9e0390), STCP(0x670b4444, 0x4bef092d), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66937e91, 0x4c9087b1), + STCP(0x66573cbb, 0x4ce10034), STCP(0x661abbc5, 0x4d31494b), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65a0fd0b, 0x4dd14c6e), + STCP(0x6563bf92, 0x4e210617), STCP(0x6526438f, 0x4e708f8f), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64aa907f, 0x4f0f1126), + STCP(0x646c59bf, 0x4f5e08e3), STCP(0x642de50d, 0x4faccfab), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63b0426d, 0x5049c999), + STCP(0x637114cc, 0x5097fc5e), STCP(0x6331a9d4, 0x50e5fd6d), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62b21c7b, 0x518169a5), + STCP(0x6271fa69, 0x51ced46e), STCP(0x62319b9d, 0x521c0cc2), + STCP(0x61f1003f, 0x5269126e), STCP(0x61b02876, 0x52b5e546), + STCP(0x616f146c, 0x53028518), STCP(0x612dc447, 0x534ef1b5), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60aa7050, 0x53e73097), + STCP(0x60686ccf, 0x5433027d), STCP(0x60262dd6, 0x547ea073), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fa0fe1f, 0x55153fd4), + STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f1ae274, 0x55ab0d46), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5e93dc1f, 0x56400758), + STCP(0x5e50015d, 0x568a34a9), STCP(0x5e0bec6e, 0x56d42c99), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5d8314b1, 0x57677b9d), + STCP(0x5d3e5237, 0x57b0d256), STCP(0x5cf95638, 0x57f9f2f8), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c6eb258, 0x588b9140), + STCP(0x5c290acc, 0x58d40e8c), STCP(0x5be32a67, 0x591c550e), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b56bfbd, 0x59ac3cfd), + STCP(0x5b1035cf, 0x59f3de12), STCP(0x5ac973b5, 0x5a3b47ab), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STP SineTable1024[] = { + STCP(0x7fffffff, 0x00000000), STCP(0x7ffff621, 0x003243f5), + STCP(0x7fffd886, 0x006487e3), STCP(0x7fffa72c, 0x0096cbc1), + STCP(0x7fff6216, 0x00c90f88), STCP(0x7fff0943, 0x00fb5330), + STCP(0x7ffe9cb2, 0x012d96b1), STCP(0x7ffe1c65, 0x015fda03), + STCP(0x7ffd885a, 0x01921d20), STCP(0x7ffce093, 0x01c45ffe), + STCP(0x7ffc250f, 0x01f6a297), STCP(0x7ffb55ce, 0x0228e4e2), + STCP(0x7ffa72d1, 0x025b26d7), STCP(0x7ff97c18, 0x028d6870), + STCP(0x7ff871a2, 0x02bfa9a4), STCP(0x7ff75370, 0x02f1ea6c), + STCP(0x7ff62182, 0x03242abf), STCP(0x7ff4dbd9, 0x03566a96), + STCP(0x7ff38274, 0x0388a9ea), STCP(0x7ff21553, 0x03bae8b2), + STCP(0x7ff09478, 0x03ed26e6), STCP(0x7feeffe1, 0x041f6480), + STCP(0x7fed5791, 0x0451a177), STCP(0x7feb9b85, 0x0483ddc3), + STCP(0x7fe9cbc0, 0x04b6195d), STCP(0x7fe7e841, 0x04e8543e), + STCP(0x7fe5f108, 0x051a8e5c), STCP(0x7fe3e616, 0x054cc7b1), + STCP(0x7fe1c76b, 0x057f0035), STCP(0x7fdf9508, 0x05b137df), + STCP(0x7fdd4eec, 0x05e36ea9), STCP(0x7fdaf519, 0x0615a48b), + STCP(0x7fd8878e, 0x0647d97c), STCP(0x7fd6064c, 0x067a0d76), + STCP(0x7fd37153, 0x06ac406f), STCP(0x7fd0c8a3, 0x06de7262), + STCP(0x7fce0c3e, 0x0710a345), STCP(0x7fcb3c23, 0x0742d311), + STCP(0x7fc85854, 0x077501be), STCP(0x7fc560cf, 0x07a72f45), + STCP(0x7fc25596, 0x07d95b9e), STCP(0x7fbf36aa, 0x080b86c2), + STCP(0x7fbc040a, 0x083db0a7), STCP(0x7fb8bdb8, 0x086fd947), + STCP(0x7fb563b3, 0x08a2009a), STCP(0x7fb1f5fc, 0x08d42699), + STCP(0x7fae7495, 0x09064b3a), STCP(0x7faadf7c, 0x09386e78), + STCP(0x7fa736b4, 0x096a9049), STCP(0x7fa37a3c, 0x099cb0a7), + STCP(0x7f9faa15, 0x09cecf89), STCP(0x7f9bc640, 0x0a00ece8), + STCP(0x7f97cebd, 0x0a3308bd), STCP(0x7f93c38c, 0x0a6522fe), + STCP(0x7f8fa4b0, 0x0a973ba5), STCP(0x7f8b7227, 0x0ac952aa), + STCP(0x7f872bf3, 0x0afb6805), STCP(0x7f82d214, 0x0b2d7baf), + STCP(0x7f7e648c, 0x0b5f8d9f), STCP(0x7f79e35a, 0x0b919dcf), + STCP(0x7f754e80, 0x0bc3ac35), STCP(0x7f70a5fe, 0x0bf5b8cb), + STCP(0x7f6be9d4, 0x0c27c389), STCP(0x7f671a05, 0x0c59cc68), + STCP(0x7f62368f, 0x0c8bd35e), STCP(0x7f5d3f75, 0x0cbdd865), + STCP(0x7f5834b7, 0x0cefdb76), STCP(0x7f531655, 0x0d21dc87), + STCP(0x7f4de451, 0x0d53db92), STCP(0x7f489eaa, 0x0d85d88f), + STCP(0x7f434563, 0x0db7d376), STCP(0x7f3dd87c, 0x0de9cc40), + STCP(0x7f3857f6, 0x0e1bc2e4), STCP(0x7f32c3d1, 0x0e4db75b), + STCP(0x7f2d1c0e, 0x0e7fa99e), STCP(0x7f2760af, 0x0eb199a4), + STCP(0x7f2191b4, 0x0ee38766), STCP(0x7f1baf1e, 0x0f1572dc), + STCP(0x7f15b8ee, 0x0f475bff), STCP(0x7f0faf25, 0x0f7942c7), + STCP(0x7f0991c4, 0x0fab272b), STCP(0x7f0360cb, 0x0fdd0926), + STCP(0x7efd1c3c, 0x100ee8ad), STCP(0x7ef6c418, 0x1040c5bb), + STCP(0x7ef05860, 0x1072a048), STCP(0x7ee9d914, 0x10a4784b), + STCP(0x7ee34636, 0x10d64dbd), STCP(0x7edc9fc6, 0x11082096), + STCP(0x7ed5e5c6, 0x1139f0cf), STCP(0x7ecf1837, 0x116bbe60), + STCP(0x7ec8371a, 0x119d8941), STCP(0x7ec14270, 0x11cf516a), + STCP(0x7eba3a39, 0x120116d5), STCP(0x7eb31e78, 0x1232d979), + STCP(0x7eabef2c, 0x1264994e), STCP(0x7ea4ac58, 0x1296564d), + STCP(0x7e9d55fc, 0x12c8106f), STCP(0x7e95ec1a, 0x12f9c7aa), + STCP(0x7e8e6eb2, 0x132b7bf9), STCP(0x7e86ddc6, 0x135d2d53), + STCP(0x7e7f3957, 0x138edbb1), STCP(0x7e778166, 0x13c0870a), + STCP(0x7e6fb5f4, 0x13f22f58), STCP(0x7e67d703, 0x1423d492), + STCP(0x7e5fe493, 0x145576b1), STCP(0x7e57dea7, 0x148715ae), + STCP(0x7e4fc53e, 0x14b8b17f), STCP(0x7e47985b, 0x14ea4a1f), + STCP(0x7e3f57ff, 0x151bdf86), STCP(0x7e37042a, 0x154d71aa), + STCP(0x7e2e9cdf, 0x157f0086), STCP(0x7e26221f, 0x15b08c12), + STCP(0x7e1d93ea, 0x15e21445), STCP(0x7e14f242, 0x16139918), + STCP(0x7e0c3d29, 0x16451a83), STCP(0x7e0374a0, 0x1676987f), + STCP(0x7dfa98a8, 0x16a81305), STCP(0x7df1a942, 0x16d98a0c), + STCP(0x7de8a670, 0x170afd8d), STCP(0x7ddf9034, 0x173c6d80), + STCP(0x7dd6668f, 0x176dd9de), STCP(0x7dcd2981, 0x179f429f), + STCP(0x7dc3d90d, 0x17d0a7bc), STCP(0x7dba7534, 0x1802092c), + STCP(0x7db0fdf8, 0x183366e9), STCP(0x7da77359, 0x1864c0ea), + STCP(0x7d9dd55a, 0x18961728), STCP(0x7d9423fc, 0x18c7699b), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x7d808728, 0x192a0304), + STCP(0x7d769bb5, 0x195b49ea), STCP(0x7d6c9ce9, 0x198c8ce7), + STCP(0x7d628ac6, 0x19bdcbf3), STCP(0x7d58654d, 0x19ef0707), + STCP(0x7d4e2c7f, 0x1a203e1b), STCP(0x7d43e05e, 0x1a517128), + STCP(0x7d3980ec, 0x1a82a026), STCP(0x7d2f0e2b, 0x1ab3cb0d), + STCP(0x7d24881b, 0x1ae4f1d6), STCP(0x7d19eebf, 0x1b161479), + STCP(0x7d0f4218, 0x1b4732ef), STCP(0x7d048228, 0x1b784d30), + STCP(0x7cf9aef0, 0x1ba96335), STCP(0x7ceec873, 0x1bda74f6), + STCP(0x7ce3ceb2, 0x1c0b826a), STCP(0x7cd8c1ae, 0x1c3c8b8c), + STCP(0x7ccda169, 0x1c6d9053), STCP(0x7cc26de5, 0x1c9e90b8), + STCP(0x7cb72724, 0x1ccf8cb3), STCP(0x7cabcd28, 0x1d00843d), + STCP(0x7ca05ff1, 0x1d31774d), STCP(0x7c94df83, 0x1d6265dd), + STCP(0x7c894bde, 0x1d934fe5), STCP(0x7c7da505, 0x1dc4355e), + STCP(0x7c71eaf9, 0x1df5163f), STCP(0x7c661dbc, 0x1e25f282), + STCP(0x7c5a3d50, 0x1e56ca1e), STCP(0x7c4e49b7, 0x1e879d0d), + STCP(0x7c4242f2, 0x1eb86b46), STCP(0x7c362904, 0x1ee934c3), + STCP(0x7c29fbee, 0x1f19f97b), STCP(0x7c1dbbb3, 0x1f4ab968), + STCP(0x7c116853, 0x1f7b7481), STCP(0x7c0501d2, 0x1fac2abf), + STCP(0x7bf88830, 0x1fdcdc1b), STCP(0x7bebfb70, 0x200d888d), + STCP(0x7bdf5b94, 0x203e300d), STCP(0x7bd2a89e, 0x206ed295), + STCP(0x7bc5e290, 0x209f701c), STCP(0x7bb9096b, 0x20d0089c), + STCP(0x7bac1d31, 0x21009c0c), STCP(0x7b9f1de6, 0x21312a65), + STCP(0x7b920b89, 0x2161b3a0), STCP(0x7b84e61f, 0x219237b5), + STCP(0x7b77ada8, 0x21c2b69c), STCP(0x7b6a6227, 0x21f3304f), + STCP(0x7b5d039e, 0x2223a4c5), STCP(0x7b4f920e, 0x225413f8), + STCP(0x7b420d7a, 0x22847de0), STCP(0x7b3475e5, 0x22b4e274), + STCP(0x7b26cb4f, 0x22e541af), STCP(0x7b190dbc, 0x23159b88), + STCP(0x7b0b3d2c, 0x2345eff8), STCP(0x7afd59a4, 0x23763ef7), + STCP(0x7aef6323, 0x23a6887f), STCP(0x7ae159ae, 0x23d6cc87), + STCP(0x7ad33d45, 0x24070b08), STCP(0x7ac50dec, 0x243743fa), + STCP(0x7ab6cba4, 0x24677758), STCP(0x7aa8766f, 0x2497a517), + STCP(0x7a9a0e50, 0x24c7cd33), STCP(0x7a8b9348, 0x24f7efa2), + STCP(0x7a7d055b, 0x25280c5e), STCP(0x7a6e648a, 0x2558235f), + STCP(0x7a5fb0d8, 0x2588349d), STCP(0x7a50ea47, 0x25b84012), + STCP(0x7a4210d8, 0x25e845b6), STCP(0x7a332490, 0x26184581), + STCP(0x7a24256f, 0x26483f6c), STCP(0x7a151378, 0x26783370), + STCP(0x7a05eead, 0x26a82186), STCP(0x79f6b711, 0x26d809a5), + STCP(0x79e76ca7, 0x2707ebc7), STCP(0x79d80f6f, 0x2737c7e3), + STCP(0x79c89f6e, 0x27679df4), STCP(0x79b91ca4, 0x27976df1), + STCP(0x79a98715, 0x27c737d3), STCP(0x7999dec4, 0x27f6fb92), + STCP(0x798a23b1, 0x2826b928), STCP(0x797a55e0, 0x2856708d), + STCP(0x796a7554, 0x288621b9), STCP(0x795a820e, 0x28b5cca5), + STCP(0x794a7c12, 0x28e5714b), STCP(0x793a6361, 0x29150fa1), + STCP(0x792a37fe, 0x2944a7a2), STCP(0x7919f9ec, 0x29743946), + STCP(0x7909a92d, 0x29a3c485), STCP(0x78f945c3, 0x29d34958), + STCP(0x78e8cfb2, 0x2a02c7b8), STCP(0x78d846fb, 0x2a323f9e), + STCP(0x78c7aba2, 0x2a61b101), STCP(0x78b6fda8, 0x2a911bdc), + STCP(0x78a63d11, 0x2ac08026), STCP(0x789569df, 0x2aefddd8), + STCP(0x78848414, 0x2b1f34eb), STCP(0x78738bb3, 0x2b4e8558), + STCP(0x786280bf, 0x2b7dcf17), STCP(0x7851633b, 0x2bad1221), + STCP(0x78403329, 0x2bdc4e6f), STCP(0x782ef08b, 0x2c0b83fa), + STCP(0x781d9b65, 0x2c3ab2b9), STCP(0x780c33b8, 0x2c69daa6), + STCP(0x77fab989, 0x2c98fbba), STCP(0x77e92cd9, 0x2cc815ee), + STCP(0x77d78daa, 0x2cf72939), STCP(0x77c5dc01, 0x2d263596), + STCP(0x77b417df, 0x2d553afc), STCP(0x77a24148, 0x2d843964), + STCP(0x7790583e, 0x2db330c7), STCP(0x777e5cc3, 0x2de2211e), + STCP(0x776c4edb, 0x2e110a62), STCP(0x775a2e89, 0x2e3fec8b), + STCP(0x7747fbce, 0x2e6ec792), STCP(0x7735b6af, 0x2e9d9b70), + STCP(0x77235f2d, 0x2ecc681e), STCP(0x7710f54c, 0x2efb2d95), + STCP(0x76fe790e, 0x2f29ebcc), STCP(0x76ebea77, 0x2f58a2be), + STCP(0x76d94989, 0x2f875262), STCP(0x76c69647, 0x2fb5fab2), + STCP(0x76b3d0b4, 0x2fe49ba7), STCP(0x76a0f8d2, 0x30133539), + STCP(0x768e0ea6, 0x3041c761), STCP(0x767b1231, 0x30705217), + STCP(0x76680376, 0x309ed556), STCP(0x7654e279, 0x30cd5115), + STCP(0x7641af3d, 0x30fbc54d), STCP(0x762e69c4, 0x312a31f8), + STCP(0x761b1211, 0x3158970e), STCP(0x7607a828, 0x3186f487), + STCP(0x75f42c0b, 0x31b54a5e), STCP(0x75e09dbd, 0x31e39889), + STCP(0x75ccfd42, 0x3211df04), STCP(0x75b94a9c, 0x32401dc6), + STCP(0x75a585cf, 0x326e54c7), STCP(0x7591aedd, 0x329c8402), + STCP(0x757dc5ca, 0x32caab6f), STCP(0x7569ca99, 0x32f8cb07), + STCP(0x7555bd4c, 0x3326e2c3), STCP(0x75419de7, 0x3354f29b), + STCP(0x752d6c6c, 0x3382fa88), STCP(0x751928e0, 0x33b0fa84), + STCP(0x7504d345, 0x33def287), STCP(0x74f06b9e, 0x340ce28b), + STCP(0x74dbf1ef, 0x343aca87), STCP(0x74c7663a, 0x3468aa76), + STCP(0x74b2c884, 0x34968250), STCP(0x749e18cd, 0x34c4520d), + STCP(0x7489571c, 0x34f219a8), STCP(0x74748371, 0x351fd918), + STCP(0x745f9dd1, 0x354d9057), STCP(0x744aa63f, 0x357b3f5d), + STCP(0x74359cbd, 0x35a8e625), STCP(0x74208150, 0x35d684a6), + STCP(0x740b53fb, 0x36041ad9), STCP(0x73f614c0, 0x3631a8b8), + STCP(0x73e0c3a3, 0x365f2e3b), STCP(0x73cb60a8, 0x368cab5c), + STCP(0x73b5ebd1, 0x36ba2014), STCP(0x73a06522, 0x36e78c5b), + STCP(0x738acc9e, 0x3714f02a), STCP(0x73752249, 0x37424b7b), + STCP(0x735f6626, 0x376f9e46), STCP(0x73499838, 0x379ce885), + STCP(0x7333b883, 0x37ca2a30), STCP(0x731dc70a, 0x37f76341), + STCP(0x7307c3d0, 0x382493b0), STCP(0x72f1aed9, 0x3851bb77), + STCP(0x72db8828, 0x387eda8e), STCP(0x72c54fc1, 0x38abf0ef), + STCP(0x72af05a7, 0x38d8fe93), STCP(0x7298a9dd, 0x39060373), + STCP(0x72823c67, 0x3932ff87), STCP(0x726bbd48, 0x395ff2c9), + STCP(0x72552c85, 0x398cdd32), STCP(0x723e8a20, 0x39b9bebc), + STCP(0x7227d61c, 0x39e6975e), STCP(0x7211107e, 0x3a136712), + STCP(0x71fa3949, 0x3a402dd2), STCP(0x71e35080, 0x3a6ceb96), + STCP(0x71cc5626, 0x3a99a057), STCP(0x71b54a41, 0x3ac64c0f), + STCP(0x719e2cd2, 0x3af2eeb7), STCP(0x7186fdde, 0x3b1f8848), + STCP(0x716fbd68, 0x3b4c18ba), STCP(0x71586b74, 0x3b78a007), + STCP(0x71410805, 0x3ba51e29), STCP(0x7129931f, 0x3bd19318), + STCP(0x71120cc5, 0x3bfdfecd), STCP(0x70fa74fc, 0x3c2a6142), + STCP(0x70e2cbc6, 0x3c56ba70), STCP(0x70cb1128, 0x3c830a50), + STCP(0x70b34525, 0x3caf50da), STCP(0x709b67c0, 0x3cdb8e09), + STCP(0x708378ff, 0x3d07c1d6), STCP(0x706b78e3, 0x3d33ec39), + STCP(0x70536771, 0x3d600d2c), STCP(0x703b44ad, 0x3d8c24a8), + STCP(0x7023109a, 0x3db832a6), STCP(0x700acb3c, 0x3de4371f), + STCP(0x6ff27497, 0x3e10320d), STCP(0x6fda0cae, 0x3e3c2369), + STCP(0x6fc19385, 0x3e680b2c), STCP(0x6fa90921, 0x3e93e950), + STCP(0x6f906d84, 0x3ebfbdcd), STCP(0x6f77c0b3, 0x3eeb889c), + STCP(0x6f5f02b2, 0x3f1749b8), STCP(0x6f463383, 0x3f430119), + STCP(0x6f2d532c, 0x3f6eaeb8), STCP(0x6f1461b0, 0x3f9a5290), + STCP(0x6efb5f12, 0x3fc5ec98), STCP(0x6ee24b57, 0x3ff17cca), + STCP(0x6ec92683, 0x401d0321), STCP(0x6eaff099, 0x40487f94), + STCP(0x6e96a99d, 0x4073f21d), STCP(0x6e7d5193, 0x409f5ab6), + STCP(0x6e63e87f, 0x40cab958), STCP(0x6e4a6e66, 0x40f60dfb), + STCP(0x6e30e34a, 0x4121589b), STCP(0x6e174730, 0x414c992f), + STCP(0x6dfd9a1c, 0x4177cfb1), STCP(0x6de3dc11, 0x41a2fc1a), + STCP(0x6dca0d14, 0x41ce1e65), STCP(0x6db02d29, 0x41f93689), + STCP(0x6d963c54, 0x42244481), STCP(0x6d7c3a98, 0x424f4845), + STCP(0x6d6227fa, 0x427a41d0), STCP(0x6d48047e, 0x42a5311b), + STCP(0x6d2dd027, 0x42d0161e), STCP(0x6d138afb, 0x42faf0d4), + STCP(0x6cf934fc, 0x4325c135), STCP(0x6cdece2f, 0x4350873c), + STCP(0x6cc45698, 0x437b42e1), STCP(0x6ca9ce3b, 0x43a5f41e), + STCP(0x6c8f351c, 0x43d09aed), STCP(0x6c748b3f, 0x43fb3746), + STCP(0x6c59d0a9, 0x4425c923), STCP(0x6c3f055d, 0x4450507e), + STCP(0x6c242960, 0x447acd50), STCP(0x6c093cb6, 0x44a53f93), + STCP(0x6bee3f62, 0x44cfa740), STCP(0x6bd3316a, 0x44fa0450), + STCP(0x6bb812d1, 0x452456bd), STCP(0x6b9ce39b, 0x454e9e80), + STCP(0x6b81a3cd, 0x4578db93), STCP(0x6b66536b, 0x45a30df0), + STCP(0x6b4af279, 0x45cd358f), STCP(0x6b2f80fb, 0x45f7526b), + STCP(0x6b13fef5, 0x4621647d), STCP(0x6af86c6c, 0x464b6bbe), + STCP(0x6adcc964, 0x46756828), STCP(0x6ac115e2, 0x469f59b4), + STCP(0x6aa551e9, 0x46c9405c), STCP(0x6a897d7d, 0x46f31c1a), + STCP(0x6a6d98a4, 0x471cece7), STCP(0x6a51a361, 0x4746b2bc), + STCP(0x6a359db9, 0x47706d93), STCP(0x6a1987b0, 0x479a1d67), + STCP(0x69fd614a, 0x47c3c22f), STCP(0x69e12a8c, 0x47ed5be6), + STCP(0x69c4e37a, 0x4816ea86), STCP(0x69a88c19, 0x48406e08), + STCP(0x698c246c, 0x4869e665), STCP(0x696fac78, 0x48935397), + STCP(0x69532442, 0x48bcb599), STCP(0x69368bce, 0x48e60c62), + STCP(0x6919e320, 0x490f57ee), STCP(0x68fd2a3d, 0x49389836), + STCP(0x68e06129, 0x4961cd33), STCP(0x68c387e9, 0x498af6df), + STCP(0x68a69e81, 0x49b41533), STCP(0x6889a4f6, 0x49dd282a), + STCP(0x686c9b4b, 0x4a062fbd), STCP(0x684f8186, 0x4a2f2be6), + STCP(0x683257ab, 0x4a581c9e), STCP(0x68151dbe, 0x4a8101de), + STCP(0x67f7d3c5, 0x4aa9dba2), STCP(0x67da79c3, 0x4ad2a9e2), + STCP(0x67bd0fbd, 0x4afb6c98), STCP(0x679f95b7, 0x4b2423be), + STCP(0x67820bb7, 0x4b4ccf4d), STCP(0x676471c0, 0x4b756f40), + STCP(0x6746c7d8, 0x4b9e0390), STCP(0x67290e02, 0x4bc68c36), + STCP(0x670b4444, 0x4bef092d), STCP(0x66ed6aa1, 0x4c177a6e), + STCP(0x66cf8120, 0x4c3fdff4), STCP(0x66b187c3, 0x4c6839b7), + STCP(0x66937e91, 0x4c9087b1), STCP(0x6675658c, 0x4cb8c9dd), + STCP(0x66573cbb, 0x4ce10034), STCP(0x66390422, 0x4d092ab0), + STCP(0x661abbc5, 0x4d31494b), STCP(0x65fc63a9, 0x4d595bfe), + STCP(0x65ddfbd3, 0x4d8162c4), STCP(0x65bf8447, 0x4da95d96), + STCP(0x65a0fd0b, 0x4dd14c6e), STCP(0x65826622, 0x4df92f46), + STCP(0x6563bf92, 0x4e210617), STCP(0x6545095f, 0x4e48d0dd), + STCP(0x6526438f, 0x4e708f8f), STCP(0x65076e25, 0x4e984229), + STCP(0x64e88926, 0x4ebfe8a5), STCP(0x64c99498, 0x4ee782fb), + STCP(0x64aa907f, 0x4f0f1126), STCP(0x648b7ce0, 0x4f369320), + STCP(0x646c59bf, 0x4f5e08e3), STCP(0x644d2722, 0x4f857269), + STCP(0x642de50d, 0x4faccfab), STCP(0x640e9386, 0x4fd420a4), + STCP(0x63ef3290, 0x4ffb654d), STCP(0x63cfc231, 0x50229da1), + STCP(0x63b0426d, 0x5049c999), STCP(0x6390b34a, 0x5070e92f), + STCP(0x637114cc, 0x5097fc5e), STCP(0x635166f9, 0x50bf031f), + STCP(0x6331a9d4, 0x50e5fd6d), STCP(0x6311dd64, 0x510ceb40), + STCP(0x62f201ac, 0x5133cc94), STCP(0x62d216b3, 0x515aa162), + STCP(0x62b21c7b, 0x518169a5), STCP(0x6292130c, 0x51a82555), + STCP(0x6271fa69, 0x51ced46e), STCP(0x6251d298, 0x51f576ea), + STCP(0x62319b9d, 0x521c0cc2), STCP(0x6211557e, 0x524295f0), + STCP(0x61f1003f, 0x5269126e), STCP(0x61d09be5, 0x528f8238), + STCP(0x61b02876, 0x52b5e546), STCP(0x618fa5f7, 0x52dc3b92), + STCP(0x616f146c, 0x53028518), STCP(0x614e73da, 0x5328c1d0), + STCP(0x612dc447, 0x534ef1b5), STCP(0x610d05b7, 0x537514c2), + STCP(0x60ec3830, 0x539b2af0), STCP(0x60cb5bb7, 0x53c13439), + STCP(0x60aa7050, 0x53e73097), STCP(0x60897601, 0x540d2005), + STCP(0x60686ccf, 0x5433027d), STCP(0x604754bf, 0x5458d7f9), + STCP(0x60262dd6, 0x547ea073), STCP(0x6004f819, 0x54a45be6), + STCP(0x5fe3b38d, 0x54ca0a4b), STCP(0x5fc26038, 0x54efab9c), + STCP(0x5fa0fe1f, 0x55153fd4), STCP(0x5f7f8d46, 0x553ac6ee), + STCP(0x5f5e0db3, 0x556040e2), STCP(0x5f3c7f6b, 0x5585adad), + STCP(0x5f1ae274, 0x55ab0d46), STCP(0x5ef936d1, 0x55d05faa), + STCP(0x5ed77c8a, 0x55f5a4d2), STCP(0x5eb5b3a2, 0x561adcb9), + STCP(0x5e93dc1f, 0x56400758), STCP(0x5e71f606, 0x566524aa), + STCP(0x5e50015d, 0x568a34a9), STCP(0x5e2dfe29, 0x56af3750), + STCP(0x5e0bec6e, 0x56d42c99), STCP(0x5de9cc33, 0x56f9147e), + STCP(0x5dc79d7c, 0x571deefa), STCP(0x5da5604f, 0x5742bc06), + STCP(0x5d8314b1, 0x57677b9d), STCP(0x5d60baa7, 0x578c2dba), + STCP(0x5d3e5237, 0x57b0d256), STCP(0x5d1bdb65, 0x57d5696d), + STCP(0x5cf95638, 0x57f9f2f8), STCP(0x5cd6c2b5, 0x581e6ef1), + STCP(0x5cb420e0, 0x5842dd54), STCP(0x5c9170bf, 0x58673e1b), + STCP(0x5c6eb258, 0x588b9140), STCP(0x5c4be5b0, 0x58afd6bd), + STCP(0x5c290acc, 0x58d40e8c), STCP(0x5c0621b2, 0x58f838a9), + STCP(0x5be32a67, 0x591c550e), STCP(0x5bc024f0, 0x594063b5), + STCP(0x5b9d1154, 0x59646498), STCP(0x5b79ef96, 0x598857b2), + STCP(0x5b56bfbd, 0x59ac3cfd), STCP(0x5b3381ce, 0x59d01475), + STCP(0x5b1035cf, 0x59f3de12), STCP(0x5aecdbc5, 0x5a1799d1), + STCP(0x5ac973b5, 0x5a3b47ab), STCP(0x5aa5fda5, 0x5a5ee79a), + STCP(0x5a82799a, 0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal6[] = { + STC(0x40000000), + STC(0xc0000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag6[] = { + STC(0x6ed9eba1), + STC(0x6ed9eba1), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal12[] = { + STC(0x6ed9eba1), + STC(0x40000000), + STC(0x40000000), + STC(0xc0000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag12[] = { + STC(0x40000000), + STC(0x6ed9eba1), + STC(0x6ed9eba1), + STC(0x6ed9eba1), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal24[] = { + STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), + STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), + STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag24[] = { + STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), + STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), STC(0x6ed9eba1), + STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal48[] = { + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x7641af3d), STC(0x5a82799a), + STC(0x30fbc54d), STC(0x6ed9eba1), STC(0x40000000), STC(0x00000000), + STC(0x658c9a2d), STC(0x2120fb83), STC(0xcf043ab3), STC(0x5a82799a), + STC(0x00000000), STC(0xa57d8666), STC(0x4debe4fe), STC(0xdedf047d), + STC(0x89be50c3), STC(0x40000000), STC(0xc0000000), STC(0x80000000), + STC(0x30fbc54d), STC(0xa57d8666), STC(0x89be50c3), STC(0x2120fb83), + STC(0x9126145f), STC(0xa57d8666), STC(0x10b5150f), STC(0x845c8ae3), + STC(0xcf043ab3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag48[] = { + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x2120fb83), + STC(0x40000000), STC(0x5a82799a), STC(0x30fbc54d), STC(0x5a82799a), + STC(0x7641af3d), STC(0x40000000), STC(0x6ed9eba1), STC(0x7fffffff), + STC(0x4debe4fe), STC(0x7ba3751d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x7fffffff), STC(0x5a82799a), STC(0x658c9a2d), STC(0x7ba3751d), + STC(0x30fbc54d), STC(0x6ed9eba1), STC(0x6ed9eba1), STC(0x00000000), + STC(0x7641af3d), STC(0x5a82799a), STC(0xcf043ab3), STC(0x7ba3751d), + STC(0x40000000), STC(0xa57d8666), STC(0x7ee7aa4c), STC(0x2120fb83), + STC(0x89be50c3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal80[] = { + STC(0x7f9afcb9), STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), + STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), + STC(0x7c769e18), STC(0x720c8075), STC(0x6154fb91), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), + STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), STC(0x00000000), + STC(0x720c8075), STC(0x4b3c8c12), STC(0x14060b68), STC(0xd8722192), + STC(0x6d23501b), STC(0x3a1c5c57), STC(0xf5f50d67), STC(0xb4c373ee), + STC(0x678dde6e), STC(0x278dde6e), STC(0xd8722192), STC(0x98722192), + STC(0x6154fb91), STC(0x14060b68), STC(0xbd1ec45c), STC(0x8643c7b3), + STC(0x5a82799a), STC(0x00000000), STC(0xa57d8666), STC(0x80000000), + STC(0x53211d18), STC(0xebf9f498), STC(0x92dcafe5), STC(0x8643c7b3), + STC(0x4b3c8c12), STC(0xd8722192), STC(0x8643c7b3), STC(0x98722192), + STC(0x42e13ba4), STC(0xc5e3a3a9), STC(0x80650347), STC(0xb4c373ee), + STC(0x3a1c5c57), STC(0xb4c373ee), STC(0x81936daf), STC(0xd8722192), + STC(0x30fbc54d), STC(0xa57d8666), STC(0x89be50c3), STC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag80[] = { + STC(0x0a0af299), STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), + STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), + STC(0x1de189a6), STC(0x3a1c5c57), STC(0x53211d18), STC(0x678dde6e), + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), STC(0x79bc384d), + STC(0x30fbc54d), STC(0x5a82799a), STC(0x7641af3d), STC(0x7fffffff), + STC(0x3a1c5c57), STC(0x678dde6e), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x42e13ba4), STC(0x720c8075), STC(0x7f9afcb9), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x79bc384d), STC(0x79bc384d), STC(0x4b3c8c12), + STC(0x53211d18), STC(0x7e6c9251), STC(0x6d23501b), STC(0x278dde6e), + STC(0x5a82799a), STC(0x7fffffff), STC(0x5a82799a), STC(0x00000000), + STC(0x6154fb91), STC(0x7e6c9251), STC(0x42e13ba4), STC(0xd8722192), + STC(0x678dde6e), STC(0x79bc384d), STC(0x278dde6e), STC(0xb4c373ee), + STC(0x6d23501b), STC(0x720c8075), STC(0x0a0af299), STC(0x98722192), + STC(0x720c8075), STC(0x678dde6e), STC(0xebf9f498), STC(0x8643c7b3), + STC(0x7641af3d), STC(0x5a82799a), STC(0xcf043ab3), STC(0x80000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal96[] = { + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7ee7aa4c), STC(0x7ba3751d), + STC(0x7d8a5f40), STC(0x7641af3d), STC(0x7ba3751d), STC(0x6ed9eba1), + STC(0x793501a9), STC(0x658c9a2d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x72ccb9db), STC(0x4debe4fe), STC(0x6ed9eba1), STC(0x40000000), + STC(0x6a6d98a4), STC(0x30fbc54d), STC(0x658c9a2d), STC(0x2120fb83), + STC(0x603c496c), STC(0x10b5150f), STC(0x5a82799a), STC(0x00000000), + STC(0x54657194), STC(0xef4aeaf1), STC(0x4debe4fe), STC(0xdedf047d), + STC(0x471cece7), STC(0xcf043ab3), STC(0x40000000), STC(0xc0000000), + STC(0x389cea72), STC(0xb2141b02), STC(0x30fbc54d), STC(0xa57d8666), + STC(0x2924edac), STC(0x9a7365d3), STC(0x2120fb83), STC(0x9126145f), + STC(0x18f8b83c), STC(0x89be50c3), STC(0x10b5150f), STC(0x845c8ae3), + STC(0x085f2137), STC(0x811855b4), STC(0x00000000), STC(0x80000000), + STC(0xf7a0dec9), STC(0x811855b4), STC(0xef4aeaf1), STC(0x845c8ae3), + STC(0xe70747c4), STC(0x89be50c3), STC(0xdedf047d), STC(0x9126145f), + STC(0xd6db1254), STC(0x9a7365d3), STC(0xcf043ab3), STC(0xa57d8666), + STC(0xc763158e), STC(0xb2141b02), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag96[] = { + STC(0x085f2137), STC(0x10b5150f), STC(0x10b5150f), STC(0x2120fb83), + STC(0x18f8b83c), STC(0x30fbc54d), STC(0x2120fb83), STC(0x40000000), + STC(0x2924edac), STC(0x4debe4fe), STC(0x30fbc54d), STC(0x5a82799a), + STC(0x389cea72), STC(0x658c9a2d), STC(0x40000000), STC(0x6ed9eba1), + STC(0x471cece7), STC(0x7641af3d), STC(0x4debe4fe), STC(0x7ba3751d), + STC(0x54657194), STC(0x7ee7aa4c), STC(0x5a82799a), STC(0x7fffffff), + STC(0x603c496c), STC(0x7ee7aa4c), STC(0x658c9a2d), STC(0x7ba3751d), + STC(0x6a6d98a4), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x6ed9eba1), + STC(0x72ccb9db), STC(0x658c9a2d), STC(0x7641af3d), STC(0x5a82799a), + STC(0x793501a9), STC(0x4debe4fe), STC(0x7ba3751d), STC(0x40000000), + STC(0x7d8a5f40), STC(0x30fbc54d), STC(0x7ee7aa4c), STC(0x2120fb83), + STC(0x7fb9d759), STC(0x10b5150f), STC(0x7fffffff), STC(0x00000000), + STC(0x7fb9d759), STC(0xef4aeaf1), STC(0x7ee7aa4c), STC(0xdedf047d), + STC(0x7d8a5f40), STC(0xcf043ab3), STC(0x7ba3751d), STC(0xc0000000), + STC(0x793501a9), STC(0xb2141b02), STC(0x7641af3d), STC(0xa57d8666), + STC(0x72ccb9db), STC(0x9a7365d3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal384[] = { + STC(0x7ffb9d15), STC(0x7fee74a2), STC(0x7fd8878e), STC(0x7fb9d759), + STC(0x7f92661d), STC(0x7f62368f), STC(0x7f294bfd), STC(0x7ee7aa4c), + STC(0x7e9d55fc), STC(0x7e4a5426), STC(0x7deeaa7a), STC(0x7fee74a2), + STC(0x7fb9d759), STC(0x7f62368f), STC(0x7ee7aa4c), STC(0x7e4a5426), + STC(0x7d8a5f40), STC(0x7ca80038), STC(0x7ba3751d), STC(0x7a7d055b), + STC(0x793501a9), STC(0x77cbc3f2), STC(0x7fd8878e), STC(0x7f62368f), + STC(0x7e9d55fc), STC(0x7d8a5f40), STC(0x7c29fbee), STC(0x7a7d055b), + STC(0x78848414), STC(0x7641af3d), STC(0x73b5ebd1), STC(0x70e2cbc6), + STC(0x6dca0d14), STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), + STC(0x7ba3751d), STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), + STC(0x6ed9eba1), STC(0x6a6d98a4), STC(0x658c9a2d), STC(0x603c496c), + STC(0x7f92661d), STC(0x7e4a5426), STC(0x7c29fbee), STC(0x793501a9), + STC(0x757075ac), STC(0x70e2cbc6), STC(0x6b93d02e), STC(0x658c9a2d), + STC(0x5ed77c8a), STC(0x577ff3da), STC(0x4f9292dc), STC(0x7f62368f), + STC(0x7d8a5f40), STC(0x7a7d055b), STC(0x7641af3d), STC(0x70e2cbc6), + STC(0x6a6d98a4), STC(0x62f201ac), STC(0x5a82799a), STC(0x5133cc94), + STC(0x471cece7), STC(0x3c56ba70), STC(0x7f294bfd), STC(0x7ca80038), + STC(0x78848414), STC(0x72ccb9db), STC(0x6b93d02e), STC(0x62f201ac), + STC(0x590443a7), STC(0x4debe4fe), STC(0x41ce1e65), STC(0x34d3957e), + STC(0x2727d486), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), + STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), + STC(0x7e9d55fc), STC(0x7a7d055b), STC(0x73b5ebd1), STC(0x6a6d98a4), + STC(0x5ed77c8a), STC(0x5133cc94), STC(0x41ce1e65), STC(0x30fbc54d), + STC(0x1f19f97b), STC(0x0c8bd35e), STC(0xf9b82684), STC(0x7e4a5426), + STC(0x793501a9), STC(0x70e2cbc6), STC(0x658c9a2d), STC(0x577ff3da), + STC(0x471cece7), STC(0x34d3957e), STC(0x2120fb83), STC(0x0c8bd35e), + STC(0xf7a0dec9), STC(0xe2ef2a3e), STC(0x7deeaa7a), STC(0x77cbc3f2), + STC(0x6dca0d14), STC(0x603c496c), STC(0x4f9292dc), STC(0x3c56ba70), + STC(0x2727d486), STC(0x10b5150f), STC(0xf9b82684), STC(0xe2ef2a3e), + STC(0xcd1693f7), STC(0x7d8a5f40), STC(0x7641af3d), STC(0x6a6d98a4), + STC(0x5a82799a), STC(0x471cece7), STC(0x30fbc54d), STC(0x18f8b83c), + STC(0x00000000), STC(0xe70747c4), STC(0xcf043ab3), STC(0xb8e31319), + STC(0x7d1d7958), STC(0x74972f92), STC(0x66cf8120), STC(0x54657194), + STC(0x3e2d7eb1), STC(0x25280c5e), STC(0x0a75d60e), STC(0xef4aeaf1), + STC(0xd4e0cb15), STC(0xbc6845ce), STC(0xa6fbbc59), STC(0x7ca80038), + STC(0x72ccb9db), STC(0x62f201ac), STC(0x4debe4fe), STC(0x34d3957e), + STC(0x18f8b83c), STC(0xfbcfdc71), STC(0xdedf047d), STC(0xc3a94590), + STC(0xab9a8e6c), STC(0x97f4a3cd), STC(0x7c29fbee), STC(0x70e2cbc6), + STC(0x5ed77c8a), STC(0x471cece7), STC(0x2b1f34eb), STC(0x0c8bd35e), + STC(0xed37ef91), STC(0xcf043ab3), STC(0xb3c0200c), STC(0x9d0dfe54), + STC(0x8c4a142f), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), + STC(0x7b1474fd), STC(0x6cb2a837), STC(0x55f5a4d2), STC(0x389cea72), + STC(0x16ea0646), STC(0xf3742ca2), STC(0xd0f53ce0), STC(0xb2141b02), + STC(0x99307ee0), STC(0x88343c0e), STC(0x806d99e3), STC(0x7a7d055b), + STC(0x6a6d98a4), STC(0x5133cc94), STC(0x30fbc54d), STC(0x0c8bd35e), + STC(0xe70747c4), STC(0xc3a94590), STC(0xa57d8666), STC(0x8f1d343a), + STC(0x8275a0c0), STC(0x809dc971), STC(0x79dd3098), STC(0x680b5c33), + STC(0x4c3fdff4), STC(0x2924edac), STC(0x02182427), STC(0xdad7f3a2), + STC(0xb727b9f7), STC(0x9a7365d3), STC(0x877b7bec), STC(0x80118b5e), + STC(0x84eb8b03), STC(0x793501a9), STC(0x658c9a2d), STC(0x471cece7), + STC(0x2120fb83), STC(0xf7a0dec9), STC(0xcf043ab3), STC(0xab9a8e6c), + STC(0x9126145f), STC(0x8275a0c0), STC(0x811855b4), STC(0x8d334625), + STC(0x78848414), STC(0x62f201ac), STC(0x41ce1e65), STC(0x18f8b83c), + STC(0xed37ef91), STC(0xc3a94590), STC(0xa1288376), STC(0x89be50c3), + STC(0x80277872), STC(0x8582faa5), STC(0x99307ee0), STC(0x77cbc3f2), + STC(0x603c496c), STC(0x3c56ba70), STC(0x10b5150f), STC(0xe2ef2a3e), + STC(0xb8e31319), STC(0x97f4a3cd), STC(0x845c8ae3), STC(0x809dc971), + STC(0x8d334625), STC(0xa8800c26), STC(0x770acdec), STC(0x5d6c2f99), + STC(0x36ba2014), STC(0x085f2137), STC(0xd8d82b7a), STC(0xaecc336c), + STC(0x901dcec4), STC(0x811855b4), STC(0x83d60412), STC(0x97f4a3cd), + STC(0xbaa34bf4), STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), + STC(0x00000000), STC(0xcf043ab3), STC(0xa57d8666), STC(0x89be50c3), + STC(0x80000000), STC(0x89be50c3), STC(0xa57d8666), STC(0xcf043ab3), + STC(0x757075ac), STC(0x577ff3da), STC(0x2b1f34eb), STC(0xf7a0dec9), + STC(0xc5842c7e), STC(0x9d0dfe54), STC(0x84eb8b03), STC(0x811855b4), + STC(0x9235f2ec), STC(0xb5715eef), STC(0xe4fa4bf1), STC(0x74972f92), + STC(0x54657194), STC(0x25280c5e), STC(0xef4aeaf1), STC(0xbc6845ce), + STC(0x9592675c), STC(0x81b5abda), STC(0x845c8ae3), STC(0x9d0dfe54), + STC(0xc763158e), STC(0xfbcfdc71), STC(0x73b5ebd1), STC(0x5133cc94), + STC(0x1f19f97b), STC(0xe70747c4), STC(0xb3c0200c), STC(0x8f1d343a), + STC(0x80277872), STC(0x89be50c3), STC(0xaa0a5b2e), STC(0xdad7f3a2), + STC(0x12c8106f), STC(0x72ccb9db), STC(0x4debe4fe), STC(0x18f8b83c), + STC(0xdedf047d), STC(0xab9a8e6c), STC(0x89be50c3), STC(0x804628a7), + STC(0x9126145f), STC(0xb8e31319), STC(0xef4aeaf1), STC(0x2924edac), + STC(0x71dba9ab), STC(0x4a8ea111), STC(0x12c8106f), STC(0xd6db1254), + STC(0xa405847e), STC(0x8582faa5), STC(0x82115586), STC(0x9a7365d3), + STC(0xc945dfec), STC(0x0430238f), STC(0x3e2d7eb1), STC(0x70e2cbc6), + STC(0x471cece7), STC(0x0c8bd35e), STC(0xcf043ab3), STC(0x9d0dfe54), + STC(0x8275a0c0), STC(0x8582faa5), STC(0xa57d8666), STC(0xdad7f3a2), + STC(0x18f8b83c), STC(0x5133cc94), STC(0x6fe2313c), STC(0x4397ba32), + STC(0x0647d97c), STC(0xc763158e), STC(0x96bfea3d), STC(0x809dc971), + STC(0x8a8f8a54), STC(0xb2141b02), STC(0xed37ef91), STC(0x2d168792), + STC(0x619a7dce), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag384[] = { + STC(0x02182427), STC(0x0430238f), STC(0x0647d97c), STC(0x085f2137), + STC(0x0a75d60e), STC(0x0c8bd35e), STC(0x0ea0f48c), STC(0x10b5150f), + STC(0x12c8106f), STC(0x14d9c245), STC(0x16ea0646), STC(0x0430238f), + STC(0x085f2137), STC(0x0c8bd35e), STC(0x10b5150f), STC(0x14d9c245), + STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x2120fb83), STC(0x25280c5e), + STC(0x2924edac), STC(0x2d168792), STC(0x0647d97c), STC(0x0c8bd35e), + STC(0x12c8106f), STC(0x18f8b83c), STC(0x1f19f97b), STC(0x25280c5e), + STC(0x2b1f34eb), STC(0x30fbc54d), STC(0x36ba2014), STC(0x3c56ba70), + STC(0x41ce1e65), STC(0x085f2137), STC(0x10b5150f), STC(0x18f8b83c), + STC(0x2120fb83), STC(0x2924edac), STC(0x30fbc54d), STC(0x389cea72), + STC(0x40000000), STC(0x471cece7), STC(0x4debe4fe), STC(0x54657194), + STC(0x0a75d60e), STC(0x14d9c245), STC(0x1f19f97b), STC(0x2924edac), + STC(0x32e96c09), STC(0x3c56ba70), STC(0x455cb40c), STC(0x4debe4fe), + STC(0x55f5a4d2), STC(0x5d6c2f99), STC(0x6442bd7e), STC(0x0c8bd35e), + STC(0x18f8b83c), STC(0x25280c5e), STC(0x30fbc54d), STC(0x3c56ba70), + STC(0x471cece7), STC(0x5133cc94), STC(0x5a82799a), STC(0x62f201ac), + STC(0x6a6d98a4), STC(0x70e2cbc6), STC(0x0ea0f48c), STC(0x1d10d5c2), + STC(0x2b1f34eb), STC(0x389cea72), STC(0x455cb40c), STC(0x5133cc94), + STC(0x5bfa7b82), STC(0x658c9a2d), STC(0x6dca0d14), STC(0x74972f92), + STC(0x79dd3098), STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), + STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), + STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), + STC(0x12c8106f), STC(0x25280c5e), STC(0x36ba2014), STC(0x471cece7), + STC(0x55f5a4d2), STC(0x62f201ac), STC(0x6dca0d14), STC(0x7641af3d), + STC(0x7c29fbee), STC(0x7f62368f), STC(0x7fd8878e), STC(0x14d9c245), + STC(0x2924edac), STC(0x3c56ba70), STC(0x4debe4fe), STC(0x5d6c2f99), + STC(0x6a6d98a4), STC(0x74972f92), STC(0x7ba3751d), STC(0x7f62368f), + STC(0x7fb9d759), STC(0x7ca80038), STC(0x16ea0646), STC(0x2d168792), + STC(0x41ce1e65), STC(0x54657194), STC(0x6442bd7e), STC(0x70e2cbc6), + STC(0x79dd3098), STC(0x7ee7aa4c), STC(0x7fd8878e), STC(0x7ca80038), + STC(0x757075ac), STC(0x18f8b83c), STC(0x30fbc54d), STC(0x471cece7), + STC(0x5a82799a), STC(0x6a6d98a4), STC(0x7641af3d), STC(0x7d8a5f40), + STC(0x7fffffff), STC(0x7d8a5f40), STC(0x7641af3d), STC(0x6a6d98a4), + STC(0x1b05b40f), STC(0x34d3957e), STC(0x4c3fdff4), STC(0x603c496c), + STC(0x6fe2313c), STC(0x7a7d055b), STC(0x7f92661d), STC(0x7ee7aa4c), + STC(0x78848414), STC(0x6cb2a837), STC(0x5bfa7b82), STC(0x1d10d5c2), + STC(0x389cea72), STC(0x5133cc94), STC(0x658c9a2d), STC(0x74972f92), + STC(0x7d8a5f40), STC(0x7fee74a2), STC(0x7ba3751d), STC(0x70e2cbc6), + STC(0x603c496c), STC(0x4a8ea111), STC(0x1f19f97b), STC(0x3c56ba70), + STC(0x55f5a4d2), STC(0x6a6d98a4), STC(0x78848414), STC(0x7f62368f), + STC(0x7e9d55fc), STC(0x7641af3d), STC(0x66cf8120), STC(0x5133cc94), + STC(0x36ba2014), STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), + STC(0x6ed9eba1), STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x2325b847), STC(0x4397ba32), STC(0x5ed77c8a), STC(0x72ccb9db), + STC(0x7deeaa7a), STC(0x7f62368f), STC(0x770acdec), STC(0x658c9a2d), + STC(0x4c3fdff4), STC(0x2d168792), STC(0x0a75d60e), STC(0x25280c5e), + STC(0x471cece7), STC(0x62f201ac), STC(0x7641af3d), STC(0x7f62368f), + STC(0x7d8a5f40), STC(0x70e2cbc6), STC(0x5a82799a), STC(0x3c56ba70), + STC(0x18f8b83c), STC(0xf3742ca2), STC(0x2727d486), STC(0x4a8ea111), + STC(0x66cf8120), STC(0x793501a9), STC(0x7ffb9d15), STC(0x7a7d055b), + STC(0x694015c3), STC(0x4debe4fe), STC(0x2b1f34eb), STC(0x0430238f), + STC(0xdcda47b9), STC(0x2924edac), STC(0x4debe4fe), STC(0x6a6d98a4), + STC(0x7ba3751d), STC(0x7fb9d759), STC(0x7641af3d), STC(0x603c496c), + STC(0x40000000), STC(0x18f8b83c), STC(0xef4aeaf1), STC(0xc763158e), + STC(0x2b1f34eb), STC(0x5133cc94), STC(0x6dca0d14), STC(0x7d8a5f40), + STC(0x7e9d55fc), STC(0x70e2cbc6), STC(0x55f5a4d2), STC(0x30fbc54d), + STC(0x0647d97c), STC(0xdad7f3a2), STC(0xb3c0200c), STC(0x2d168792), + STC(0x54657194), STC(0x70e2cbc6), STC(0x7ee7aa4c), STC(0x7ca80038), + STC(0x6a6d98a4), STC(0x4a8ea111), STC(0x2120fb83), STC(0xf3742ca2), + STC(0xc763158e), STC(0xa293d067), STC(0x2f0ac320), STC(0x577ff3da), + STC(0x73b5ebd1), STC(0x7fb9d759), STC(0x79dd3098), STC(0x62f201ac), + STC(0x3e2d7eb1), STC(0x10b5150f), STC(0xe0e60685), STC(0xb5715eef), + STC(0x946c2fd2), STC(0x30fbc54d), STC(0x5a82799a), STC(0x7641af3d), + STC(0x7fffffff), STC(0x7641af3d), STC(0x5a82799a), STC(0x30fbc54d), + STC(0x00000000), STC(0xcf043ab3), STC(0xa57d8666), STC(0x89be50c3), + STC(0x32e96c09), STC(0x5d6c2f99), STC(0x78848414), STC(0x7fb9d759), + STC(0x71dba9ab), STC(0x5133cc94), STC(0x2325b847), STC(0xef4aeaf1), + STC(0xbe31e19b), STC(0x97f4a3cd), STC(0x82e286a8), STC(0x34d3957e), + STC(0x603c496c), STC(0x7a7d055b), STC(0x7ee7aa4c), STC(0x6cb2a837), + STC(0x471cece7), STC(0x14d9c245), STC(0xdedf047d), STC(0xaecc336c), + STC(0x8d334625), STC(0x80118b5e), STC(0x36ba2014), STC(0x62f201ac), + STC(0x7c29fbee), STC(0x7d8a5f40), STC(0x66cf8120), STC(0x3c56ba70), + STC(0x0647d97c), STC(0xcf043ab3), STC(0xa1288376), STC(0x8582faa5), + STC(0x8162aa04), STC(0x389cea72), STC(0x658c9a2d), STC(0x7d8a5f40), + STC(0x7ba3751d), STC(0x603c496c), STC(0x30fbc54d), STC(0xf7a0dec9), + STC(0xc0000000), STC(0x9592675c), STC(0x811855b4), STC(0x86cafe57), + STC(0x3a7bd382), STC(0x680b5c33), STC(0x7e9d55fc), STC(0x793501a9), + STC(0x590443a7), STC(0x25280c5e), STC(0xe915f9ba), STC(0xb2141b02), + STC(0x8c4a142f), STC(0x80118b5e), STC(0x901dcec4), STC(0x3c56ba70), + STC(0x6a6d98a4), STC(0x7f62368f), STC(0x7641af3d), STC(0x5133cc94), + STC(0x18f8b83c), STC(0xdad7f3a2), STC(0xa57d8666), STC(0x8582faa5), + STC(0x8275a0c0), STC(0x9d0dfe54), STC(0x3e2d7eb1), STC(0x6cb2a837), + STC(0x7fd8878e), STC(0x72ccb9db), STC(0x48d84609), STC(0x0c8bd35e), + STC(0xcd1693f7), STC(0x9a7365d3), STC(0x8162aa04), STC(0x88343c0e), + STC(0xad308a71), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal60[] = { + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x7d33f0ca), + STC(0x74ef0ebc), STC(0x678dde6e), STC(0x79bc384d), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x74ef0ebc), STC(0x55a6125c), STC(0x278dde6e), + STC(0x6ed9eba1), STC(0x40000000), STC(0x00000000), STC(0x678dde6e), + STC(0x278dde6e), STC(0xd8722192), STC(0x5f1f5ea1), STC(0x0d61304e), + STC(0xb4c373ee), STC(0x55a6125c), STC(0xf29ecfb2), STC(0x98722192), + STC(0x4b3c8c12), STC(0xd8722192), STC(0x8643c7b3), STC(0x40000000), + STC(0xc0000000), STC(0x80000000), STC(0x340ff242), STC(0xaa59eda4), + STC(0x8643c7b3), STC(0x278dde6e), STC(0x98722192), STC(0x98722192), + STC(0x1a9cd9ac), STC(0x8b10f144), STC(0xb4c373ee), STC(0x0d61304e), + STC(0x82cc0f36), STC(0xd8722192), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag60[] = { + STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x1a9cd9ac), + STC(0x340ff242), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x4b3c8c12), + STC(0x678dde6e), STC(0x340ff242), STC(0x5f1f5ea1), STC(0x79bc384d), + STC(0x40000000), STC(0x6ed9eba1), STC(0x7fffffff), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x79bc384d), STC(0x55a6125c), STC(0x7f4c7e54), + STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x7f4c7e54), STC(0x4b3c8c12), + STC(0x678dde6e), STC(0x79bc384d), STC(0x278dde6e), STC(0x6ed9eba1), + STC(0x6ed9eba1), STC(0x00000000), STC(0x74ef0ebc), STC(0x5f1f5ea1), + STC(0xd8722192), STC(0x79bc384d), STC(0x4b3c8c12), STC(0xb4c373ee), + STC(0x7d33f0ca), STC(0x340ff242), STC(0x98722192), STC(0x7f4c7e54), + STC(0x1a9cd9ac), STC(0x8643c7b3), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal120[] = { + STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), + STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), STC(0x7f4c7e54), + STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), STC(0x6ed9eba1), + STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), + STC(0x3a1c5c57), STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), + STC(0x55a6125c), STC(0x40000000), STC(0x278dde6e), STC(0x0d61304e), + STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), + STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), STC(0x79bc384d), + STC(0x678dde6e), STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), + STC(0xd8722192), STC(0xb4c373ee), STC(0x777f903c), STC(0x5f1f5ea1), + STC(0x3a1c5c57), STC(0x0d61304e), STC(0xdedf047d), STC(0xb4c373ee), + STC(0x94a6715d), STC(0x74ef0ebc), STC(0x55a6125c), STC(0x278dde6e), + STC(0xf29ecfb2), STC(0xc0000000), STC(0x98722192), STC(0x82cc0f36), + STC(0x720c8075), STC(0x4b3c8c12), STC(0x14060b68), STC(0xd8722192), + STC(0xa57d8666), STC(0x8643c7b3), STC(0x81936daf), STC(0x6ed9eba1), + STC(0x40000000), STC(0x00000000), STC(0xc0000000), STC(0x9126145f), + STC(0x80000000), STC(0x9126145f), STC(0x6b598ea3), STC(0x340ff242), + STC(0xebf9f498), STC(0xaa59eda4), STC(0x845c8ae3), STC(0x8643c7b3), + STC(0xaf726def), STC(0x678dde6e), STC(0x278dde6e), STC(0xd8722192), + STC(0x98722192), STC(0x80000000), STC(0x98722192), STC(0xd8722192), + STC(0x637984d4), STC(0x1a9cd9ac), STC(0xc5e3a3a9), STC(0x8b10f144), + STC(0x845c8ae3), STC(0xb4c373ee), STC(0x06b2f1d2), STC(0x5f1f5ea1), + STC(0x0d61304e), STC(0xb4c373ee), STC(0x82cc0f36), STC(0x9126145f), + STC(0xd8722192), STC(0x340ff242), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag120[] = { + STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), + STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), STC(0x0d61304e), + STC(0x1a9cd9ac), STC(0x278dde6e), STC(0x340ff242), STC(0x40000000), + STC(0x4b3c8c12), STC(0x55a6125c), STC(0x14060b68), STC(0x278dde6e), + STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), + STC(0x720c8075), STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), + STC(0x5f1f5ea1), STC(0x6ed9eba1), STC(0x79bc384d), STC(0x7f4c7e54), + STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), + STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), STC(0x278dde6e), + STC(0x4b3c8c12), STC(0x678dde6e), STC(0x79bc384d), STC(0x7fffffff), + STC(0x79bc384d), STC(0x678dde6e), STC(0x2ddf0040), STC(0x55a6125c), + STC(0x720c8075), STC(0x7f4c7e54), STC(0x7ba3751d), STC(0x678dde6e), + STC(0x45b6bb5e), STC(0x340ff242), STC(0x5f1f5ea1), STC(0x79bc384d), + STC(0x7f4c7e54), STC(0x6ed9eba1), STC(0x4b3c8c12), STC(0x1a9cd9ac), + STC(0x3a1c5c57), STC(0x678dde6e), STC(0x7e6c9251), STC(0x79bc384d), + STC(0x5a82799a), STC(0x278dde6e), STC(0xebf9f498), STC(0x40000000), + STC(0x6ed9eba1), STC(0x7fffffff), STC(0x6ed9eba1), STC(0x40000000), + STC(0x00000000), STC(0xc0000000), STC(0x45b6bb5e), STC(0x74ef0ebc), + STC(0x7e6c9251), STC(0x5f1f5ea1), STC(0x2120fb83), STC(0xd8722192), + STC(0x9c867b2c), STC(0x4b3c8c12), STC(0x79bc384d), STC(0x79bc384d), + STC(0x4b3c8c12), STC(0x00000000), STC(0xb4c373ee), STC(0x8643c7b3), + STC(0x508d9211), STC(0x7d33f0ca), STC(0x720c8075), STC(0x340ff242), + STC(0xdedf047d), STC(0x98722192), STC(0x802ce84c), STC(0x55a6125c), + STC(0x7f4c7e54), STC(0x678dde6e), STC(0x1a9cd9ac), STC(0xc0000000), + STC(0x8643c7b3), STC(0x8b10f144), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal192[] = { + STC(0x7fee74a2), STC(0x7fb9d759), STC(0x7f62368f), STC(0x7ee7aa4c), + STC(0x7e4a5426), STC(0x7d8a5f40), STC(0x7ca80038), STC(0x7ba3751d), + STC(0x7a7d055b), STC(0x793501a9), STC(0x77cbc3f2), STC(0x7641af3d), + STC(0x74972f92), STC(0x72ccb9db), STC(0x70e2cbc6), STC(0x7fb9d759), + STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), STC(0x793501a9), + STC(0x7641af3d), STC(0x72ccb9db), STC(0x6ed9eba1), STC(0x6a6d98a4), + STC(0x658c9a2d), STC(0x603c496c), STC(0x5a82799a), STC(0x54657194), + STC(0x4debe4fe), STC(0x471cece7), STC(0x7f62368f), STC(0x7d8a5f40), + STC(0x7a7d055b), STC(0x7641af3d), STC(0x70e2cbc6), STC(0x6a6d98a4), + STC(0x62f201ac), STC(0x5a82799a), STC(0x5133cc94), STC(0x471cece7), + STC(0x3c56ba70), STC(0x30fbc54d), STC(0x25280c5e), STC(0x18f8b83c), + STC(0x0c8bd35e), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x6ed9eba1), STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), + STC(0x40000000), STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), + STC(0x00000000), STC(0xef4aeaf1), STC(0xdedf047d), STC(0xcf043ab3), + STC(0x7e4a5426), STC(0x793501a9), STC(0x70e2cbc6), STC(0x658c9a2d), + STC(0x577ff3da), STC(0x471cece7), STC(0x34d3957e), STC(0x2120fb83), + STC(0x0c8bd35e), STC(0xf7a0dec9), STC(0xe2ef2a3e), STC(0xcf043ab3), + STC(0xbc6845ce), STC(0xab9a8e6c), STC(0x9d0dfe54), STC(0x7d8a5f40), + STC(0x7641af3d), STC(0x6a6d98a4), STC(0x5a82799a), STC(0x471cece7), + STC(0x30fbc54d), STC(0x18f8b83c), STC(0x00000000), STC(0xe70747c4), + STC(0xcf043ab3), STC(0xb8e31319), STC(0xa57d8666), STC(0x9592675c), + STC(0x89be50c3), STC(0x8275a0c0), STC(0x7ca80038), STC(0x72ccb9db), + STC(0x62f201ac), STC(0x4debe4fe), STC(0x34d3957e), STC(0x18f8b83c), + STC(0xfbcfdc71), STC(0xdedf047d), STC(0xc3a94590), STC(0xab9a8e6c), + STC(0x97f4a3cd), STC(0x89be50c3), STC(0x81b5abda), STC(0x804628a7), + STC(0x8582faa5), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x9126145f), STC(0x845c8ae3), + STC(0x80000000), STC(0x845c8ae3), STC(0x9126145f), STC(0xa57d8666), + STC(0x7a7d055b), STC(0x6a6d98a4), STC(0x5133cc94), STC(0x30fbc54d), + STC(0x0c8bd35e), STC(0xe70747c4), STC(0xc3a94590), STC(0xa57d8666), + STC(0x8f1d343a), STC(0x8275a0c0), STC(0x809dc971), STC(0x89be50c3), + STC(0x9d0dfe54), STC(0xb8e31319), STC(0xdad7f3a2), STC(0x793501a9), + STC(0x658c9a2d), STC(0x471cece7), STC(0x2120fb83), STC(0xf7a0dec9), + STC(0xcf043ab3), STC(0xab9a8e6c), STC(0x9126145f), STC(0x8275a0c0), + STC(0x811855b4), STC(0x8d334625), STC(0xa57d8666), STC(0xc763158e), + STC(0xef4aeaf1), STC(0x18f8b83c), STC(0x77cbc3f2), STC(0x603c496c), + STC(0x3c56ba70), STC(0x10b5150f), STC(0xe2ef2a3e), STC(0xb8e31319), + STC(0x97f4a3cd), STC(0x845c8ae3), STC(0x809dc971), STC(0x8d334625), + STC(0xa8800c26), STC(0xcf043ab3), STC(0xfbcfdc71), STC(0x2924edac), + STC(0x5133cc94), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag192[] = { + STC(0x0430238f), STC(0x085f2137), STC(0x0c8bd35e), STC(0x10b5150f), + STC(0x14d9c245), STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x2120fb83), + STC(0x25280c5e), STC(0x2924edac), STC(0x2d168792), STC(0x30fbc54d), + STC(0x34d3957e), STC(0x389cea72), STC(0x3c56ba70), STC(0x085f2137), + STC(0x10b5150f), STC(0x18f8b83c), STC(0x2120fb83), STC(0x2924edac), + STC(0x30fbc54d), STC(0x389cea72), STC(0x40000000), STC(0x471cece7), + STC(0x4debe4fe), STC(0x54657194), STC(0x5a82799a), STC(0x603c496c), + STC(0x658c9a2d), STC(0x6a6d98a4), STC(0x0c8bd35e), STC(0x18f8b83c), + STC(0x25280c5e), STC(0x30fbc54d), STC(0x3c56ba70), STC(0x471cece7), + STC(0x5133cc94), STC(0x5a82799a), STC(0x62f201ac), STC(0x6a6d98a4), + STC(0x70e2cbc6), STC(0x7641af3d), STC(0x7a7d055b), STC(0x7d8a5f40), + STC(0x7f62368f), STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), + STC(0x40000000), STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), + STC(0x6ed9eba1), STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), + STC(0x7fffffff), STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), + STC(0x14d9c245), STC(0x2924edac), STC(0x3c56ba70), STC(0x4debe4fe), + STC(0x5d6c2f99), STC(0x6a6d98a4), STC(0x74972f92), STC(0x7ba3751d), + STC(0x7f62368f), STC(0x7fb9d759), STC(0x7ca80038), STC(0x7641af3d), + STC(0x6cb2a837), STC(0x603c496c), STC(0x5133cc94), STC(0x18f8b83c), + STC(0x30fbc54d), STC(0x471cece7), STC(0x5a82799a), STC(0x6a6d98a4), + STC(0x7641af3d), STC(0x7d8a5f40), STC(0x7fffffff), STC(0x7d8a5f40), + STC(0x7641af3d), STC(0x6a6d98a4), STC(0x5a82799a), STC(0x471cece7), + STC(0x30fbc54d), STC(0x18f8b83c), STC(0x1d10d5c2), STC(0x389cea72), + STC(0x5133cc94), STC(0x658c9a2d), STC(0x74972f92), STC(0x7d8a5f40), + STC(0x7fee74a2), STC(0x7ba3751d), STC(0x70e2cbc6), STC(0x603c496c), + STC(0x4a8ea111), STC(0x30fbc54d), STC(0x14d9c245), STC(0xf7a0dec9), + STC(0xdad7f3a2), STC(0x2120fb83), STC(0x40000000), STC(0x5a82799a), + STC(0x6ed9eba1), STC(0x7ba3751d), STC(0x7fffffff), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), STC(0xa57d8666), + STC(0x25280c5e), STC(0x471cece7), STC(0x62f201ac), STC(0x7641af3d), + STC(0x7f62368f), STC(0x7d8a5f40), STC(0x70e2cbc6), STC(0x5a82799a), + STC(0x3c56ba70), STC(0x18f8b83c), STC(0xf3742ca2), STC(0xcf043ab3), + STC(0xaecc336c), STC(0x9592675c), STC(0x8582faa5), STC(0x2924edac), + STC(0x4debe4fe), STC(0x6a6d98a4), STC(0x7ba3751d), STC(0x7fb9d759), + STC(0x7641af3d), STC(0x603c496c), STC(0x40000000), STC(0x18f8b83c), + STC(0xef4aeaf1), STC(0xc763158e), STC(0xa57d8666), STC(0x8d334625), + STC(0x811855b4), STC(0x8275a0c0), STC(0x2d168792), STC(0x54657194), + STC(0x70e2cbc6), STC(0x7ee7aa4c), STC(0x7ca80038), STC(0x6a6d98a4), + STC(0x4a8ea111), STC(0x2120fb83), STC(0xf3742ca2), STC(0xc763158e), + STC(0xa293d067), STC(0x89be50c3), STC(0x80118b5e), STC(0x86cafe57), + STC(0x9d0dfe54), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal240[] = { + STC(0x7ff4c56f), STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), + STC(0x7ee7aa4c), STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), + STC(0x7c769e18), STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), + STC(0x78a879f4), STC(0x777f903c), STC(0x7641af3d), STC(0x7fd317b4), + STC(0x7f4c7e54), STC(0x7e6c9251), STC(0x7d33f0ca), STC(0x7ba3751d), + STC(0x79bc384d), STC(0x777f903c), STC(0x74ef0ebc), STC(0x720c8075), + STC(0x6ed9eba1), STC(0x6b598ea3), STC(0x678dde6e), STC(0x637984d4), + STC(0x5f1f5ea1), STC(0x5a82799a), STC(0x7f9afcb9), STC(0x7e6c9251), + STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), STC(0x720c8075), + STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), STC(0x5a82799a), + STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), STC(0x3a1c5c57), + STC(0x30fbc54d), STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), + STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), + STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), + STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), + STC(0x658c9a2d), STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), + STC(0x30fbc54d), STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), + STC(0xef4aeaf1), STC(0xdedf047d), STC(0xcf043ab3), STC(0x7e6c9251), + STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), + STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), + STC(0x00000000), STC(0xebf9f498), STC(0xd8722192), STC(0xc5e3a3a9), + STC(0xb4c373ee), STC(0xa57d8666), STC(0x7ddb4bfc), STC(0x777f903c), + STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), STC(0x3a1c5c57), + STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d67), STC(0xdedf047d), + STC(0xc8e5032b), STC(0xb4c373ee), STC(0xa326eec0), STC(0x94a6715d), + STC(0x89be50c3), STC(0x7d33f0ca), STC(0x74ef0ebc), STC(0x678dde6e), + STC(0x55a6125c), STC(0x40000000), STC(0x278dde6e), STC(0x0d61304e), + STC(0xf29ecfb2), STC(0xd8722192), STC(0xc0000000), STC(0xaa59eda4), + STC(0x98722192), STC(0x8b10f144), STC(0x82cc0f36), STC(0x80000000), + STC(0x7c769e18), STC(0x720c8075), STC(0x6154fb91), STC(0x4b3c8c12), + STC(0x30fbc54d), STC(0x14060b68), STC(0xf5f50d67), STC(0xd8722192), + STC(0xbd1ec45c), STC(0xa57d8666), STC(0x92dcafe5), STC(0x8643c7b3), + STC(0x80650347), STC(0x81936daf), STC(0x89be50c3), STC(0x7ba3751d), + STC(0x6ed9eba1), STC(0x5a82799a), STC(0x40000000), STC(0x2120fb83), + STC(0x00000000), STC(0xdedf047d), STC(0xc0000000), STC(0xa57d8666), + STC(0x9126145f), STC(0x845c8ae3), STC(0x80000000), STC(0x845c8ae3), + STC(0x9126145f), STC(0xa57d8666), STC(0x7aba9ae6), STC(0x6b598ea3), + STC(0x53211d18), STC(0x340ff242), STC(0x10b5150f), STC(0xebf9f498), + STC(0xc8e5032b), STC(0xaa59eda4), STC(0x92dcafe5), STC(0x845c8ae3), + STC(0x800b3a91), STC(0x8643c7b3), STC(0x96830876), STC(0xaf726def), + STC(0xcf043ab3), STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), + STC(0x278dde6e), STC(0x00000000), STC(0xd8722192), STC(0xb4c373ee), + STC(0x98722192), STC(0x8643c7b3), STC(0x80000000), STC(0x8643c7b3), + STC(0x98722192), STC(0xb4c373ee), STC(0xd8722192), STC(0x00000000), + STC(0x78a879f4), STC(0x637984d4), STC(0x42e13ba4), STC(0x1a9cd9ac), + STC(0xef4aeaf1), STC(0xc5e3a3a9), STC(0xa326eec0), STC(0x8b10f144), + STC(0x80650347), STC(0x845c8ae3), STC(0x96830876), STC(0xb4c373ee), + STC(0xdba5629b), STC(0x06b2f1d2), STC(0x30fbc54d), STC(0x777f903c), + STC(0x5f1f5ea1), STC(0x3a1c5c57), STC(0x0d61304e), STC(0xdedf047d), + STC(0xb4c373ee), STC(0x94a6715d), STC(0x82cc0f36), STC(0x81936daf), + STC(0x9126145f), STC(0xaf726def), STC(0xd8722192), STC(0x06b2f1d2), + STC(0x340ff242), STC(0x5a82799a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag240[] = { + STC(0x0359c428), STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), + STC(0x10b5150f), STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), + STC(0x1de189a6), STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), + STC(0x2aba2ee4), STC(0x2ddf0040), STC(0x30fbc54d), STC(0x06b2f1d2), + STC(0x0d61304e), STC(0x14060b68), STC(0x1a9cd9ac), STC(0x2120fb83), + STC(0x278dde6e), STC(0x2ddf0040), STC(0x340ff242), STC(0x3a1c5c57), + STC(0x40000000), STC(0x45b6bb5e), STC(0x4b3c8c12), STC(0x508d9211), + STC(0x55a6125c), STC(0x5a82799a), STC(0x0a0af299), STC(0x14060b68), + STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), STC(0x3a1c5c57), + STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), STC(0x5a82799a), + STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), STC(0x720c8075), + STC(0x7641af3d), STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), + STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), + STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), + STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), + STC(0x10b5150f), STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), + STC(0x4debe4fe), STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), + STC(0x7641af3d), STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), + STC(0x7ee7aa4c), STC(0x7ba3751d), STC(0x7641af3d), STC(0x14060b68), + STC(0x278dde6e), STC(0x3a1c5c57), STC(0x4b3c8c12), STC(0x5a82799a), + STC(0x678dde6e), STC(0x720c8075), STC(0x79bc384d), STC(0x7e6c9251), + STC(0x7fffffff), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), + STC(0x678dde6e), STC(0x5a82799a), STC(0x17537e63), STC(0x2ddf0040), + STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), STC(0x720c8075), + STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), STC(0x7ba3751d), + STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), STC(0x45b6bb5e), + STC(0x30fbc54d), STC(0x1a9cd9ac), STC(0x340ff242), STC(0x4b3c8c12), + STC(0x5f1f5ea1), STC(0x6ed9eba1), STC(0x79bc384d), STC(0x7f4c7e54), + STC(0x7f4c7e54), STC(0x79bc384d), STC(0x6ed9eba1), STC(0x5f1f5ea1), + STC(0x4b3c8c12), STC(0x340ff242), STC(0x1a9cd9ac), STC(0x00000000), + STC(0x1de189a6), STC(0x3a1c5c57), STC(0x53211d18), STC(0x678dde6e), + STC(0x7641af3d), STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x79bc384d), + STC(0x6d23501b), STC(0x5a82799a), STC(0x42e13ba4), STC(0x278dde6e), + STC(0x0a0af299), STC(0xebf9f498), STC(0xcf043ab3), STC(0x2120fb83), + STC(0x40000000), STC(0x5a82799a), STC(0x6ed9eba1), STC(0x7ba3751d), + STC(0x7fffffff), STC(0x7ba3751d), STC(0x6ed9eba1), STC(0x5a82799a), + STC(0x40000000), STC(0x2120fb83), STC(0x00000000), STC(0xdedf047d), + STC(0xc0000000), STC(0xa57d8666), STC(0x245a9d65), STC(0x45b6bb5e), + STC(0x6154fb91), STC(0x74ef0ebc), STC(0x7ee7aa4c), STC(0x7e6c9251), + STC(0x7387ea23), STC(0x5f1f5ea1), STC(0x42e13ba4), STC(0x2120fb83), + STC(0xfca63bd8), STC(0xd8722192), STC(0xb780001c), STC(0x9c867b2c), + STC(0x89be50c3), STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), + STC(0x79bc384d), STC(0x7fffffff), STC(0x79bc384d), STC(0x678dde6e), + STC(0x4b3c8c12), STC(0x278dde6e), STC(0x00000000), STC(0xd8722192), + STC(0xb4c373ee), STC(0x98722192), STC(0x8643c7b3), STC(0x80000000), + STC(0x2aba2ee4), STC(0x508d9211), STC(0x6d23501b), STC(0x7d33f0ca), + STC(0x7ee7aa4c), STC(0x720c8075), STC(0x581c00b3), STC(0x340ff242), + STC(0x0a0af299), STC(0xdedf047d), STC(0xb780001c), STC(0x98722192), + STC(0x8545651a), STC(0x802ce84c), STC(0x89be50c3), STC(0x2ddf0040), + STC(0x55a6125c), STC(0x720c8075), STC(0x7f4c7e54), STC(0x7ba3751d), + STC(0x678dde6e), STC(0x45b6bb5e), STC(0x1a9cd9ac), STC(0xebf9f498), + STC(0xc0000000), STC(0x9c867b2c), STC(0x8643c7b3), STC(0x802ce84c), + STC(0x8b10f144), STC(0xa57d8666), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal480[] = { + STC(0x7ffd3154), STC(0x7ff4c56f), STC(0x7fe6bcb0), STC(0x7fd317b4), + STC(0x7fb9d759), STC(0x7f9afcb9), STC(0x7f76892f), STC(0x7f4c7e54), + STC(0x7f1cde01), STC(0x7ee7aa4c), STC(0x7eace58a), STC(0x7e6c9251), + STC(0x7e26b371), STC(0x7ddb4bfc), STC(0x7d8a5f40), STC(0x7d33f0ca), + STC(0x7cd80464), STC(0x7c769e18), STC(0x7c0fc22a), STC(0x7ba3751d), + STC(0x7b31bbb2), STC(0x7aba9ae6), STC(0x7a3e17f2), STC(0x79bc384d), + STC(0x793501a9), STC(0x78a879f4), STC(0x7816a759), STC(0x777f903c), + STC(0x76e33b3f), STC(0x7641af3d), STC(0x759af34c), STC(0x7ff4c56f), + STC(0x7fd317b4), STC(0x7f9afcb9), STC(0x7f4c7e54), STC(0x7ee7aa4c), + STC(0x7e6c9251), STC(0x7ddb4bfc), STC(0x7d33f0ca), STC(0x7c769e18), + STC(0x7ba3751d), STC(0x7aba9ae6), STC(0x79bc384d), STC(0x78a879f4), + STC(0x777f903c), STC(0x7641af3d), STC(0x74ef0ebc), STC(0x7387ea23), + STC(0x720c8075), STC(0x707d1443), STC(0x6ed9eba1), STC(0x6d23501b), + STC(0x6b598ea3), STC(0x697cf78a), STC(0x678dde6e), STC(0x658c9a2d), + STC(0x637984d4), STC(0x6154fb91), STC(0x5f1f5ea1), STC(0x5cd91140), + STC(0x5a82799a), STC(0x581c00b3), STC(0x7fe6bcb0), STC(0x7f9afcb9), + STC(0x7f1cde01), STC(0x7e6c9251), STC(0x7d8a5f40), STC(0x7c769e18), + STC(0x7b31bbb2), STC(0x79bc384d), STC(0x7816a759), STC(0x7641af3d), + STC(0x743e0918), STC(0x720c8075), STC(0x6fadf2fc), STC(0x6d23501b), + STC(0x6a6d98a4), STC(0x678dde6e), STC(0x648543e4), STC(0x6154fb91), + STC(0x5dfe47ad), STC(0x5a82799a), STC(0x56e2f15d), STC(0x53211d18), + STC(0x4f3e7875), STC(0x4b3c8c12), STC(0x471cece7), STC(0x42e13ba4), + STC(0x3e8b240e), STC(0x3a1c5c57), STC(0x3596a46c), STC(0x30fbc54d), + STC(0x2c4d9050), STC(0x7fd317b4), STC(0x7f4c7e54), STC(0x7e6c9251), + STC(0x7d33f0ca), STC(0x7ba3751d), STC(0x79bc384d), STC(0x777f903c), + STC(0x74ef0ebc), STC(0x720c8075), STC(0x6ed9eba1), STC(0x6b598ea3), + STC(0x678dde6e), STC(0x637984d4), STC(0x5f1f5ea1), STC(0x5a82799a), + STC(0x55a6125c), STC(0x508d9211), STC(0x4b3c8c12), STC(0x45b6bb5e), + STC(0x40000000), STC(0x3a1c5c57), STC(0x340ff242), STC(0x2ddf0040), + STC(0x278dde6e), STC(0x2120fb83), STC(0x1a9cd9ac), STC(0x14060b68), + STC(0x0d61304e), STC(0x06b2f1d2), STC(0x00000000), STC(0xf94d0e2e), + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), + STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), STC(0x6ed9eba1), + STC(0x6a6d98a4), STC(0x658c9a2d), STC(0x603c496c), STC(0x5a82799a), + STC(0x54657194), STC(0x4debe4fe), STC(0x471cece7), STC(0x40000000), + STC(0x389cea72), STC(0x30fbc54d), STC(0x2924edac), STC(0x2120fb83), + STC(0x18f8b83c), STC(0x10b5150f), STC(0x085f2137), STC(0x00000000), + STC(0xf7a0dec9), STC(0xef4aeaf1), STC(0xe70747c4), STC(0xdedf047d), + STC(0xd6db1254), STC(0xcf043ab3), STC(0xc763158e), STC(0x7f9afcb9), + STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), + STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), + STC(0x5a82799a), STC(0x53211d18), STC(0x4b3c8c12), STC(0x42e13ba4), + STC(0x3a1c5c57), STC(0x30fbc54d), STC(0x278dde6e), STC(0x1de189a6), + STC(0x14060b68), STC(0x0a0af299), STC(0x00000000), STC(0xf5f50d67), + STC(0xebf9f498), STC(0xe21e765a), STC(0xd8722192), STC(0xcf043ab3), + STC(0xc5e3a3a9), STC(0xbd1ec45c), STC(0xb4c373ee), STC(0xacdee2e8), + STC(0xa57d8666), STC(0x9eab046f), STC(0x7f76892f), STC(0x7ddb4bfc), + STC(0x7b31bbb2), STC(0x777f903c), STC(0x72ccb9db), STC(0x6d23501b), + STC(0x668f7c25), STC(0x5f1f5ea1), STC(0x56e2f15d), STC(0x4debe4fe), + STC(0x444d7aff), STC(0x3a1c5c57), STC(0x2f6e6d16), STC(0x245a9d65), + STC(0x18f8b83c), STC(0x0d61304e), STC(0x01aceb7c), STC(0xf5f50d67), + STC(0xea52c166), STC(0xdedf047d), STC(0xd3b26fb0), STC(0xc8e5032b), + STC(0xbe8df2ba), STC(0xb4c373ee), STC(0xab9a8e6c), STC(0xa326eec0), + STC(0x9b7abc1c), STC(0x94a6715d), STC(0x8eb8b9a0), STC(0x89be50c3), + STC(0x85c1e80e), STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), + STC(0x74ef0ebc), STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), + STC(0x55a6125c), STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), + STC(0x278dde6e), STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), + STC(0xf29ecfb2), STC(0xe5632654), STC(0xd8722192), STC(0xcbf00dbe), + STC(0xc0000000), STC(0xb4c373ee), STC(0xaa59eda4), STC(0xa0e0a15f), + STC(0x98722192), STC(0x9126145f), STC(0x8b10f144), STC(0x8643c7b3), + STC(0x82cc0f36), STC(0x80b381ac), STC(0x80000000), STC(0x80b381ac), + STC(0x7f1cde01), STC(0x7c769e18), STC(0x7816a759), STC(0x720c8075), + STC(0x6a6d98a4), STC(0x6154fb91), STC(0x56e2f15d), STC(0x4b3c8c12), + STC(0x3e8b240e), STC(0x30fbc54d), STC(0x22be8f87), STC(0x14060b68), + STC(0x05067734), STC(0xf5f50d67), STC(0xe70747c4), STC(0xd8722192), + STC(0xca695b94), STC(0xbd1ec45c), STC(0xb0c1878b), STC(0xa57d8666), + STC(0x9b7abc1c), STC(0x92dcafe5), STC(0x8bc1f6e8), STC(0x8643c7b3), + STC(0x8275a0c0), STC(0x80650347), STC(0x80194350), STC(0x81936daf), + STC(0x84ce444e), STC(0x89be50c3), STC(0x90520d04), STC(0x7ee7aa4c), + STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), + STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), + STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf1), + STC(0xdedf047d), STC(0xcf043ab3), STC(0xc0000000), STC(0xb2141b02), + STC(0xa57d8666), STC(0x9a7365d3), STC(0x9126145f), STC(0x89be50c3), + STC(0x845c8ae3), STC(0x811855b4), STC(0x80000000), STC(0x811855b4), + STC(0x845c8ae3), STC(0x89be50c3), STC(0x9126145f), STC(0x9a7365d3), + STC(0xa57d8666), STC(0xb2141b02), STC(0x7eace58a), STC(0x7aba9ae6), + STC(0x743e0918), STC(0x6b598ea3), STC(0x603c496c), STC(0x53211d18), + STC(0x444d7aff), STC(0x340ff242), STC(0x22be8f87), STC(0x10b5150f), + STC(0xfe531484), STC(0xebf9f498), STC(0xda0aecf9), STC(0xc8e5032b), + STC(0xb8e31319), STC(0xaa59eda4), STC(0x9d969742), STC(0x92dcafe5), + STC(0x8a650cb4), STC(0x845c8ae3), STC(0x80e321ff), STC(0x800b3a91), + STC(0x81d94c8f), STC(0x8643c7b3), STC(0x8d334625), STC(0x96830876), + STC(0xa201b853), STC(0xaf726def), STC(0xbe8df2ba), STC(0xcf043ab3), + STC(0xe07e0c84), STC(0x7e6c9251), STC(0x79bc384d), STC(0x720c8075), + STC(0x678dde6e), STC(0x5a82799a), STC(0x4b3c8c12), STC(0x3a1c5c57), + STC(0x278dde6e), STC(0x14060b68), STC(0x00000000), STC(0xebf9f498), + STC(0xd8722192), STC(0xc5e3a3a9), STC(0xb4c373ee), STC(0xa57d8666), + STC(0x98722192), STC(0x8df37f8b), STC(0x8643c7b3), STC(0x81936daf), + STC(0x80000000), STC(0x81936daf), STC(0x8643c7b3), STC(0x8df37f8b), + STC(0x98722192), STC(0xa57d8666), STC(0xb4c373ee), STC(0xc5e3a3a9), + STC(0xd8722192), STC(0xebf9f498), STC(0x00000000), STC(0x14060b68), + STC(0x7e26b371), STC(0x78a879f4), STC(0x6fadf2fc), STC(0x637984d4), + STC(0x54657194), STC(0x42e13ba4), STC(0x2f6e6d16), STC(0x1a9cd9ac), + STC(0x05067734), STC(0xef4aeaf1), STC(0xda0aecf9), STC(0xc5e3a3a9), + STC(0xb36a1978), STC(0xa326eec0), STC(0x9592675c), STC(0x8b10f144), + STC(0x83f03dd6), STC(0x80650347), STC(0x808976d1), STC(0x845c8ae3), + STC(0x8bc1f6e8), STC(0x96830876), STC(0xa45037c9), STC(0xb4c373ee), + STC(0xc763158e), STC(0xdba5629b), STC(0xf0f488d9), STC(0x06b2f1d2), + STC(0x1c3fd045), STC(0x30fbc54d), STC(0x444d7aff), STC(0x7ddb4bfc), + STC(0x777f903c), STC(0x6d23501b), STC(0x5f1f5ea1), STC(0x4debe4fe), + STC(0x3a1c5c57), STC(0x245a9d65), STC(0x0d61304e), STC(0xf5f50d67), + STC(0xdedf047d), STC(0xc8e5032b), STC(0xb4c373ee), STC(0xa326eec0), + STC(0x94a6715d), STC(0x89be50c3), STC(0x82cc0f36), STC(0x800b3a91), + STC(0x81936daf), STC(0x8757860c), STC(0x9126145f), STC(0x9eab046f), + STC(0xaf726def), STC(0xc2ec7635), STC(0xd8722192), STC(0xef4aeaf1), + STC(0x06b2f1d2), STC(0x1de189a6), STC(0x340ff242), STC(0x487fffe4), + STC(0x5a82799a), STC(0x697cf78a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag480[] = { + STC(0x01aceb7c), STC(0x0359c428), STC(0x05067734), STC(0x06b2f1d2), + STC(0x085f2137), STC(0x0a0af299), STC(0x0bb65336), STC(0x0d61304e), + STC(0x0f0b7727), STC(0x10b5150f), STC(0x125df75b), STC(0x14060b68), + STC(0x15ad3e9a), STC(0x17537e63), STC(0x18f8b83c), STC(0x1a9cd9ac), + STC(0x1c3fd045), STC(0x1de189a6), STC(0x1f81f37c), STC(0x2120fb83), + STC(0x22be8f87), STC(0x245a9d65), STC(0x25f51307), STC(0x278dde6e), + STC(0x2924edac), STC(0x2aba2ee4), STC(0x2c4d9050), STC(0x2ddf0040), + STC(0x2f6e6d16), STC(0x30fbc54d), STC(0x3286f779), STC(0x0359c428), + STC(0x06b2f1d2), STC(0x0a0af299), STC(0x0d61304e), STC(0x10b5150f), + STC(0x14060b68), STC(0x17537e63), STC(0x1a9cd9ac), STC(0x1de189a6), + STC(0x2120fb83), STC(0x245a9d65), STC(0x278dde6e), STC(0x2aba2ee4), + STC(0x2ddf0040), STC(0x30fbc54d), STC(0x340ff242), STC(0x371afcd5), + STC(0x3a1c5c57), STC(0x3d1389cb), STC(0x40000000), STC(0x42e13ba4), + STC(0x45b6bb5e), STC(0x487fffe4), STC(0x4b3c8c12), STC(0x4debe4fe), + STC(0x508d9211), STC(0x53211d18), STC(0x55a6125c), STC(0x581c00b3), + STC(0x5a82799a), STC(0x5cd91140), STC(0x05067734), STC(0x0a0af299), + STC(0x0f0b7727), STC(0x14060b68), STC(0x18f8b83c), STC(0x1de189a6), + STC(0x22be8f87), STC(0x278dde6e), STC(0x2c4d9050), STC(0x30fbc54d), + STC(0x3596a46c), STC(0x3a1c5c57), STC(0x3e8b240e), STC(0x42e13ba4), + STC(0x471cece7), STC(0x4b3c8c12), STC(0x4f3e7875), STC(0x53211d18), + STC(0x56e2f15d), STC(0x5a82799a), STC(0x5dfe47ad), STC(0x6154fb91), + STC(0x648543e4), STC(0x678dde6e), STC(0x6a6d98a4), STC(0x6d23501b), + STC(0x6fadf2fc), STC(0x720c8075), STC(0x743e0918), STC(0x7641af3d), + STC(0x7816a759), STC(0x06b2f1d2), STC(0x0d61304e), STC(0x14060b68), + STC(0x1a9cd9ac), STC(0x2120fb83), STC(0x278dde6e), STC(0x2ddf0040), + STC(0x340ff242), STC(0x3a1c5c57), STC(0x40000000), STC(0x45b6bb5e), + STC(0x4b3c8c12), STC(0x508d9211), STC(0x55a6125c), STC(0x5a82799a), + STC(0x5f1f5ea1), STC(0x637984d4), STC(0x678dde6e), STC(0x6b598ea3), + STC(0x6ed9eba1), STC(0x720c8075), STC(0x74ef0ebc), STC(0x777f903c), + STC(0x79bc384d), STC(0x7ba3751d), STC(0x7d33f0ca), STC(0x7e6c9251), + STC(0x7f4c7e54), STC(0x7fd317b4), STC(0x7fffffff), STC(0x7fd317b4), + STC(0x085f2137), STC(0x10b5150f), STC(0x18f8b83c), STC(0x2120fb83), + STC(0x2924edac), STC(0x30fbc54d), STC(0x389cea72), STC(0x40000000), + STC(0x471cece7), STC(0x4debe4fe), STC(0x54657194), STC(0x5a82799a), + STC(0x603c496c), STC(0x658c9a2d), STC(0x6a6d98a4), STC(0x6ed9eba1), + STC(0x72ccb9db), STC(0x7641af3d), STC(0x793501a9), STC(0x7ba3751d), + STC(0x7d8a5f40), STC(0x7ee7aa4c), STC(0x7fb9d759), STC(0x7fffffff), + STC(0x7fb9d759), STC(0x7ee7aa4c), STC(0x7d8a5f40), STC(0x7ba3751d), + STC(0x793501a9), STC(0x7641af3d), STC(0x72ccb9db), STC(0x0a0af299), + STC(0x14060b68), STC(0x1de189a6), STC(0x278dde6e), STC(0x30fbc54d), + STC(0x3a1c5c57), STC(0x42e13ba4), STC(0x4b3c8c12), STC(0x53211d18), + STC(0x5a82799a), STC(0x6154fb91), STC(0x678dde6e), STC(0x6d23501b), + STC(0x720c8075), STC(0x7641af3d), STC(0x79bc384d), STC(0x7c769e18), + STC(0x7e6c9251), STC(0x7f9afcb9), STC(0x7fffffff), STC(0x7f9afcb9), + STC(0x7e6c9251), STC(0x7c769e18), STC(0x79bc384d), STC(0x7641af3d), + STC(0x720c8075), STC(0x6d23501b), STC(0x678dde6e), STC(0x6154fb91), + STC(0x5a82799a), STC(0x53211d18), STC(0x0bb65336), STC(0x17537e63), + STC(0x22be8f87), STC(0x2ddf0040), STC(0x389cea72), STC(0x42e13ba4), + STC(0x4c95e688), STC(0x55a6125c), STC(0x5dfe47ad), STC(0x658c9a2d), + STC(0x6c40cf2c), STC(0x720c8075), STC(0x76e33b3f), STC(0x7aba9ae6), + STC(0x7d8a5f40), STC(0x7f4c7e54), STC(0x7ffd3154), STC(0x7f9afcb9), + STC(0x7e26b371), STC(0x7ba3751d), STC(0x7816a759), STC(0x7387ea23), + STC(0x6e010780), STC(0x678dde6e), STC(0x603c496c), STC(0x581c00b3), + STC(0x4f3e7875), STC(0x45b6bb5e), STC(0x3b9941b1), STC(0x30fbc54d), + STC(0x25f51307), STC(0x0d61304e), STC(0x1a9cd9ac), STC(0x278dde6e), + STC(0x340ff242), STC(0x40000000), STC(0x4b3c8c12), STC(0x55a6125c), + STC(0x5f1f5ea1), STC(0x678dde6e), STC(0x6ed9eba1), STC(0x74ef0ebc), + STC(0x79bc384d), STC(0x7d33f0ca), STC(0x7f4c7e54), STC(0x7fffffff), + STC(0x7f4c7e54), STC(0x7d33f0ca), STC(0x79bc384d), STC(0x74ef0ebc), + STC(0x6ed9eba1), STC(0x678dde6e), STC(0x5f1f5ea1), STC(0x55a6125c), + STC(0x4b3c8c12), STC(0x40000000), STC(0x340ff242), STC(0x278dde6e), + STC(0x1a9cd9ac), STC(0x0d61304e), STC(0x00000000), STC(0xf29ecfb2), + STC(0x0f0b7727), STC(0x1de189a6), STC(0x2c4d9050), STC(0x3a1c5c57), + STC(0x471cece7), STC(0x53211d18), STC(0x5dfe47ad), STC(0x678dde6e), + STC(0x6fadf2fc), STC(0x7641af3d), STC(0x7b31bbb2), STC(0x7e6c9251), + STC(0x7fe6bcb0), STC(0x7f9afcb9), STC(0x7d8a5f40), STC(0x79bc384d), + STC(0x743e0918), STC(0x6d23501b), STC(0x648543e4), STC(0x5a82799a), + STC(0x4f3e7875), STC(0x42e13ba4), STC(0x3596a46c), STC(0x278dde6e), + STC(0x18f8b83c), STC(0x0a0af299), STC(0xfaf988cc), STC(0xebf9f498), + STC(0xdd417079), STC(0xcf043ab3), STC(0xc174dbf2), STC(0x10b5150f), + STC(0x2120fb83), STC(0x30fbc54d), STC(0x40000000), STC(0x4debe4fe), + STC(0x5a82799a), STC(0x658c9a2d), STC(0x6ed9eba1), STC(0x7641af3d), + STC(0x7ba3751d), STC(0x7ee7aa4c), STC(0x7fffffff), STC(0x7ee7aa4c), + STC(0x7ba3751d), STC(0x7641af3d), STC(0x6ed9eba1), STC(0x658c9a2d), + STC(0x5a82799a), STC(0x4debe4fe), STC(0x40000000), STC(0x30fbc54d), + STC(0x2120fb83), STC(0x10b5150f), STC(0x00000000), STC(0xef4aeaf1), + STC(0xdedf047d), STC(0xcf043ab3), STC(0xc0000000), STC(0xb2141b02), + STC(0xa57d8666), STC(0x9a7365d3), STC(0x125df75b), STC(0x245a9d65), + STC(0x3596a46c), STC(0x45b6bb5e), STC(0x54657194), STC(0x6154fb91), + STC(0x6c40cf2c), STC(0x74ef0ebc), STC(0x7b31bbb2), STC(0x7ee7aa4c), + STC(0x7ffd3154), STC(0x7e6c9251), STC(0x7a3e17f2), STC(0x7387ea23), + STC(0x6a6d98a4), STC(0x5f1f5ea1), STC(0x51d92321), STC(0x42e13ba4), + STC(0x3286f779), STC(0x2120fb83), STC(0x0f0b7727), STC(0xfca63bd8), + STC(0xea52c166), STC(0xd8722192), STC(0xc763158e), STC(0xb780001c), + STC(0xa91d0ea3), STC(0x9c867b2c), STC(0x91fef880), STC(0x89be50c3), + STC(0x83f03dd6), STC(0x14060b68), STC(0x278dde6e), STC(0x3a1c5c57), + STC(0x4b3c8c12), STC(0x5a82799a), STC(0x678dde6e), STC(0x720c8075), + STC(0x79bc384d), STC(0x7e6c9251), STC(0x7fffffff), STC(0x7e6c9251), + STC(0x79bc384d), STC(0x720c8075), STC(0x678dde6e), STC(0x5a82799a), + STC(0x4b3c8c12), STC(0x3a1c5c57), STC(0x278dde6e), STC(0x14060b68), + STC(0x00000000), STC(0xebf9f498), STC(0xd8722192), STC(0xc5e3a3a9), + STC(0xb4c373ee), STC(0xa57d8666), STC(0x98722192), STC(0x8df37f8b), + STC(0x8643c7b3), STC(0x81936daf), STC(0x80000000), STC(0x81936daf), + STC(0x15ad3e9a), STC(0x2aba2ee4), STC(0x3e8b240e), STC(0x508d9211), + STC(0x603c496c), STC(0x6d23501b), STC(0x76e33b3f), STC(0x7d33f0ca), + STC(0x7fe6bcb0), STC(0x7ee7aa4c), STC(0x7a3e17f2), STC(0x720c8075), + STC(0x668f7c25), STC(0x581c00b3), STC(0x471cece7), STC(0x340ff242), + STC(0x1f81f37c), STC(0x0a0af299), STC(0xf449acca), STC(0xdedf047d), + STC(0xca695b94), STC(0xb780001c), STC(0xa6aecd5e), STC(0x98722192), + STC(0x8d334625), STC(0x8545651a), STC(0x80e321ff), STC(0x802ce84c), + STC(0x8327fb9c), STC(0x89be50c3), STC(0x93bf30d4), STC(0x17537e63), + STC(0x2ddf0040), STC(0x42e13ba4), STC(0x55a6125c), STC(0x658c9a2d), + STC(0x720c8075), STC(0x7aba9ae6), STC(0x7f4c7e54), STC(0x7f9afcb9), + STC(0x7ba3751d), STC(0x7387ea23), STC(0x678dde6e), STC(0x581c00b3), + STC(0x45b6bb5e), STC(0x30fbc54d), STC(0x1a9cd9ac), STC(0x0359c428), + STC(0xebf9f498), STC(0xd545d11c), STC(0xc0000000), STC(0xacdee2e8), + STC(0x9c867b2c), STC(0x8f82ebbd), STC(0x8643c7b3), STC(0x811855b4), + STC(0x802ce84c), STC(0x838961e8), STC(0x8b10f144), STC(0x96830876), + STC(0xa57d8666), STC(0xb780001c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorReal20[] = { + STC(0x79bc384d), STC(0x678dde6e), STC(0x4b3c8c12), STC(0x678dde6e), + STC(0x278dde6e), STC(0xd8722192), STC(0x4b3c8c12), STC(0xd8722192), + STC(0x8643c7b3), STC(0x278dde6e), STC(0x98722192), STC(0x98722192), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_STB RotVectorImag20[] = { + STC(0x278dde6e), STC(0x4b3c8c12), STC(0x678dde6e), STC(0x4b3c8c12), + STC(0x79bc384d), STC(0x79bc384d), STC(0x678dde6e), STC(0x79bc384d), + STC(0x278dde6e), STC(0x79bc384d), STC(0x4b3c8c12), STC(0xb4c373ee), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow8[] = { + WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7a7d055b, 0x25280c5e), + WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x62f201ac, 0x5133cc94), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow12[] = { + WTCP(0x7fb9d759, 0x085f2137), WTCP(0x7d8a5f40, 0x18f8b83c), + WTCP(0x793501a9, 0x2924edac), WTCP(0x72ccb9db, 0x389cea72), + WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x603c496c, 0x54657194), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow16[] = { + WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7e9d55fc, 0x12c8106f), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x78848414, 0x2b1f34eb), + WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x6dca0d14, 0x41ce1e65), + WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x5ed77c8a, 0x55f5a4d2), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow20[] = { + WTCP(0x7fe6bcb0, 0x05067734), WTCP(0x7f1cde01, 0x0f0b7727), + WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7b31bbb2, 0x22be8f87), + WTCP(0x7816a759, 0x2c4d9050), WTCP(0x743e0918, 0x3596a46c), + WTCP(0x6fadf2fc, 0x3e8b240e), WTCP(0x6a6d98a4, 0x471cece7), + WTCP(0x648543e4, 0x4f3e7875), WTCP(0x5dfe47ad, 0x56e2f15d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow24[] = { + WTCP(0x7fee74a2, 0x0430238f), WTCP(0x7f62368f, 0x0c8bd35e), + WTCP(0x7e4a5426, 0x14d9c245), WTCP(0x7ca80038, 0x1d10d5c2), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x77cbc3f2, 0x2d168792), + WTCP(0x74972f92, 0x34d3957e), WTCP(0x70e2cbc6, 0x3c56ba70), + WTCP(0x6cb2a837, 0x4397ba32), WTCP(0x680b5c33, 0x4a8ea111), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x5d6c2f99, 0x577ff3da), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow32[] = { + WTCP(0x7ff62182, 0x03242abf), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f0991c4, 0x0fab272b), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7ce3ceb2, 0x1c0b826a), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x798a23b1, 0x2826b928), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x7504d345, 0x33def287), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x6f5f02b2, 0x3f1749b8), WTCP(0x6c242960, 0x447acd50), + WTCP(0x68a69e81, 0x49b41533), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x60ec3830, 0x539b2af0), WTCP(0x5cb420e0, 0x5842dd54), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow40[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow48[] = { + WTCP(0x7ffb9d15, 0x02182427), WTCP(0x7fd8878e, 0x0647d97c), + WTCP(0x7f92661d, 0x0a75d60e), WTCP(0x7f294bfd, 0x0ea0f48c), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7deeaa7a, 0x16ea0646), + WTCP(0x7d1d7958, 0x1b05b40f), WTCP(0x7c29fbee, 0x1f19f97b), + WTCP(0x7b1474fd, 0x2325b847), WTCP(0x79dd3098, 0x2727d486), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x770acdec, 0x2f0ac320), + WTCP(0x757075ac, 0x32e96c09), WTCP(0x73b5ebd1, 0x36ba2014), + WTCP(0x71dba9ab, 0x3a7bd382), WTCP(0x6fe2313c, 0x3e2d7eb1), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6b93d02e, 0x455cb40c), + WTCP(0x694015c3, 0x48d84609), WTCP(0x66cf8120, 0x4c3fdff4), + WTCP(0x6442bd7e, 0x4f9292dc), WTCP(0x619a7dce, 0x52cf758f), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5bfa7b82, 0x590443a7), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow64[] = { + WTCP(0x7ffd885a, 0x01921d20), WTCP(0x7fe9cbc0, 0x04b6195d), + WTCP(0x7fc25596, 0x07d95b9e), WTCP(0x7f872bf3, 0x0afb6805), + WTCP(0x7f3857f6, 0x0e1bc2e4), WTCP(0x7ed5e5c6, 0x1139f0cf), + WTCP(0x7e5fe493, 0x145576b1), WTCP(0x7dd6668f, 0x176dd9de), + WTCP(0x7d3980ec, 0x1a82a026), WTCP(0x7c894bde, 0x1d934fe5), + WTCP(0x7bc5e290, 0x209f701c), WTCP(0x7aef6323, 0x23a6887f), + WTCP(0x7a05eead, 0x26a82186), WTCP(0x7909a92d, 0x29a3c485), + WTCP(0x77fab989, 0x2c98fbba), WTCP(0x76d94989, 0x2f875262), + WTCP(0x75a585cf, 0x326e54c7), WTCP(0x745f9dd1, 0x354d9057), + WTCP(0x7307c3d0, 0x382493b0), WTCP(0x719e2cd2, 0x3af2eeb7), + WTCP(0x7023109a, 0x3db832a6), WTCP(0x6e96a99d, 0x4073f21d), + WTCP(0x6cf934fc, 0x4325c135), WTCP(0x6b4af279, 0x45cd358f), + WTCP(0x698c246c, 0x4869e665), WTCP(0x67bd0fbd, 0x4afb6c98), + WTCP(0x65ddfbd3, 0x4d8162c4), WTCP(0x63ef3290, 0x4ffb654d), + WTCP(0x61f1003f, 0x5269126e), WTCP(0x5fe3b38d, 0x54ca0a4b), + WTCP(0x5dc79d7c, 0x571deefa), WTCP(0x5b9d1154, 0x59646498), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow96[] = { + WTCP(0x7ffee744, 0x010c1460), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7fe49698, 0x053c0a01), WTCP(0x7fca47b9, 0x07538d6b), + WTCP(0x7fa736b4, 0x096a9049), WTCP(0x7f7b65ef, 0x0b80edf1), + WTCP(0x7f46d86c, 0x0d9681c2), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7ec3962a, 0x11beb9aa), WTCP(0x7e74ea6a, 0x13d114d0), + WTCP(0x7e1d93ea, 0x15e21445), WTCP(0x7dbd98a4, 0x17f193c5), + WTCP(0x7d54ff2e, 0x19ff6f2a), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7c6a0ef2, 0x1e15a99a), WTCP(0x7be7c847, 0x201dc0ef), + WTCP(0x7b5d039e, 0x2223a4c5), WTCP(0x7ac9ca7a, 0x2427319d), + WTCP(0x7a2e26f2, 0x26284422), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x78ddcbf5, 0x2a226db5), WTCP(0x78292b8d, 0x2c1b3efb), + WTCP(0x776c4edb, 0x2e110a62), WTCP(0x76a742d1, 0x3003ad85), + WTCP(0x75da14ef, 0x31f30638), WTCP(0x7504d345, 0x33def287), + WTCP(0x74278c72, 0x35c750bc), WTCP(0x73424fa0, 0x37abff5d), + WTCP(0x72552c85, 0x398cdd32), WTCP(0x71603361, 0x3b69c947), + WTCP(0x706374ff, 0x3d42a2ec), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6e52ee52, 0x40e79d8c), WTCP(0x6d3f4a40, 0x42b37e96), + WTCP(0x6c242960, 0x447acd50), WTCP(0x6b019f1a, 0x463d6a87), + WTCP(0x69d7bf57, 0x47fb3757), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x676e5183, 0x4b67e5e4), WTCP(0x662eedc3, 0x4d168b8b), + WTCP(0x64e88926, 0x4ebfe8a5), WTCP(0x639b3a0b, 0x5063e008), + WTCP(0x62471749, 0x520254ef), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x5f8ab487, 0x552e4605), WTCP(0x5e22a487, 0x56bb8a90), + WTCP(0x5cb420e0, 0x5842dd54), WTCP(0x5b3f42ae, 0x59c42381), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow120[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow128[] = { + WTCP(0x7fff6216, 0x00c90f88), WTCP(0x7ffa72d1, 0x025b26d7), + WTCP(0x7ff09478, 0x03ed26e6), WTCP(0x7fe1c76b, 0x057f0035), + WTCP(0x7fce0c3e, 0x0710a345), WTCP(0x7fb563b3, 0x08a2009a), + WTCP(0x7f97cebd, 0x0a3308bd), WTCP(0x7f754e80, 0x0bc3ac35), + WTCP(0x7f4de451, 0x0d53db92), WTCP(0x7f2191b4, 0x0ee38766), + WTCP(0x7ef05860, 0x1072a048), WTCP(0x7eba3a39, 0x120116d5), + WTCP(0x7e7f3957, 0x138edbb1), WTCP(0x7e3f57ff, 0x151bdf86), + WTCP(0x7dfa98a8, 0x16a81305), WTCP(0x7db0fdf8, 0x183366e9), + WTCP(0x7d628ac6, 0x19bdcbf3), WTCP(0x7d0f4218, 0x1b4732ef), + WTCP(0x7cb72724, 0x1ccf8cb3), WTCP(0x7c5a3d50, 0x1e56ca1e), + WTCP(0x7bf88830, 0x1fdcdc1b), WTCP(0x7b920b89, 0x2161b3a0), + WTCP(0x7b26cb4f, 0x22e541af), WTCP(0x7ab6cba4, 0x24677758), + WTCP(0x7a4210d8, 0x25e845b6), WTCP(0x79c89f6e, 0x27679df4), + WTCP(0x794a7c12, 0x28e5714b), WTCP(0x78c7aba2, 0x2a61b101), + WTCP(0x78403329, 0x2bdc4e6f), WTCP(0x77b417df, 0x2d553afc), + WTCP(0x77235f2d, 0x2ecc681e), WTCP(0x768e0ea6, 0x3041c761), + WTCP(0x75f42c0b, 0x31b54a5e), WTCP(0x7555bd4c, 0x3326e2c3), + WTCP(0x74b2c884, 0x34968250), WTCP(0x740b53fb, 0x36041ad9), + WTCP(0x735f6626, 0x376f9e46), WTCP(0x72af05a7, 0x38d8fe93), + WTCP(0x71fa3949, 0x3a402dd2), WTCP(0x71410805, 0x3ba51e29), + WTCP(0x708378ff, 0x3d07c1d6), WTCP(0x6fc19385, 0x3e680b2c), + WTCP(0x6efb5f12, 0x3fc5ec98), WTCP(0x6e30e34a, 0x4121589b), + WTCP(0x6d6227fa, 0x427a41d0), WTCP(0x6c8f351c, 0x43d09aed), + WTCP(0x6bb812d1, 0x452456bd), WTCP(0x6adcc964, 0x46756828), + WTCP(0x69fd614a, 0x47c3c22f), WTCP(0x6919e320, 0x490f57ee), + WTCP(0x683257ab, 0x4a581c9e), WTCP(0x6746c7d8, 0x4b9e0390), + WTCP(0x66573cbb, 0x4ce10034), WTCP(0x6563bf92, 0x4e210617), + WTCP(0x646c59bf, 0x4f5e08e3), WTCP(0x637114cc, 0x5097fc5e), + WTCP(0x6271fa69, 0x51ced46e), WTCP(0x616f146c, 0x53028518), + WTCP(0x60686ccf, 0x5433027d), WTCP(0x5f5e0db3, 0x556040e2), + WTCP(0x5e50015d, 0x568a34a9), WTCP(0x5d3e5237, 0x57b0d256), + WTCP(0x5c290acc, 0x58d40e8c), WTCP(0x5b1035cf, 0x59f3de12), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow160[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow192[] = { + WTCP(0x7fffb9d1, 0x00860a79), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ff92577, 0x029e28e2), WTCP(0x7ff2913a, 0x03aa292a), + WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fded530, 0x05c1f4e7), + WTCP(0x7fd1adb9, 0x06cdb72f), WTCP(0x7fc25596, 0x07d95b9e), + WTCP(0x7fb0cd0a, 0x08e4dda0), WTCP(0x7f9d1461, 0x09f0389f), + WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f6f141f, 0x0c066740), + WTCP(0x7f54cd4f, 0x0d1131ba), WTCP(0x7f3857f6, 0x0e1bc2e4), + WTCP(0x7f19b491, 0x0f26162a), WTCP(0x7ef8e3a6, 0x103026fe), + WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7eb0bb8a, 0x12436f10), + WTCP(0x7e896595, 0x134c9d34), WTCP(0x7e5fe493, 0x145576b1), + WTCP(0x7e34393b, 0x155df6fc), WTCP(0x7e06644c, 0x1666198d), + WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7da440d6, 0x1875336a), + WTCP(0x7d6ff3fe, 0x197c21ad), WTCP(0x7d3980ec, 0x1a82a026), + WTCP(0x7d00e88f, 0x1b88aa55), WTCP(0x7cc62bdf, 0x1c8e3bbe), + WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7c4a4996, 0x1e97e251), + WTCP(0x7c09261d, 0x1f9bee8a), WTCP(0x7bc5e290, 0x209f701c), + WTCP(0x7b808015, 0x21a26295), WTCP(0x7b38ffde, 0x22a4c185), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7aa3ab29, 0x24a7b317), + WTCP(0x7a55d93a, 0x25a83ce6), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79b3ece0, 0x27a75c95), WTCP(0x795fd53a, 0x28a5e9b4), + WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78b16a32, 0x2aa0e8b0), + WTCP(0x785719cc, 0x2b9d51dd), WTCP(0x77fab989, 0x2c98fbba), + WTCP(0x779c4afc, 0x2d93e1f8), WTCP(0x773bcfc4, 0x2e8e0048), + WTCP(0x76d94989, 0x2f875262), WTCP(0x7674b9fa, 0x307fd401), + WTCP(0x760e22d1, 0x317780e2), WTCP(0x75a585cf, 0x326e54c7), + WTCP(0x753ae4c0, 0x33644b76), WTCP(0x74ce4177, 0x345960b7), + WTCP(0x745f9dd1, 0x354d9057), WTCP(0x73eefbb3, 0x3640d627), + WTCP(0x737c5d0b, 0x37332dfd), WTCP(0x7307c3d0, 0x382493b0), + WTCP(0x72913201, 0x3915031f), WTCP(0x7218a9a7, 0x3a04782a), + WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x7121bd9c, 0x3be062b0), + WTCP(0x70a35e25, 0x3cccd004), WTCP(0x7023109a, 0x3db832a6), + WTCP(0x6fa0d72c, 0x3ea2868c), WTCP(0x6f1cb416, 0x3f8bc7b4), + WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6e0eba0c, 0x415b01ce), + WTCP(0x6d84e7b7, 0x4240f2d1), WTCP(0x6cf934fc, 0x4325c135), + WTCP(0x6c6ba43e, 0x44096910), WTCP(0x6bdc37eb, 0x44ebe679), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6ab7d663, 0x46ad5278), + WTCP(0x6a22e630, 0x478c395a), WTCP(0x698c246c, 0x4869e665), + WTCP(0x68f393ae, 0x494655cc), WTCP(0x68593691, 0x4a2183c8), + WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x671f21dc, 0x4bd40c80), + WTCP(0x667f6fa5, 0x4cab5fc9), WTCP(0x65ddfbd3, 0x4d8162c4), + WTCP(0x653ac92b, 0x4e5611c5), WTCP(0x6495da79, 0x4f296928), + WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x6346d44b, 0x50cc029c), + WTCP(0x629cc28c, 0x519b3d80), WTCP(0x61f1003f, 0x5269126e), + WTCP(0x61439053, 0x53357ddf), WTCP(0x609475c3, 0x54007c51), + WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5f314cba, 0x55922457), + WTCP(0x5e7d4458, 0x5658c709), WTCP(0x5dc79d7c, 0x571deefa), + WTCP(0x5d105b44, 0x57e198c7), WTCP(0x5c5780d3, 0x58a3c118), + WTCP(0x5b9d1154, 0x59646498), WTCP(0x5ae10ff9, 0x5a237ffa), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow240[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow256[] = { + WTCP(0x7fffd886, 0x006487e3), WTCP(0x7ffe9cb2, 0x012d96b1), + WTCP(0x7ffc250f, 0x01f6a297), WTCP(0x7ff871a2, 0x02bfa9a4), + WTCP(0x7ff38274, 0x0388a9ea), WTCP(0x7fed5791, 0x0451a177), + WTCP(0x7fe5f108, 0x051a8e5c), WTCP(0x7fdd4eec, 0x05e36ea9), + WTCP(0x7fd37153, 0x06ac406f), WTCP(0x7fc85854, 0x077501be), + WTCP(0x7fbc040a, 0x083db0a7), WTCP(0x7fae7495, 0x09064b3a), + WTCP(0x7f9faa15, 0x09cecf89), WTCP(0x7f8fa4b0, 0x0a973ba5), + WTCP(0x7f7e648c, 0x0b5f8d9f), WTCP(0x7f6be9d4, 0x0c27c389), + WTCP(0x7f5834b7, 0x0cefdb76), WTCP(0x7f434563, 0x0db7d376), + WTCP(0x7f2d1c0e, 0x0e7fa99e), WTCP(0x7f15b8ee, 0x0f475bff), + WTCP(0x7efd1c3c, 0x100ee8ad), WTCP(0x7ee34636, 0x10d64dbd), + WTCP(0x7ec8371a, 0x119d8941), WTCP(0x7eabef2c, 0x1264994e), + WTCP(0x7e8e6eb2, 0x132b7bf9), WTCP(0x7e6fb5f4, 0x13f22f58), + WTCP(0x7e4fc53e, 0x14b8b17f), WTCP(0x7e2e9cdf, 0x157f0086), + WTCP(0x7e0c3d29, 0x16451a83), WTCP(0x7de8a670, 0x170afd8d), + WTCP(0x7dc3d90d, 0x17d0a7bc), WTCP(0x7d9dd55a, 0x18961728), + WTCP(0x7d769bb5, 0x195b49ea), WTCP(0x7d4e2c7f, 0x1a203e1b), + WTCP(0x7d24881b, 0x1ae4f1d6), WTCP(0x7cf9aef0, 0x1ba96335), + WTCP(0x7ccda169, 0x1c6d9053), WTCP(0x7ca05ff1, 0x1d31774d), + WTCP(0x7c71eaf9, 0x1df5163f), WTCP(0x7c4242f2, 0x1eb86b46), + WTCP(0x7c116853, 0x1f7b7481), WTCP(0x7bdf5b94, 0x203e300d), + WTCP(0x7bac1d31, 0x21009c0c), WTCP(0x7b77ada8, 0x21c2b69c), + WTCP(0x7b420d7a, 0x22847de0), WTCP(0x7b0b3d2c, 0x2345eff8), + WTCP(0x7ad33d45, 0x24070b08), WTCP(0x7a9a0e50, 0x24c7cd33), + WTCP(0x7a5fb0d8, 0x2588349d), WTCP(0x7a24256f, 0x26483f6c), + WTCP(0x79e76ca7, 0x2707ebc7), WTCP(0x79a98715, 0x27c737d3), + WTCP(0x796a7554, 0x288621b9), WTCP(0x792a37fe, 0x2944a7a2), + WTCP(0x78e8cfb2, 0x2a02c7b8), WTCP(0x78a63d11, 0x2ac08026), + WTCP(0x786280bf, 0x2b7dcf17), WTCP(0x781d9b65, 0x2c3ab2b9), + WTCP(0x77d78daa, 0x2cf72939), WTCP(0x7790583e, 0x2db330c7), + WTCP(0x7747fbce, 0x2e6ec792), WTCP(0x76fe790e, 0x2f29ebcc), + WTCP(0x76b3d0b4, 0x2fe49ba7), WTCP(0x76680376, 0x309ed556), + WTCP(0x761b1211, 0x3158970e), WTCP(0x75ccfd42, 0x3211df04), + WTCP(0x757dc5ca, 0x32caab6f), WTCP(0x752d6c6c, 0x3382fa88), + WTCP(0x74dbf1ef, 0x343aca87), WTCP(0x7489571c, 0x34f219a8), + WTCP(0x74359cbd, 0x35a8e625), WTCP(0x73e0c3a3, 0x365f2e3b), + WTCP(0x738acc9e, 0x3714f02a), WTCP(0x7333b883, 0x37ca2a30), + WTCP(0x72db8828, 0x387eda8e), WTCP(0x72823c67, 0x3932ff87), + WTCP(0x7227d61c, 0x39e6975e), WTCP(0x71cc5626, 0x3a99a057), + WTCP(0x716fbd68, 0x3b4c18ba), WTCP(0x71120cc5, 0x3bfdfecd), + WTCP(0x70b34525, 0x3caf50da), WTCP(0x70536771, 0x3d600d2c), + WTCP(0x6ff27497, 0x3e10320d), WTCP(0x6f906d84, 0x3ebfbdcd), + WTCP(0x6f2d532c, 0x3f6eaeb8), WTCP(0x6ec92683, 0x401d0321), + WTCP(0x6e63e87f, 0x40cab958), WTCP(0x6dfd9a1c, 0x4177cfb1), + WTCP(0x6d963c54, 0x42244481), WTCP(0x6d2dd027, 0x42d0161e), + WTCP(0x6cc45698, 0x437b42e1), WTCP(0x6c59d0a9, 0x4425c923), + WTCP(0x6bee3f62, 0x44cfa740), WTCP(0x6b81a3cd, 0x4578db93), + WTCP(0x6b13fef5, 0x4621647d), WTCP(0x6aa551e9, 0x46c9405c), + WTCP(0x6a359db9, 0x47706d93), WTCP(0x69c4e37a, 0x4816ea86), + WTCP(0x69532442, 0x48bcb599), WTCP(0x68e06129, 0x4961cd33), + WTCP(0x686c9b4b, 0x4a062fbd), WTCP(0x67f7d3c5, 0x4aa9dba2), + WTCP(0x67820bb7, 0x4b4ccf4d), WTCP(0x670b4444, 0x4bef092d), + WTCP(0x66937e91, 0x4c9087b1), WTCP(0x661abbc5, 0x4d31494b), + WTCP(0x65a0fd0b, 0x4dd14c6e), WTCP(0x6526438f, 0x4e708f8f), + WTCP(0x64aa907f, 0x4f0f1126), WTCP(0x642de50d, 0x4faccfab), + WTCP(0x63b0426d, 0x5049c999), WTCP(0x6331a9d4, 0x50e5fd6d), + WTCP(0x62b21c7b, 0x518169a5), WTCP(0x62319b9d, 0x521c0cc2), + WTCP(0x61b02876, 0x52b5e546), WTCP(0x612dc447, 0x534ef1b5), + WTCP(0x60aa7050, 0x53e73097), WTCP(0x60262dd6, 0x547ea073), + WTCP(0x5fa0fe1f, 0x55153fd4), WTCP(0x5f1ae274, 0x55ab0d46), + WTCP(0x5e93dc1f, 0x56400758), WTCP(0x5e0bec6e, 0x56d42c99), + WTCP(0x5d8314b1, 0x57677b9d), WTCP(0x5cf95638, 0x57f9f2f8), + WTCP(0x5c6eb258, 0x588b9140), WTCP(0x5be32a67, 0x591c550e), + WTCP(0x5b56bfbd, 0x59ac3cfd), WTCP(0x5ac973b5, 0x5a3b47ab), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow384[] = { + WTCP(0x7fffee74, 0x00430546), WTCP(0x7fff6216, 0x00c90f88), + WTCP(0x7ffe495b, 0x014f18ee), WTCP(0x7ffca443, 0x01d520e4), + WTCP(0x7ffa72d1, 0x025b26d7), WTCP(0x7ff7b507, 0x02e12a36), + WTCP(0x7ff46ae8, 0x03672a6c), WTCP(0x7ff09478, 0x03ed26e6), + WTCP(0x7fec31ba, 0x04731f13), WTCP(0x7fe742b4, 0x04f9125e), + WTCP(0x7fe1c76b, 0x057f0035), WTCP(0x7fdbbfe6, 0x0604e805), + WTCP(0x7fd52c29, 0x068ac93b), WTCP(0x7fce0c3e, 0x0710a345), + WTCP(0x7fc6602c, 0x0796758f), WTCP(0x7fbe27fa, 0x081c3f87), + WTCP(0x7fb563b3, 0x08a2009a), WTCP(0x7fac135f, 0x0927b836), + WTCP(0x7fa2370a, 0x09ad65c8), WTCP(0x7f97cebd, 0x0a3308bd), + WTCP(0x7f8cda84, 0x0ab8a082), WTCP(0x7f815a6b, 0x0b3e2c86), + WTCP(0x7f754e80, 0x0bc3ac35), WTCP(0x7f68b6ce, 0x0c491efe), + WTCP(0x7f5b9364, 0x0cce844e), WTCP(0x7f4de451, 0x0d53db92), + WTCP(0x7f3fa9a2, 0x0dd92439), WTCP(0x7f30e369, 0x0e5e5db0), + WTCP(0x7f2191b4, 0x0ee38766), WTCP(0x7f11b495, 0x0f68a0c8), + WTCP(0x7f014c1e, 0x0feda943), WTCP(0x7ef05860, 0x1072a048), + WTCP(0x7eded96d, 0x10f78543), WTCP(0x7ecccf5a, 0x117c57a2), + WTCP(0x7eba3a39, 0x120116d5), WTCP(0x7ea71a20, 0x1285c249), + WTCP(0x7e936f22, 0x130a596e), WTCP(0x7e7f3957, 0x138edbb1), + WTCP(0x7e6a78d3, 0x14134881), WTCP(0x7e552dae, 0x14979f4e), + WTCP(0x7e3f57ff, 0x151bdf86), WTCP(0x7e28f7de, 0x15a00897), + WTCP(0x7e120d63, 0x162419f2), WTCP(0x7dfa98a8, 0x16a81305), + WTCP(0x7de299c6, 0x172bf33f), WTCP(0x7dca10d8, 0x17afba11), + WTCP(0x7db0fdf8, 0x183366e9), WTCP(0x7d976142, 0x18b6f936), + WTCP(0x7d7d3ad3, 0x193a706a), WTCP(0x7d628ac6, 0x19bdcbf3), + WTCP(0x7d475139, 0x1a410b41), WTCP(0x7d2b8e4a, 0x1ac42dc5), + WTCP(0x7d0f4218, 0x1b4732ef), WTCP(0x7cf26cc1, 0x1bca1a2f), + WTCP(0x7cd50e65, 0x1c4ce2f6), WTCP(0x7cb72724, 0x1ccf8cb3), + WTCP(0x7c98b71f, 0x1d5216d8), WTCP(0x7c79be78, 0x1dd480d6), + WTCP(0x7c5a3d50, 0x1e56ca1e), WTCP(0x7c3a33ca, 0x1ed8f220), + WTCP(0x7c19a209, 0x1f5af84f), WTCP(0x7bf88830, 0x1fdcdc1b), + WTCP(0x7bd6e665, 0x205e9cf6), WTCP(0x7bb4bccb, 0x20e03a51), + WTCP(0x7b920b89, 0x2161b3a0), WTCP(0x7b6ed2c5, 0x21e30853), + WTCP(0x7b4b12a4, 0x226437dc), WTCP(0x7b26cb4f, 0x22e541af), + WTCP(0x7b01fced, 0x2366253d), WTCP(0x7adca7a6, 0x23e6e1fa), + WTCP(0x7ab6cba4, 0x24677758), WTCP(0x7a90690f, 0x24e7e4c9), + WTCP(0x7a698012, 0x256829c2), WTCP(0x7a4210d8, 0x25e845b6), + WTCP(0x7a1a1b8c, 0x26683818), WTCP(0x79f1a05a, 0x26e8005b), + WTCP(0x79c89f6e, 0x27679df4), WTCP(0x799f18f4, 0x27e71057), + WTCP(0x79750d1c, 0x286656f8), WTCP(0x794a7c12, 0x28e5714b), + WTCP(0x791f6605, 0x29645ec5), WTCP(0x78f3cb25, 0x29e31edb), + WTCP(0x78c7aba2, 0x2a61b101), WTCP(0x789b07ab, 0x2ae014ae), + WTCP(0x786ddf72, 0x2b5e4956), WTCP(0x78403329, 0x2bdc4e6f), + WTCP(0x78120300, 0x2c5a236f), WTCP(0x77e34f2c, 0x2cd7c7cc), + WTCP(0x77b417df, 0x2d553afc), WTCP(0x77845d4e, 0x2dd27c75), + WTCP(0x77541fab, 0x2e4f8bae), WTCP(0x77235f2d, 0x2ecc681e), + WTCP(0x76f21c09, 0x2f49113d), WTCP(0x76c05674, 0x2fc58680), + WTCP(0x768e0ea6, 0x3041c761), WTCP(0x765b44d5, 0x30bdd356), + WTCP(0x7627f939, 0x3139a9d7), WTCP(0x75f42c0b, 0x31b54a5e), + WTCP(0x75bfdd83, 0x3230b461), WTCP(0x758b0ddb, 0x32abe75a), + WTCP(0x7555bd4c, 0x3326e2c3), WTCP(0x751fec11, 0x33a1a612), + WTCP(0x74e99a65, 0x341c30c4), WTCP(0x74b2c884, 0x34968250), + WTCP(0x747b76a9, 0x35109a31), WTCP(0x7443a512, 0x358a77e0), + WTCP(0x740b53fb, 0x36041ad9), WTCP(0x73d283a2, 0x367d8296), + WTCP(0x73993447, 0x36f6ae91), WTCP(0x735f6626, 0x376f9e46), + WTCP(0x73251981, 0x37e85130), WTCP(0x72ea4e96, 0x3860c6cb), + WTCP(0x72af05a7, 0x38d8fe93), WTCP(0x72733ef3, 0x3950f804), + WTCP(0x7236fabe, 0x39c8b29a), WTCP(0x71fa3949, 0x3a402dd2), + WTCP(0x71bcfad6, 0x3ab76929), WTCP(0x717f3fa8, 0x3b2e641c), + WTCP(0x71410805, 0x3ba51e29), WTCP(0x7102542f, 0x3c1b96ce), + WTCP(0x70c3246b, 0x3c91cd88), WTCP(0x708378ff, 0x3d07c1d6), + WTCP(0x70435230, 0x3d7d7337), WTCP(0x7002b045, 0x3df2e129), + WTCP(0x6fc19385, 0x3e680b2c), WTCP(0x6f7ffc37, 0x3edcf0c0), + WTCP(0x6f3deaa4, 0x3f519164), WTCP(0x6efb5f12, 0x3fc5ec98), + WTCP(0x6eb859cc, 0x403a01dc), WTCP(0x6e74db1c, 0x40add0b2), + WTCP(0x6e30e34a, 0x4121589b), WTCP(0x6dec72a2, 0x41949917), + WTCP(0x6da7896e, 0x420791a8), WTCP(0x6d6227fa, 0x427a41d0), + WTCP(0x6d1c4e93, 0x42eca912), WTCP(0x6cd5fd85, 0x435ec6f0), + WTCP(0x6c8f351c, 0x43d09aed), WTCP(0x6c47f5a7, 0x4442248b), + WTCP(0x6c003f74, 0x44b3634f), WTCP(0x6bb812d1, 0x452456bd), + WTCP(0x6b6f700e, 0x4594fe58), WTCP(0x6b265779, 0x460559a4), + WTCP(0x6adcc964, 0x46756828), WTCP(0x6a92c61f, 0x46e52967), + WTCP(0x6a484dfc, 0x47549ce7), WTCP(0x69fd614a, 0x47c3c22f), + WTCP(0x69b2005e, 0x483298c4), WTCP(0x69662b8a, 0x48a1202c), + WTCP(0x6919e320, 0x490f57ee), WTCP(0x68cd2775, 0x497d3f93), + WTCP(0x687ff8dc, 0x49ead6a0), WTCP(0x683257ab, 0x4a581c9e), + WTCP(0x67e44436, 0x4ac51114), WTCP(0x6795bed3, 0x4b31b38d), + WTCP(0x6746c7d8, 0x4b9e0390), WTCP(0x66f75f9b, 0x4c0a00a6), + WTCP(0x66a78675, 0x4c75aa5a), WTCP(0x66573cbb, 0x4ce10034), + WTCP(0x660682c7, 0x4d4c01c0), WTCP(0x65b558f1, 0x4db6ae88), + WTCP(0x6563bf92, 0x4e210617), WTCP(0x6511b703, 0x4e8b07f9), + WTCP(0x64bf3f9f, 0x4ef4b3b9), WTCP(0x646c59bf, 0x4f5e08e3), + WTCP(0x641905bf, 0x4fc70704), WTCP(0x63c543fa, 0x502fada9), + WTCP(0x637114cc, 0x5097fc5e), WTCP(0x631c7892, 0x50fff2b2), + WTCP(0x62c76fa7, 0x51679033), WTCP(0x6271fa69, 0x51ced46e), + WTCP(0x621c1937, 0x5235bef4), WTCP(0x61c5cc6d, 0x529c4f51), + WTCP(0x616f146c, 0x53028518), WTCP(0x6117f191, 0x53685fd6), + WTCP(0x60c0643d, 0x53cddf1d), WTCP(0x60686ccf, 0x5433027d), + WTCP(0x60100ba8, 0x5497c988), WTCP(0x5fb74129, 0x54fc33ce), + WTCP(0x5f5e0db3, 0x556040e2), WTCP(0x5f0471a8, 0x55c3f056), + WTCP(0x5eaa6d6b, 0x562741bd), WTCP(0x5e50015d, 0x568a34a9), + WTCP(0x5df52de3, 0x56ecc8af), WTCP(0x5d99f35f, 0x574efd62), + WTCP(0x5d3e5237, 0x57b0d256), WTCP(0x5ce24acd, 0x58124720), + WTCP(0x5c85dd88, 0x58735b56), WTCP(0x5c290acc, 0x58d40e8c), + WTCP(0x5bcbd300, 0x5934605a), WTCP(0x5b6e3689, 0x59945054), + WTCP(0x5b1035cf, 0x59f3de12), WTCP(0x5ab1d138, 0x5a53092c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow480[] = { + 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), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow512[] = { + WTCP(0x7ffff621, 0x003243f5), WTCP(0x7fffa72c, 0x0096cbc1), + WTCP(0x7fff0943, 0x00fb5330), WTCP(0x7ffe1c65, 0x015fda03), + WTCP(0x7ffce093, 0x01c45ffe), WTCP(0x7ffb55ce, 0x0228e4e2), + WTCP(0x7ff97c18, 0x028d6870), WTCP(0x7ff75370, 0x02f1ea6c), + WTCP(0x7ff4dbd9, 0x03566a96), WTCP(0x7ff21553, 0x03bae8b2), + WTCP(0x7feeffe1, 0x041f6480), WTCP(0x7feb9b85, 0x0483ddc3), + WTCP(0x7fe7e841, 0x04e8543e), WTCP(0x7fe3e616, 0x054cc7b1), + WTCP(0x7fdf9508, 0x05b137df), WTCP(0x7fdaf519, 0x0615a48b), + WTCP(0x7fd6064c, 0x067a0d76), WTCP(0x7fd0c8a3, 0x06de7262), + WTCP(0x7fcb3c23, 0x0742d311), WTCP(0x7fc560cf, 0x07a72f45), + WTCP(0x7fbf36aa, 0x080b86c2), WTCP(0x7fb8bdb8, 0x086fd947), + WTCP(0x7fb1f5fc, 0x08d42699), WTCP(0x7faadf7c, 0x09386e78), + WTCP(0x7fa37a3c, 0x099cb0a7), WTCP(0x7f9bc640, 0x0a00ece8), + WTCP(0x7f93c38c, 0x0a6522fe), WTCP(0x7f8b7227, 0x0ac952aa), + WTCP(0x7f82d214, 0x0b2d7baf), WTCP(0x7f79e35a, 0x0b919dcf), + WTCP(0x7f70a5fe, 0x0bf5b8cb), WTCP(0x7f671a05, 0x0c59cc68), + WTCP(0x7f5d3f75, 0x0cbdd865), WTCP(0x7f531655, 0x0d21dc87), + WTCP(0x7f489eaa, 0x0d85d88f), WTCP(0x7f3dd87c, 0x0de9cc40), + WTCP(0x7f32c3d1, 0x0e4db75b), WTCP(0x7f2760af, 0x0eb199a4), + WTCP(0x7f1baf1e, 0x0f1572dc), WTCP(0x7f0faf25, 0x0f7942c7), + WTCP(0x7f0360cb, 0x0fdd0926), WTCP(0x7ef6c418, 0x1040c5bb), + WTCP(0x7ee9d914, 0x10a4784b), WTCP(0x7edc9fc6, 0x11082096), + WTCP(0x7ecf1837, 0x116bbe60), WTCP(0x7ec14270, 0x11cf516a), + WTCP(0x7eb31e78, 0x1232d979), WTCP(0x7ea4ac58, 0x1296564d), + WTCP(0x7e95ec1a, 0x12f9c7aa), WTCP(0x7e86ddc6, 0x135d2d53), + WTCP(0x7e778166, 0x13c0870a), WTCP(0x7e67d703, 0x1423d492), + WTCP(0x7e57dea7, 0x148715ae), WTCP(0x7e47985b, 0x14ea4a1f), + WTCP(0x7e37042a, 0x154d71aa), WTCP(0x7e26221f, 0x15b08c12), + WTCP(0x7e14f242, 0x16139918), WTCP(0x7e0374a0, 0x1676987f), + WTCP(0x7df1a942, 0x16d98a0c), WTCP(0x7ddf9034, 0x173c6d80), + WTCP(0x7dcd2981, 0x179f429f), WTCP(0x7dba7534, 0x1802092c), + WTCP(0x7da77359, 0x1864c0ea), WTCP(0x7d9423fc, 0x18c7699b), + WTCP(0x7d808728, 0x192a0304), WTCP(0x7d6c9ce9, 0x198c8ce7), + WTCP(0x7d58654d, 0x19ef0707), WTCP(0x7d43e05e, 0x1a517128), + WTCP(0x7d2f0e2b, 0x1ab3cb0d), WTCP(0x7d19eebf, 0x1b161479), + WTCP(0x7d048228, 0x1b784d30), WTCP(0x7ceec873, 0x1bda74f6), + WTCP(0x7cd8c1ae, 0x1c3c8b8c), WTCP(0x7cc26de5, 0x1c9e90b8), + WTCP(0x7cabcd28, 0x1d00843d), WTCP(0x7c94df83, 0x1d6265dd), + WTCP(0x7c7da505, 0x1dc4355e), WTCP(0x7c661dbc, 0x1e25f282), + WTCP(0x7c4e49b7, 0x1e879d0d), WTCP(0x7c362904, 0x1ee934c3), + WTCP(0x7c1dbbb3, 0x1f4ab968), WTCP(0x7c0501d2, 0x1fac2abf), + WTCP(0x7bebfb70, 0x200d888d), WTCP(0x7bd2a89e, 0x206ed295), + WTCP(0x7bb9096b, 0x20d0089c), WTCP(0x7b9f1de6, 0x21312a65), + WTCP(0x7b84e61f, 0x219237b5), WTCP(0x7b6a6227, 0x21f3304f), + WTCP(0x7b4f920e, 0x225413f8), WTCP(0x7b3475e5, 0x22b4e274), + WTCP(0x7b190dbc, 0x23159b88), WTCP(0x7afd59a4, 0x23763ef7), + WTCP(0x7ae159ae, 0x23d6cc87), WTCP(0x7ac50dec, 0x243743fa), + WTCP(0x7aa8766f, 0x2497a517), WTCP(0x7a8b9348, 0x24f7efa2), + WTCP(0x7a6e648a, 0x2558235f), WTCP(0x7a50ea47, 0x25b84012), + WTCP(0x7a332490, 0x26184581), WTCP(0x7a151378, 0x26783370), + WTCP(0x79f6b711, 0x26d809a5), WTCP(0x79d80f6f, 0x2737c7e3), + WTCP(0x79b91ca4, 0x27976df1), WTCP(0x7999dec4, 0x27f6fb92), + WTCP(0x797a55e0, 0x2856708d), WTCP(0x795a820e, 0x28b5cca5), + WTCP(0x793a6361, 0x29150fa1), WTCP(0x7919f9ec, 0x29743946), + WTCP(0x78f945c3, 0x29d34958), WTCP(0x78d846fb, 0x2a323f9e), + WTCP(0x78b6fda8, 0x2a911bdc), WTCP(0x789569df, 0x2aefddd8), + WTCP(0x78738bb3, 0x2b4e8558), WTCP(0x7851633b, 0x2bad1221), + WTCP(0x782ef08b, 0x2c0b83fa), WTCP(0x780c33b8, 0x2c69daa6), + WTCP(0x77e92cd9, 0x2cc815ee), WTCP(0x77c5dc01, 0x2d263596), + WTCP(0x77a24148, 0x2d843964), WTCP(0x777e5cc3, 0x2de2211e), + WTCP(0x775a2e89, 0x2e3fec8b), WTCP(0x7735b6af, 0x2e9d9b70), + WTCP(0x7710f54c, 0x2efb2d95), WTCP(0x76ebea77, 0x2f58a2be), + WTCP(0x76c69647, 0x2fb5fab2), WTCP(0x76a0f8d2, 0x30133539), + WTCP(0x767b1231, 0x30705217), WTCP(0x7654e279, 0x30cd5115), + WTCP(0x762e69c4, 0x312a31f8), WTCP(0x7607a828, 0x3186f487), + WTCP(0x75e09dbd, 0x31e39889), WTCP(0x75b94a9c, 0x32401dc6), + WTCP(0x7591aedd, 0x329c8402), WTCP(0x7569ca99, 0x32f8cb07), + WTCP(0x75419de7, 0x3354f29b), WTCP(0x751928e0, 0x33b0fa84), + WTCP(0x74f06b9e, 0x340ce28b), WTCP(0x74c7663a, 0x3468aa76), + WTCP(0x749e18cd, 0x34c4520d), WTCP(0x74748371, 0x351fd918), + WTCP(0x744aa63f, 0x357b3f5d), WTCP(0x74208150, 0x35d684a6), + WTCP(0x73f614c0, 0x3631a8b8), WTCP(0x73cb60a8, 0x368cab5c), + WTCP(0x73a06522, 0x36e78c5b), WTCP(0x73752249, 0x37424b7b), + WTCP(0x73499838, 0x379ce885), WTCP(0x731dc70a, 0x37f76341), + WTCP(0x72f1aed9, 0x3851bb77), WTCP(0x72c54fc1, 0x38abf0ef), + WTCP(0x7298a9dd, 0x39060373), WTCP(0x726bbd48, 0x395ff2c9), + WTCP(0x723e8a20, 0x39b9bebc), WTCP(0x7211107e, 0x3a136712), + WTCP(0x71e35080, 0x3a6ceb96), WTCP(0x71b54a41, 0x3ac64c0f), + WTCP(0x7186fdde, 0x3b1f8848), WTCP(0x71586b74, 0x3b78a007), + WTCP(0x7129931f, 0x3bd19318), WTCP(0x70fa74fc, 0x3c2a6142), + WTCP(0x70cb1128, 0x3c830a50), WTCP(0x709b67c0, 0x3cdb8e09), + WTCP(0x706b78e3, 0x3d33ec39), WTCP(0x703b44ad, 0x3d8c24a8), + WTCP(0x700acb3c, 0x3de4371f), WTCP(0x6fda0cae, 0x3e3c2369), + WTCP(0x6fa90921, 0x3e93e950), WTCP(0x6f77c0b3, 0x3eeb889c), + WTCP(0x6f463383, 0x3f430119), WTCP(0x6f1461b0, 0x3f9a5290), + WTCP(0x6ee24b57, 0x3ff17cca), WTCP(0x6eaff099, 0x40487f94), + WTCP(0x6e7d5193, 0x409f5ab6), WTCP(0x6e4a6e66, 0x40f60dfb), + WTCP(0x6e174730, 0x414c992f), WTCP(0x6de3dc11, 0x41a2fc1a), + WTCP(0x6db02d29, 0x41f93689), WTCP(0x6d7c3a98, 0x424f4845), + WTCP(0x6d48047e, 0x42a5311b), WTCP(0x6d138afb, 0x42faf0d4), + WTCP(0x6cdece2f, 0x4350873c), WTCP(0x6ca9ce3b, 0x43a5f41e), + WTCP(0x6c748b3f, 0x43fb3746), WTCP(0x6c3f055d, 0x4450507e), + WTCP(0x6c093cb6, 0x44a53f93), WTCP(0x6bd3316a, 0x44fa0450), + WTCP(0x6b9ce39b, 0x454e9e80), WTCP(0x6b66536b, 0x45a30df0), + WTCP(0x6b2f80fb, 0x45f7526b), WTCP(0x6af86c6c, 0x464b6bbe), + WTCP(0x6ac115e2, 0x469f59b4), WTCP(0x6a897d7d, 0x46f31c1a), + WTCP(0x6a51a361, 0x4746b2bc), WTCP(0x6a1987b0, 0x479a1d67), + WTCP(0x69e12a8c, 0x47ed5be6), WTCP(0x69a88c19, 0x48406e08), + WTCP(0x696fac78, 0x48935397), WTCP(0x69368bce, 0x48e60c62), + WTCP(0x68fd2a3d, 0x49389836), WTCP(0x68c387e9, 0x498af6df), + WTCP(0x6889a4f6, 0x49dd282a), WTCP(0x684f8186, 0x4a2f2be6), + WTCP(0x68151dbe, 0x4a8101de), WTCP(0x67da79c3, 0x4ad2a9e2), + WTCP(0x679f95b7, 0x4b2423be), WTCP(0x676471c0, 0x4b756f40), + WTCP(0x67290e02, 0x4bc68c36), WTCP(0x66ed6aa1, 0x4c177a6e), + WTCP(0x66b187c3, 0x4c6839b7), WTCP(0x6675658c, 0x4cb8c9dd), + WTCP(0x66390422, 0x4d092ab0), WTCP(0x65fc63a9, 0x4d595bfe), + WTCP(0x65bf8447, 0x4da95d96), WTCP(0x65826622, 0x4df92f46), + WTCP(0x6545095f, 0x4e48d0dd), WTCP(0x65076e25, 0x4e984229), + WTCP(0x64c99498, 0x4ee782fb), WTCP(0x648b7ce0, 0x4f369320), + WTCP(0x644d2722, 0x4f857269), WTCP(0x640e9386, 0x4fd420a4), + WTCP(0x63cfc231, 0x50229da1), WTCP(0x6390b34a, 0x5070e92f), + WTCP(0x635166f9, 0x50bf031f), WTCP(0x6311dd64, 0x510ceb40), + WTCP(0x62d216b3, 0x515aa162), WTCP(0x6292130c, 0x51a82555), + WTCP(0x6251d298, 0x51f576ea), WTCP(0x6211557e, 0x524295f0), + WTCP(0x61d09be5, 0x528f8238), WTCP(0x618fa5f7, 0x52dc3b92), + WTCP(0x614e73da, 0x5328c1d0), WTCP(0x610d05b7, 0x537514c2), + WTCP(0x60cb5bb7, 0x53c13439), WTCP(0x60897601, 0x540d2005), + WTCP(0x604754bf, 0x5458d7f9), WTCP(0x6004f819, 0x54a45be6), + WTCP(0x5fc26038, 0x54efab9c), WTCP(0x5f7f8d46, 0x553ac6ee), + WTCP(0x5f3c7f6b, 0x5585adad), WTCP(0x5ef936d1, 0x55d05faa), + WTCP(0x5eb5b3a2, 0x561adcb9), WTCP(0x5e71f606, 0x566524aa), + WTCP(0x5e2dfe29, 0x56af3750), WTCP(0x5de9cc33, 0x56f9147e), + WTCP(0x5da5604f, 0x5742bc06), WTCP(0x5d60baa7, 0x578c2dba), + WTCP(0x5d1bdb65, 0x57d5696d), WTCP(0x5cd6c2b5, 0x581e6ef1), + WTCP(0x5c9170bf, 0x58673e1b), WTCP(0x5c4be5b0, 0x58afd6bd), + WTCP(0x5c0621b2, 0x58f838a9), WTCP(0x5bc024f0, 0x594063b5), + WTCP(0x5b79ef96, 0x598857b2), WTCP(0x5b3381ce, 0x59d01475), + WTCP(0x5aecdbc5, 0x5a1799d1), WTCP(0x5aa5fda5, 0x5a5ee79a), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow768[] = { + WTCP(0x7ffffb9d, 0x002182a4), WTCP(0x7fffd886, 0x006487e3), + WTCP(0x7fff9257, 0x00a78d06), WTCP(0x7fff2910, 0x00ea91fc), + WTCP(0x7ffe9cb2, 0x012d96b1), WTCP(0x7ffded3d, 0x01709b13), + WTCP(0x7ffd1ab2, 0x01b39f11), WTCP(0x7ffc250f, 0x01f6a297), + WTCP(0x7ffb0c56, 0x0239a593), WTCP(0x7ff9d087, 0x027ca7f3), + WTCP(0x7ff871a2, 0x02bfa9a4), WTCP(0x7ff6efa7, 0x0302aa95), + WTCP(0x7ff54a98, 0x0345aab2), WTCP(0x7ff38274, 0x0388a9ea), + WTCP(0x7ff1973b, 0x03cba829), WTCP(0x7fef88ef, 0x040ea55e), + WTCP(0x7fed5791, 0x0451a177), WTCP(0x7feb031f, 0x04949c60), + WTCP(0x7fe88b9c, 0x04d79608), WTCP(0x7fe5f108, 0x051a8e5c), + WTCP(0x7fe33364, 0x055d854a), WTCP(0x7fe052af, 0x05a07abf), + WTCP(0x7fdd4eec, 0x05e36ea9), WTCP(0x7fda281b, 0x062660f6), + WTCP(0x7fd6de3d, 0x06695194), WTCP(0x7fd37153, 0x06ac406f), + WTCP(0x7fcfe15d, 0x06ef2d76), WTCP(0x7fcc2e5d, 0x07321897), + WTCP(0x7fc85854, 0x077501be), WTCP(0x7fc45f42, 0x07b7e8da), + WTCP(0x7fc04329, 0x07facdd9), WTCP(0x7fbc040a, 0x083db0a7), + WTCP(0x7fb7a1e6, 0x08809133), WTCP(0x7fb31cbf, 0x08c36f6a), + WTCP(0x7fae7495, 0x09064b3a), WTCP(0x7fa9a96a, 0x09492491), + WTCP(0x7fa4bb3f, 0x098bfb5c), WTCP(0x7f9faa15, 0x09cecf89), + WTCP(0x7f9a75ef, 0x0a11a106), WTCP(0x7f951ecc, 0x0a546fc0), + WTCP(0x7f8fa4b0, 0x0a973ba5), WTCP(0x7f8a079a, 0x0ada04a3), + WTCP(0x7f84478e, 0x0b1ccaa7), WTCP(0x7f7e648c, 0x0b5f8d9f), + WTCP(0x7f785e96, 0x0ba24d79), WTCP(0x7f7235ad, 0x0be50a23), + WTCP(0x7f6be9d4, 0x0c27c389), WTCP(0x7f657b0c, 0x0c6a799b), + WTCP(0x7f5ee957, 0x0cad2c45), WTCP(0x7f5834b7, 0x0cefdb76), + WTCP(0x7f515d2d, 0x0d32871a), WTCP(0x7f4a62bb, 0x0d752f20), + WTCP(0x7f434563, 0x0db7d376), WTCP(0x7f3c0528, 0x0dfa7409), + WTCP(0x7f34a20b, 0x0e3d10c7), WTCP(0x7f2d1c0e, 0x0e7fa99e), + WTCP(0x7f257334, 0x0ec23e7b), WTCP(0x7f1da77e, 0x0f04cf4c), + WTCP(0x7f15b8ee, 0x0f475bff), WTCP(0x7f0da787, 0x0f89e482), + WTCP(0x7f05734b, 0x0fcc68c2), WTCP(0x7efd1c3c, 0x100ee8ad), + WTCP(0x7ef4a25d, 0x10516432), WTCP(0x7eec05af, 0x1093db3d), + WTCP(0x7ee34636, 0x10d64dbd), WTCP(0x7eda63f3, 0x1118bb9f), + WTCP(0x7ed15ee9, 0x115b24d1), WTCP(0x7ec8371a, 0x119d8941), + WTCP(0x7ebeec89, 0x11dfe8dc), WTCP(0x7eb57f39, 0x12224392), + WTCP(0x7eabef2c, 0x1264994e), WTCP(0x7ea23c65, 0x12a6ea00), + WTCP(0x7e9866e6, 0x12e93594), WTCP(0x7e8e6eb2, 0x132b7bf9), + WTCP(0x7e8453cc, 0x136dbd1d), WTCP(0x7e7a1636, 0x13aff8ed), + WTCP(0x7e6fb5f4, 0x13f22f58), WTCP(0x7e653308, 0x1434604a), + WTCP(0x7e5a8d75, 0x14768bb3), WTCP(0x7e4fc53e, 0x14b8b17f), + WTCP(0x7e44da66, 0x14fad19e), WTCP(0x7e39ccf0, 0x153cebfb), + WTCP(0x7e2e9cdf, 0x157f0086), WTCP(0x7e234a36, 0x15c10f2d), + WTCP(0x7e17d4f8, 0x160317dc), WTCP(0x7e0c3d29, 0x16451a83), + WTCP(0x7e0082cb, 0x1687170f), WTCP(0x7df4a5e2, 0x16c90d6e), + WTCP(0x7de8a670, 0x170afd8d), WTCP(0x7ddc847a, 0x174ce75b), + WTCP(0x7dd04003, 0x178ecac6), WTCP(0x7dc3d90d, 0x17d0a7bc), + WTCP(0x7db74f9d, 0x18127e2a), WTCP(0x7daaa3b5, 0x18544dff), + WTCP(0x7d9dd55a, 0x18961728), WTCP(0x7d90e48f, 0x18d7d993), + WTCP(0x7d83d156, 0x1919952f), WTCP(0x7d769bb5, 0x195b49ea), + WTCP(0x7d6943ae, 0x199cf7b0), WTCP(0x7d5bc946, 0x19de9e72), + WTCP(0x7d4e2c7f, 0x1a203e1b), WTCP(0x7d406d5e, 0x1a61d69b), + WTCP(0x7d328be6, 0x1aa367df), WTCP(0x7d24881b, 0x1ae4f1d6), + WTCP(0x7d166201, 0x1b26746d), WTCP(0x7d08199c, 0x1b67ef93), + WTCP(0x7cf9aef0, 0x1ba96335), WTCP(0x7ceb2201, 0x1beacf42), + WTCP(0x7cdc72d3, 0x1c2c33a7), WTCP(0x7ccda169, 0x1c6d9053), + WTCP(0x7cbeadc8, 0x1caee534), WTCP(0x7caf97f4, 0x1cf03238), + WTCP(0x7ca05ff1, 0x1d31774d), WTCP(0x7c9105c3, 0x1d72b461), + WTCP(0x7c81896f, 0x1db3e962), WTCP(0x7c71eaf9, 0x1df5163f), + WTCP(0x7c622a64, 0x1e363ae5), WTCP(0x7c5247b6, 0x1e775743), + WTCP(0x7c4242f2, 0x1eb86b46), WTCP(0x7c321c1e, 0x1ef976de), + WTCP(0x7c21d33c, 0x1f3a79f7), WTCP(0x7c116853, 0x1f7b7481), + WTCP(0x7c00db66, 0x1fbc6669), WTCP(0x7bf02c7b, 0x1ffd4f9e), + WTCP(0x7bdf5b94, 0x203e300d), WTCP(0x7bce68b8, 0x207f07a6), + WTCP(0x7bbd53eb, 0x20bfd656), WTCP(0x7bac1d31, 0x21009c0c), + WTCP(0x7b9ac490, 0x214158b5), WTCP(0x7b894a0b, 0x21820c41), + WTCP(0x7b77ada8, 0x21c2b69c), WTCP(0x7b65ef6c, 0x220357b6), + WTCP(0x7b540f5b, 0x2243ef7d), WTCP(0x7b420d7a, 0x22847de0), + WTCP(0x7b2fe9cf, 0x22c502cb), WTCP(0x7b1da45e, 0x23057e2e), + WTCP(0x7b0b3d2c, 0x2345eff8), WTCP(0x7af8b43f, 0x23865816), + WTCP(0x7ae6099b, 0x23c6b676), WTCP(0x7ad33d45, 0x24070b08), + WTCP(0x7ac04f44, 0x244755b9), WTCP(0x7aad3f9b, 0x24879678), + WTCP(0x7a9a0e50, 0x24c7cd33), WTCP(0x7a86bb68, 0x2507f9d8), + WTCP(0x7a7346e9, 0x25481c57), WTCP(0x7a5fb0d8, 0x2588349d), + WTCP(0x7a4bf93a, 0x25c84299), WTCP(0x7a382015, 0x26084639), + WTCP(0x7a24256f, 0x26483f6c), WTCP(0x7a10094c, 0x26882e21), + WTCP(0x79fbcbb2, 0x26c81245), WTCP(0x79e76ca7, 0x2707ebc7), + WTCP(0x79d2ec30, 0x2747ba95), WTCP(0x79be4a53, 0x27877e9f), + WTCP(0x79a98715, 0x27c737d3), WTCP(0x7994a27d, 0x2806e61f), + WTCP(0x797f9c90, 0x28468971), WTCP(0x796a7554, 0x288621b9), + WTCP(0x79552cce, 0x28c5aee5), WTCP(0x793fc305, 0x290530e3), + WTCP(0x792a37fe, 0x2944a7a2), WTCP(0x79148bbf, 0x29841311), + WTCP(0x78febe4e, 0x29c3731e), WTCP(0x78e8cfb2, 0x2a02c7b8), + WTCP(0x78d2bfef, 0x2a4210ce), WTCP(0x78bc8f0d, 0x2a814e4d), + WTCP(0x78a63d11, 0x2ac08026), WTCP(0x788fca01, 0x2affa646), + WTCP(0x787935e4, 0x2b3ec09c), WTCP(0x786280bf, 0x2b7dcf17), + WTCP(0x784baa9a, 0x2bbcd1a6), WTCP(0x7834b37a, 0x2bfbc837), + WTCP(0x781d9b65, 0x2c3ab2b9), WTCP(0x78066262, 0x2c79911b), + WTCP(0x77ef0877, 0x2cb8634b), WTCP(0x77d78daa, 0x2cf72939), + WTCP(0x77bff203, 0x2d35e2d3), WTCP(0x77a83587, 0x2d749008), + WTCP(0x7790583e, 0x2db330c7), WTCP(0x77785a2d, 0x2df1c4fe), + WTCP(0x77603b5a, 0x2e304c9d), WTCP(0x7747fbce, 0x2e6ec792), + WTCP(0x772f9b8e, 0x2ead35cd), WTCP(0x77171aa1, 0x2eeb973b), + WTCP(0x76fe790e, 0x2f29ebcc), WTCP(0x76e5b6dc, 0x2f68336f), + WTCP(0x76ccd411, 0x2fa66e13), WTCP(0x76b3d0b4, 0x2fe49ba7), + WTCP(0x769aaccc, 0x3022bc19), WTCP(0x7681685f, 0x3060cf59), + WTCP(0x76680376, 0x309ed556), WTCP(0x764e7e17, 0x30dccdfe), + WTCP(0x7634d848, 0x311ab941), WTCP(0x761b1211, 0x3158970e), + WTCP(0x76012b79, 0x31966753), WTCP(0x75e72487, 0x31d42a00), + WTCP(0x75ccfd42, 0x3211df04), WTCP(0x75b2b5b2, 0x324f864e), + WTCP(0x75984ddc, 0x328d1fcc), WTCP(0x757dc5ca, 0x32caab6f), + WTCP(0x75631d82, 0x33082925), WTCP(0x7548550b, 0x334598de), + WTCP(0x752d6c6c, 0x3382fa88), WTCP(0x751263ae, 0x33c04e13), + WTCP(0x74f73ad7, 0x33fd936e), WTCP(0x74dbf1ef, 0x343aca87), + WTCP(0x74c088fe, 0x3477f350), WTCP(0x74a5000a, 0x34b50db5), + WTCP(0x7489571c, 0x34f219a8), WTCP(0x746d8e3a, 0x352f1716), + WTCP(0x7451a56e, 0x356c05f0), WTCP(0x74359cbd, 0x35a8e625), + WTCP(0x74197431, 0x35e5b7a3), WTCP(0x73fd2bd0, 0x36227a5b), + WTCP(0x73e0c3a3, 0x365f2e3b), WTCP(0x73c43bb1, 0x369bd334), + WTCP(0x73a79402, 0x36d86934), WTCP(0x738acc9e, 0x3714f02a), + WTCP(0x736de58d, 0x37516807), WTCP(0x7350ded7, 0x378dd0b9), + WTCP(0x7333b883, 0x37ca2a30), WTCP(0x7316729a, 0x3806745c), + WTCP(0x72f90d24, 0x3842af2b), WTCP(0x72db8828, 0x387eda8e), + WTCP(0x72bde3af, 0x38baf674), WTCP(0x72a01fc2, 0x38f702cd), + WTCP(0x72823c67, 0x3932ff87), WTCP(0x726439a8, 0x396eec93), + WTCP(0x7246178c, 0x39aac9e0), WTCP(0x7227d61c, 0x39e6975e), + WTCP(0x72097560, 0x3a2254fc), WTCP(0x71eaf561, 0x3a5e02aa), + WTCP(0x71cc5626, 0x3a99a057), WTCP(0x71ad97b9, 0x3ad52df4), + WTCP(0x718eba22, 0x3b10ab70), WTCP(0x716fbd68, 0x3b4c18ba), + WTCP(0x7150a195, 0x3b8775c2), WTCP(0x713166b1, 0x3bc2c279), + WTCP(0x71120cc5, 0x3bfdfecd), WTCP(0x70f293d9, 0x3c392aaf), + WTCP(0x70d2fbf6, 0x3c74460e), WTCP(0x70b34525, 0x3caf50da), + WTCP(0x70936f6e, 0x3cea4b04), WTCP(0x70737ad9, 0x3d253479), + WTCP(0x70536771, 0x3d600d2c), WTCP(0x7033353d, 0x3d9ad50b), + WTCP(0x7012e447, 0x3dd58c06), WTCP(0x6ff27497, 0x3e10320d), + WTCP(0x6fd1e635, 0x3e4ac711), WTCP(0x6fb1392c, 0x3e854b01), + WTCP(0x6f906d84, 0x3ebfbdcd), WTCP(0x6f6f8346, 0x3efa1f65), + WTCP(0x6f4e7a7b, 0x3f346fb8), WTCP(0x6f2d532c, 0x3f6eaeb8), + WTCP(0x6f0c0d62, 0x3fa8dc54), WTCP(0x6eeaa927, 0x3fe2f87c), + WTCP(0x6ec92683, 0x401d0321), WTCP(0x6ea7857f, 0x4056fc31), + WTCP(0x6e85c626, 0x4090e39e), WTCP(0x6e63e87f, 0x40cab958), + WTCP(0x6e41ec95, 0x41047d4e), WTCP(0x6e1fd271, 0x413e2f71), + WTCP(0x6dfd9a1c, 0x4177cfb1), WTCP(0x6ddb439f, 0x41b15dfe), + WTCP(0x6db8cf04, 0x41eada49), WTCP(0x6d963c54, 0x42244481), + WTCP(0x6d738b99, 0x425d9c97), WTCP(0x6d50bcdc, 0x4296e27b), + WTCP(0x6d2dd027, 0x42d0161e), WTCP(0x6d0ac584, 0x43093770), + WTCP(0x6ce79cfc, 0x43424661), WTCP(0x6cc45698, 0x437b42e1), + WTCP(0x6ca0f262, 0x43b42ce1), WTCP(0x6c7d7065, 0x43ed0452), + WTCP(0x6c59d0a9, 0x4425c923), WTCP(0x6c361339, 0x445e7b46), + WTCP(0x6c12381e, 0x44971aaa), WTCP(0x6bee3f62, 0x44cfa740), + WTCP(0x6bca2910, 0x450820f8), WTCP(0x6ba5f530, 0x454087c4), + WTCP(0x6b81a3cd, 0x4578db93), WTCP(0x6b5d34f1, 0x45b11c57), + WTCP(0x6b38a8a6, 0x45e949ff), WTCP(0x6b13fef5, 0x4621647d), + WTCP(0x6aef37e9, 0x46596bc1), WTCP(0x6aca538c, 0x46915fbb), + WTCP(0x6aa551e9, 0x46c9405c), WTCP(0x6a803308, 0x47010d96), + WTCP(0x6a5af6f5, 0x4738c758), WTCP(0x6a359db9, 0x47706d93), + WTCP(0x6a102760, 0x47a80039), WTCP(0x69ea93f2, 0x47df7f3a), + WTCP(0x69c4e37a, 0x4816ea86), WTCP(0x699f1604, 0x484e420f), + WTCP(0x69792b98, 0x488585c5), WTCP(0x69532442, 0x48bcb599), + WTCP(0x692d000c, 0x48f3d17c), WTCP(0x6906bf00, 0x492ad95f), + WTCP(0x68e06129, 0x4961cd33), WTCP(0x68b9e692, 0x4998ace9), + WTCP(0x68934f44, 0x49cf7871), WTCP(0x686c9b4b, 0x4a062fbd), + WTCP(0x6845cab1, 0x4a3cd2be), WTCP(0x681edd81, 0x4a736165), + WTCP(0x67f7d3c5, 0x4aa9dba2), WTCP(0x67d0ad88, 0x4ae04167), + WTCP(0x67a96ad5, 0x4b1692a5), WTCP(0x67820bb7, 0x4b4ccf4d), + WTCP(0x675a9038, 0x4b82f750), WTCP(0x6732f863, 0x4bb90aa0), + WTCP(0x670b4444, 0x4bef092d), WTCP(0x66e373e4, 0x4c24f2e9), + WTCP(0x66bb8750, 0x4c5ac7c4), WTCP(0x66937e91, 0x4c9087b1), + WTCP(0x666b59b3, 0x4cc632a0), WTCP(0x664318c0, 0x4cfbc883), + WTCP(0x661abbc5, 0x4d31494b), WTCP(0x65f242cc, 0x4d66b4e9), + WTCP(0x65c9addf, 0x4d9c0b4f), WTCP(0x65a0fd0b, 0x4dd14c6e), + WTCP(0x6578305a, 0x4e067837), WTCP(0x654f47d7, 0x4e3b8e9d), + WTCP(0x6526438f, 0x4e708f8f), WTCP(0x64fd238b, 0x4ea57b01), + WTCP(0x64d3e7d7, 0x4eda50e2), WTCP(0x64aa907f, 0x4f0f1126), + WTCP(0x64811d8e, 0x4f43bbbd), WTCP(0x64578f0f, 0x4f785099), + WTCP(0x642de50d, 0x4faccfab), WTCP(0x64041f95, 0x4fe138e5), + WTCP(0x63da3eb1, 0x50158c39), WTCP(0x63b0426d, 0x5049c999), + WTCP(0x63862ad5, 0x507df0f6), WTCP(0x635bf7f3, 0x50b20241), + WTCP(0x6331a9d4, 0x50e5fd6d), WTCP(0x63074084, 0x5119e26b), + WTCP(0x62dcbc0d, 0x514db12d), WTCP(0x62b21c7b, 0x518169a5), + WTCP(0x628761db, 0x51b50bc4), WTCP(0x625c8c38, 0x51e8977d), + WTCP(0x62319b9d, 0x521c0cc2), WTCP(0x62069017, 0x524f6b83), + WTCP(0x61db69b1, 0x5282b3b4), WTCP(0x61b02876, 0x52b5e546), + WTCP(0x6184cc74, 0x52e9002a), WTCP(0x615955b6, 0x531c0454), + WTCP(0x612dc447, 0x534ef1b5), WTCP(0x61021834, 0x5381c83f), + WTCP(0x60d65188, 0x53b487e5), WTCP(0x60aa7050, 0x53e73097), + WTCP(0x607e7497, 0x5419c249), WTCP(0x60525e6b, 0x544c3cec), + WTCP(0x60262dd6, 0x547ea073), WTCP(0x5ff9e2e5, 0x54b0ecd0), + WTCP(0x5fcd7da4, 0x54e321f5), WTCP(0x5fa0fe1f, 0x55153fd4), + WTCP(0x5f746462, 0x55474660), WTCP(0x5f47b07a, 0x5579358b), + WTCP(0x5f1ae274, 0x55ab0d46), WTCP(0x5eedfa5a, 0x55dccd86), + WTCP(0x5ec0f839, 0x560e763b), WTCP(0x5e93dc1f, 0x56400758), + WTCP(0x5e66a617, 0x567180d0), WTCP(0x5e39562d, 0x56a2e295), + WTCP(0x5e0bec6e, 0x56d42c99), WTCP(0x5dde68e7, 0x57055ed0), + WTCP(0x5db0cba4, 0x5736792b), WTCP(0x5d8314b1, 0x57677b9d), + WTCP(0x5d55441b, 0x57986619), WTCP(0x5d2759ee, 0x57c93891), + WTCP(0x5cf95638, 0x57f9f2f8), WTCP(0x5ccb3905, 0x582a9540), + WTCP(0x5c9d0260, 0x585b1f5c), WTCP(0x5c6eb258, 0x588b9140), + WTCP(0x5c4048f9, 0x58bbeadd), WTCP(0x5c11c64f, 0x58ec2c26), + WTCP(0x5be32a67, 0x591c550e), WTCP(0x5bb4754e, 0x594c6588), + WTCP(0x5b85a711, 0x597c5d87), WTCP(0x5b56bfbd, 0x59ac3cfd), + WTCP(0x5b27bf5e, 0x59dc03de), WTCP(0x5af8a602, 0x5a0bb21c), + WTCP(0x5ac973b5, 0x5a3b47ab), WTCP(0x5a9a2884, 0x5a6ac47c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow960[] = { + WTCP(0x7ffffd31, 0x001aceea), WTCP(0x7fffe6bc, 0x00506cb9), + WTCP(0x7fffb9d1, 0x00860a79), WTCP(0x7fff7671, 0x00bba822), + WTCP(0x7fff1c9b, 0x00f145ab), WTCP(0x7ffeac50, 0x0126e309), + WTCP(0x7ffe2590, 0x015c8033), WTCP(0x7ffd885a, 0x01921d20), + WTCP(0x7ffcd4b0, 0x01c7b9c6), WTCP(0x7ffc0a91, 0x01fd561d), + WTCP(0x7ffb29fd, 0x0232f21a), WTCP(0x7ffa32f4, 0x02688db4), + WTCP(0x7ff92577, 0x029e28e2), WTCP(0x7ff80186, 0x02d3c39b), + WTCP(0x7ff6c720, 0x03095dd5), WTCP(0x7ff57647, 0x033ef786), + WTCP(0x7ff40efa, 0x037490a5), WTCP(0x7ff2913a, 0x03aa292a), + WTCP(0x7ff0fd07, 0x03dfc109), WTCP(0x7fef5260, 0x0415583b), + WTCP(0x7fed9148, 0x044aeeb5), WTCP(0x7febb9bd, 0x0480846e), + WTCP(0x7fe9cbc0, 0x04b6195d), WTCP(0x7fe7c752, 0x04ebad79), + WTCP(0x7fe5ac72, 0x052140b7), WTCP(0x7fe37b22, 0x0556d30f), + WTCP(0x7fe13361, 0x058c6478), WTCP(0x7fded530, 0x05c1f4e7), + WTCP(0x7fdc608f, 0x05f78453), WTCP(0x7fd9d57f, 0x062d12b4), + WTCP(0x7fd73401, 0x06629ffe), WTCP(0x7fd47c14, 0x06982c2b), + WTCP(0x7fd1adb9, 0x06cdb72f), WTCP(0x7fcec8f1, 0x07034101), + WTCP(0x7fcbcdbc, 0x0738c998), WTCP(0x7fc8bc1b, 0x076e50eb), + WTCP(0x7fc5940e, 0x07a3d6f0), WTCP(0x7fc25596, 0x07d95b9e), + WTCP(0x7fbf00b3, 0x080edeec), WTCP(0x7fbb9567, 0x084460cf), + WTCP(0x7fb813b0, 0x0879e140), WTCP(0x7fb47b91, 0x08af6033), + WTCP(0x7fb0cd0a, 0x08e4dda0), WTCP(0x7fad081b, 0x091a597e), + WTCP(0x7fa92cc5, 0x094fd3c3), WTCP(0x7fa53b09, 0x09854c66), + WTCP(0x7fa132e8, 0x09bac35d), WTCP(0x7f9d1461, 0x09f0389f), + WTCP(0x7f98df77, 0x0a25ac23), WTCP(0x7f949429, 0x0a5b1dde), + WTCP(0x7f903279, 0x0a908dc9), WTCP(0x7f8bba66, 0x0ac5fbd9), + WTCP(0x7f872bf3, 0x0afb6805), WTCP(0x7f82871f, 0x0b30d244), + WTCP(0x7f7dcbec, 0x0b663a8c), WTCP(0x7f78fa5b, 0x0b9ba0d5), + WTCP(0x7f74126b, 0x0bd10513), WTCP(0x7f6f141f, 0x0c066740), + WTCP(0x7f69ff76, 0x0c3bc74f), WTCP(0x7f64d473, 0x0c71253a), + WTCP(0x7f5f9315, 0x0ca680f5), WTCP(0x7f5a3b5e, 0x0cdbda79), + WTCP(0x7f54cd4f, 0x0d1131ba), WTCP(0x7f4f48e8, 0x0d4686b1), + WTCP(0x7f49ae2a, 0x0d7bd954), WTCP(0x7f43fd18, 0x0db12999), + WTCP(0x7f3e35b0, 0x0de67776), WTCP(0x7f3857f6, 0x0e1bc2e4), + WTCP(0x7f3263e9, 0x0e510bd8), WTCP(0x7f2c598a, 0x0e865248), + WTCP(0x7f2638db, 0x0ebb962c), WTCP(0x7f2001dd, 0x0ef0d77b), + WTCP(0x7f19b491, 0x0f26162a), WTCP(0x7f1350f8, 0x0f5b5231), + WTCP(0x7f0cd712, 0x0f908b86), WTCP(0x7f0646e2, 0x0fc5c220), + WTCP(0x7effa069, 0x0ffaf5f6), WTCP(0x7ef8e3a6, 0x103026fe), + WTCP(0x7ef2109d, 0x1065552e), WTCP(0x7eeb274d, 0x109a807e), + WTCP(0x7ee427b9, 0x10cfa8e5), WTCP(0x7edd11e1, 0x1104ce58), + WTCP(0x7ed5e5c6, 0x1139f0cf), WTCP(0x7ecea36b, 0x116f1040), + WTCP(0x7ec74acf, 0x11a42ca2), WTCP(0x7ebfdbf5, 0x11d945eb), + WTCP(0x7eb856de, 0x120e5c13), WTCP(0x7eb0bb8a, 0x12436f10), + WTCP(0x7ea909fc, 0x12787ed8), WTCP(0x7ea14235, 0x12ad8b63), + WTCP(0x7e996436, 0x12e294a7), WTCP(0x7e917000, 0x13179a9b), + WTCP(0x7e896595, 0x134c9d34), WTCP(0x7e8144f6, 0x13819c6c), + WTCP(0x7e790e25, 0x13b69836), WTCP(0x7e70c124, 0x13eb908c), + WTCP(0x7e685df2, 0x14208563), WTCP(0x7e5fe493, 0x145576b1), + WTCP(0x7e575508, 0x148a646e), WTCP(0x7e4eaf51, 0x14bf4e91), + WTCP(0x7e45f371, 0x14f43510), WTCP(0x7e3d2169, 0x152917e1), + WTCP(0x7e34393b, 0x155df6fc), WTCP(0x7e2b3ae8, 0x1592d257), + WTCP(0x7e222672, 0x15c7a9ea), WTCP(0x7e18fbda, 0x15fc7daa), + WTCP(0x7e0fbb22, 0x16314d8e), WTCP(0x7e06644c, 0x1666198d), + WTCP(0x7dfcf759, 0x169ae19f), WTCP(0x7df3744b, 0x16cfa5b9), + WTCP(0x7de9db23, 0x170465d2), WTCP(0x7de02be4, 0x173921e2), + WTCP(0x7dd6668f, 0x176dd9de), WTCP(0x7dcc8b25, 0x17a28dbe), + WTCP(0x7dc299a9, 0x17d73d79), WTCP(0x7db8921c, 0x180be904), + WTCP(0x7dae747f, 0x18409058), WTCP(0x7da440d6, 0x1875336a), + WTCP(0x7d99f721, 0x18a9d231), WTCP(0x7d8f9762, 0x18de6ca5), + WTCP(0x7d85219c, 0x191302bc), WTCP(0x7d7a95cf, 0x1947946c), + WTCP(0x7d6ff3fe, 0x197c21ad), WTCP(0x7d653c2b, 0x19b0aa75), + WTCP(0x7d5a6e57, 0x19e52ebb), WTCP(0x7d4f8a85, 0x1a19ae76), + WTCP(0x7d4490b6, 0x1a4e299d), WTCP(0x7d3980ec, 0x1a82a026), + WTCP(0x7d2e5b2a, 0x1ab71208), WTCP(0x7d231f70, 0x1aeb7f3a), + WTCP(0x7d17cdc2, 0x1b1fe7b3), WTCP(0x7d0c6621, 0x1b544b6a), + WTCP(0x7d00e88f, 0x1b88aa55), WTCP(0x7cf5550e, 0x1bbd046c), + WTCP(0x7ce9aba1, 0x1bf159a4), WTCP(0x7cddec48, 0x1c25a9f6), + WTCP(0x7cd21707, 0x1c59f557), WTCP(0x7cc62bdf, 0x1c8e3bbe), + WTCP(0x7cba2ad3, 0x1cc27d23), WTCP(0x7cae13e4, 0x1cf6b97c), + WTCP(0x7ca1e715, 0x1d2af0c1), WTCP(0x7c95a467, 0x1d5f22e7), + WTCP(0x7c894bde, 0x1d934fe5), WTCP(0x7c7cdd7b, 0x1dc777b3), + WTCP(0x7c705940, 0x1dfb9a48), WTCP(0x7c63bf2f, 0x1e2fb79a), + WTCP(0x7c570f4b, 0x1e63cfa0), WTCP(0x7c4a4996, 0x1e97e251), + WTCP(0x7c3d6e13, 0x1ecbefa4), WTCP(0x7c307cc2, 0x1efff78f), + WTCP(0x7c2375a8, 0x1f33fa0a), WTCP(0x7c1658c5, 0x1f67f70b), + WTCP(0x7c09261d, 0x1f9bee8a), WTCP(0x7bfbddb1, 0x1fcfe07d), + WTCP(0x7bee7f85, 0x2003ccdb), WTCP(0x7be10b99, 0x2037b39b), + WTCP(0x7bd381f1, 0x206b94b4), WTCP(0x7bc5e290, 0x209f701c), + WTCP(0x7bb82d76, 0x20d345cc), WTCP(0x7baa62a8, 0x210715b8), + WTCP(0x7b9c8226, 0x213adfda), WTCP(0x7b8e8bf5, 0x216ea426), + WTCP(0x7b808015, 0x21a26295), WTCP(0x7b725e8a, 0x21d61b1e), + WTCP(0x7b642756, 0x2209cdb6), WTCP(0x7b55da7c, 0x223d7a55), + WTCP(0x7b4777fe, 0x227120f3), WTCP(0x7b38ffde, 0x22a4c185), + WTCP(0x7b2a721f, 0x22d85c04), WTCP(0x7b1bcec4, 0x230bf065), + WTCP(0x7b0d15d0, 0x233f7ea0), WTCP(0x7afe4744, 0x237306ab), + WTCP(0x7aef6323, 0x23a6887f), WTCP(0x7ae06971, 0x23da0411), + WTCP(0x7ad15a2f, 0x240d7958), WTCP(0x7ac23561, 0x2440e84d), + WTCP(0x7ab2fb09, 0x247450e4), WTCP(0x7aa3ab29, 0x24a7b317), + WTCP(0x7a9445c5, 0x24db0edb), WTCP(0x7a84cade, 0x250e6427), + WTCP(0x7a753a79, 0x2541b2f3), WTCP(0x7a659496, 0x2574fb36), + WTCP(0x7a55d93a, 0x25a83ce6), WTCP(0x7a460867, 0x25db77fa), + WTCP(0x7a362220, 0x260eac6a), WTCP(0x7a262668, 0x2641da2d), + WTCP(0x7a161540, 0x26750139), WTCP(0x7a05eead, 0x26a82186), + WTCP(0x79f5b2b1, 0x26db3b0a), WTCP(0x79e5614f, 0x270e4dbd), + WTCP(0x79d4fa89, 0x27415996), WTCP(0x79c47e63, 0x27745e8c), + WTCP(0x79b3ece0, 0x27a75c95), WTCP(0x79a34602, 0x27da53a9), + WTCP(0x799289cc, 0x280d43bf), WTCP(0x7981b841, 0x28402cce), + WTCP(0x7970d165, 0x28730ecd), WTCP(0x795fd53a, 0x28a5e9b4), + WTCP(0x794ec3c3, 0x28d8bd78), WTCP(0x793d9d03, 0x290b8a12), + WTCP(0x792c60fe, 0x293e4f78), WTCP(0x791b0fb5, 0x29710da1), + WTCP(0x7909a92d, 0x29a3c485), WTCP(0x78f82d68, 0x29d6741b), + WTCP(0x78e69c69, 0x2a091c59), WTCP(0x78d4f634, 0x2a3bbd37), + WTCP(0x78c33acb, 0x2a6e56ac), WTCP(0x78b16a32, 0x2aa0e8b0), + WTCP(0x789f846b, 0x2ad37338), WTCP(0x788d897b, 0x2b05f63d), + WTCP(0x787b7963, 0x2b3871b5), WTCP(0x78695428, 0x2b6ae598), + WTCP(0x785719cc, 0x2b9d51dd), WTCP(0x7844ca53, 0x2bcfb67b), + WTCP(0x783265c0, 0x2c021369), WTCP(0x781fec15, 0x2c34689e), + WTCP(0x780d5d57, 0x2c66b611), WTCP(0x77fab989, 0x2c98fbba), + WTCP(0x77e800ad, 0x2ccb3990), WTCP(0x77d532c7, 0x2cfd6f8a), + WTCP(0x77c24fdb, 0x2d2f9d9f), WTCP(0x77af57eb, 0x2d61c3c7), + WTCP(0x779c4afc, 0x2d93e1f8), WTCP(0x77892910, 0x2dc5f829), + WTCP(0x7775f22a, 0x2df80653), WTCP(0x7762a64f, 0x2e2a0c6c), + WTCP(0x774f4581, 0x2e5c0a6b), WTCP(0x773bcfc4, 0x2e8e0048), + WTCP(0x7728451c, 0x2ebfedfa), WTCP(0x7714a58b, 0x2ef1d377), + WTCP(0x7700f115, 0x2f23b0b9), WTCP(0x76ed27be, 0x2f5585b5), + WTCP(0x76d94989, 0x2f875262), WTCP(0x76c55679, 0x2fb916b9), + WTCP(0x76b14e93, 0x2fead2b0), WTCP(0x769d31d9, 0x301c863f), + WTCP(0x76890050, 0x304e315d), WTCP(0x7674b9fa, 0x307fd401), + WTCP(0x76605edb, 0x30b16e23), WTCP(0x764beef8, 0x30e2ffb9), + WTCP(0x76376a52, 0x311488bc), WTCP(0x7622d0ef, 0x31460922), + WTCP(0x760e22d1, 0x317780e2), WTCP(0x75f95ffc, 0x31a8eff5), + WTCP(0x75e48874, 0x31da5651), WTCP(0x75cf9c3d, 0x320bb3ee), + WTCP(0x75ba9b5a, 0x323d08c3), WTCP(0x75a585cf, 0x326e54c7), + WTCP(0x75905ba0, 0x329f97f3), WTCP(0x757b1ccf, 0x32d0d23c), + WTCP(0x7565c962, 0x3302039b), WTCP(0x7550615c, 0x33332c06), + WTCP(0x753ae4c0, 0x33644b76), WTCP(0x75255392, 0x339561e1), + WTCP(0x750fadd7, 0x33c66f40), WTCP(0x74f9f391, 0x33f77388), + WTCP(0x74e424c5, 0x34286eb3), WTCP(0x74ce4177, 0x345960b7), + WTCP(0x74b849aa, 0x348a498b), WTCP(0x74a23d62, 0x34bb2927), + WTCP(0x748c1ca4, 0x34ebff83), WTCP(0x7475e772, 0x351ccc96), + WTCP(0x745f9dd1, 0x354d9057), WTCP(0x74493fc5, 0x357e4abe), + WTCP(0x7432cd51, 0x35aefbc2), WTCP(0x741c467b, 0x35dfa35a), + WTCP(0x7405ab45, 0x3610417f), WTCP(0x73eefbb3, 0x3640d627), + WTCP(0x73d837ca, 0x3671614b), WTCP(0x73c15f8d, 0x36a1e2e0), + WTCP(0x73aa7301, 0x36d25ae0), WTCP(0x7393722a, 0x3702c942), + WTCP(0x737c5d0b, 0x37332dfd), WTCP(0x736533a9, 0x37638908), + WTCP(0x734df607, 0x3793da5b), WTCP(0x7336a42b, 0x37c421ee), + WTCP(0x731f3e17, 0x37f45fb7), WTCP(0x7307c3d0, 0x382493b0), + WTCP(0x72f0355a, 0x3854bdcf), WTCP(0x72d892ba, 0x3884de0b), + WTCP(0x72c0dbf3, 0x38b4f45d), WTCP(0x72a91109, 0x38e500bc), + WTCP(0x72913201, 0x3915031f), WTCP(0x72793edf, 0x3944fb7e), + WTCP(0x726137a8, 0x3974e9d0), WTCP(0x72491c5e, 0x39a4ce0e), + WTCP(0x7230ed07, 0x39d4a82f), WTCP(0x7218a9a7, 0x3a04782a), + WTCP(0x72005242, 0x3a343df7), WTCP(0x71e7e6dc, 0x3a63f98d), + WTCP(0x71cf677a, 0x3a93aae5), WTCP(0x71b6d420, 0x3ac351f6), + WTCP(0x719e2cd2, 0x3af2eeb7), WTCP(0x71857195, 0x3b228120), + WTCP(0x716ca26c, 0x3b52092a), WTCP(0x7153bf5d, 0x3b8186ca), + WTCP(0x713ac86b, 0x3bb0f9fa), WTCP(0x7121bd9c, 0x3be062b0), + WTCP(0x71089ef2, 0x3c0fc0e6), WTCP(0x70ef6c74, 0x3c3f1491), + WTCP(0x70d62625, 0x3c6e5daa), WTCP(0x70bccc09, 0x3c9d9c28), + WTCP(0x70a35e25, 0x3cccd004), WTCP(0x7089dc7e, 0x3cfbf935), + WTCP(0x70704718, 0x3d2b17b3), WTCP(0x70569df8, 0x3d5a2b75), + WTCP(0x703ce122, 0x3d893474), WTCP(0x7023109a, 0x3db832a6), + WTCP(0x70092c65, 0x3de72604), WTCP(0x6fef3488, 0x3e160e85), + WTCP(0x6fd52907, 0x3e44ec22), WTCP(0x6fbb09e7, 0x3e73bed2), + WTCP(0x6fa0d72c, 0x3ea2868c), WTCP(0x6f8690db, 0x3ed14349), + WTCP(0x6f6c36f8, 0x3efff501), WTCP(0x6f51c989, 0x3f2e9bab), + WTCP(0x6f374891, 0x3f5d373e), WTCP(0x6f1cb416, 0x3f8bc7b4), + WTCP(0x6f020c1c, 0x3fba4d03), WTCP(0x6ee750a8, 0x3fe8c724), + WTCP(0x6ecc81be, 0x4017360e), WTCP(0x6eb19f64, 0x404599b9), + WTCP(0x6e96a99d, 0x4073f21d), WTCP(0x6e7ba06f, 0x40a23f32), + WTCP(0x6e6083de, 0x40d080f0), WTCP(0x6e4553ef, 0x40feb74f), + WTCP(0x6e2a10a8, 0x412ce246), WTCP(0x6e0eba0c, 0x415b01ce), + WTCP(0x6df35020, 0x418915de), WTCP(0x6dd7d2ea, 0x41b71e6f), + WTCP(0x6dbc426e, 0x41e51b77), WTCP(0x6da09eb1, 0x42130cf0), + WTCP(0x6d84e7b7, 0x4240f2d1), WTCP(0x6d691d87, 0x426ecd12), + WTCP(0x6d4d4023, 0x429c9bab), WTCP(0x6d314f93, 0x42ca5e94), + WTCP(0x6d154bd9, 0x42f815c5), WTCP(0x6cf934fc, 0x4325c135), + WTCP(0x6cdd0b00, 0x435360de), WTCP(0x6cc0cdea, 0x4380f4b7), + WTCP(0x6ca47dbf, 0x43ae7cb7), WTCP(0x6c881a84, 0x43dbf8d7), + WTCP(0x6c6ba43e, 0x44096910), WTCP(0x6c4f1af2, 0x4436cd58), + WTCP(0x6c327ea6, 0x446425a8), WTCP(0x6c15cf5d, 0x449171f8), + WTCP(0x6bf90d1d, 0x44beb240), WTCP(0x6bdc37eb, 0x44ebe679), + WTCP(0x6bbf4fcd, 0x45190e99), WTCP(0x6ba254c7, 0x45462a9a), + WTCP(0x6b8546de, 0x45733a73), WTCP(0x6b682617, 0x45a03e1d), + WTCP(0x6b4af279, 0x45cd358f), WTCP(0x6b2dac06, 0x45fa20c2), + WTCP(0x6b1052c6, 0x4626ffae), WTCP(0x6af2e6bc, 0x4653d24b), + WTCP(0x6ad567ef, 0x46809891), WTCP(0x6ab7d663, 0x46ad5278), + WTCP(0x6a9a321d, 0x46d9fff8), WTCP(0x6a7c7b23, 0x4706a10a), + WTCP(0x6a5eb17a, 0x473335a5), WTCP(0x6a40d527, 0x475fbdc3), + WTCP(0x6a22e630, 0x478c395a), WTCP(0x6a04e499, 0x47b8a864), + WTCP(0x69e6d067, 0x47e50ad8), WTCP(0x69c8a9a1, 0x481160ae), + WTCP(0x69aa704c, 0x483da9e0), WTCP(0x698c246c, 0x4869e665), + WTCP(0x696dc607, 0x48961635), WTCP(0x694f5523, 0x48c23949), + WTCP(0x6930d1c4, 0x48ee4f98), WTCP(0x69123bf1, 0x491a591c), + WTCP(0x68f393ae, 0x494655cc), WTCP(0x68d4d900, 0x497245a1), + WTCP(0x68b60bee, 0x499e2892), WTCP(0x68972c7d, 0x49c9fe99), + WTCP(0x68783ab1, 0x49f5c7ae), WTCP(0x68593691, 0x4a2183c8), + WTCP(0x683a2022, 0x4a4d32e1), WTCP(0x681af76a, 0x4a78d4f0), + WTCP(0x67fbbc6d, 0x4aa469ee), WTCP(0x67dc6f31, 0x4acff1d3), + WTCP(0x67bd0fbd, 0x4afb6c98), WTCP(0x679d9e14, 0x4b26da35), + WTCP(0x677e1a3e, 0x4b523aa2), WTCP(0x675e843e, 0x4b7d8dd8), + WTCP(0x673edc1c, 0x4ba8d3cf), WTCP(0x671f21dc, 0x4bd40c80), + WTCP(0x66ff5584, 0x4bff37e2), WTCP(0x66df771a, 0x4c2a55ef), + WTCP(0x66bf86a3, 0x4c55669f), WTCP(0x669f8425, 0x4c8069ea), + WTCP(0x667f6fa5, 0x4cab5fc9), WTCP(0x665f4929, 0x4cd64834), + WTCP(0x663f10b7, 0x4d012324), WTCP(0x661ec654, 0x4d2bf091), + WTCP(0x65fe6a06, 0x4d56b073), WTCP(0x65ddfbd3, 0x4d8162c4), + WTCP(0x65bd7bc0, 0x4dac077b), WTCP(0x659ce9d4, 0x4dd69e92), + WTCP(0x657c4613, 0x4e012800), WTCP(0x655b9083, 0x4e2ba3be), + WTCP(0x653ac92b, 0x4e5611c5), WTCP(0x6519f010, 0x4e80720e), + WTCP(0x64f90538, 0x4eaac490), WTCP(0x64d808a8, 0x4ed50945), + WTCP(0x64b6fa66, 0x4eff4025), WTCP(0x6495da79, 0x4f296928), + WTCP(0x6474a8e5, 0x4f538448), WTCP(0x645365b2, 0x4f7d917c), + WTCP(0x643210e4, 0x4fa790be), WTCP(0x6410aa81, 0x4fd18206), + WTCP(0x63ef3290, 0x4ffb654d), WTCP(0x63cda916, 0x50253a8b), + WTCP(0x63ac0e19, 0x504f01ba), WTCP(0x638a619e, 0x5078bad1), + WTCP(0x6368a3ad, 0x50a265c9), WTCP(0x6346d44b, 0x50cc029c), + WTCP(0x6324f37d, 0x50f59141), WTCP(0x6303014a, 0x511f11b2), + WTCP(0x62e0fdb8, 0x514883e7), WTCP(0x62bee8cc, 0x5171e7d9), + WTCP(0x629cc28c, 0x519b3d80), WTCP(0x627a8b00, 0x51c484d6), + WTCP(0x6258422c, 0x51edbdd4), WTCP(0x6235e816, 0x5216e871), + WTCP(0x62137cc5, 0x524004a7), WTCP(0x61f1003f, 0x5269126e), + WTCP(0x61ce7289, 0x529211c0), WTCP(0x61abd3ab, 0x52bb0295), + WTCP(0x618923a9, 0x52e3e4e6), WTCP(0x61666289, 0x530cb8ac), + WTCP(0x61439053, 0x53357ddf), WTCP(0x6120ad0d, 0x535e3479), + WTCP(0x60fdb8bb, 0x5386dc72), WTCP(0x60dab365, 0x53af75c3), + WTCP(0x60b79d10, 0x53d80065), WTCP(0x609475c3, 0x54007c51), + WTCP(0x60713d84, 0x5428e980), WTCP(0x604df459, 0x545147eb), + WTCP(0x602a9a48, 0x5479978a), WTCP(0x60072f57, 0x54a1d857), + WTCP(0x5fe3b38d, 0x54ca0a4b), WTCP(0x5fc026f0, 0x54f22d5d), + WTCP(0x5f9c8987, 0x551a4189), WTCP(0x5f78db56, 0x554246c6), + WTCP(0x5f551c65, 0x556a3d0d), WTCP(0x5f314cba, 0x55922457), + WTCP(0x5f0d6c5b, 0x55b9fc9e), WTCP(0x5ee97b4f, 0x55e1c5da), + WTCP(0x5ec5799b, 0x56098005), WTCP(0x5ea16747, 0x56312b17), + WTCP(0x5e7d4458, 0x5658c709), WTCP(0x5e5910d4, 0x568053d5), + WTCP(0x5e34ccc3, 0x56a7d174), WTCP(0x5e10782b, 0x56cf3fde), + WTCP(0x5dec1311, 0x56f69f0d), WTCP(0x5dc79d7c, 0x571deefa), + WTCP(0x5da31773, 0x57452f9d), WTCP(0x5d7e80fc, 0x576c60f1), + WTCP(0x5d59da1e, 0x579382ee), WTCP(0x5d3522de, 0x57ba958d), + WTCP(0x5d105b44, 0x57e198c7), WTCP(0x5ceb8355, 0x58088c96), + WTCP(0x5cc69b19, 0x582f70f3), WTCP(0x5ca1a295, 0x585645d7), + WTCP(0x5c7c99d1, 0x587d0b3b), WTCP(0x5c5780d3, 0x58a3c118), + WTCP(0x5c3257a0, 0x58ca6767), WTCP(0x5c0d1e41, 0x58f0fe23), + WTCP(0x5be7d4ba, 0x59178543), WTCP(0x5bc27b14, 0x593dfcc2), + WTCP(0x5b9d1154, 0x59646498), WTCP(0x5b779780, 0x598abcbe), + WTCP(0x5b520da1, 0x59b1052f), WTCP(0x5b2c73bb, 0x59d73de3), + WTCP(0x5b06c9d6, 0x59fd66d4), WTCP(0x5ae10ff9, 0x5a237ffa), + WTCP(0x5abb4629, 0x5a498950), WTCP(0x5a956c6e, 0x5a6f82ce), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP SineWindow1024[] = { + WTCP(0x7ffffd88, 0x001921fb), WTCP(0x7fffe9cb, 0x004b65ee), + WTCP(0x7fffc251, 0x007da9d4), WTCP(0x7fff8719, 0x00afeda8), + WTCP(0x7fff3824, 0x00e23160), WTCP(0x7ffed572, 0x011474f6), + WTCP(0x7ffe5f03, 0x0146b860), WTCP(0x7ffdd4d7, 0x0178fb99), + WTCP(0x7ffd36ee, 0x01ab3e97), WTCP(0x7ffc8549, 0x01dd8154), + WTCP(0x7ffbbfe6, 0x020fc3c6), WTCP(0x7ffae6c7, 0x024205e8), + WTCP(0x7ff9f9ec, 0x027447b0), WTCP(0x7ff8f954, 0x02a68917), + WTCP(0x7ff7e500, 0x02d8ca16), WTCP(0x7ff6bcf0, 0x030b0aa4), + WTCP(0x7ff58125, 0x033d4abb), WTCP(0x7ff4319d, 0x036f8a51), + WTCP(0x7ff2ce5b, 0x03a1c960), WTCP(0x7ff1575d, 0x03d407df), + WTCP(0x7fefcca4, 0x040645c7), WTCP(0x7fee2e30, 0x04388310), + WTCP(0x7fec7c02, 0x046abfb3), WTCP(0x7feab61a, 0x049cfba7), + WTCP(0x7fe8dc78, 0x04cf36e5), WTCP(0x7fe6ef1c, 0x05017165), + WTCP(0x7fe4ee06, 0x0533ab20), WTCP(0x7fe2d938, 0x0565e40d), + WTCP(0x7fe0b0b1, 0x05981c26), WTCP(0x7fde7471, 0x05ca5361), + WTCP(0x7fdc247a, 0x05fc89b8), WTCP(0x7fd9c0ca, 0x062ebf22), + WTCP(0x7fd74964, 0x0660f398), WTCP(0x7fd4be46, 0x06932713), + WTCP(0x7fd21f72, 0x06c5598a), WTCP(0x7fcf6ce8, 0x06f78af6), + WTCP(0x7fcca6a7, 0x0729bb4e), WTCP(0x7fc9ccb2, 0x075bea8c), + WTCP(0x7fc6df08, 0x078e18a7), WTCP(0x7fc3dda9, 0x07c04598), + WTCP(0x7fc0c896, 0x07f27157), WTCP(0x7fbd9fd0, 0x08249bdd), + WTCP(0x7fba6357, 0x0856c520), WTCP(0x7fb7132b, 0x0888ed1b), + WTCP(0x7fb3af4e, 0x08bb13c5), WTCP(0x7fb037bf, 0x08ed3916), + WTCP(0x7facac7f, 0x091f5d06), WTCP(0x7fa90d8e, 0x09517f8f), + WTCP(0x7fa55aee, 0x0983a0a7), WTCP(0x7fa1949e, 0x09b5c048), + WTCP(0x7f9dbaa0, 0x09e7de6a), WTCP(0x7f99ccf4, 0x0a19fb04), + WTCP(0x7f95cb9a, 0x0a4c1610), WTCP(0x7f91b694, 0x0a7e2f85), + WTCP(0x7f8d8de1, 0x0ab0475c), WTCP(0x7f895182, 0x0ae25d8d), + WTCP(0x7f850179, 0x0b147211), WTCP(0x7f809dc5, 0x0b4684df), + WTCP(0x7f7c2668, 0x0b7895f0), WTCP(0x7f779b62, 0x0baaa53b), + WTCP(0x7f72fcb4, 0x0bdcb2bb), WTCP(0x7f6e4a5e, 0x0c0ebe66), + WTCP(0x7f698461, 0x0c40c835), WTCP(0x7f64aabf, 0x0c72d020), + WTCP(0x7f5fbd77, 0x0ca4d620), WTCP(0x7f5abc8a, 0x0cd6da2d), + WTCP(0x7f55a7fa, 0x0d08dc3f), WTCP(0x7f507fc7, 0x0d3adc4e), + WTCP(0x7f4b43f2, 0x0d6cda53), WTCP(0x7f45f47b, 0x0d9ed646), + WTCP(0x7f409164, 0x0dd0d01f), WTCP(0x7f3b1aad, 0x0e02c7d7), + WTCP(0x7f359057, 0x0e34bd66), WTCP(0x7f2ff263, 0x0e66b0c3), + WTCP(0x7f2a40d2, 0x0e98a1e9), WTCP(0x7f247ba5, 0x0eca90ce), + WTCP(0x7f1ea2dc, 0x0efc7d6b), WTCP(0x7f18b679, 0x0f2e67b8), + WTCP(0x7f12b67c, 0x0f604faf), WTCP(0x7f0ca2e7, 0x0f923546), + WTCP(0x7f067bba, 0x0fc41876), WTCP(0x7f0040f6, 0x0ff5f938), + WTCP(0x7ef9f29d, 0x1027d784), WTCP(0x7ef390ae, 0x1059b352), + WTCP(0x7eed1b2c, 0x108b8c9b), WTCP(0x7ee69217, 0x10bd6356), + WTCP(0x7edff570, 0x10ef377d), WTCP(0x7ed94538, 0x11210907), + WTCP(0x7ed28171, 0x1152d7ed), WTCP(0x7ecbaa1a, 0x1184a427), + WTCP(0x7ec4bf36, 0x11b66dad), WTCP(0x7ebdc0c6, 0x11e83478), + WTCP(0x7eb6aeca, 0x1219f880), WTCP(0x7eaf8943, 0x124bb9be), + WTCP(0x7ea85033, 0x127d7829), WTCP(0x7ea1039b, 0x12af33ba), + WTCP(0x7e99a37c, 0x12e0ec6a), WTCP(0x7e922fd6, 0x1312a230), + WTCP(0x7e8aa8ac, 0x13445505), WTCP(0x7e830dff, 0x137604e2), + WTCP(0x7e7b5fce, 0x13a7b1bf), WTCP(0x7e739e1d, 0x13d95b93), + WTCP(0x7e6bc8eb, 0x140b0258), WTCP(0x7e63e03b, 0x143ca605), + WTCP(0x7e5be40c, 0x146e4694), WTCP(0x7e53d462, 0x149fe3fc), + WTCP(0x7e4bb13c, 0x14d17e36), WTCP(0x7e437a9c, 0x1503153a), + WTCP(0x7e3b3083, 0x1534a901), WTCP(0x7e32d2f4, 0x15663982), + WTCP(0x7e2a61ed, 0x1597c6b7), WTCP(0x7e21dd73, 0x15c95097), + WTCP(0x7e194584, 0x15fad71b), WTCP(0x7e109a24, 0x162c5a3b), + WTCP(0x7e07db52, 0x165dd9f0), WTCP(0x7dff0911, 0x168f5632), + WTCP(0x7df62362, 0x16c0cef9), WTCP(0x7ded2a47, 0x16f2443e), + WTCP(0x7de41dc0, 0x1723b5f9), WTCP(0x7ddafdce, 0x17552422), + WTCP(0x7dd1ca75, 0x17868eb3), WTCP(0x7dc883b4, 0x17b7f5a3), + WTCP(0x7dbf298d, 0x17e958ea), WTCP(0x7db5bc02, 0x181ab881), + WTCP(0x7dac3b15, 0x184c1461), WTCP(0x7da2a6c6, 0x187d6c82), + WTCP(0x7d98ff17, 0x18aec0db), WTCP(0x7d8f4409, 0x18e01167), + WTCP(0x7d85759f, 0x19115e1c), WTCP(0x7d7b93da, 0x1942a6f3), + WTCP(0x7d719eba, 0x1973ebe6), WTCP(0x7d679642, 0x19a52ceb), + WTCP(0x7d5d7a74, 0x19d669fc), WTCP(0x7d534b50, 0x1a07a311), + WTCP(0x7d4908d9, 0x1a38d823), WTCP(0x7d3eb30f, 0x1a6a0929), + WTCP(0x7d3449f5, 0x1a9b361d), WTCP(0x7d29cd8c, 0x1acc5ef6), + WTCP(0x7d1f3dd6, 0x1afd83ad), WTCP(0x7d149ad5, 0x1b2ea43a), + WTCP(0x7d09e489, 0x1b5fc097), WTCP(0x7cff1af5, 0x1b90d8bb), + WTCP(0x7cf43e1a, 0x1bc1ec9e), WTCP(0x7ce94dfb, 0x1bf2fc3a), + WTCP(0x7cde4a98, 0x1c240786), WTCP(0x7cd333f3, 0x1c550e7c), + WTCP(0x7cc80a0f, 0x1c861113), WTCP(0x7cbcccec, 0x1cb70f43), + WTCP(0x7cb17c8d, 0x1ce80906), WTCP(0x7ca618f3, 0x1d18fe54), + WTCP(0x7c9aa221, 0x1d49ef26), WTCP(0x7c8f1817, 0x1d7adb73), + WTCP(0x7c837ad8, 0x1dabc334), WTCP(0x7c77ca65, 0x1ddca662), + WTCP(0x7c6c06c0, 0x1e0d84f5), WTCP(0x7c602fec, 0x1e3e5ee5), + WTCP(0x7c5445e9, 0x1e6f342c), WTCP(0x7c4848ba, 0x1ea004c1), + WTCP(0x7c3c3860, 0x1ed0d09d), WTCP(0x7c3014de, 0x1f0197b8), + WTCP(0x7c23de35, 0x1f325a0b), WTCP(0x7c179467, 0x1f63178f), + WTCP(0x7c0b3777, 0x1f93d03c), WTCP(0x7bfec765, 0x1fc4840a), + WTCP(0x7bf24434, 0x1ff532f2), WTCP(0x7be5ade6, 0x2025dcec), + WTCP(0x7bd9047c, 0x205681f1), WTCP(0x7bcc47fa, 0x208721f9), + WTCP(0x7bbf7860, 0x20b7bcfe), WTCP(0x7bb295b0, 0x20e852f6), + WTCP(0x7ba59fee, 0x2118e3dc), WTCP(0x7b989719, 0x21496fa7), + WTCP(0x7b8b7b36, 0x2179f64f), WTCP(0x7b7e4c45, 0x21aa77cf), + WTCP(0x7b710a49, 0x21daf41d), WTCP(0x7b63b543, 0x220b6b32), + WTCP(0x7b564d36, 0x223bdd08), WTCP(0x7b48d225, 0x226c4996), + WTCP(0x7b3b4410, 0x229cb0d5), WTCP(0x7b2da2fa, 0x22cd12bd), + WTCP(0x7b1feee5, 0x22fd6f48), WTCP(0x7b1227d3, 0x232dc66d), + WTCP(0x7b044dc7, 0x235e1826), WTCP(0x7af660c2, 0x238e646a), + WTCP(0x7ae860c7, 0x23beab33), WTCP(0x7ada4dd8, 0x23eeec78), + WTCP(0x7acc27f7, 0x241f2833), WTCP(0x7abdef25, 0x244f5e5c), + WTCP(0x7aafa367, 0x247f8eec), WTCP(0x7aa144bc, 0x24afb9da), + WTCP(0x7a92d329, 0x24dfdf20), WTCP(0x7a844eae, 0x250ffeb7), + WTCP(0x7a75b74f, 0x25401896), WTCP(0x7a670d0d, 0x25702cb7), + WTCP(0x7a584feb, 0x25a03b11), WTCP(0x7a497feb, 0x25d0439f), + WTCP(0x7a3a9d0f, 0x26004657), WTCP(0x7a2ba75a, 0x26304333), + WTCP(0x7a1c9ece, 0x26603a2c), WTCP(0x7a0d836d, 0x26902b39), + WTCP(0x79fe5539, 0x26c01655), WTCP(0x79ef1436, 0x26effb76), + WTCP(0x79dfc064, 0x271fda96), WTCP(0x79d059c8, 0x274fb3ae), + WTCP(0x79c0e062, 0x277f86b5), WTCP(0x79b15435, 0x27af53a6), + WTCP(0x79a1b545, 0x27df1a77), WTCP(0x79920392, 0x280edb23), + WTCP(0x79823f20, 0x283e95a1), WTCP(0x797267f2, 0x286e49ea), + WTCP(0x79627e08, 0x289df7f8), WTCP(0x79528167, 0x28cd9fc1), + WTCP(0x79427210, 0x28fd4140), WTCP(0x79325006, 0x292cdc6d), + WTCP(0x79221b4b, 0x295c7140), WTCP(0x7911d3e2, 0x298bffb2), + WTCP(0x790179cd, 0x29bb87bc), WTCP(0x78f10d0f, 0x29eb0957), + WTCP(0x78e08dab, 0x2a1a847b), WTCP(0x78cffba3, 0x2a49f920), + WTCP(0x78bf56f9, 0x2a796740), WTCP(0x78ae9fb0, 0x2aa8ced3), + WTCP(0x789dd5cb, 0x2ad82fd2), WTCP(0x788cf94c, 0x2b078a36), + WTCP(0x787c0a36, 0x2b36ddf7), WTCP(0x786b088c, 0x2b662b0e), + WTCP(0x7859f44f, 0x2b957173), WTCP(0x7848cd83, 0x2bc4b120), + WTCP(0x7837942b, 0x2bf3ea0d), WTCP(0x78264849, 0x2c231c33), + WTCP(0x7814e9df, 0x2c52478a), WTCP(0x780378f1, 0x2c816c0c), + WTCP(0x77f1f581, 0x2cb089b1), WTCP(0x77e05f91, 0x2cdfa071), + WTCP(0x77ceb725, 0x2d0eb046), WTCP(0x77bcfc3f, 0x2d3db928), + WTCP(0x77ab2ee2, 0x2d6cbb10), WTCP(0x77994f11, 0x2d9bb5f6), + WTCP(0x77875cce, 0x2dcaa9d5), WTCP(0x7775581d, 0x2df996a3), + WTCP(0x776340ff, 0x2e287c5a), WTCP(0x77511778, 0x2e575af3), + WTCP(0x773edb8b, 0x2e863267), WTCP(0x772c8d3a, 0x2eb502ae), + WTCP(0x771a2c88, 0x2ee3cbc1), WTCP(0x7707b979, 0x2f128d99), + WTCP(0x76f5340e, 0x2f41482e), WTCP(0x76e29c4b, 0x2f6ffb7a), + WTCP(0x76cff232, 0x2f9ea775), WTCP(0x76bd35c7, 0x2fcd4c19), + WTCP(0x76aa670d, 0x2ffbe95d), WTCP(0x76978605, 0x302a7f3a), + WTCP(0x768492b4, 0x30590dab), WTCP(0x76718d1c, 0x308794a6), + WTCP(0x765e7540, 0x30b61426), WTCP(0x764b4b23, 0x30e48c22), + WTCP(0x76380ec8, 0x3112fc95), WTCP(0x7624c031, 0x31416576), + WTCP(0x76115f63, 0x316fc6be), WTCP(0x75fdec60, 0x319e2067), + WTCP(0x75ea672a, 0x31cc7269), WTCP(0x75d6cfc5, 0x31fabcbd), + WTCP(0x75c32634, 0x3228ff5c), WTCP(0x75af6a7b, 0x32573a3f), + WTCP(0x759b9c9b, 0x32856d5e), WTCP(0x7587bc98, 0x32b398b3), + WTCP(0x7573ca75, 0x32e1bc36), WTCP(0x755fc635, 0x330fd7e1), + WTCP(0x754bafdc, 0x333debab), WTCP(0x7537876c, 0x336bf78f), + WTCP(0x75234ce8, 0x3399fb85), WTCP(0x750f0054, 0x33c7f785), + WTCP(0x74faa1b3, 0x33f5eb89), WTCP(0x74e63108, 0x3423d78a), + WTCP(0x74d1ae55, 0x3451bb81), WTCP(0x74bd199f, 0x347f9766), + WTCP(0x74a872e8, 0x34ad6b32), WTCP(0x7493ba34, 0x34db36df), + WTCP(0x747eef85, 0x3508fa66), WTCP(0x746a12df, 0x3536b5be), + WTCP(0x74552446, 0x356468e2), WTCP(0x744023bc, 0x359213c9), + WTCP(0x742b1144, 0x35bfb66e), WTCP(0x7415ece2, 0x35ed50c9), + WTCP(0x7400b69a, 0x361ae2d3), WTCP(0x73eb6e6e, 0x36486c86), + WTCP(0x73d61461, 0x3675edd9), WTCP(0x73c0a878, 0x36a366c6), + WTCP(0x73ab2ab4, 0x36d0d746), WTCP(0x73959b1b, 0x36fe3f52), + WTCP(0x737ff9ae, 0x372b9ee3), WTCP(0x736a4671, 0x3758f5f2), + WTCP(0x73548168, 0x37864477), WTCP(0x733eaa96, 0x37b38a6d), + WTCP(0x7328c1ff, 0x37e0c7cc), WTCP(0x7312c7a5, 0x380dfc8d), + WTCP(0x72fcbb8c, 0x383b28a9), WTCP(0x72e69db7, 0x38684c19), + WTCP(0x72d06e2b, 0x389566d6), WTCP(0x72ba2cea, 0x38c278d9), + WTCP(0x72a3d9f7, 0x38ef821c), WTCP(0x728d7557, 0x391c8297), + WTCP(0x7276ff0d, 0x39497a43), WTCP(0x7260771b, 0x39766919), + WTCP(0x7249dd86, 0x39a34f13), WTCP(0x72333251, 0x39d02c2a), + WTCP(0x721c7580, 0x39fd0056), WTCP(0x7205a716, 0x3a29cb91), + WTCP(0x71eec716, 0x3a568dd4), WTCP(0x71d7d585, 0x3a834717), + WTCP(0x71c0d265, 0x3aaff755), WTCP(0x71a9bdba, 0x3adc9e86), + WTCP(0x71929789, 0x3b093ca3), WTCP(0x717b5fd3, 0x3b35d1a5), + WTCP(0x7164169d, 0x3b625d86), WTCP(0x714cbbeb, 0x3b8ee03e), + WTCP(0x71354fc0, 0x3bbb59c7), WTCP(0x711dd220, 0x3be7ca1a), + WTCP(0x7106430e, 0x3c143130), WTCP(0x70eea28e, 0x3c408f03), + WTCP(0x70d6f0a4, 0x3c6ce38a), WTCP(0x70bf2d53, 0x3c992ec0), + WTCP(0x70a7589f, 0x3cc5709e), WTCP(0x708f728b, 0x3cf1a91c), + WTCP(0x70777b1c, 0x3d1dd835), WTCP(0x705f7255, 0x3d49fde1), + WTCP(0x70475839, 0x3d761a19), WTCP(0x702f2ccd, 0x3da22cd7), + WTCP(0x7016f014, 0x3dce3614), WTCP(0x6ffea212, 0x3dfa35c8), + WTCP(0x6fe642ca, 0x3e262bee), WTCP(0x6fcdd241, 0x3e52187f), + WTCP(0x6fb5507a, 0x3e7dfb73), WTCP(0x6f9cbd79, 0x3ea9d4c3), + WTCP(0x6f841942, 0x3ed5a46b), WTCP(0x6f6b63d8, 0x3f016a61), + WTCP(0x6f529d40, 0x3f2d26a0), WTCP(0x6f39c57d, 0x3f58d921), + WTCP(0x6f20dc92, 0x3f8481dd), WTCP(0x6f07e285, 0x3fb020ce), + WTCP(0x6eeed758, 0x3fdbb5ec), WTCP(0x6ed5bb10, 0x40074132), + WTCP(0x6ebc8db0, 0x4032c297), WTCP(0x6ea34f3d, 0x405e3a16), + WTCP(0x6e89ffb9, 0x4089a7a8), WTCP(0x6e709f2a, 0x40b50b46), + WTCP(0x6e572d93, 0x40e064ea), WTCP(0x6e3daaf8, 0x410bb48c), + WTCP(0x6e24175c, 0x4136fa27), WTCP(0x6e0a72c5, 0x416235b2), + WTCP(0x6df0bd35, 0x418d6729), WTCP(0x6dd6f6b1, 0x41b88e84), + WTCP(0x6dbd1f3c, 0x41e3abbc), WTCP(0x6da336dc, 0x420ebecb), + WTCP(0x6d893d93, 0x4239c7aa), WTCP(0x6d6f3365, 0x4264c653), + WTCP(0x6d551858, 0x428fbabe), WTCP(0x6d3aec6e, 0x42baa4e6), + WTCP(0x6d20afac, 0x42e584c3), WTCP(0x6d066215, 0x43105a50), + WTCP(0x6cec03af, 0x433b2585), WTCP(0x6cd1947c, 0x4365e65b), + WTCP(0x6cb71482, 0x43909ccd), WTCP(0x6c9c83c3, 0x43bb48d4), + WTCP(0x6c81e245, 0x43e5ea68), WTCP(0x6c67300b, 0x44108184), + WTCP(0x6c4c6d1a, 0x443b0e21), WTCP(0x6c319975, 0x44659039), + WTCP(0x6c16b521, 0x449007c4), WTCP(0x6bfbc021, 0x44ba74bd), + WTCP(0x6be0ba7b, 0x44e4d71c), WTCP(0x6bc5a431, 0x450f2edb), + WTCP(0x6baa7d49, 0x45397bf4), WTCP(0x6b8f45c7, 0x4563be60), + WTCP(0x6b73fdae, 0x458df619), WTCP(0x6b58a503, 0x45b82318), + WTCP(0x6b3d3bcb, 0x45e24556), WTCP(0x6b21c208, 0x460c5cce), + WTCP(0x6b0637c1, 0x46366978), WTCP(0x6aea9cf8, 0x46606b4e), + WTCP(0x6acef1b2, 0x468a624a), WTCP(0x6ab335f4, 0x46b44e65), + WTCP(0x6a9769c1, 0x46de2f99), WTCP(0x6a7b8d1e, 0x470805df), + WTCP(0x6a5fa010, 0x4731d131), WTCP(0x6a43a29a, 0x475b9188), + WTCP(0x6a2794c1, 0x478546de), WTCP(0x6a0b7689, 0x47aef12c), + WTCP(0x69ef47f6, 0x47d8906d), WTCP(0x69d3090e, 0x48022499), + WTCP(0x69b6b9d3, 0x482badab), WTCP(0x699a5a4c, 0x48552b9b), + WTCP(0x697dea7b, 0x487e9e64), WTCP(0x69616a65, 0x48a805ff), + WTCP(0x6944da10, 0x48d16265), WTCP(0x6928397e, 0x48fab391), + WTCP(0x690b88b5, 0x4923f97b), WTCP(0x68eec7b9, 0x494d341e), + WTCP(0x68d1f68f, 0x49766373), WTCP(0x68b5153a, 0x499f8774), + WTCP(0x689823bf, 0x49c8a01b), WTCP(0x687b2224, 0x49f1ad61), + WTCP(0x685e106c, 0x4a1aaf3f), WTCP(0x6840ee9b, 0x4a43a5b0), + WTCP(0x6823bcb7, 0x4a6c90ad), WTCP(0x68067ac3, 0x4a957030), + WTCP(0x67e928c5, 0x4abe4433), WTCP(0x67cbc6c0, 0x4ae70caf), + WTCP(0x67ae54ba, 0x4b0fc99d), WTCP(0x6790d2b6, 0x4b387af9), + WTCP(0x677340ba, 0x4b6120bb), WTCP(0x67559eca, 0x4b89badd), + WTCP(0x6737ecea, 0x4bb24958), WTCP(0x671a2b20, 0x4bdacc28), + WTCP(0x66fc596f, 0x4c034345), WTCP(0x66de77dc, 0x4c2baea9), + WTCP(0x66c0866d, 0x4c540e4e), WTCP(0x66a28524, 0x4c7c622d), + WTCP(0x66847408, 0x4ca4aa41), WTCP(0x6666531d, 0x4ccce684), + WTCP(0x66482267, 0x4cf516ee), WTCP(0x6629e1ec, 0x4d1d3b7a), + WTCP(0x660b91af, 0x4d455422), WTCP(0x65ed31b5, 0x4d6d60df), + WTCP(0x65cec204, 0x4d9561ac), WTCP(0x65b0429f, 0x4dbd5682), + WTCP(0x6591b38c, 0x4de53f5a), WTCP(0x657314cf, 0x4e0d1c30), + WTCP(0x6554666d, 0x4e34ecfc), WTCP(0x6535a86b, 0x4e5cb1b9), + WTCP(0x6516dacd, 0x4e846a60), WTCP(0x64f7fd98, 0x4eac16eb), + WTCP(0x64d910d1, 0x4ed3b755), WTCP(0x64ba147d, 0x4efb4b96), + WTCP(0x649b08a0, 0x4f22d3aa), WTCP(0x647bed3f, 0x4f4a4f89), + WTCP(0x645cc260, 0x4f71bf2e), WTCP(0x643d8806, 0x4f992293), + WTCP(0x641e3e38, 0x4fc079b1), WTCP(0x63fee4f8, 0x4fe7c483), + WTCP(0x63df7c4d, 0x500f0302), WTCP(0x63c0043b, 0x50363529), + WTCP(0x63a07cc7, 0x505d5af1), WTCP(0x6380e5f6, 0x50847454), + WTCP(0x63613fcd, 0x50ab814d), WTCP(0x63418a50, 0x50d281d5), + WTCP(0x6321c585, 0x50f975e6), WTCP(0x6301f171, 0x51205d7b), + WTCP(0x62e20e17, 0x5147388c), WTCP(0x62c21b7e, 0x516e0715), + WTCP(0x62a219aa, 0x5194c910), WTCP(0x628208a1, 0x51bb7e75), + WTCP(0x6261e866, 0x51e22740), WTCP(0x6241b8ff, 0x5208c36a), + WTCP(0x62217a72, 0x522f52ee), WTCP(0x62012cc2, 0x5255d5c5), + WTCP(0x61e0cff5, 0x527c4bea), WTCP(0x61c06410, 0x52a2b556), + WTCP(0x619fe918, 0x52c91204), WTCP(0x617f5f12, 0x52ef61ee), + WTCP(0x615ec603, 0x5315a50e), WTCP(0x613e1df0, 0x533bdb5d), + WTCP(0x611d66de, 0x536204d7), WTCP(0x60fca0d2, 0x53882175), + WTCP(0x60dbcbd1, 0x53ae3131), WTCP(0x60bae7e1, 0x53d43406), + WTCP(0x6099f505, 0x53fa29ed), WTCP(0x6078f344, 0x542012e1), + WTCP(0x6057e2a2, 0x5445eedb), WTCP(0x6036c325, 0x546bbdd7), + WTCP(0x601594d1, 0x54917fce), WTCP(0x5ff457ad, 0x54b734ba), + WTCP(0x5fd30bbc, 0x54dcdc96), WTCP(0x5fb1b104, 0x5502775c), + WTCP(0x5f90478a, 0x55280505), WTCP(0x5f6ecf53, 0x554d858d), + WTCP(0x5f4d4865, 0x5572f8ed), WTCP(0x5f2bb2c5, 0x55985f20), + WTCP(0x5f0a0e77, 0x55bdb81f), WTCP(0x5ee85b82, 0x55e303e6), + WTCP(0x5ec699e9, 0x5608426e), WTCP(0x5ea4c9b3, 0x562d73b2), + WTCP(0x5e82eae5, 0x565297ab), WTCP(0x5e60fd84, 0x5677ae54), + WTCP(0x5e3f0194, 0x569cb7a8), WTCP(0x5e1cf71c, 0x56c1b3a1), + WTCP(0x5dfade20, 0x56e6a239), WTCP(0x5dd8b6a7, 0x570b8369), + WTCP(0x5db680b4, 0x5730572e), WTCP(0x5d943c4e, 0x57551d80), + WTCP(0x5d71e979, 0x5779d65b), WTCP(0x5d4f883b, 0x579e81b8), + WTCP(0x5d2d189a, 0x57c31f92), WTCP(0x5d0a9a9a, 0x57e7afe4), + WTCP(0x5ce80e41, 0x580c32a7), WTCP(0x5cc57394, 0x5830a7d6), + WTCP(0x5ca2ca99, 0x58550f6c), WTCP(0x5c801354, 0x58796962), + WTCP(0x5c5d4dcc, 0x589db5b3), WTCP(0x5c3a7a05, 0x58c1f45b), + WTCP(0x5c179806, 0x58e62552), WTCP(0x5bf4a7d2, 0x590a4893), + WTCP(0x5bd1a971, 0x592e5e19), WTCP(0x5bae9ce7, 0x595265df), + WTCP(0x5b8b8239, 0x59765fde), WTCP(0x5b68596d, 0x599a4c12), + WTCP(0x5b452288, 0x59be2a74), WTCP(0x5b21dd90, 0x59e1faff), + WTCP(0x5afe8a8b, 0x5a05bdae), WTCP(0x5adb297d, 0x5a29727b), + WTCP(0x5ab7ba6c, 0x5a4d1960), WTCP(0x5a943d5e, 0x5a70b258), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow96[] = { + WTCP(0x7ffffffd, 0x0001a838), WTCP(0x7fffffe2, 0x00056e83), + WTCP(0x7fffff79, 0x000b9fda), WTCP(0x7ffffe45, 0x00150e8e), + WTCP(0x7ffffb4d, 0x0022aeeb), WTCP(0x7ffff4c6, 0x00359b36), + WTCP(0x7fffe792, 0x004f14ff), WTCP(0x7fffce8b, 0x0070858c), + WTCP(0x7fffa18f, 0x009b7d75), WTCP(0x7fff5439, 0x00d1b353), + WTCP(0x7ffed442, 0x0115018f), WTCP(0x7ffe0775, 0x01676335), + WTCP(0x7ffcc937, 0x01caefcb), WTCP(0x7ffae79f, 0x0241d62e), + WTCP(0x7ff82019, 0x02ce567f), WTCP(0x7ff41ba4, 0x0372bb25), + WTCP(0x7fee6ac3, 0x043150fc), WTCP(0x7fe68129, 0x050c5ec8), + WTCP(0x7fdbb164, 0x06061c0f), WTCP(0x7fcd2894, 0x0720a779), + WTCP(0x7fb9ea80, 0x085dfce2), WTCP(0x7fa0ce2e, 0x09bfeb4d), + WTCP(0x7f807b45, 0x0b480ae2), WTCP(0x7f576880, 0x0cf7b339), + WTCP(0x7f23db4e, 0x0ecff212), WTCP(0x7ee3e8ee, 0x10d182c0), + WTCP(0x7e95791f, 0x12fcc670), WTCP(0x7e364a74, 0x1551bd88), + WTCP(0x7dc3f864, 0x17d00238), WTCP(0x7d3c02fd, 0x1a76c47e), + WTCP(0x7c9bd82a, 0x1d44c7ad), WTCP(0x7be0de56, 0x203861a1), + WTCP(0x7b08803d, 0x234f7ba6), WTCP(0x7a103993, 0x26879530), + WTCP(0x78f5a442, 0x29ddc854), WTCP(0x77b685de, 0x2d4ed00f), + WTCP(0x7650dcf5, 0x30d7103d), WTCP(0x74c2ede4, 0x34729f2d), + WTCP(0x730b4edb, 0x381d50ad), WTCP(0x7128f2c1, 0x3bd2c273), + WTCP(0x6f1b32a9, 0x3f8e698f), WTCP(0x6ce1d5a0, 0x434ba0d6), + WTCP(0x6a7d16a3, 0x4705b7e5), WTCP(0x67eda890, 0x4ab80288), + WTCP(0x6534b7f8, 0x4e5de842), WTCP(0x6253eacd, 0x51f2f39a), + WTCP(0x5f4d5de1, 0x5572e0f7), WTCP(0x5c23a04a, 0x58d9acb9), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow120[] = { + WTCP(0x7ffffffe, 0x00017b6f), WTCP(0x7fffffef, 0x00042d2f), + WTCP(0x7fffffbb, 0x000849d0), WTCP(0x7fffff36, 0x000e3494), + WTCP(0x7ffffe0c, 0x00165efd), WTCP(0x7ffffbac, 0x002149be), + WTCP(0x7ffff72e, 0x002f854c), WTCP(0x7fffef24, 0x0041b235), + WTCP(0x7fffe167, 0x0058814f), WTCP(0x7fffcacd, 0x0074b3af), + WTCP(0x7fffa6d0, 0x00971a67), WTCP(0x7fff6f1e, 0x00c0960e), + WTCP(0x7fff1b12, 0x00f21602), WTCP(0x7ffe9f0b, 0x012c9775), + WTCP(0x7ffdebb2, 0x01712428), WTCP(0x7ffced1b, 0x01c0d0f7), + WTCP(0x7ffb89c2, 0x021cbc12), WTCP(0x7ff9a17c, 0x02860b05), + WTCP(0x7ff70c39, 0x02fde875), WTCP(0x7ff398bc, 0x038581b3), + WTCP(0x7fef0b3b, 0x041e040c), WTCP(0x7fe91bf3, 0x04c899f4), + WTCP(0x7fe175ba, 0x05866803), WTCP(0x7fd7b493, 0x065889d5), + WTCP(0x7fcb6459, 0x07400ed4), WTCP(0x7fbbff82, 0x083df6e9), + WTCP(0x7fa8ee09, 0x09532f37), WTCP(0x7f91849a, 0x0a808ed1), + WTCP(0x7f7503f2, 0x0bc6d381), WTCP(0x7f52989a, 0x0d269eb0), + WTCP(0x7f295af4, 0x0ea07270), WTCP(0x7ef84fb6, 0x1034aeb6), + WTCP(0x7ebe68c5, 0x11e38ed2), WTCP(0x7e7a8686, 0x13ad2733), + WTCP(0x7e2b79a3, 0x1591636d), WTCP(0x7dd0053c, 0x179004a7), + WTCP(0x7d66e18b, 0x19a8a05f), WTCP(0x7ceebef0, 0x1bda9fa2), + WTCP(0x7c664953, 0x1e253ea1), WTCP(0x7bcc2be8, 0x20878cce), + WTCP(0x7b1f1526, 0x23006d5d), WTCP(0x7a5dbb01, 0x258e9848), + WTCP(0x7986df3e, 0x28309bc6), WTCP(0x789953e0, 0x2ae4de3e), + WTCP(0x7793ff88, 0x2da9a0a8), WTCP(0x7675e1cc, 0x307d0163), + WTCP(0x753e1763, 0x335cff72), WTCP(0x73ebde10, 0x36477e1f), + WTCP(0x727e984e, 0x393a48f1), WTCP(0x70f5d09b, 0x3c3317f9), + WTCP(0x6f513c60, 0x3f2f945c), WTCP(0x6d90be61, 0x422d5d18), + WTCP(0x6bb468b1, 0x452a0bf3), WTCP(0x69bc7e1e, 0x48233a81), + WTCP(0x67a97317, 0x4b16873e), WTCP(0x657bedfa, 0x4e019a9d), + WTCP(0x6334c6d2, 0x50e22c0b), WTCP(0x60d50689, 0x53b606cb), + WTCP(0x5e5de588, 0x567b0ea7), WTCP(0x5bd0c9c6, 0x592f4460), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow128[] = { + WTCP(0x7ffffffe, 0x00016f63), WTCP(0x7ffffff1, 0x0003e382), + WTCP(0x7fffffc7, 0x00078f64), WTCP(0x7fffff5d, 0x000cc323), + WTCP(0x7ffffe76, 0x0013d9ed), WTCP(0x7ffffcaa, 0x001d3a9d), + WTCP(0x7ffff953, 0x0029581f), WTCP(0x7ffff372, 0x0038b1bd), + WTCP(0x7fffe98b, 0x004bd34d), WTCP(0x7fffd975, 0x00635538), + WTCP(0x7fffc024, 0x007fdc64), WTCP(0x7fff995b, 0x00a219f1), + WTCP(0x7fff5f5b, 0x00cacad0), WTCP(0x7fff0a75, 0x00fab72d), + WTCP(0x7ffe9091, 0x0132b1af), WTCP(0x7ffde49e, 0x01739689), + WTCP(0x7ffcf5ef, 0x01be4a63), WTCP(0x7ffbaf84, 0x0213b910), + WTCP(0x7ff9f73a, 0x0274d41e), WTCP(0x7ff7acf1, 0x02e2913a), + WTCP(0x7ff4a99a, 0x035de86c), WTCP(0x7ff0be3d, 0x03e7d233), + WTCP(0x7febb2f1, 0x0481457c), WTCP(0x7fe545d4, 0x052b357c), + WTCP(0x7fdd2a02, 0x05e68f77), WTCP(0x7fd30695, 0x06b4386f), + WTCP(0x7fc675b4, 0x07950acb), WTCP(0x7fb703be, 0x0889d3ef), + WTCP(0x7fa42e89, 0x099351e0), WTCP(0x7f8d64d8, 0x0ab230e0), + WTCP(0x7f7205f8, 0x0be70923), WTCP(0x7f516195, 0x0d325c93), + WTCP(0x7f2ab7d0, 0x0e9494ae), WTCP(0x7efd3997, 0x100e0085), + WTCP(0x7ec8094a, 0x119ed2ef), WTCP(0x7e8a3ba7, 0x134720d8), + WTCP(0x7e42d906, 0x1506dfdc), WTCP(0x7df0dee4, 0x16dde50b), + WTCP(0x7d9341b4, 0x18cbe3f7), WTCP(0x7d28ef02, 0x1ad06e07), + WTCP(0x7cb0cfcc, 0x1ceaf215), WTCP(0x7c29cb20, 0x1f1abc4f), + WTCP(0x7b92c8eb, 0x215ef677), WTCP(0x7aeab4ec, 0x23b6a867), + WTCP(0x7a3081d0, 0x2620b8ec), WTCP(0x79632c5a, 0x289beef5), + WTCP(0x7881be95, 0x2b26f30b), WTCP(0x778b5304, 0x2dc0511f), + WTCP(0x767f17c0, 0x30667aa2), WTCP(0x755c5178, 0x3317c8dd), + WTCP(0x74225e50, 0x35d27f98), WTCP(0x72d0b887, 0x3894cff3), + WTCP(0x7166f8e7, 0x3b5cdb7b), WTCP(0x6fe4d8e8, 0x3e28b770), + WTCP(0x6e4a3491, 0x40f6702a), WTCP(0x6c970bfc, 0x43c40caa), + WTCP(0x6acb8483, 0x468f9231), WTCP(0x68e7e994, 0x495707f5), + WTCP(0x66ecad1c, 0x4c187ac7), WTCP(0x64da6797, 0x4ed200c5), + WTCP(0x62b1d7b7, 0x5181bcea), WTCP(0x6073e1ae, 0x5425e28e), + WTCP(0x5e218e16, 0x56bcb8c2), WTCP(0x5bbc0875, 0x59449d76), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow256[] = { + WTCP(0x7fffffff, 0x000103c8), WTCP(0x7ffffffc, 0x000203ad), + WTCP(0x7ffffff5, 0x0003410a), WTCP(0x7fffffe9, 0x0004c6ce), + WTCP(0x7fffffd4, 0x00069ee0), WTCP(0x7fffffb2, 0x0008d376), + WTCP(0x7fffff7d, 0x000b6f5a), WTCP(0x7fffff2e, 0x000e7dfd), + WTCP(0x7ffffeba, 0x00120b83), WTCP(0x7ffffe16, 0x001624cd), + WTCP(0x7ffffd30, 0x001ad778), WTCP(0x7ffffbf3, 0x002031e2), + WTCP(0x7ffffa48, 0x00264330), WTCP(0x7ffff80d, 0x002d1b4b), + WTCP(0x7ffff51d, 0x0034cae6), WTCP(0x7ffff147, 0x003d637c), + WTCP(0x7fffec54, 0x0046f751), WTCP(0x7fffe5fe, 0x00519974), + WTCP(0x7fffddf3, 0x005d5dba), WTCP(0x7fffd3d2, 0x006a58c1), + WTCP(0x7fffc72a, 0x00789feb), WTCP(0x7fffb772, 0x0088495d), + WTCP(0x7fffa40e, 0x00996bfb), WTCP(0x7fff8c46, 0x00ac1f63), + WTCP(0x7fff6f46, 0x00c07bec), WTCP(0x7fff4c19, 0x00d69a9b), + WTCP(0x7fff21a6, 0x00ee9523), WTCP(0x7ffeeeab, 0x010885d9), + WTCP(0x7ffeb1b8, 0x012487b1), WTCP(0x7ffe692f, 0x0142b631), + WTCP(0x7ffe1335, 0x01632d6f), WTCP(0x7ffdadb8, 0x01860a00), + WTCP(0x7ffd3661, 0x01ab68f3), WTCP(0x7ffcaa91, 0x01d367c5), + WTCP(0x7ffc075b, 0x01fe2453), WTCP(0x7ffb497e, 0x022bbcd0), + WTCP(0x7ffa6d59, 0x025c4fba), WTCP(0x7ff96eeb, 0x028ffbc7), + WTCP(0x7ff849c6, 0x02c6dfdb), WTCP(0x7ff6f90b, 0x03011afc), + WTCP(0x7ff57760, 0x033ecc3a), WTCP(0x7ff3bee7, 0x038012a8), + WTCP(0x7ff1c939, 0x03c50d47), WTCP(0x7fef8f5a, 0x040ddaf6), + WTCP(0x7fed09b4, 0x045a9a64), WTCP(0x7fea300e, 0x04ab69f9), + WTCP(0x7fe6f980, 0x050067c7), WTCP(0x7fe35c70, 0x0559b17b), + WTCP(0x7fdf4e88, 0x05b76443), WTCP(0x7fdac4ad, 0x06199cc4), + WTCP(0x7fd5b2f8, 0x068076fe), WTCP(0x7fd00caf, 0x06ec0e41), + WTCP(0x7fc9c441, 0x075c7d16), WTCP(0x7fc2cb3b, 0x07d1dd2c), + WTCP(0x7fbb1242, 0x084c4745), WTCP(0x7fb28915, 0x08cbd323), + WTCP(0x7fa91e7e, 0x09509778), WTCP(0x7f9ec059, 0x09daa9cc), + WTCP(0x7f935b87, 0x0a6a1e74), WTCP(0x7f86dbf2, 0x0aff0877), + WTCP(0x7f792c8a, 0x0b997983), WTCP(0x7f6a3746, 0x0c3981d6), + WTCP(0x7f59e520, 0x0cdf3030), WTCP(0x7f481e1c, 0x0d8a91c3), + WTCP(0x7f34c949, 0x0e3bb222), WTCP(0x7f1fccc3, 0x0ef29b30), + WTCP(0x7f090dbc, 0x0faf5513), WTCP(0x7ef0707d, 0x1071e629), + WTCP(0x7ed5d872, 0x113a52f4), WTCP(0x7eb92831, 0x12089e14), + WTCP(0x7e9a4183, 0x12dcc836), WTCP(0x7e790571, 0x13b6d010), + WTCP(0x7e55544e, 0x1496b24f), WTCP(0x7e2f0dc8, 0x157c6998), + WTCP(0x7e0610f1, 0x1667ee77), WTCP(0x7dda3c54, 0x17593760), + WTCP(0x7dab6e06, 0x185038a3), WTCP(0x7d7983b3, 0x194ce46e), + WTCP(0x7d445ab5, 0x1a4f2ac4), WTCP(0x7d0bd028, 0x1b56f981), + WTCP(0x7ccfc0fd, 0x1c643c54), WTCP(0x7c900a11, 0x1d76dcc2), + WTCP(0x7c4c8844, 0x1e8ec227), WTCP(0x7c05188d, 0x1fabd1bb), + WTCP(0x7bb99817, 0x20cdee92), WTCP(0x7b69e455, 0x21f4f9a6), + WTCP(0x7b15db1a, 0x2320d1dc), WTCP(0x7abd5ab8, 0x2451540c), + WTCP(0x7a604213, 0x25865b09), WTCP(0x79fe70bf, 0x26bfbfaf), + WTCP(0x7997c716, 0x27fd58ed), WTCP(0x792c2654, 0x293efbd0), + WTCP(0x78bb70b0, 0x2a847b97), WTCP(0x78458976, 0x2bcda9bb), + WTCP(0x77ca551d, 0x2d1a5608), WTCP(0x7749b965, 0x2e6a4ea6), + WTCP(0x76c39d68, 0x2fbd6036), WTCP(0x7637e9b8, 0x311355dc), + WTCP(0x75a68873, 0x326bf95a), WTCP(0x750f6559, 0x33c71326), + WTCP(0x74726de1, 0x35246a7e), WTCP(0x73cf914f, 0x3683c582), + WTCP(0x7326c0c8, 0x37e4e94b), WTCP(0x7277ef5f, 0x39479a08), + WTCP(0x71c3122f, 0x3aab9b14), WTCP(0x71082063, 0x3c10af11), + WTCP(0x7047134a, 0x3d769807), WTCP(0x6f7fe661, 0x3edd177c), + WTCP(0x6eb29763, 0x4043ee92), WTCP(0x6ddf2651, 0x41aade26), + WTCP(0x6d05957c, 0x4311a6e8), WTCP(0x6c25e98f, 0x4478097b), + WTCP(0x6b402991, 0x45ddc693), WTCP(0x6a545ef0, 0x47429f13), + WTCP(0x6962957f, 0x48a65427), WTCP(0x686adb7c, 0x4a08a764), + WTCP(0x676d418d, 0x4b695ae8), WTCP(0x6669dac2, 0x4cc83171), + WTCP(0x6560bc90, 0x4e24ee7d), WTCP(0x6451fecf, 0x4f7f5668), + WTCP(0x633dbbb1, 0x50d72e85), WTCP(0x62240fbd, 0x522c3d3b), + WTCP(0x610519c7, 0x537e4a1f), WTCP(0x5fe0fae3, 0x54cd1e10), + WTCP(0x5eb7d65c, 0x5618834c), WTCP(0x5d89d1a5, 0x57604590), + WTCP(0x5c57144b, 0x58a43227), WTCP(0x5b1fc7e6, 0x59e41808), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow768[] = { + WTCP(0x7fffff85, 0x000b11d9), WTCP(0x7ffffef0, 0x00107aa9), + WTCP(0x7ffffe3e, 0x0015351c), WTCP(0x7ffffd6c, 0x0019b0a1), + WTCP(0x7ffffc77, 0x001e1656), WTCP(0x7ffffb5b, 0x00227a80), + WTCP(0x7ffffa16, 0x0026e8d3), WTCP(0x7ffff8a4, 0x002b68c9), + WTCP(0x7ffff700, 0x002fff8a), WTCP(0x7ffff528, 0x0034b0d9), + WTCP(0x7ffff316, 0x00397f9c), WTCP(0x7ffff0c6, 0x003e6e22), + WTCP(0x7fffee35, 0x00437e53), WTCP(0x7fffeb5b, 0x0048b1d0), + WTCP(0x7fffe836, 0x004e0a05), WTCP(0x7fffe4be, 0x00538837), + WTCP(0x7fffe0ef, 0x00592d8e), WTCP(0x7fffdcc3, 0x005efb1a), + WTCP(0x7fffd832, 0x0064f1da), WTCP(0x7fffd337, 0x006b12c1), + WTCP(0x7fffcdcb, 0x00715eb4), WTCP(0x7fffc7e7, 0x0077d692), + WTCP(0x7fffc182, 0x007e7b30), WTCP(0x7fffba96, 0x00854d61), + WTCP(0x7fffb31b, 0x008c4df0), WTCP(0x7fffab06, 0x00937da6), + WTCP(0x7fffa251, 0x009add48), WTCP(0x7fff98f1, 0x00a26d98), + WTCP(0x7fff8edd, 0x00aa2f57), WTCP(0x7fff840b, 0x00b22343), + WTCP(0x7fff7870, 0x00ba4a19), WTCP(0x7fff6c02, 0x00c2a495), + WTCP(0x7fff5eb5, 0x00cb3371), WTCP(0x7fff507e, 0x00d3f767), + WTCP(0x7fff4150, 0x00dcf130), WTCP(0x7fff311f, 0x00e62183), + WTCP(0x7fff1fde, 0x00ef8919), WTCP(0x7fff0d7f, 0x00f928a7), + WTCP(0x7ffef9f4, 0x010300e5), WTCP(0x7ffee52f, 0x010d1288), + WTCP(0x7ffecf20, 0x01175e47), WTCP(0x7ffeb7b8, 0x0121e4d6), + WTCP(0x7ffe9ee6, 0x012ca6eb), WTCP(0x7ffe849b, 0x0137a53b), + WTCP(0x7ffe68c4, 0x0142e07a), WTCP(0x7ffe4b50, 0x014e595c), + WTCP(0x7ffe2c2c, 0x015a1095), WTCP(0x7ffe0b45, 0x016606da), + WTCP(0x7ffde888, 0x01723cde), WTCP(0x7ffdc3df, 0x017eb353), + WTCP(0x7ffd9d37, 0x018b6aed), WTCP(0x7ffd7479, 0x0198645f), + WTCP(0x7ffd4990, 0x01a5a05b), WTCP(0x7ffd1c63, 0x01b31f92), + WTCP(0x7ffcecdc, 0x01c0e2b8), WTCP(0x7ffcbae2, 0x01ceea7d), + WTCP(0x7ffc865c, 0x01dd3793), WTCP(0x7ffc4f2f, 0x01ebcaaa), + WTCP(0x7ffc1542, 0x01faa472), WTCP(0x7ffbd879, 0x0209c59c), + WTCP(0x7ffb98b7, 0x02192ed7), WTCP(0x7ffb55e0, 0x0228e0d2), + WTCP(0x7ffb0fd6, 0x0238dc3c), WTCP(0x7ffac679, 0x024921c3), + WTCP(0x7ffa79ac, 0x0259b215), WTCP(0x7ffa294d, 0x026a8dde), + WTCP(0x7ff9d53b, 0x027bb5cc), WTCP(0x7ff97d54, 0x028d2a8a), + WTCP(0x7ff92175, 0x029eecc3), WTCP(0x7ff8c17a, 0x02b0fd23), + WTCP(0x7ff85d3f, 0x02c35c53), WTCP(0x7ff7f49d, 0x02d60afd), + WTCP(0x7ff7876e, 0x02e909ca), WTCP(0x7ff7158b, 0x02fc5960), + WTCP(0x7ff69eca, 0x030ffa69), WTCP(0x7ff62303, 0x0323ed89), + WTCP(0x7ff5a20a, 0x03383367), WTCP(0x7ff51bb3, 0x034ccca7), + WTCP(0x7ff48fd3, 0x0361b9ed), WTCP(0x7ff3fe3c, 0x0376fbdd), + WTCP(0x7ff366be, 0x038c9317), WTCP(0x7ff2c929, 0x03a2803e), + WTCP(0x7ff2254e, 0x03b8c3f2), WTCP(0x7ff17afa, 0x03cf5ed1), + WTCP(0x7ff0c9f9, 0x03e6517a), WTCP(0x7ff01218, 0x03fd9c8a), + WTCP(0x7fef5321, 0x0415409c), WTCP(0x7fee8cde, 0x042d3e4d), + WTCP(0x7fedbf17, 0x04459634), WTCP(0x7fece993, 0x045e48ec), + WTCP(0x7fec0c18, 0x0477570a), WTCP(0x7feb266a, 0x0490c127), + WTCP(0x7fea384e, 0x04aa87d5), WTCP(0x7fe94186, 0x04c4abaa), + WTCP(0x7fe841d3, 0x04df2d37), WTCP(0x7fe738f4, 0x04fa0d0d), + WTCP(0x7fe626a9, 0x05154bbc), WTCP(0x7fe50aaf, 0x0530e9d3), + WTCP(0x7fe3e4c1, 0x054ce7dd), WTCP(0x7fe2b49b, 0x05694667), + WTCP(0x7fe179f6, 0x058605fa), WTCP(0x7fe0348b, 0x05a3271e), + WTCP(0x7fdee410, 0x05c0aa5c), WTCP(0x7fdd883b, 0x05de9038), + WTCP(0x7fdc20c1, 0x05fcd935), WTCP(0x7fdaad53, 0x061b85d6), + WTCP(0x7fd92da5, 0x063a969c), WTCP(0x7fd7a166, 0x065a0c06), + WTCP(0x7fd60844, 0x0679e690), WTCP(0x7fd461ee, 0x069a26b6), + WTCP(0x7fd2ae10, 0x06baccf2), WTCP(0x7fd0ec55, 0x06dbd9bd), + WTCP(0x7fcf1c65, 0x06fd4d8c), WTCP(0x7fcd3de9, 0x071f28d3), + WTCP(0x7fcb5088, 0x07416c06), WTCP(0x7fc953e6, 0x07641794), + WTCP(0x7fc747a8, 0x07872bee), WTCP(0x7fc52b70, 0x07aaa97f), + WTCP(0x7fc2fedf, 0x07ce90b4), WTCP(0x7fc0c195, 0x07f2e1f4), + WTCP(0x7fbe732f, 0x08179da7), WTCP(0x7fbc134b, 0x083cc431), + WTCP(0x7fb9a183, 0x086255f7), WTCP(0x7fb71d72, 0x08885359), + WTCP(0x7fb486af, 0x08aebcb5), WTCP(0x7fb1dcd3, 0x08d59269), + WTCP(0x7faf1f72, 0x08fcd4cf), WTCP(0x7fac4e21, 0x09248440), + WTCP(0x7fa96873, 0x094ca111), WTCP(0x7fa66df8, 0x09752b98), + WTCP(0x7fa35e40, 0x099e2425), WTCP(0x7fa038db, 0x09c78b09), + WTCP(0x7f9cfd54, 0x09f16090), WTCP(0x7f99ab38, 0x0a1ba507), + WTCP(0x7f964210, 0x0a4658b6), WTCP(0x7f92c165, 0x0a717be2), + WTCP(0x7f8f28bf, 0x0a9d0ed1), WTCP(0x7f8b77a4, 0x0ac911c4), + WTCP(0x7f87ad97, 0x0af584fb), WTCP(0x7f83ca1d, 0x0b2268b2), + WTCP(0x7f7fccb5, 0x0b4fbd23), WTCP(0x7f7bb4e2, 0x0b7d8288), + WTCP(0x7f778221, 0x0babb915), WTCP(0x7f7333f1, 0x0bda60fd), + WTCP(0x7f6ec9cd, 0x0c097a72), WTCP(0x7f6a4330, 0x0c3905a1), + WTCP(0x7f659f94, 0x0c6902b6), WTCP(0x7f60de70, 0x0c9971d9), + WTCP(0x7f5bff3b, 0x0cca5331), WTCP(0x7f57016b, 0x0cfba6e3), + WTCP(0x7f51e474, 0x0d2d6d0e), WTCP(0x7f4ca7c8, 0x0d5fa5d2), + WTCP(0x7f474ad9, 0x0d92514a), WTCP(0x7f41cd17, 0x0dc56f90), + WTCP(0x7f3c2df1, 0x0df900bb), WTCP(0x7f366cd5, 0x0e2d04de), + WTCP(0x7f30892e, 0x0e617c0a), WTCP(0x7f2a8269, 0x0e96664e), + WTCP(0x7f2457ef, 0x0ecbc3b5), WTCP(0x7f1e0929, 0x0f019449), + WTCP(0x7f17957e, 0x0f37d80f), WTCP(0x7f10fc55, 0x0f6e8f0c), + WTCP(0x7f0a3d14, 0x0fa5b940), WTCP(0x7f03571d, 0x0fdd56a8), + WTCP(0x7efc49d4, 0x10156740), WTCP(0x7ef5149b, 0x104deb00), + WTCP(0x7eedb6d2, 0x1086e1dd), WTCP(0x7ee62fda, 0x10c04bca), + WTCP(0x7ede7f11, 0x10fa28b7), WTCP(0x7ed6a3d5, 0x11347890), + WTCP(0x7ece9d81, 0x116f3b3f), WTCP(0x7ec66b73, 0x11aa70ac), + WTCP(0x7ebe0d04, 0x11e618ba), WTCP(0x7eb5818d, 0x1222334c), + WTCP(0x7eacc869, 0x125ec03e), WTCP(0x7ea3e0ef, 0x129bbf6e), + WTCP(0x7e9aca75, 0x12d930b2), WTCP(0x7e918452, 0x131713e2), + WTCP(0x7e880ddb, 0x135568cf), WTCP(0x7e7e6665, 0x13942f49), + WTCP(0x7e748d43, 0x13d3671e), WTCP(0x7e6a81c8, 0x14131017), + WTCP(0x7e604347, 0x145329fa), WTCP(0x7e55d111, 0x1493b48c), + WTCP(0x7e4b2a76, 0x14d4af8e), WTCP(0x7e404ec8, 0x15161abe), + WTCP(0x7e353d55, 0x1557f5d7), WTCP(0x7e29f56c, 0x159a4090), + WTCP(0x7e1e765c, 0x15dcfaa0), WTCP(0x7e12bf72, 0x162023b7), + WTCP(0x7e06cffc, 0x1663bb86), WTCP(0x7dfaa746, 0x16a7c1b9), + WTCP(0x7dee449e, 0x16ec35f7), WTCP(0x7de1a74e, 0x173117e9), + WTCP(0x7dd4cea3, 0x17766731), WTCP(0x7dc7b9e7, 0x17bc236f), + WTCP(0x7dba6865, 0x18024c40), WTCP(0x7dacd968, 0x1848e13f), + WTCP(0x7d9f0c3a, 0x188fe204), WTCP(0x7d910025, 0x18d74e22), + WTCP(0x7d82b472, 0x191f252c), WTCP(0x7d74286c, 0x196766ae), + WTCP(0x7d655b5b, 0x19b01236), WTCP(0x7d564c8a, 0x19f9274b), + WTCP(0x7d46fb40, 0x1a42a574), WTCP(0x7d3766c8, 0x1a8c8c32), + WTCP(0x7d278e6a, 0x1ad6db06), WTCP(0x7d17716f, 0x1b21916c), + WTCP(0x7d070f22, 0x1b6caedf), WTCP(0x7cf666cb, 0x1bb832d5), + WTCP(0x7ce577b3, 0x1c041cc2), WTCP(0x7cd44124, 0x1c506c17), + WTCP(0x7cc2c269, 0x1c9d2044), WTCP(0x7cb0faca, 0x1cea38b2), + WTCP(0x7c9ee992, 0x1d37b4cc), WTCP(0x7c8c8e0c, 0x1d8593f5), + WTCP(0x7c79e782, 0x1dd3d592), WTCP(0x7c66f541, 0x1e227903), + WTCP(0x7c53b692, 0x1e717da3), WTCP(0x7c402ac3, 0x1ec0e2cf), + WTCP(0x7c2c5120, 0x1f10a7dc), WTCP(0x7c1828f6, 0x1f60cc21), + WTCP(0x7c03b193, 0x1fb14eef), WTCP(0x7beeea44, 0x20022f96), + WTCP(0x7bd9d259, 0x20536d61), WTCP(0x7bc46921, 0x20a5079a), + WTCP(0x7baeadec, 0x20f6fd8a), WTCP(0x7b98a00b, 0x21494e73), + WTCP(0x7b823ecf, 0x219bf998), WTCP(0x7b6b898b, 0x21eefe37), + WTCP(0x7b547f93, 0x22425b8d), WTCP(0x7b3d203a, 0x229610d4), + WTCP(0x7b256ad5, 0x22ea1d42), WTCP(0x7b0d5ebb, 0x233e800c), + WTCP(0x7af4fb42, 0x23933864), WTCP(0x7adc3fc2, 0x23e8457a), + WTCP(0x7ac32b95, 0x243da679), WTCP(0x7aa9be14, 0x24935a8d), + WTCP(0x7a8ff69a, 0x24e960dd), WTCP(0x7a75d485, 0x253fb88e), + WTCP(0x7a5b5731, 0x259660c3), WTCP(0x7a407dfe, 0x25ed589c), + WTCP(0x7a25484c, 0x26449f38), WTCP(0x7a09b57c, 0x269c33b1), + WTCP(0x79edc4f1, 0x26f41522), WTCP(0x79d1760e, 0x274c42a0), + WTCP(0x79b4c83b, 0x27a4bb40), WTCP(0x7997badd, 0x27fd7e15), + WTCP(0x797a4d5e, 0x28568a2f), WTCP(0x795c7f26, 0x28afde9a), + WTCP(0x793e4fa3, 0x29097a63), WTCP(0x791fbe40, 0x29635c92), + WTCP(0x7900ca6e, 0x29bd842e), WTCP(0x78e1739c, 0x2a17f03e), + WTCP(0x78c1b93d, 0x2a729fc2), WTCP(0x78a19ac4, 0x2acd91bc), + WTCP(0x788117a7, 0x2b28c52a), WTCP(0x78602f5e, 0x2b843909), + WTCP(0x783ee163, 0x2bdfec54), WTCP(0x781d2d2f, 0x2c3bde02), + WTCP(0x77fb1241, 0x2c980d0a), WTCP(0x77d89017, 0x2cf47862), + WTCP(0x77b5a632, 0x2d511efb), WTCP(0x77925416, 0x2dadffc6), + WTCP(0x776e9947, 0x2e0b19b3), WTCP(0x774a754d, 0x2e686bae), + WTCP(0x7725e7b0, 0x2ec5f4a4), WTCP(0x7700effd, 0x2f23b37d), + WTCP(0x76db8dbf, 0x2f81a721), WTCP(0x76b5c088, 0x2fdfce77), + WTCP(0x768f87e8, 0x303e2863), WTCP(0x7668e375, 0x309cb3c8), + WTCP(0x7641d2c4, 0x30fb6f88), WTCP(0x761a556e, 0x315a5a82), + WTCP(0x75f26b0e, 0x31b97394), WTCP(0x75ca1341, 0x3218b99c), + WTCP(0x75a14da8, 0x32782b74), WTCP(0x757819e4, 0x32d7c7f6), + WTCP(0x754e779a, 0x33378dfc), WTCP(0x75246671, 0x33977c5b), + WTCP(0x74f9e613, 0x33f791e9), WTCP(0x74cef62b, 0x3457cd7c), + WTCP(0x74a3966a, 0x34b82de6), WTCP(0x7477c67f, 0x3518b1f9), + WTCP(0x744b861e, 0x35795887), WTCP(0x741ed4ff, 0x35da205e), + WTCP(0x73f1b2da, 0x363b084e), WTCP(0x73c41f6b, 0x369c0f24), + WTCP(0x73961a71, 0x36fd33ac), WTCP(0x7367a3ac, 0x375e74b1), + WTCP(0x7338bae1, 0x37bfd0ff), WTCP(0x73095fd7, 0x3821475f), + WTCP(0x72d99257, 0x3882d699), WTCP(0x72a9522d, 0x38e47d75), + WTCP(0x72789f28, 0x39463aba), WTCP(0x7247791b, 0x39a80d2e), + WTCP(0x7215dfda, 0x3a09f397), WTCP(0x71e3d33d, 0x3a6becba), + WTCP(0x71b1531f, 0x3acdf75a), WTCP(0x717e5f5d, 0x3b30123b), + WTCP(0x714af7d7, 0x3b923c20), WTCP(0x71171c72, 0x3bf473cc), + WTCP(0x70e2cd14, 0x3c56b7ff), WTCP(0x70ae09a6, 0x3cb9077b), + WTCP(0x7078d215, 0x3d1b6101), WTCP(0x7043264f, 0x3d7dc353), + WTCP(0x700d0648, 0x3de02d2e), WTCP(0x6fd671f5, 0x3e429d55), + WTCP(0x6f9f694f, 0x3ea51285), WTCP(0x6f67ec52, 0x3f078b7f), + WTCP(0x6f2ffafb, 0x3f6a0701), WTCP(0x6ef7954e, 0x3fcc83ca), + WTCP(0x6ebebb4e, 0x402f009a), WTCP(0x6e856d05, 0x40917c2e), + WTCP(0x6e4baa7e, 0x40f3f546), WTCP(0x6e1173c6, 0x41566aa1), + WTCP(0x6dd6c8ef, 0x41b8dafc), WTCP(0x6d9baa0f, 0x421b4518), + WTCP(0x6d60173d, 0x427da7b1), WTCP(0x6d241094, 0x42e00189), + WTCP(0x6ce79632, 0x4342515e), WTCP(0x6caaa839, 0x43a495ef), + WTCP(0x6c6d46ce, 0x4406cdfd), WTCP(0x6c2f7218, 0x4468f848), + WTCP(0x6bf12a42, 0x44cb138f), WTCP(0x6bb26f7b, 0x452d1e94), + WTCP(0x6b7341f5, 0x458f1818), WTCP(0x6b33a1e3, 0x45f0fede), + WTCP(0x6af38f7e, 0x4652d1a6), WTCP(0x6ab30b01, 0x46b48f34), + WTCP(0x6a7214ab, 0x4716364c), WTCP(0x6a30acbd, 0x4777c5b2), + WTCP(0x69eed37c, 0x47d93c2a), WTCP(0x69ac8930, 0x483a987a), + WTCP(0x6969ce24, 0x489bd968), WTCP(0x6926a2a8, 0x48fcfdbb), + WTCP(0x68e3070c, 0x495e043b), WTCP(0x689efba7, 0x49beebb0), + WTCP(0x685a80cf, 0x4a1fb2e5), WTCP(0x681596e1, 0x4a8058a4), + WTCP(0x67d03e3b, 0x4ae0dbb8), WTCP(0x678a773f, 0x4b413aee), + WTCP(0x67444253, 0x4ba17514), WTCP(0x66fd9fde, 0x4c0188f8), + WTCP(0x66b6904c, 0x4c61756b), WTCP(0x666f140d, 0x4cc1393d), + WTCP(0x66272b91, 0x4d20d341), WTCP(0x65ded74d, 0x4d80424a), + WTCP(0x659617bb, 0x4ddf852d), WTCP(0x654ced55, 0x4e3e9ac1), + WTCP(0x6503589b, 0x4e9d81dc), WTCP(0x64b95a0d, 0x4efc3959), + WTCP(0x646ef230, 0x4f5ac010), WTCP(0x6424218d, 0x4fb914df), + WTCP(0x63d8e8ae, 0x501736a1), WTCP(0x638d4822, 0x50752438), + WTCP(0x6341407a, 0x50d2dc82), WTCP(0x62f4d24b, 0x51305e61), + WTCP(0x62a7fe2b, 0x518da8bb), WTCP(0x625ac4b5, 0x51eaba74), + WTCP(0x620d2686, 0x52479273), WTCP(0x61bf2440, 0x52a42fa2), + WTCP(0x6170be85, 0x530090ea), WTCP(0x6121f5fb, 0x535cb53a), + WTCP(0x60d2cb4e, 0x53b89b7e), WTCP(0x60833f28, 0x541442a8), + WTCP(0x60335239, 0x546fa9a9), WTCP(0x5fe30533, 0x54cacf77), + WTCP(0x5f9258cc, 0x5525b306), WTCP(0x5f414dbb, 0x55805350), + WTCP(0x5eefe4bc, 0x55daaf4e), WTCP(0x5e9e1e8c, 0x5634c5fe), + WTCP(0x5e4bfbec, 0x568e965c), WTCP(0x5df97d9e, 0x56e81f6c), + WTCP(0x5da6a46a, 0x5741602e), WTCP(0x5d537118, 0x579a57a8), + WTCP(0x5cffe474, 0x57f304e2), WTCP(0x5cabff4c, 0x584b66e4), + WTCP(0x5c57c271, 0x58a37cbb), WTCP(0x5c032eb7, 0x58fb4576), + WTCP(0x5bae44f4, 0x5952c024), WTCP(0x5b590602, 0x59a9ebd8), + WTCP(0x5b0372bb, 0x5a00c7a8), WTCP(0x5aad8bfe, 0x5a5752ac), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow960[] = { + WTCP(0x7fffff9e, 0x0009e6ac), WTCP(0x7fffff2b, 0x000e96d5), + WTCP(0x7ffffea6, 0x0012987e), WTCP(0x7ffffe0e, 0x001652b6), + WTCP(0x7ffffd60, 0x0019ebce), WTCP(0x7ffffc9c, 0x001d76bf), + WTCP(0x7ffffbbf, 0x0020fe79), WTCP(0x7ffffac9, 0x002489ef), + WTCP(0x7ffff9b7, 0x00281de2), WTCP(0x7ffff887, 0x002bbdbb), + WTCP(0x7ffff737, 0x002f6c0d), WTCP(0x7ffff5c6, 0x00332ad8), + WTCP(0x7ffff431, 0x0036fbb9), WTCP(0x7ffff276, 0x003ae004), + WTCP(0x7ffff092, 0x003ed8d8), WTCP(0x7fffee84, 0x0042e72f), + WTCP(0x7fffec48, 0x00470be3), WTCP(0x7fffe9dd, 0x004b47b8), + WTCP(0x7fffe73f, 0x004f9b5f), WTCP(0x7fffe46b, 0x0054077a), + WTCP(0x7fffe15f, 0x00588ca1), WTCP(0x7fffde17, 0x005d2b61), + WTCP(0x7fffda91, 0x0061e442), WTCP(0x7fffd6c9, 0x0066b7c2), + WTCP(0x7fffd2bb, 0x006ba65c), WTCP(0x7fffce65, 0x0070b087), + WTCP(0x7fffc9c2, 0x0075d6b5), WTCP(0x7fffc4cf, 0x007b1955), + WTCP(0x7fffbf87, 0x008078d5), WTCP(0x7fffb9e7, 0x0085f5a0), + WTCP(0x7fffb3ea, 0x008b901d), WTCP(0x7fffad8c, 0x009148b4), + WTCP(0x7fffa6c9, 0x00971fcb), WTCP(0x7fff9f9c, 0x009d15c7), + WTCP(0x7fff9800, 0x00a32b0b), WTCP(0x7fff8ff0, 0x00a95ff9), + WTCP(0x7fff8767, 0x00afb4f4), WTCP(0x7fff7e5f, 0x00b62a5c), + WTCP(0x7fff74d4, 0x00bcc093), WTCP(0x7fff6ac0, 0x00c377f8), + WTCP(0x7fff601c, 0x00ca50eb), WTCP(0x7fff54e3, 0x00d14bcb), + WTCP(0x7fff490e, 0x00d868f7), WTCP(0x7fff3c98, 0x00dfa8ce), + WTCP(0x7fff2f79, 0x00e70bad), WTCP(0x7fff21ac, 0x00ee91f3), + WTCP(0x7fff1328, 0x00f63bfe), WTCP(0x7fff03e7, 0x00fe0a2c), + WTCP(0x7ffef3e1, 0x0105fcd9), WTCP(0x7ffee310, 0x010e1462), + WTCP(0x7ffed16a, 0x01165126), WTCP(0x7ffebee9, 0x011eb381), + WTCP(0x7ffeab83, 0x01273bd0), WTCP(0x7ffe9731, 0x012fea6f), + WTCP(0x7ffe81ea, 0x0138bfbc), WTCP(0x7ffe6ba4, 0x0141bc12), + WTCP(0x7ffe5457, 0x014adfce), WTCP(0x7ffe3bfa, 0x01542b4d), + WTCP(0x7ffe2282, 0x015d9ee9), WTCP(0x7ffe07e6, 0x01673b01), + WTCP(0x7ffdec1b, 0x0170ffee), WTCP(0x7ffdcf17, 0x017aee0e), + WTCP(0x7ffdb0d0, 0x018505bc), WTCP(0x7ffd913b, 0x018f4754), + WTCP(0x7ffd704b, 0x0199b330), WTCP(0x7ffd4df7, 0x01a449ad), + WTCP(0x7ffd2a31, 0x01af0b25), WTCP(0x7ffd04ef, 0x01b9f7f4), + WTCP(0x7ffcde23, 0x01c51074), WTCP(0x7ffcb5c1, 0x01d05501), + WTCP(0x7ffc8bbc, 0x01dbc5f5), WTCP(0x7ffc6006, 0x01e763ab), + WTCP(0x7ffc3293, 0x01f32e7d), WTCP(0x7ffc0354, 0x01ff26c5), + WTCP(0x7ffbd23b, 0x020b4cde), WTCP(0x7ffb9f3a, 0x0217a120), + WTCP(0x7ffb6a41, 0x022423e6), WTCP(0x7ffb3342, 0x0230d58a), + WTCP(0x7ffafa2d, 0x023db664), WTCP(0x7ffabef2, 0x024ac6ce), + WTCP(0x7ffa8180, 0x02580720), WTCP(0x7ffa41c9, 0x026577b3), + WTCP(0x7ff9ffb9, 0x027318e0), WTCP(0x7ff9bb41, 0x0280eaff), + WTCP(0x7ff9744e, 0x028eee68), WTCP(0x7ff92acf, 0x029d2371), + WTCP(0x7ff8deb1, 0x02ab8a74), WTCP(0x7ff88fe2, 0x02ba23c7), + WTCP(0x7ff83e4d, 0x02c8efc0), WTCP(0x7ff7e9e1, 0x02d7eeb7), + WTCP(0x7ff79288, 0x02e72101), WTCP(0x7ff7382f, 0x02f686f5), + WTCP(0x7ff6dac1, 0x030620e9), WTCP(0x7ff67a29, 0x0315ef31), + WTCP(0x7ff61651, 0x0325f224), WTCP(0x7ff5af23, 0x03362a14), + WTCP(0x7ff5448a, 0x03469758), WTCP(0x7ff4d66d, 0x03573a42), + WTCP(0x7ff464b7, 0x03681327), WTCP(0x7ff3ef4f, 0x0379225a), + WTCP(0x7ff3761d, 0x038a682e), WTCP(0x7ff2f90a, 0x039be4f4), + WTCP(0x7ff277fb, 0x03ad9900), WTCP(0x7ff1f2d8, 0x03bf84a3), + WTCP(0x7ff16986, 0x03d1a82e), WTCP(0x7ff0dbec, 0x03e403f3), + WTCP(0x7ff049ef, 0x03f69840), WTCP(0x7fefb373, 0x04096568), + WTCP(0x7fef185d, 0x041c6bb8), WTCP(0x7fee7890, 0x042fab81), + WTCP(0x7fedd3f1, 0x04432510), WTCP(0x7fed2a61, 0x0456d8b4), + WTCP(0x7fec7bc4, 0x046ac6ba), WTCP(0x7febc7fb, 0x047eef70), + WTCP(0x7feb0ee8, 0x04935322), WTCP(0x7fea506b, 0x04a7f21d), + WTCP(0x7fe98c65, 0x04bcccab), WTCP(0x7fe8c2b7, 0x04d1e318), + WTCP(0x7fe7f33e, 0x04e735af), WTCP(0x7fe71ddb, 0x04fcc4ba), + WTCP(0x7fe6426c, 0x05129081), WTCP(0x7fe560ce, 0x0528994d), + WTCP(0x7fe478df, 0x053edf68), WTCP(0x7fe38a7c, 0x05556318), + WTCP(0x7fe29581, 0x056c24a5), WTCP(0x7fe199ca, 0x05832455), + WTCP(0x7fe09733, 0x059a626e), WTCP(0x7fdf8d95, 0x05b1df35), + WTCP(0x7fde7ccb, 0x05c99aef), WTCP(0x7fdd64af, 0x05e195e0), + WTCP(0x7fdc451a, 0x05f9d04b), WTCP(0x7fdb1de4, 0x06124a73), + WTCP(0x7fd9eee5, 0x062b0499), WTCP(0x7fd8b7f5, 0x0643ff00), + WTCP(0x7fd778ec, 0x065d39e7), WTCP(0x7fd6319e, 0x0676b58f), + WTCP(0x7fd4e1e2, 0x06907237), WTCP(0x7fd3898d, 0x06aa701d), + WTCP(0x7fd22873, 0x06c4af80), WTCP(0x7fd0be6a, 0x06df309c), + WTCP(0x7fcf4b44, 0x06f9f3ad), WTCP(0x7fcdced4, 0x0714f8f0), + WTCP(0x7fcc48ed, 0x0730409f), WTCP(0x7fcab960, 0x074bcaf5), + WTCP(0x7fc91fff, 0x0767982a), WTCP(0x7fc77c9a, 0x0783a877), + WTCP(0x7fc5cf02, 0x079ffc14), WTCP(0x7fc41705, 0x07bc9338), + WTCP(0x7fc25474, 0x07d96e19), WTCP(0x7fc0871b, 0x07f68ced), + WTCP(0x7fbeaeca, 0x0813efe7), WTCP(0x7fbccb4c, 0x0831973d), + WTCP(0x7fbadc70, 0x084f8320), WTCP(0x7fb8e200, 0x086db3c3), + WTCP(0x7fb6dbc8, 0x088c2957), WTCP(0x7fb4c993, 0x08aae40c), + WTCP(0x7fb2ab2b, 0x08c9e412), WTCP(0x7fb0805a, 0x08e92997), + WTCP(0x7fae48e9, 0x0908b4c9), WTCP(0x7fac04a0, 0x092885d6), + WTCP(0x7fa9b347, 0x09489ce8), WTCP(0x7fa754a6, 0x0968fa2c), + WTCP(0x7fa4e884, 0x09899dcb), WTCP(0x7fa26ea6, 0x09aa87ee), + WTCP(0x7f9fe6d1, 0x09cbb8be), WTCP(0x7f9d50cc, 0x09ed3062), + WTCP(0x7f9aac5a, 0x0a0eef00), WTCP(0x7f97f93f, 0x0a30f4bf), + WTCP(0x7f95373e, 0x0a5341c2), WTCP(0x7f92661b, 0x0a75d62e), + WTCP(0x7f8f8596, 0x0a98b224), WTCP(0x7f8c9572, 0x0abbd5c7), + WTCP(0x7f89956f, 0x0adf4137), WTCP(0x7f86854d, 0x0b02f494), + WTCP(0x7f8364cd, 0x0b26effd), WTCP(0x7f8033ae, 0x0b4b338f), + WTCP(0x7f7cf1ae, 0x0b6fbf67), WTCP(0x7f799e8b, 0x0b9493a0), + WTCP(0x7f763a03, 0x0bb9b056), WTCP(0x7f72c3d2, 0x0bdf15a2), + WTCP(0x7f6f3bb5, 0x0c04c39c), WTCP(0x7f6ba168, 0x0c2aba5d), + WTCP(0x7f67f4a6, 0x0c50f9fa), WTCP(0x7f643529, 0x0c77828a), + WTCP(0x7f6062ac, 0x0c9e5420), WTCP(0x7f5c7ce8, 0x0cc56ed1), + WTCP(0x7f588397, 0x0cecd2ae), WTCP(0x7f547670, 0x0d147fc8), + WTCP(0x7f50552c, 0x0d3c7630), WTCP(0x7f4c1f83, 0x0d64b5f6), + WTCP(0x7f47d52a, 0x0d8d3f26), WTCP(0x7f4375d9, 0x0db611ce), + WTCP(0x7f3f0144, 0x0ddf2dfa), WTCP(0x7f3a7723, 0x0e0893b4), + WTCP(0x7f35d729, 0x0e324306), WTCP(0x7f31210a, 0x0e5c3bf9), + WTCP(0x7f2c547b, 0x0e867e94), WTCP(0x7f27712e, 0x0eb10add), + WTCP(0x7f2276d8, 0x0edbe0da), WTCP(0x7f1d6529, 0x0f07008e), + WTCP(0x7f183bd3, 0x0f3269fc), WTCP(0x7f12fa89, 0x0f5e1d27), + WTCP(0x7f0da0fb, 0x0f8a1a0e), WTCP(0x7f082ed8, 0x0fb660b1), + WTCP(0x7f02a3d2, 0x0fe2f10f), WTCP(0x7efcff98, 0x100fcb25), + WTCP(0x7ef741d9, 0x103ceeee), WTCP(0x7ef16a42, 0x106a5c66), + WTCP(0x7eeb7884, 0x10981386), WTCP(0x7ee56c4a, 0x10c61447), + WTCP(0x7edf4543, 0x10f45ea0), WTCP(0x7ed9031b, 0x1122f288), + WTCP(0x7ed2a57f, 0x1151cff3), WTCP(0x7ecc2c1a, 0x1180f6d5), + WTCP(0x7ec59699, 0x11b06720), WTCP(0x7ebee4a6, 0x11e020c8), + WTCP(0x7eb815ed, 0x121023ba), WTCP(0x7eb12a18, 0x12406fe8), + WTCP(0x7eaa20d1, 0x1271053e), WTCP(0x7ea2f9c2, 0x12a1e3a9), + WTCP(0x7e9bb494, 0x12d30b15), WTCP(0x7e9450f0, 0x13047b6c), + WTCP(0x7e8cce7f, 0x13363497), WTCP(0x7e852ce9, 0x1368367f), + WTCP(0x7e7d6bd6, 0x139a8109), WTCP(0x7e758aee, 0x13cd141b), + WTCP(0x7e6d89d9, 0x13ffef99), WTCP(0x7e65683d, 0x14331368), + WTCP(0x7e5d25c1, 0x14667f67), WTCP(0x7e54c20b, 0x149a3379), + WTCP(0x7e4c3cc3, 0x14ce2f7c), WTCP(0x7e43958e, 0x1502734f), + WTCP(0x7e3acc11, 0x1536fece), WTCP(0x7e31dff2, 0x156bd1d6), + WTCP(0x7e28d0d7, 0x15a0ec41), WTCP(0x7e1f9e63, 0x15d64de9), + WTCP(0x7e16483d, 0x160bf6a5), WTCP(0x7e0cce08, 0x1641e64c), + WTCP(0x7e032f6a, 0x16781cb4), WTCP(0x7df96c05, 0x16ae99b2), + WTCP(0x7def837e, 0x16e55d18), WTCP(0x7de57579, 0x171c66ba), + WTCP(0x7ddb419a, 0x1753b667), WTCP(0x7dd0e784, 0x178b4bef), + WTCP(0x7dc666d9, 0x17c32721), WTCP(0x7dbbbf3e, 0x17fb47ca), + WTCP(0x7db0f056, 0x1833adb5), WTCP(0x7da5f9c3, 0x186c58ae), + WTCP(0x7d9adb29, 0x18a5487d), WTCP(0x7d8f9429, 0x18de7cec), + WTCP(0x7d842467, 0x1917f5c1), WTCP(0x7d788b86, 0x1951b2c2), + WTCP(0x7d6cc927, 0x198bb3b4), WTCP(0x7d60dced, 0x19c5f85a), + WTCP(0x7d54c67c, 0x1a008077), WTCP(0x7d488574, 0x1a3b4bcb), + WTCP(0x7d3c1979, 0x1a765a17), WTCP(0x7d2f822d, 0x1ab1ab18), + WTCP(0x7d22bf32, 0x1aed3e8d), WTCP(0x7d15d02b, 0x1b291432), + WTCP(0x7d08b4ba, 0x1b652bc1), WTCP(0x7cfb6c82, 0x1ba184f5), + WTCP(0x7cedf725, 0x1bde1f86), WTCP(0x7ce05445, 0x1c1afb2c), + WTCP(0x7cd28386, 0x1c58179c), WTCP(0x7cc48489, 0x1c95748d), + WTCP(0x7cb656f3, 0x1cd311b1), WTCP(0x7ca7fa65, 0x1d10eebd), + WTCP(0x7c996e83, 0x1d4f0b60), WTCP(0x7c8ab2f0, 0x1d8d674c), + WTCP(0x7c7bc74f, 0x1dcc0230), WTCP(0x7c6cab44, 0x1e0adbbb), + WTCP(0x7c5d5e71, 0x1e49f398), WTCP(0x7c4de07c, 0x1e894973), + WTCP(0x7c3e3108, 0x1ec8dcf8), WTCP(0x7c2e4fb9, 0x1f08add0), + WTCP(0x7c1e3c34, 0x1f48bba3), WTCP(0x7c0df61d, 0x1f890618), + WTCP(0x7bfd7d18, 0x1fc98cd6), WTCP(0x7becd0cc, 0x200a4f80), + WTCP(0x7bdbf0dd, 0x204b4dbc), WTCP(0x7bcadcf1, 0x208c872c), + WTCP(0x7bb994ae, 0x20cdfb71), WTCP(0x7ba817b9, 0x210faa2c), + WTCP(0x7b9665bb, 0x215192fc), WTCP(0x7b847e58, 0x2193b57f), + WTCP(0x7b726139, 0x21d61153), WTCP(0x7b600e05, 0x2218a614), + WTCP(0x7b4d8463, 0x225b735d), WTCP(0x7b3ac3fc, 0x229e78c7), + WTCP(0x7b27cc79, 0x22e1b5eb), WTCP(0x7b149d82, 0x23252a62), + WTCP(0x7b0136c1, 0x2368d5c2), WTCP(0x7aed97df, 0x23acb7a0), + WTCP(0x7ad9c087, 0x23f0cf92), WTCP(0x7ac5b063, 0x24351d2a), + WTCP(0x7ab1671e, 0x24799ffc), WTCP(0x7a9ce464, 0x24be5799), + WTCP(0x7a8827e1, 0x25034391), WTCP(0x7a733142, 0x25486375), + WTCP(0x7a5e0033, 0x258db6d2), WTCP(0x7a489461, 0x25d33d35), + WTCP(0x7a32ed7c, 0x2618f62c), WTCP(0x7a1d0b31, 0x265ee143), + WTCP(0x7a06ed2f, 0x26a4fe02), WTCP(0x79f09327, 0x26eb4bf5), + WTCP(0x79d9fcc8, 0x2731caa3), WTCP(0x79c329c2, 0x27787995), + WTCP(0x79ac19c9, 0x27bf5850), WTCP(0x7994cc8d, 0x2806665c), + WTCP(0x797d41c1, 0x284da33c), WTCP(0x79657918, 0x28950e74), + WTCP(0x794d7247, 0x28dca788), WTCP(0x79352d01, 0x29246dfa), + WTCP(0x791ca8fc, 0x296c614a), WTCP(0x7903e5ee, 0x29b480f9), + WTCP(0x78eae38d, 0x29fccc87), WTCP(0x78d1a191, 0x2a454372), + WTCP(0x78b81fb1, 0x2a8de537), WTCP(0x789e5da6, 0x2ad6b155), + WTCP(0x78845b29, 0x2b1fa745), WTCP(0x786a17f5, 0x2b68c684), + WTCP(0x784f93c4, 0x2bb20e8c), WTCP(0x7834ce53, 0x2bfb7ed7), + WTCP(0x7819c75c, 0x2c4516dc), WTCP(0x77fe7e9e, 0x2c8ed615), + WTCP(0x77e2f3d7, 0x2cd8bbf7), WTCP(0x77c726c5, 0x2d22c7fa), + WTCP(0x77ab1728, 0x2d6cf993), WTCP(0x778ec4c0, 0x2db75037), + WTCP(0x77722f4e, 0x2e01cb59), WTCP(0x77555695, 0x2e4c6a6d), + WTCP(0x77383a58, 0x2e972ce6), WTCP(0x771ada5a, 0x2ee21235), + WTCP(0x76fd3660, 0x2f2d19cc), WTCP(0x76df4e30, 0x2f78431a), + WTCP(0x76c12190, 0x2fc38d91), WTCP(0x76a2b047, 0x300ef89d), + WTCP(0x7683fa1e, 0x305a83af), WTCP(0x7664fede, 0x30a62e34), + WTCP(0x7645be51, 0x30f1f798), WTCP(0x76263842, 0x313ddf49), + WTCP(0x76066c7e, 0x3189e4b1), WTCP(0x75e65ad1, 0x31d6073d), + WTCP(0x75c60309, 0x32224657), WTCP(0x75a564f6, 0x326ea168), + WTCP(0x75848067, 0x32bb17da), WTCP(0x7563552d, 0x3307a917), + WTCP(0x7541e31a, 0x33545486), WTCP(0x75202a02, 0x33a1198e), + WTCP(0x74fe29b8, 0x33edf798), WTCP(0x74dbe211, 0x343aee09), + WTCP(0x74b952e3, 0x3487fc48), WTCP(0x74967c06, 0x34d521bb), + WTCP(0x74735d51, 0x35225dc7), WTCP(0x744ff69f, 0x356fafcf), + WTCP(0x742c47c9, 0x35bd173a), WTCP(0x740850ab, 0x360a9369), + WTCP(0x73e41121, 0x365823c1), WTCP(0x73bf8909, 0x36a5c7a4), + WTCP(0x739ab842, 0x36f37e75), WTCP(0x73759eab, 0x37414796), + WTCP(0x73503c26, 0x378f2268), WTCP(0x732a9095, 0x37dd0e4c), + WTCP(0x73049bda, 0x382b0aa4), WTCP(0x72de5ddb, 0x387916d0), + WTCP(0x72b7d67d, 0x38c73230), WTCP(0x729105a6, 0x39155c24), + WTCP(0x7269eb3f, 0x3963940c), WTCP(0x72428730, 0x39b1d946), + WTCP(0x721ad964, 0x3a002b31), WTCP(0x71f2e1c5, 0x3a4e892c), + WTCP(0x71caa042, 0x3a9cf296), WTCP(0x71a214c7, 0x3aeb66cc), + WTCP(0x71793f43, 0x3b39e52c), WTCP(0x71501fa6, 0x3b886d14), + WTCP(0x7126b5e3, 0x3bd6fde1), WTCP(0x70fd01eb, 0x3c2596f1), + WTCP(0x70d303b2, 0x3c74379f), WTCP(0x70a8bb2e, 0x3cc2df49), + WTCP(0x707e2855, 0x3d118d4c), WTCP(0x70534b1e, 0x3d604103), + WTCP(0x70282381, 0x3daef9cc), WTCP(0x6ffcb17a, 0x3dfdb702), + WTCP(0x6fd0f504, 0x3e4c7800), WTCP(0x6fa4ee1a, 0x3e9b3c25), + WTCP(0x6f789cbb, 0x3eea02ca), WTCP(0x6f4c00e5, 0x3f38cb4b), + WTCP(0x6f1f1a9a, 0x3f879505), WTCP(0x6ef1e9da, 0x3fd65f53), + WTCP(0x6ec46ea9, 0x40252990), WTCP(0x6e96a90b, 0x4073f318), + WTCP(0x6e689905, 0x40c2bb46), WTCP(0x6e3a3e9d, 0x41118176), + WTCP(0x6e0b99dd, 0x41604504), WTCP(0x6ddcaacc, 0x41af054a), + WTCP(0x6dad7177, 0x41fdc1a5), WTCP(0x6d7dede8, 0x424c7970), + WTCP(0x6d4e202e, 0x429b2c06), WTCP(0x6d1e0855, 0x42e9d8c4), + WTCP(0x6ceda66f, 0x43387f05), WTCP(0x6cbcfa8d, 0x43871e26), + WTCP(0x6c8c04c0, 0x43d5b581), WTCP(0x6c5ac51d, 0x44244474), + WTCP(0x6c293bb8, 0x4472ca5a), WTCP(0x6bf768a8, 0x44c14690), + WTCP(0x6bc54c06, 0x450fb873), WTCP(0x6b92e5e9, 0x455e1f5f), + WTCP(0x6b60366c, 0x45ac7ab2), WTCP(0x6b2d3dab, 0x45fac9c8), + WTCP(0x6af9fbc2, 0x46490bff), WTCP(0x6ac670d1, 0x469740b5), + WTCP(0x6a929cf6, 0x46e56747), WTCP(0x6a5e8053, 0x47337f13), + WTCP(0x6a2a1b0a, 0x47818779), WTCP(0x69f56d3e, 0x47cf7fd6), + WTCP(0x69c07715, 0x481d678a), WTCP(0x698b38b4, 0x486b3df3), + WTCP(0x6955b243, 0x48b90272), WTCP(0x691fe3ec, 0x4906b466), + WTCP(0x68e9cdd8, 0x49545330), WTCP(0x68b37033, 0x49a1de30), + WTCP(0x687ccb29, 0x49ef54c8), WTCP(0x6845dee9, 0x4a3cb657), + WTCP(0x680eaba3, 0x4a8a0242), WTCP(0x67d73187, 0x4ad737e9), + WTCP(0x679f70c7, 0x4b2456af), WTCP(0x67676997, 0x4b715df7), + WTCP(0x672f1c2b, 0x4bbe4d25), WTCP(0x66f688ba, 0x4c0b239c), + WTCP(0x66bdaf7b, 0x4c57e0c2), WTCP(0x668490a6, 0x4ca483fa), + WTCP(0x664b2c76, 0x4cf10cac), WTCP(0x66118326, 0x4d3d7a3b), + WTCP(0x65d794f3, 0x4d89cc0f), WTCP(0x659d621a, 0x4dd6018f), + WTCP(0x6562eada, 0x4e221a22), WTCP(0x65282f74, 0x4e6e1530), + WTCP(0x64ed302b, 0x4eb9f222), WTCP(0x64b1ed40, 0x4f05b061), + WTCP(0x647666f8, 0x4f514f57), WTCP(0x643a9d99, 0x4f9cce6f), + WTCP(0x63fe916a, 0x4fe82d13), WTCP(0x63c242b2, 0x50336aaf), + WTCP(0x6385b1bc, 0x507e86b0), WTCP(0x6348ded1, 0x50c98082), + WTCP(0x630bca3f, 0x51145793), WTCP(0x62ce7451, 0x515f0b51), + WTCP(0x6290dd57, 0x51a99b2b), WTCP(0x625305a0, 0x51f40692), + WTCP(0x6214ed7d, 0x523e4cf5), WTCP(0x61d69541, 0x52886dc5), + WTCP(0x6197fd3e, 0x52d26875), WTCP(0x615925c9, 0x531c3c77), + WTCP(0x611a0f39, 0x5365e93e), WTCP(0x60dab9e3, 0x53af6e3e), + WTCP(0x609b2621, 0x53f8caed), WTCP(0x605b544c, 0x5441fec0), + WTCP(0x601b44bf, 0x548b092e), WTCP(0x5fdaf7d5, 0x54d3e9ae), + WTCP(0x5f9a6deb, 0x551c9fb7), WTCP(0x5f59a761, 0x55652ac3), + WTCP(0x5f18a494, 0x55ad8a4d), WTCP(0x5ed765e6, 0x55f5bdcd), + WTCP(0x5e95ebb8, 0x563dc4c1), WTCP(0x5e54366d, 0x56859ea3), + WTCP(0x5e12466a, 0x56cd4af3), WTCP(0x5dd01c13, 0x5714c92d), + WTCP(0x5d8db7cf, 0x575c18d0), WTCP(0x5d4b1a05, 0x57a3395e), + WTCP(0x5d08431e, 0x57ea2a56), WTCP(0x5cc53384, 0x5830eb3a), + WTCP(0x5c81eba0, 0x58777b8e), WTCP(0x5c3e6bdf, 0x58bddad5), + WTCP(0x5bfab4af, 0x59040893), WTCP(0x5bb6c67c, 0x594a044f), + WTCP(0x5b72a1b6, 0x598fcd8e), WTCP(0x5b2e46ce, 0x59d563d9), + WTCP(0x5ae9b634, 0x5a1ac6b8), WTCP(0x5aa4f05a, 0x5a5ff5b5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_WTP KBDWindow1024[] = { + WTCP(0x7fffffa4, 0x0009962f), WTCP(0x7fffff39, 0x000e16fb), + WTCP(0x7ffffebf, 0x0011ea65), WTCP(0x7ffffe34, 0x0015750e), + WTCP(0x7ffffd96, 0x0018dc74), WTCP(0x7ffffce5, 0x001c332e), + WTCP(0x7ffffc1f, 0x001f83f5), WTCP(0x7ffffb43, 0x0022d59a), + WTCP(0x7ffffa4f, 0x00262cc2), WTCP(0x7ffff942, 0x00298cc4), + WTCP(0x7ffff81a, 0x002cf81f), WTCP(0x7ffff6d6, 0x003070c4), + WTCP(0x7ffff573, 0x0033f840), WTCP(0x7ffff3f1, 0x00378fd9), + WTCP(0x7ffff24d, 0x003b38a1), WTCP(0x7ffff085, 0x003ef381), + WTCP(0x7fffee98, 0x0042c147), WTCP(0x7fffec83, 0x0046a2a8), + WTCP(0x7fffea44, 0x004a9847), WTCP(0x7fffe7d8, 0x004ea2b7), + WTCP(0x7fffe53f, 0x0052c283), WTCP(0x7fffe274, 0x0056f829), + WTCP(0x7fffdf76, 0x005b4422), WTCP(0x7fffdc43, 0x005fa6dd), + WTCP(0x7fffd8d6, 0x006420c8), WTCP(0x7fffd52f, 0x0068b249), + WTCP(0x7fffd149, 0x006d5bc4), WTCP(0x7fffcd22, 0x00721d9a), + WTCP(0x7fffc8b6, 0x0076f828), WTCP(0x7fffc404, 0x007bebca), + WTCP(0x7fffbf06, 0x0080f8d9), WTCP(0x7fffb9bb, 0x00861fae), + WTCP(0x7fffb41e, 0x008b609e), WTCP(0x7fffae2c, 0x0090bbff), + WTCP(0x7fffa7e1, 0x00963224), WTCP(0x7fffa13a, 0x009bc362), + WTCP(0x7fff9a32, 0x00a17009), WTCP(0x7fff92c5, 0x00a7386c), + WTCP(0x7fff8af0, 0x00ad1cdc), WTCP(0x7fff82ad, 0x00b31da8), + WTCP(0x7fff79f9, 0x00b93b21), WTCP(0x7fff70cf, 0x00bf7596), + WTCP(0x7fff672a, 0x00c5cd57), WTCP(0x7fff5d05, 0x00cc42b1), + WTCP(0x7fff525c, 0x00d2d5f3), WTCP(0x7fff4729, 0x00d9876c), + WTCP(0x7fff3b66, 0x00e05769), WTCP(0x7fff2f10, 0x00e74638), + WTCP(0x7fff221f, 0x00ee5426), WTCP(0x7fff148e, 0x00f58182), + WTCP(0x7fff0658, 0x00fcce97), WTCP(0x7ffef776, 0x01043bb3), + WTCP(0x7ffee7e2, 0x010bc923), WTCP(0x7ffed795, 0x01137733), + WTCP(0x7ffec68a, 0x011b4631), WTCP(0x7ffeb4ba, 0x01233669), + WTCP(0x7ffea21d, 0x012b4827), WTCP(0x7ffe8eac, 0x01337bb8), + WTCP(0x7ffe7a61, 0x013bd167), WTCP(0x7ffe6533, 0x01444982), + WTCP(0x7ffe4f1c, 0x014ce454), WTCP(0x7ffe3813, 0x0155a229), + WTCP(0x7ffe2011, 0x015e834d), WTCP(0x7ffe070d, 0x0167880c), + WTCP(0x7ffdecff, 0x0170b0b2), WTCP(0x7ffdd1df, 0x0179fd8b), + WTCP(0x7ffdb5a2, 0x01836ee1), WTCP(0x7ffd9842, 0x018d0500), + WTCP(0x7ffd79b3, 0x0196c035), WTCP(0x7ffd59ee, 0x01a0a0ca), + WTCP(0x7ffd38e8, 0x01aaa70a), WTCP(0x7ffd1697, 0x01b4d341), + WTCP(0x7ffcf2f2, 0x01bf25b9), WTCP(0x7ffccdee, 0x01c99ebd), + WTCP(0x7ffca780, 0x01d43e99), WTCP(0x7ffc7f9e, 0x01df0597), + WTCP(0x7ffc563d, 0x01e9f401), WTCP(0x7ffc2b51, 0x01f50a22), + WTCP(0x7ffbfecf, 0x02004844), WTCP(0x7ffbd0ab, 0x020baeb1), + WTCP(0x7ffba0da, 0x02173db4), WTCP(0x7ffb6f4f, 0x0222f596), + WTCP(0x7ffb3bfd, 0x022ed6a1), WTCP(0x7ffb06d8, 0x023ae11f), + WTCP(0x7ffacfd3, 0x02471558), WTCP(0x7ffa96e0, 0x02537397), + WTCP(0x7ffa5bf2, 0x025ffc25), WTCP(0x7ffa1efc, 0x026caf4a), + WTCP(0x7ff9dfee, 0x02798d4f), WTCP(0x7ff99ebb, 0x0286967c), + WTCP(0x7ff95b55, 0x0293cb1b), WTCP(0x7ff915ab, 0x02a12b72), + WTCP(0x7ff8cdaf, 0x02aeb7cb), WTCP(0x7ff88351, 0x02bc706d), + WTCP(0x7ff83682, 0x02ca559f), WTCP(0x7ff7e731, 0x02d867a9), + WTCP(0x7ff7954e, 0x02e6a6d2), WTCP(0x7ff740c8, 0x02f51361), + WTCP(0x7ff6e98e, 0x0303ad9c), WTCP(0x7ff68f8f, 0x031275ca), + WTCP(0x7ff632ba, 0x03216c30), WTCP(0x7ff5d2fb, 0x03309116), + WTCP(0x7ff57042, 0x033fe4bf), WTCP(0x7ff50a7a, 0x034f6773), + WTCP(0x7ff4a192, 0x035f1975), WTCP(0x7ff43576, 0x036efb0a), + WTCP(0x7ff3c612, 0x037f0c78), WTCP(0x7ff35353, 0x038f4e02), + WTCP(0x7ff2dd24, 0x039fbfeb), WTCP(0x7ff26370, 0x03b06279), + WTCP(0x7ff1e623, 0x03c135ed), WTCP(0x7ff16527, 0x03d23a8b), + WTCP(0x7ff0e067, 0x03e37095), WTCP(0x7ff057cc, 0x03f4d84e), + WTCP(0x7fefcb40, 0x040671f7), WTCP(0x7fef3aad, 0x04183dd3), + WTCP(0x7feea5fa, 0x042a3c22), WTCP(0x7fee0d11, 0x043c6d25), + WTCP(0x7fed6fda, 0x044ed11d), WTCP(0x7fecce3d, 0x04616849), + WTCP(0x7fec2821, 0x047432eb), WTCP(0x7feb7d6c, 0x04873140), + WTCP(0x7feace07, 0x049a6388), WTCP(0x7fea19d6, 0x04adca01), + WTCP(0x7fe960c0, 0x04c164ea), WTCP(0x7fe8a2aa, 0x04d53481), + WTCP(0x7fe7df79, 0x04e93902), WTCP(0x7fe71712, 0x04fd72aa), + WTCP(0x7fe6495a, 0x0511e1b6), WTCP(0x7fe57634, 0x05268663), + WTCP(0x7fe49d83, 0x053b60eb), WTCP(0x7fe3bf2b, 0x05507189), + WTCP(0x7fe2db0f, 0x0565b879), WTCP(0x7fe1f110, 0x057b35f4), + WTCP(0x7fe10111, 0x0590ea35), WTCP(0x7fe00af3, 0x05a6d574), + WTCP(0x7fdf0e97, 0x05bcf7ea), WTCP(0x7fde0bdd, 0x05d351cf), + WTCP(0x7fdd02a6, 0x05e9e35c), WTCP(0x7fdbf2d2, 0x0600acc8), + WTCP(0x7fdadc40, 0x0617ae48), WTCP(0x7fd9becf, 0x062ee814), + WTCP(0x7fd89a5e, 0x06465a62), WTCP(0x7fd76eca, 0x065e0565), + WTCP(0x7fd63bf1, 0x0675e954), WTCP(0x7fd501b0, 0x068e0662), + WTCP(0x7fd3bfe4, 0x06a65cc3), WTCP(0x7fd2766a, 0x06beecaa), + WTCP(0x7fd1251e, 0x06d7b648), WTCP(0x7fcfcbda, 0x06f0b9d1), + WTCP(0x7fce6a7a, 0x0709f775), WTCP(0x7fcd00d8, 0x07236f65), + WTCP(0x7fcb8ecf, 0x073d21d2), WTCP(0x7fca1439, 0x07570eea), + WTCP(0x7fc890ed, 0x077136dd), WTCP(0x7fc704c7, 0x078b99da), + WTCP(0x7fc56f9d, 0x07a6380d), WTCP(0x7fc3d147, 0x07c111a4), + WTCP(0x7fc2299e, 0x07dc26cc), WTCP(0x7fc07878, 0x07f777b1), + WTCP(0x7fbebdac, 0x0813047d), WTCP(0x7fbcf90f, 0x082ecd5b), + WTCP(0x7fbb2a78, 0x084ad276), WTCP(0x7fb951bc, 0x086713f7), + WTCP(0x7fb76eaf, 0x08839206), WTCP(0x7fb58126, 0x08a04ccb), + WTCP(0x7fb388f4, 0x08bd446e), WTCP(0x7fb185ee, 0x08da7915), + WTCP(0x7faf77e5, 0x08f7eae7), WTCP(0x7fad5ead, 0x09159a09), + WTCP(0x7fab3a17, 0x0933869f), WTCP(0x7fa909f6, 0x0951b0cd), + WTCP(0x7fa6ce1a, 0x097018b7), WTCP(0x7fa48653, 0x098ebe7f), + WTCP(0x7fa23273, 0x09ada248), WTCP(0x7f9fd249, 0x09ccc431), + WTCP(0x7f9d65a4, 0x09ec245b), WTCP(0x7f9aec53, 0x0a0bc2e7), + WTCP(0x7f986625, 0x0a2b9ff3), WTCP(0x7f95d2e7, 0x0a4bbb9e), + WTCP(0x7f933267, 0x0a6c1604), WTCP(0x7f908472, 0x0a8caf43), + WTCP(0x7f8dc8d5, 0x0aad8776), WTCP(0x7f8aff5c, 0x0ace9eb9), + WTCP(0x7f8827d3, 0x0aeff526), WTCP(0x7f854204, 0x0b118ad8), + WTCP(0x7f824dbb, 0x0b335fe6), WTCP(0x7f7f4ac3, 0x0b557469), + WTCP(0x7f7c38e4, 0x0b77c879), WTCP(0x7f7917e9, 0x0b9a5c2b), + WTCP(0x7f75e79b, 0x0bbd2f97), WTCP(0x7f72a7c3, 0x0be042d0), + WTCP(0x7f6f5828, 0x0c0395ec), WTCP(0x7f6bf892, 0x0c2728fd), + WTCP(0x7f6888c9, 0x0c4afc16), WTCP(0x7f650894, 0x0c6f0f4a), + WTCP(0x7f6177b9, 0x0c9362a8), WTCP(0x7f5dd5ff, 0x0cb7f642), + WTCP(0x7f5a232a, 0x0cdcca26), WTCP(0x7f565f00, 0x0d01de63), + WTCP(0x7f528947, 0x0d273307), WTCP(0x7f4ea1c2, 0x0d4cc81f), + WTCP(0x7f4aa835, 0x0d729db7), WTCP(0x7f469c65, 0x0d98b3da), + WTCP(0x7f427e13, 0x0dbf0a92), WTCP(0x7f3e4d04, 0x0de5a1e9), + WTCP(0x7f3a08f9, 0x0e0c79e7), WTCP(0x7f35b1b4, 0x0e339295), + WTCP(0x7f3146f8, 0x0e5aebfa), WTCP(0x7f2cc884, 0x0e82861a), + WTCP(0x7f28361b, 0x0eaa60fd), WTCP(0x7f238f7c, 0x0ed27ca5), + WTCP(0x7f1ed467, 0x0efad917), WTCP(0x7f1a049d, 0x0f237656), + WTCP(0x7f151fdc, 0x0f4c5462), WTCP(0x7f1025e3, 0x0f75733d), + WTCP(0x7f0b1672, 0x0f9ed2e6), WTCP(0x7f05f146, 0x0fc8735e), + WTCP(0x7f00b61d, 0x0ff254a1), WTCP(0x7efb64b4, 0x101c76ae), + WTCP(0x7ef5fcca, 0x1046d981), WTCP(0x7ef07e19, 0x10717d15), + WTCP(0x7eeae860, 0x109c6165), WTCP(0x7ee53b5b, 0x10c7866a), + WTCP(0x7edf76c4, 0x10f2ec1e), WTCP(0x7ed99a58, 0x111e9279), + WTCP(0x7ed3a5d1, 0x114a7971), WTCP(0x7ecd98eb, 0x1176a0fc), + WTCP(0x7ec77360, 0x11a30910), WTCP(0x7ec134eb, 0x11cfb1a1), + WTCP(0x7ebadd44, 0x11fc9aa2), WTCP(0x7eb46c27, 0x1229c406), + WTCP(0x7eade14c, 0x12572dbf), WTCP(0x7ea73c6c, 0x1284d7bc), + WTCP(0x7ea07d41, 0x12b2c1ed), WTCP(0x7e99a382, 0x12e0ec42), + WTCP(0x7e92aee7, 0x130f56a8), WTCP(0x7e8b9f2a, 0x133e010b), + WTCP(0x7e847402, 0x136ceb59), WTCP(0x7e7d2d25, 0x139c157b), + WTCP(0x7e75ca4c, 0x13cb7f5d), WTCP(0x7e6e4b2d, 0x13fb28e6), + WTCP(0x7e66af7f, 0x142b1200), WTCP(0x7e5ef6f8, 0x145b3a92), + WTCP(0x7e572150, 0x148ba281), WTCP(0x7e4f2e3b, 0x14bc49b4), + WTCP(0x7e471d70, 0x14ed300f), WTCP(0x7e3eeea5, 0x151e5575), + WTCP(0x7e36a18e, 0x154fb9c9), WTCP(0x7e2e35e2, 0x15815ced), + WTCP(0x7e25ab56, 0x15b33ec1), WTCP(0x7e1d019e, 0x15e55f25), + WTCP(0x7e14386e, 0x1617bdf9), WTCP(0x7e0b4f7d, 0x164a5b19), + WTCP(0x7e02467e, 0x167d3662), WTCP(0x7df91d25, 0x16b04fb2), + WTCP(0x7defd327, 0x16e3a6e2), WTCP(0x7de66837, 0x17173bce), + WTCP(0x7ddcdc0a, 0x174b0e4d), WTCP(0x7dd32e53, 0x177f1e39), + WTCP(0x7dc95ec6, 0x17b36b69), WTCP(0x7dbf6d17, 0x17e7f5b3), + WTCP(0x7db558f9, 0x181cbcec), WTCP(0x7dab221f, 0x1851c0e9), + WTCP(0x7da0c83c, 0x1887017d), WTCP(0x7d964b05, 0x18bc7e7c), + WTCP(0x7d8baa2b, 0x18f237b6), WTCP(0x7d80e563, 0x19282cfd), + WTCP(0x7d75fc5e, 0x195e5e20), WTCP(0x7d6aeed0, 0x1994caee), + WTCP(0x7d5fbc6d, 0x19cb7335), WTCP(0x7d5464e6, 0x1a0256c2), + WTCP(0x7d48e7ef, 0x1a397561), WTCP(0x7d3d453b, 0x1a70cede), + WTCP(0x7d317c7c, 0x1aa86301), WTCP(0x7d258d65, 0x1ae03195), + WTCP(0x7d1977aa, 0x1b183a63), WTCP(0x7d0d3afc, 0x1b507d30), + WTCP(0x7d00d710, 0x1b88f9c5), WTCP(0x7cf44b97, 0x1bc1afe6), + WTCP(0x7ce79846, 0x1bfa9f58), WTCP(0x7cdabcce, 0x1c33c7e0), + WTCP(0x7ccdb8e4, 0x1c6d293f), WTCP(0x7cc08c39, 0x1ca6c337), + WTCP(0x7cb33682, 0x1ce0958a), WTCP(0x7ca5b772, 0x1d1a9ff8), + WTCP(0x7c980ebd, 0x1d54e240), WTCP(0x7c8a3c14, 0x1d8f5c21), + WTCP(0x7c7c3f2e, 0x1dca0d56), WTCP(0x7c6e17bc, 0x1e04f59f), + WTCP(0x7c5fc573, 0x1e4014b4), WTCP(0x7c514807, 0x1e7b6a53), + WTCP(0x7c429f2c, 0x1eb6f633), WTCP(0x7c33ca96, 0x1ef2b80f), + WTCP(0x7c24c9fa, 0x1f2eaf9e), WTCP(0x7c159d0d, 0x1f6adc98), + WTCP(0x7c064383, 0x1fa73eb2), WTCP(0x7bf6bd11, 0x1fe3d5a3), + WTCP(0x7be7096c, 0x2020a11e), WTCP(0x7bd7284a, 0x205da0d8), + WTCP(0x7bc71960, 0x209ad483), WTCP(0x7bb6dc65, 0x20d83bd1), + WTCP(0x7ba6710d, 0x2115d674), WTCP(0x7b95d710, 0x2153a41b), + WTCP(0x7b850e24, 0x2191a476), WTCP(0x7b7415ff, 0x21cfd734), + WTCP(0x7b62ee59, 0x220e3c02), WTCP(0x7b5196e9, 0x224cd28d), + WTCP(0x7b400f67, 0x228b9a82), WTCP(0x7b2e578a, 0x22ca938a), + WTCP(0x7b1c6f0b, 0x2309bd52), WTCP(0x7b0a55a1, 0x23491783), + WTCP(0x7af80b07, 0x2388a1c4), WTCP(0x7ae58ef5, 0x23c85bbf), + WTCP(0x7ad2e124, 0x2408451a), WTCP(0x7ac0014e, 0x24485d7c), + WTCP(0x7aacef2e, 0x2488a48a), WTCP(0x7a99aa7e, 0x24c919e9), + WTCP(0x7a8632f8, 0x2509bd3d), WTCP(0x7a728858, 0x254a8e29), + WTCP(0x7a5eaa5a, 0x258b8c50), WTCP(0x7a4a98b9, 0x25ccb753), + WTCP(0x7a365333, 0x260e0ed3), WTCP(0x7a21d983, 0x264f9271), + WTCP(0x7a0d2b68, 0x269141cb), WTCP(0x79f8489e, 0x26d31c80), + WTCP(0x79e330e4, 0x2715222f), WTCP(0x79cde3f8, 0x27575273), + WTCP(0x79b8619a, 0x2799acea), WTCP(0x79a2a989, 0x27dc3130), + WTCP(0x798cbb85, 0x281ededf), WTCP(0x7976974e, 0x2861b591), + WTCP(0x79603ca5, 0x28a4b4e0), WTCP(0x7949ab4c, 0x28e7dc65), + WTCP(0x7932e304, 0x292b2bb8), WTCP(0x791be390, 0x296ea270), + WTCP(0x7904acb3, 0x29b24024), WTCP(0x78ed3e30, 0x29f6046b), + WTCP(0x78d597cc, 0x2a39eed8), WTCP(0x78bdb94a, 0x2a7dff02), + WTCP(0x78a5a270, 0x2ac2347c), WTCP(0x788d5304, 0x2b068eda), + WTCP(0x7874cacb, 0x2b4b0dae), WTCP(0x785c098d, 0x2b8fb08a), + WTCP(0x78430f11, 0x2bd47700), WTCP(0x7829db1f, 0x2c1960a1), + WTCP(0x78106d7f, 0x2c5e6cfd), WTCP(0x77f6c5fb, 0x2ca39ba3), + WTCP(0x77dce45c, 0x2ce8ec23), WTCP(0x77c2c86e, 0x2d2e5e0b), + WTCP(0x77a871fa, 0x2d73f0e8), WTCP(0x778de0cd, 0x2db9a449), + WTCP(0x777314b2, 0x2dff77b8), WTCP(0x77580d78, 0x2e456ac4), + WTCP(0x773ccaeb, 0x2e8b7cf6), WTCP(0x77214cdb, 0x2ed1addb), + WTCP(0x77059315, 0x2f17fcfb), WTCP(0x76e99d69, 0x2f5e69e2), + WTCP(0x76cd6ba9, 0x2fa4f419), WTCP(0x76b0fda4, 0x2feb9b27), + WTCP(0x7694532e, 0x30325e96), WTCP(0x76776c17, 0x30793dee), + WTCP(0x765a4834, 0x30c038b5), WTCP(0x763ce759, 0x31074e72), + WTCP(0x761f4959, 0x314e7eab), WTCP(0x76016e0b, 0x3195c8e6), + WTCP(0x75e35545, 0x31dd2ca9), WTCP(0x75c4fedc, 0x3224a979), + WTCP(0x75a66aab, 0x326c3ed8), WTCP(0x75879887, 0x32b3ec4d), + WTCP(0x7568884b, 0x32fbb159), WTCP(0x754939d1, 0x33438d81), + WTCP(0x7529acf4, 0x338b8045), WTCP(0x7509e18e, 0x33d3892a), + WTCP(0x74e9d77d, 0x341ba7b1), WTCP(0x74c98e9e, 0x3463db5a), + WTCP(0x74a906cd, 0x34ac23a7), WTCP(0x74883fec, 0x34f48019), + WTCP(0x746739d8, 0x353cf02f), WTCP(0x7445f472, 0x3585736a), + WTCP(0x74246f9c, 0x35ce0949), WTCP(0x7402ab37, 0x3616b14c), + WTCP(0x73e0a727, 0x365f6af0), WTCP(0x73be6350, 0x36a835b5), + WTCP(0x739bdf95, 0x36f11118), WTCP(0x73791bdd, 0x3739fc98), + WTCP(0x7356180e, 0x3782f7b2), WTCP(0x7332d410, 0x37cc01e3), + WTCP(0x730f4fc9, 0x38151aa8), WTCP(0x72eb8b24, 0x385e417e), + WTCP(0x72c7860a, 0x38a775e1), WTCP(0x72a34066, 0x38f0b74d), + WTCP(0x727eba24, 0x393a053e), WTCP(0x7259f331, 0x39835f30), + WTCP(0x7234eb79, 0x39ccc49e), WTCP(0x720fa2eb, 0x3a163503), + WTCP(0x71ea1977, 0x3a5fafda), WTCP(0x71c44f0c, 0x3aa9349e), + WTCP(0x719e439d, 0x3af2c2ca), WTCP(0x7177f71a, 0x3b3c59d7), + WTCP(0x71516978, 0x3b85f940), WTCP(0x712a9aaa, 0x3bcfa07e), + WTCP(0x71038aa4, 0x3c194f0d), WTCP(0x70dc395e, 0x3c630464), + WTCP(0x70b4a6cd, 0x3cacbfff), WTCP(0x708cd2e9, 0x3cf68155), + WTCP(0x7064bdab, 0x3d4047e1), WTCP(0x703c670d, 0x3d8a131c), + WTCP(0x7013cf0a, 0x3dd3e27e), WTCP(0x6feaf59c, 0x3e1db580), + WTCP(0x6fc1dac1, 0x3e678b9b), WTCP(0x6f987e76, 0x3eb16449), + WTCP(0x6f6ee0b9, 0x3efb3f01), WTCP(0x6f45018b, 0x3f451b3d), + WTCP(0x6f1ae0eb, 0x3f8ef874), WTCP(0x6ef07edb, 0x3fd8d620), + WTCP(0x6ec5db5d, 0x4022b3b9), WTCP(0x6e9af675, 0x406c90b7), + WTCP(0x6e6fd027, 0x40b66c93), WTCP(0x6e446879, 0x410046c5), + WTCP(0x6e18bf71, 0x414a1ec6), WTCP(0x6decd517, 0x4193f40d), + WTCP(0x6dc0a972, 0x41ddc615), WTCP(0x6d943c8d, 0x42279455), + WTCP(0x6d678e71, 0x42715e45), WTCP(0x6d3a9f2a, 0x42bb235f), + WTCP(0x6d0d6ec5, 0x4304e31a), WTCP(0x6cdffd4f, 0x434e9cf1), + WTCP(0x6cb24ad6, 0x4398505b), WTCP(0x6c84576b, 0x43e1fcd1), + WTCP(0x6c56231c, 0x442ba1cd), WTCP(0x6c27adfd, 0x44753ec7), + WTCP(0x6bf8f81e, 0x44bed33a), WTCP(0x6bca0195, 0x45085e9d), + WTCP(0x6b9aca75, 0x4551e06b), WTCP(0x6b6b52d5, 0x459b581e), + WTCP(0x6b3b9ac9, 0x45e4c52f), WTCP(0x6b0ba26b, 0x462e2717), + WTCP(0x6adb69d3, 0x46777d52), WTCP(0x6aaaf11b, 0x46c0c75a), + WTCP(0x6a7a385c, 0x470a04a9), WTCP(0x6a493fb3, 0x475334b9), + WTCP(0x6a18073d, 0x479c5707), WTCP(0x69e68f17, 0x47e56b0c), + WTCP(0x69b4d761, 0x482e7045), WTCP(0x6982e039, 0x4877662c), + WTCP(0x6950a9c0, 0x48c04c3f), WTCP(0x691e341a, 0x490921f8), + WTCP(0x68eb7f67, 0x4951e6d5), WTCP(0x68b88bcd, 0x499a9a51), + WTCP(0x68855970, 0x49e33beb), WTCP(0x6851e875, 0x4a2bcb1f), + WTCP(0x681e3905, 0x4a74476b), WTCP(0x67ea4b47, 0x4abcb04c), + WTCP(0x67b61f63, 0x4b050541), WTCP(0x6781b585, 0x4b4d45c9), + WTCP(0x674d0dd6, 0x4b957162), WTCP(0x67182883, 0x4bdd878c), + WTCP(0x66e305b8, 0x4c2587c6), WTCP(0x66ada5a5, 0x4c6d7190), + WTCP(0x66780878, 0x4cb5446a), WTCP(0x66422e60, 0x4cfcffd5), + WTCP(0x660c1790, 0x4d44a353), WTCP(0x65d5c439, 0x4d8c2e64), + WTCP(0x659f348e, 0x4dd3a08c), WTCP(0x656868c3, 0x4e1af94b), + WTCP(0x6531610d, 0x4e623825), WTCP(0x64fa1da3, 0x4ea95c9d), + WTCP(0x64c29ebb, 0x4ef06637), WTCP(0x648ae48d, 0x4f375477), + WTCP(0x6452ef53, 0x4f7e26e1), WTCP(0x641abf46, 0x4fc4dcfb), + WTCP(0x63e254a2, 0x500b7649), WTCP(0x63a9afa2, 0x5051f253), + WTCP(0x6370d083, 0x5098509f), WTCP(0x6337b784, 0x50de90b3), + WTCP(0x62fe64e3, 0x5124b218), WTCP(0x62c4d8e0, 0x516ab455), + WTCP(0x628b13bc, 0x51b096f3), WTCP(0x625115b8, 0x51f6597b), + WTCP(0x6216df18, 0x523bfb78), WTCP(0x61dc701f, 0x52817c72), + WTCP(0x61a1c912, 0x52c6dbf5), WTCP(0x6166ea36, 0x530c198d), + WTCP(0x612bd3d2, 0x535134c5), WTCP(0x60f0862d, 0x53962d2a), + WTCP(0x60b50190, 0x53db024a), WTCP(0x60794644, 0x541fb3b1), + WTCP(0x603d5494, 0x546440ef), WTCP(0x60012cca, 0x54a8a992), + WTCP(0x5fc4cf33, 0x54eced2b), WTCP(0x5f883c1c, 0x55310b48), + WTCP(0x5f4b73d2, 0x5575037c), WTCP(0x5f0e76a5, 0x55b8d558), + WTCP(0x5ed144e5, 0x55fc806f), WTCP(0x5e93dee1, 0x56400452), + WTCP(0x5e5644ec, 0x56836096), WTCP(0x5e187757, 0x56c694cf), + WTCP(0x5dda7677, 0x5709a092), WTCP(0x5d9c429f, 0x574c8374), + WTCP(0x5d5ddc24, 0x578f3d0d), WTCP(0x5d1f435d, 0x57d1ccf2), + WTCP(0x5ce078a0, 0x581432bd), WTCP(0x5ca17c45, 0x58566e04), + WTCP(0x5c624ea4, 0x58987e63), WTCP(0x5c22f016, 0x58da6372), + WTCP(0x5be360f6, 0x591c1ccc), WTCP(0x5ba3a19f, 0x595daa0d), + WTCP(0x5b63b26c, 0x599f0ad1), WTCP(0x5b2393ba, 0x59e03eb6), + WTCP(0x5ae345e7, 0x5a214558), WTCP(0x5aa2c951, 0x5a621e56), +}; + +/** + * \brief Helper table containing the length, rasterand shape mapping to + * individual window slope tables. [0: sine ][0: radix2 raster + * ][ceil(log2(length)) length 4 .. 1024 ] [1: 10ms raster + * ][ceil(log2(length)) length 3.25 .. 960 ] [2: 3/4 of radix 2 + * raster][ceil(log2(length)) length 3 .. 768 ] [1: KBD ][0: + * radix2 raster ][ceil(log2(length)) length 128 .. 1024 ] [1: 10ms + * raster ][ceil(log2(length)) length 120 .. 960 ] [2: + * 3/4 of radix 2 raster][ceil(log2(length)) length 96 .. 768 ] + */ +const FIXP_WTP *const windowSlopes[2][4][9] = { + { /* Sine */ + {/* Radix 2 */ + NULL, SineWindow8, SineWindow16, SineWindow32, SineWindow64, + SineWindow128, SineWindow256, SineWindow512, SineWindow1024}, + { /* 10ms raster */ + NULL, /* 3.25 */ + NULL, /* 7.5 */ + NULL, NULL, NULL, SineWindow120, SineWindow240, SineWindow480, + SineWindow960}, + { /* 3/4 radix2 raster */ + NULL, /* 3 */ + NULL, /* 6 */ + SineWindow12, SineWindow24, SineWindow48, SineWindow96, SineWindow192, + SineWindow384, SineWindow768}, + { + /* 3/4 radix2 raster */ + NULL, + NULL, /* 3 */ + NULL, /* 6 */ + SineWindow20, + SineWindow40, + NULL, + SineWindow160, + NULL, + NULL, + }}, + { /* KBD */ + {/* Radix 2 */ + NULL, KBDWindow128, KBDWindow256, SineWindow512, KBDWindow1024}, + {/* 10ms raster */ + NULL, KBDWindow120, NULL, SineWindow480, KBDWindow960}, + {/* 3/4 radix2 raster */ + NULL, KBDWindow96, + SineWindow192, /* This entry might be accessed for erred bit streams. */ + NULL, KBDWindow768}, + {NULL, NULL, NULL, NULL}}}; + +const FIXP_WTP *FDKgetWindowSlope(int length, int shape) { + const FIXP_WTP *w = NULL; + int raster, ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS - 1 - fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ((length) >> (ld2_length - 2)) { + case 0x8: /* radix 2 */ + raster = 0; + ld2_length--; /* revert + 1 because of ceil(log2(length)) from above. */ + break; + case 0xf: /* 10 ms */ + raster = 1; + break; + case 0xc: /* 3/4 of radix 2 */ + raster = 2; + break; + default: + raster = 0; + break; + } + + /* The table for sine windows (shape == 0) is 4 entries longer. */ + if (shape == 1) { + ld2_length -= 4; + } + + /* Look up table */ + w = windowSlopes[shape & 1][raster][ld2_length]; + + FDK_ASSERT(w != NULL); + + return w; +} + + /* + * QMF filter and twiddle tables + */ + +#ifdef QMF_COEFF_16BIT +#define QFC(x) FX_DBL2FXCONST_SGL(x) +#define QTCFL(x) FL2FXCONST_SGL(x) +#define QTC(x) FX_DBL2FXCONST_SGL(x) +#else +#define QFC(x) ((FIXP_DBL)(x)) +#define QTCFL(x) FL2FXCONST_DBL(x) +#define QTC(x) ((FIXP_DBL)(x)) +#endif /* ARCH_PREFER_MULT_32x16 */ + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, optimized by PE 010516 + + The coeffs are rearranged compared with the reference in the following + way, exploiting symmetry : + sbr_qmf_64[5] = p_64_640_qmf[0]; + sbr_qmf_64[6] = p_64_640_qmf[128]; + sbr_qmf_64[7] = p_64_640_qmf[256]; + sbr_qmf_64[8] = p_64_640_qmf[384]; + sbr_qmf_64[9] = p_64_640_qmf[512]; + + sbr_qmf_64[10] = p_64_640_qmf[1]; + sbr_qmf_64[11] = p_64_640_qmf[129]; + sbr_qmf_64[12] = p_64_640_qmf[257]; + sbr_qmf_64[13] = p_64_640_qmf[385]; + sbr_qmf_64[14] = p_64_640_qmf[513]; + . + . + . + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[62]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[190]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[318]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[446]; + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[574]; + + sbr_qmf_64_640_qmf[320] = p_64_640_qmf[63]; + sbr_qmf_64_640_qmf[321] = p_64_640_qmf[191]; + sbr_qmf_64_640_qmf[322] = p_64_640_qmf[319]; + sbr_qmf_64_640_qmf[323] = p_64_640_qmf[447]; + sbr_qmf_64_640_qmf[324] = p_64_640_qmf[575]; + + sbr_qmf_64_640_qmf[319] = p_64_640_qmf[64]; + sbr_qmf_64_640_qmf[318] = p_64_640_qmf[192]; + sbr_qmf_64_640_qmf[317] = p_64_640_qmf[320]; + sbr_qmf_64_640_qmf[316] = p_64_640_qmf[448]; + sbr_qmf_64_640_qmf[315] = p_64_640_qmf[576]; + + sbr_qmf_64_640_qmf[314] = p_64_640_qmf[65]; + sbr_qmf_64_640_qmf[313] = p_64_640_qmf[193]; + sbr_qmf_64_640_qmf[312] = p_64_640_qmf[321]; + sbr_qmf_64_640_qmf[311] = p_64_640_qmf[449]; + sbr_qmf_64_640_qmf[310] = p_64_640_qmf[577]; + . + . + . + sbr_qmf_64[9] = p_64_640_qmf[126] + sbr_qmf_64[8] = p_64_640_qmf[254]; + sbr_qmf_64[7] = p_64_640_qmf[382]; + sbr_qmf_64[6] = p_64_640_qmf[510]; + sbr_qmf_64[5] = p_64_640_qmf[638]; + + sbr_qmf_64[4] = p_64_640_qmf[127] + sbr_qmf_64[3] = p_64_640_qmf[255]; + sbr_qmf_64[2] = p_64_640_qmf[383]; + sbr_qmf_64[1] = p_64_640_qmf[511]; + sbr_qmf_64[0] = p_64_640_qmf[639]; + + Max sum of all FIR filter absolute coefficients is: 0x7FF5B201 + thus, the filter output is not required to be scaled. + + \showinitializer +*/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt120[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffefcdb5), QFC(0x02828e13), QFC(0x35eecfd1), + QFC(0xd94e53e3), QFC(0xfefdfe42), QFC(0xffec30b0), QFC(0x036b8e20), + QFC(0x3daa7c5c), QFC(0xe08b3fa6), QFC(0xff8f33fc), QFC(0xffe88ba8), + QFC(0x04694101), QFC(0x4547daeb), QFC(0xe75f8bb7), QFC(0x0000e790), + QFC(0xffe69150), QFC(0x057341bc), QFC(0x4c9ef50f), QFC(0xedb0fdbd), + QFC(0x00549c76), QFC(0xffe6db43), QFC(0x067ef951), QFC(0x5389d1bb), + QFC(0xf36dbfe6), QFC(0x008cbe92), QFC(0xffea353a), QFC(0x077fedb3), + QFC(0x59e2f69e), QFC(0xf887507c), QFC(0x00acbd2f), QFC(0xfff176e1), + QFC(0x086685a4), QFC(0x5f845914), QFC(0xfcf2b6c8), QFC(0x00b881db), + QFC(0xfffd1253), QFC(0x09233c49), QFC(0x64504658), QFC(0x00adb69e), + QFC(0x00b4790a), QFC(0x000d31b5), QFC(0x09a3e163), QFC(0x682b39a4), + QFC(0x03b8f8dc), QFC(0x00a520bb), QFC(0x0021e26b), QFC(0x09d536b4), + QFC(0x6afb0c80), QFC(0x06186566), QFC(0x008db1f0), QFC(0x003a81c0), + QFC(0x09a505f2), QFC(0x6cb28145), QFC(0x07d6e67c), QFC(0x00728512), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt200[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffefd5d9), QFC(0x022c39a4), QFC(0x32d6e6f6), + QFC(0xd652421f), QFC(0xfebafd64), QFC(0xffef3d2e), QFC(0x02af2a39), + QFC(0x377b44a6), QFC(0xdac7ff47), QFC(0xff1d9e1f), QFC(0xffed03e9), + QFC(0x033b07ff), QFC(0x3c1fc4e4), QFC(0xdf2029d5), QFC(0xff74a37e), + QFC(0xffeab7cc), QFC(0x03cf3ade), QFC(0x40bc12f6), QFC(0xe3546cf8), + QFC(0xffc070af), QFC(0xffe88ba8), QFC(0x04694101), QFC(0x4547daeb), + QFC(0xe75f8bb7), QFC(0x0000e790), QFC(0xffe7546d), QFC(0x050826e6), + QFC(0x49ba0a48), QFC(0xeb3ac63a), QFC(0x0036aa5d), QFC(0xffe6665c), + QFC(0x05a92d73), QFC(0x4e0b0602), QFC(0xeee323fd), QFC(0x0061fdf9), + QFC(0xffe6858d), QFC(0x0649e26b), QFC(0x523225cf), QFC(0xf2549ca7), + QFC(0x00838276), QFC(0xffe7e0bd), QFC(0x06e7cba4), QFC(0x5627597c), + QFC(0xf58c23ae), QFC(0x009c49df), QFC(0xffea353a), QFC(0x077fedb3), + QFC(0x59e2f69e), QFC(0xf887507c), QFC(0x00acbd2f), QFC(0xffee0a64), + QFC(0x080e83ac), QFC(0x5d5bac5e), QFC(0xfb432a8a), QFC(0x00b5e294), + QFC(0xfff35c0f), QFC(0x08905893), QFC(0x608bf7c1), QFC(0xfdbfe2d8), + QFC(0x00b8dcd6), QFC(0xfffa67ed), QFC(0x0901a70f), QFC(0x636d2657), + QFC(0xfffccdc7), QFC(0x00b66387), QFC(0x0002f512), QFC(0x095eb98e), + QFC(0x65f9595d), QFC(0x01fa380f), QFC(0x00afb0f3), QFC(0x000d31b5), + QFC(0x09a3e163), QFC(0x682b39a4), QFC(0x03b8f8dc), QFC(0x00a520bb), + QFC(0x00193141), QFC(0x09cc1a7d), QFC(0x69fbfee3), QFC(0x05395430), + QFC(0x0097ce05), QFC(0x00269ad4), QFC(0x09d3fe14), QFC(0x6b69bfaf), + QFC(0x067e12f2), QFC(0x00889924), QFC(0x003567de), QFC(0x09b75cca), + QFC(0x6c716eb9), QFC(0x0789e850), QFC(0x00781556), QFC(0x0045436a), + QFC(0x097277a9), QFC(0x6d110fe4), QFC(0x085f29c6), QFC(0x00670cb6), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos40[] = { + QTC(0x7fef5260), QTC(0x7f69ff76), QTC(0x7e5fe493), QTC(0x7cd21707), + QTC(0x7ac23561), QTC(0x783265c0), QTC(0x75255392), QTC(0x719e2cd2), + QTC(0x6da09eb1), QTC(0x6930d1c4), QTC(0x645365b2), QTC(0x5f0d6c5b), + QTC(0x59646498), QTC(0x535e3479), QTC(0x4d012324), QTC(0x4653d24b), + QTC(0x3f5d373e), QTC(0x382493b0), QTC(0x30b16e23), QTC(0x290b8a12), + QTC(0x213adfda), QTC(0x1947946c), QTC(0x1139f0cf), QTC(0x091a597e), + QTC(0x00f145ab), QTC(0xf8c73668), QTC(0xf0a4adcf), QTC(0xe8922622), + QTC(0xe09808f5), QTC(0xd8bea66a), QTC(0xd10e2c89), QTC(0xc98e9eb5), + QTC(0xc247cd5a), QTC(0xbb414dc0), QTC(0xb4827228), QTC(0xae12422c), + QTC(0xa7f7736a), QTC(0xa2386284), QTC(0x9cdb0c83), QTC(0x97e50896), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin40[] = { + QTC(0x0415583b), QTC(0x0c3bc74f), QTC(0x145576b1), QTC(0x1c59f557), + QTC(0x2440e84d), QTC(0x2c021369), QTC(0x339561e1), QTC(0x3af2eeb7), + QTC(0x42130cf0), QTC(0x48ee4f98), QTC(0x4f7d917c), QTC(0x55b9fc9e), + QTC(0x5b9d1154), QTC(0x6120ad0d), QTC(0x663f10b7), QTC(0x6af2e6bc), + QTC(0x6f374891), QTC(0x7307c3d0), QTC(0x76605edb), QTC(0x793d9d03), + QTC(0x7b9c8226), QTC(0x7d7a95cf), QTC(0x7ed5e5c6), QTC(0x7fad081b), + QTC(0x7fff1c9b), QTC(0x7fcbcdbc), QTC(0x7f1350f8), QTC(0x7dd6668f), + QTC(0x7c1658c5), QTC(0x79d4fa89), QTC(0x7714a58b), QTC(0x73d837ca), + QTC(0x7023109a), QTC(0x6bf90d1d), QTC(0x675e843e), QTC(0x6258422c), + QTC(0x5ceb8355), QTC(0x571deefa), QTC(0x50f59141), QTC(0x4a78d4f0), +}; + +/* This filter is scaled (0.8*pfilt) */ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt400[] = { + QFC(0x00000000), QFC(0x015be9b1), QFC(0x24fb90f5), QFC(0xdb046f0b), + QFC(0xfea4164f), QFC(0xfff15ed6), QFC(0x018b53a8), QFC(0x26d2bd4e), + QFC(0xdcd812f9), QFC(0xfed12595), QFC(0xfff3117b), QFC(0x01bcfae9), + QFC(0x28abebf8), QFC(0xdea834e5), QFC(0xfefbfdea), QFC(0xfff32e53), + QFC(0x01f075de), QFC(0x2a86e540), QFC(0xe07383c3), QFC(0xff24936e), + QFC(0xfff29758), QFC(0x0225bb61), QFC(0x2c629d51), QFC(0xe2399905), + QFC(0xff4ae4e6), QFC(0xfff1ab73), QFC(0x025cb6d7), QFC(0x2e3e69f9), + QFC(0xe3fa13fc), QFC(0xff6eefd4), QFC(0xfff0cfed), QFC(0x0295a000), + QFC(0x30196a50), QFC(0xe5b354ab), QFC(0xff9082cb), QFC(0xffefd442), + QFC(0x02d01d61), QFC(0x31f2b6ac), QFC(0xe765dadc), QFC(0xffb0037f), + QFC(0xffeef970), QFC(0x030c2f18), QFC(0x33c9a8c5), QFC(0xe910572d), + QFC(0xffcd26f2), QFC(0xffee0f91), QFC(0x03494088), QFC(0x359ce8be), + QFC(0xeab28265), QFC(0xffe8133f), QFC(0xffed3c86), QFC(0x03876734), + QFC(0x376caf22), QFC(0xec4c6fc6), QFC(0x0000b940), QFC(0xffecb05f), + QFC(0x03c6b32b), QFC(0x3936c186), QFC(0xeddbfa4a), QFC(0x00174372), + QFC(0xffec438a), QFC(0x04068585), QFC(0x3afb3b6d), QFC(0xef62382f), + QFC(0x002bbb7e), QFC(0xffebc5c7), QFC(0x0446af4f), QFC(0x3cb9159f), + QFC(0xf0de3518), QFC(0x003e0713), QFC(0xffeb8517), QFC(0x0487578f), + QFC(0x3e6f3802), QFC(0xf24f4ffd), QFC(0x004e64c7), QFC(0xffeb8b0d), + QFC(0x04c7cd0d), QFC(0x401d78d8), QFC(0xf3b6114c), QFC(0x005ccd60), + QFC(0xffeb9e0a), QFC(0x0507e855), QFC(0x41c1b7d9), QFC(0xf5107d52), + QFC(0x0069352b), QFC(0xffec0c97), QFC(0x054789e4), QFC(0x435c76d2), + QFC(0xf6600380), QFC(0x0073ff44), QFC(0xffecb3ca), QFC(0x05863c83), + QFC(0x44ec4796), QFC(0xf7a34fbf), QFC(0x007d07e5), QFC(0xffed65ae), + QFC(0x05c3bdde), QFC(0x46702a28), QFC(0xf8da6b28), QFC(0x008444ef), + QFC(0xffee90fb), QFC(0x05fff15c), QFC(0x47e8c54c), QFC(0xfa05d9fc), + QFC(0x008a30f2), QFC(0xffefff78), QFC(0x0639db53), QFC(0x4952ab1e), + QFC(0xfb23d977), QFC(0x008e9313), QFC(0xfff1a1ea), QFC(0x067202f0), + QFC(0x4aafbd18), QFC(0xfc35bba2), QFC(0x00918210), QFC(0xfff3a45f), + QFC(0x06a741b7), QFC(0x4bfdfb06), QFC(0xfd3aee85), QFC(0x009350b6), + QFC(0xfff5e33f), QFC(0x06d9e076), QFC(0x4d3cc634), QFC(0xfe331be0), + QFC(0x0093e3de), QFC(0xfff867de), QFC(0x07090b4f), QFC(0x4e6cc1b3), + QFC(0xff1f4fd2), QFC(0x00936109), QFC(0xfffb8658), QFC(0x073485a5), + QFC(0x4f8a8512), QFC(0xfffd716c), QFC(0x0091e939), QFC(0xfffec6af), + QFC(0x075c2159), QFC(0x50986228), QFC(0x00cfb536), QFC(0x008f7f85), + QFC(0x00025da8), QFC(0x077efad8), QFC(0x5194477e), QFC(0x0194f9a6), + QFC(0x008c8d8f), QFC(0x00064e63), QFC(0x079d423f), QFC(0x527db75e), + QFC(0x024d9e1c), QFC(0x00886b36), QFC(0x000a8e2a), QFC(0x07b64de9), + QFC(0x5355c7b6), QFC(0x02fa60b0), QFC(0x00841a2f), QFC(0x000f2b4f), + QFC(0x07c95704), QFC(0x5418bd4a), QFC(0x0399eb6f), QFC(0x007eea79), + QFC(0x00142767), QFC(0x07d67b97), QFC(0x54c998b6), QFC(0x042ddcf3), + QFC(0x0079719e), QFC(0x00193ee8), QFC(0x07dd27cf), QFC(0x55662c93), + QFC(0x04b5da5c), QFC(0x007369b7), QFC(0x001ee243), QFC(0x07dccb44), + QFC(0x55ee32f2), QFC(0x0531a8c2), QFC(0x006d4750), QFC(0x002471ce), + QFC(0x07d588d9), QFC(0x566317ad), QFC(0x05a2ff7a), QFC(0x0066c7aa), + QFC(0x002ab97f), QFC(0x07c5e3d5), QFC(0x56c12561), QFC(0x0607ed0d), + QFC(0x00601112), QFC(0x0030e1af), QFC(0x07ae9698), QFC(0x570be9e8), + QFC(0x0662a78a), QFC(0x005958bb), QFC(0x00376922), QFC(0x078ec621), + QFC(0x5740d984), QFC(0x06b287d1), QFC(0x00527092), QFC(0x003e065c), + QFC(0x0765b74d), QFC(0x57607ccb), QFC(0x06f819ec), QFC(0x004b9363), + QFC(0x0044afb4), QFC(0x0734450e), QFC(0x576c3e7e), QFC(0x0734450e), + QFC(0x0044afb4), QFC(0xfea4164f), QFC(0xdb046f0b), QFC(0x24fb90f5), + QFC(0x015be9b1), QFC(0x00000000), +}; + +const FIXP_QTW qmf_phaseshift_cos16[] = { + QTC(0x7fc25596), QTC(0x7dd6668f), QTC(0x7a05eead), QTC(0x745f9dd1), + QTC(0x6cf934fc), QTC(0x63ef3290), QTC(0x59646498), QTC(0x4d8162c4), + QTC(0x4073f21d), QTC(0x326e54c7), QTC(0x23a6887f), QTC(0x145576b1), + QTC(0x04b6195d), QTC(0xf50497fb), QTC(0xe57d5fda), QTC(0xd65c3b7b), +}; +const FIXP_QTW qmf_phaseshift_sin16[] = { + QTC(0x07d95b9e), QTC(0x176dd9de), QTC(0x26a82186), QTC(0x354d9057), + QTC(0x4325c135), QTC(0x4ffb654d), QTC(0x5b9d1154), QTC(0x65ddfbd3), + QTC(0x6e96a99d), QTC(0x75a585cf), QTC(0x7aef6323), QTC(0x7e5fe493), + QTC(0x7fe9cbc0), QTC(0x7f872bf3), QTC(0x7d3980ec), QTC(0x7909a92d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt240[] = { + /* FP filter implementation */ + QFC(0x00000000), QFC(0x0121ed68), QFC(0x1ed1a380), QFC(0xe12e5c80), + QFC(0xfede1298), QFC(0xfff4b438), QFC(0x0164d8de), QFC(0x21610064), + QFC(0xe3b64ef2), QFC(0xff1ba1be), QFC(0xfff533ce), QFC(0x01ac5eb8), + QFC(0x23f48a8e), QFC(0xe63437e4), QFC(0xff53fed7), QFC(0xfff40ee0), + QFC(0x01f7edb3), QFC(0x26895855), QFC(0xe8a5bb55), QFC(0xff871d30), + QFC(0xfff2cb20), QFC(0x0247b415), QFC(0x291c52e4), QFC(0xeb077fc7), + QFC(0xffb4cd53), QFC(0xfff18a22), QFC(0x029b070e), QFC(0x2baa29ab), + QFC(0xed57da15), QFC(0xffdd4df1), QFC(0xfff05d1b), QFC(0x02f0d600), + QFC(0x2e2fe755), QFC(0xef9507d5), QFC(0x00009a60), QFC(0xffefac36), + QFC(0x0348fcbc), QFC(0x30a98c1c), QFC(0xf1bba8f2), QFC(0x001eed4c), + QFC(0xffef0b8b), QFC(0x03a22bd2), QFC(0x3314a372), QFC(0xf3cb53d5), + QFC(0x0038684e), QFC(0xffeef3e0), QFC(0x03fbd58b), QFC(0x356de4ab), + QFC(0xf5c263c0), QFC(0x004d55d0), QFC(0xffef3cd8), QFC(0x0454a637), + QFC(0x37b13672), QFC(0xf79e7feb), QFC(0x005dd461), QFC(0xfff01619), + QFC(0x04abb9c0), QFC(0x39dc5c00), QFC(0xf95f9279), QFC(0x006a5b4d), + QFC(0xfff178d2), QFC(0x04fff3cb), QFC(0x3beca455), QFC(0xfb04e050), + QFC(0x007328ca), QFC(0xfff390f0), QFC(0x054fa1dc), QFC(0x3ddd668e), + QFC(0xfc8c7550), QFC(0x00788f16), QFC(0xfff64f40), QFC(0x0599ae6b), + QFC(0x3fad90c7), QFC(0xfdf72485), QFC(0x007b013c), QFC(0xfff9abe4), + QFC(0x05dcdec0), QFC(0x415aa155), QFC(0xff44c284), QFC(0x007ad0dd), + QFC(0xfffe0c37), QFC(0x06177d87), QFC(0x42e02f00), QFC(0x0073cf14), + QFC(0x007850b2), QFC(0x000314dd), QFC(0x0647fe8b), QFC(0x443e0472), + QFC(0x0185ddb7), QFC(0x00741328), QFC(0x0008cbce), QFC(0x066d40eb), + QFC(0x45722655), QFC(0x027b5093), QFC(0x006e15d2), QFC(0x000f67a8), + QFC(0x0684f772), QFC(0x46789539), QFC(0x03537bc9), QFC(0x0066c76d), + QFC(0x001696f2), QFC(0x068e247c), QFC(0x47520855), QFC(0x04104399), + QFC(0x005e76a0), QFC(0x001e5ed7), QFC(0x06874760), QFC(0x47fd3e55), + QFC(0x04b27f90), QFC(0x0055a663), QFC(0x0027012b), QFC(0x066e03f9), + QFC(0x487700c7), QFC(0x0539eefc), QFC(0x004c58b7), QFC(0x0030042f), + QFC(0x0641b0ab), QFC(0x48c0afc7), QFC(0x05a90172), QFC(0x0042c9e7), + QFC(0x00393d16), QFC(0x0600e435), QFC(0x48da3400), QFC(0x0600e435), + QFC(0x00393d16), QFC(0xfede1298), QFC(0xe12e5c80), QFC(0x1ed1a380), + QFC(0x0121ed68), QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos24[] = { + QTC(0x7fded530), QTC(0x7ed5e5c6), QTC(0x7cc62bdf), QTC(0x79b3ece0), + QTC(0x75a585cf), QTC(0x70a35e25), QTC(0x6ab7d663), QTC(0x63ef3290), + QTC(0x5c5780d3), QTC(0x54007c51), QTC(0x4afb6c98), QTC(0x415b01ce), + QTC(0x37332dfd), QTC(0x2c98fbba), QTC(0x21a26295), QTC(0x1666198d), + QTC(0x0afb6805), QTC(0xff79f587), QTC(0xf3f998c0), QTC(0xe8922622), + QTC(0xdd5b3e7b), QTC(0xd26c1e08), QTC(0xc7db6c50), QTC(0xbdbf0d2f), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin24[] = { + QTC(0x05c1f4e7), QTC(0x1139f0cf), QTC(0x1c8e3bbe), QTC(0x27a75c95), + QTC(0x326e54c7), QTC(0x3cccd004), QTC(0x46ad5278), QTC(0x4ffb654d), + QTC(0x58a3c118), QTC(0x609475c3), QTC(0x67bd0fbd), QTC(0x6e0eba0c), + QTC(0x737c5d0b), QTC(0x77fab989), QTC(0x7b808015), QTC(0x7e06644c), + QTC(0x7f872bf3), QTC(0x7fffb9d1), QTC(0x7f6f141f), QTC(0x7dd6668f), + QTC(0x7b38ffde), QTC(0x779c4afc), QTC(0x7307c3d0), QTC(0x6d84e7b7), +}; + +/* qmf_pfilt640 is used with stride 2 instead of qmf_pfilt320[] */ + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos32[] = { + QTC(0x7fe9cbc0), QTC(0x7f3857f6), QTC(0x7dd6668f), QTC(0x7bc5e290), + QTC(0x7909a92d), QTC(0x75a585cf), QTC(0x719e2cd2), QTC(0x6cf934fc), + QTC(0x67bd0fbd), QTC(0x61f1003f), QTC(0x5b9d1154), QTC(0x54ca0a4b), + QTC(0x4d8162c4), QTC(0x45cd358f), QTC(0x3db832a6), QTC(0x354d9057), + QTC(0x2c98fbba), QTC(0x23a6887f), QTC(0x1a82a026), QTC(0x1139f0cf), + QTC(0x07d95b9e), QTC(0xfe6de2e0), QTC(0xf50497fb), QTC(0xebaa894f), + QTC(0xe26cb01b), QTC(0xd957de7a), QTC(0xd078ad9e), QTC(0xc7db6c50), + QTC(0xbf8c0de3), QTC(0xb796199b), QTC(0xb0049ab3), QTC(0xa8e21106), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin32[] = { + QTC(0x04b6195d), QTC(0x0e1bc2e4), QTC(0x176dd9de), QTC(0x209f701c), + QTC(0x29a3c485), QTC(0x326e54c7), QTC(0x3af2eeb7), QTC(0x4325c135), + QTC(0x4afb6c98), QTC(0x5269126e), QTC(0x59646498), QTC(0x5fe3b38d), + QTC(0x65ddfbd3), QTC(0x6b4af279), QTC(0x7023109a), QTC(0x745f9dd1), + QTC(0x77fab989), QTC(0x7aef6323), QTC(0x7d3980ec), QTC(0x7ed5e5c6), + QTC(0x7fc25596), QTC(0x7ffd885a), QTC(0x7f872bf3), QTC(0x7e5fe493), + QTC(0x7c894bde), QTC(0x7a05eead), QTC(0x76d94989), QTC(0x7307c3d0), + QTC(0x6e96a99d), QTC(0x698c246c), QTC(0x63ef3290), QTC(0x5dc79d7c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos_downsamp32[] = { + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), + QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), + QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), + QTC(0xf9b82684), QTC(0xed37ef91), QTC(0xe0e60685), QTC(0xd4e0cb15), + QTC(0xc945dfec), QTC(0xbe31e19b), QTC(0xb3c0200c), QTC(0xaa0a5b2e), + QTC(0xa1288376), QTC(0x99307ee0), QTC(0x9235f2ec), QTC(0x8c4a142f), + QTC(0x877b7bec), QTC(0x83d60412), QTC(0x8162aa04), QTC(0x80277872), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin_downsamp32[] = { + QTC(0x0647d97c), QTC(0x12c8106f), QTC(0x1f19f97b), QTC(0x2b1f34eb), + QTC(0x36ba2014), QTC(0x41ce1e65), QTC(0x4c3fdff4), QTC(0x55f5a4d2), + QTC(0x5ed77c8a), QTC(0x66cf8120), QTC(0x6dca0d14), QTC(0x73b5ebd1), + QTC(0x78848414), QTC(0x7c29fbee), QTC(0x7e9d55fc), QTC(0x7fd8878e), + QTC(0x7fd8878e), QTC(0x7e9d55fc), QTC(0x7c29fbee), QTC(0x78848414), + QTC(0x73b5ebd1), QTC(0x6dca0d14), QTC(0x66cf8120), QTC(0x5ed77c8a), + QTC(0x55f5a4d2), QTC(0x4c3fdff4), QTC(0x41ce1e65), QTC(0x36ba2014), + QTC(0x2b1f34eb), QTC(0x1f19f97b), QTC(0x12c8106f), QTC(0x0647d97c), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt640[] = { + QFC(0x00000000), QFC(0x01b2e41d), QFC(0x2e3a7532), QFC(0xd1c58ace), + QFC(0xfe4d1be3), QFC(0xffede50e), QFC(0x01d78bfc), QFC(0x2faa221c), + QFC(0xd3337b3d), QFC(0xfe70b8d1), QFC(0xffed978a), QFC(0x01fd3ba0), + QFC(0x311af3a4), QFC(0xd49fd55f), QFC(0xfe933dc0), QFC(0xffefc9b9), + QFC(0x02244a25), QFC(0x328cc6f0), QFC(0xd60a46e5), QFC(0xfeb48d0d), + QFC(0xfff0065d), QFC(0x024bf7a1), QFC(0x33ff670e), QFC(0xd7722f04), + QFC(0xfed4bec3), QFC(0xffeff6ca), QFC(0x0274ba43), QFC(0x3572ec70), + QFC(0xd8d7f21f), QFC(0xfef3f6ab), QFC(0xffef7b8b), QFC(0x029e35b4), + QFC(0x36e69691), QFC(0xda3b176a), QFC(0xff120d70), QFC(0xffeedfa4), + QFC(0x02c89901), QFC(0x385a49c4), QFC(0xdb9b5b12), QFC(0xff2ef725), + QFC(0xffee1650), QFC(0x02f3e48d), QFC(0x39ce0477), QFC(0xdcf898fb), + QFC(0xff4aabc8), QFC(0xffed651d), QFC(0x03201116), QFC(0x3b415115), + QFC(0xde529086), QFC(0xff6542d1), QFC(0xffecc31b), QFC(0x034d01f1), + QFC(0x3cb41219), QFC(0xdfa93ab5), QFC(0xff7ee3f1), QFC(0xffebe77b), + QFC(0x037ad438), QFC(0x3e25b17e), QFC(0xe0fc421e), QFC(0xff975c01), + QFC(0xffeb50b2), QFC(0x03a966bc), QFC(0x3f962fb8), QFC(0xe24b8f66), + QFC(0xffaea5d6), QFC(0xffea9192), QFC(0x03d8afe6), QFC(0x41058bc6), + QFC(0xe396a45d), QFC(0xffc4e365), QFC(0xffe9ca76), QFC(0x04083fec), + QFC(0x4272a385), QFC(0xe4de0cb0), QFC(0xffda17f2), QFC(0xffe940f4), + QFC(0x043889c6), QFC(0x43de620a), QFC(0xe620c476), QFC(0xffee183b), + QFC(0xffe88ba8), QFC(0x04694101), QFC(0x4547daeb), QFC(0xe75f8bb7), + QFC(0x0000e790), QFC(0xffe83a07), QFC(0x049aa82f), QFC(0x46aea856), + QFC(0xe89971b7), QFC(0x00131c75), QFC(0xffe79e16), QFC(0x04cc2fcf), + QFC(0x4812f848), QFC(0xe9cea84a), QFC(0x0023b989), QFC(0xffe7746e), + QFC(0x04fe20be), QFC(0x4973fef2), QFC(0xeafee7f1), QFC(0x0033b927), + QFC(0xffe6d466), QFC(0x05303f88), QFC(0x4ad237a2), QFC(0xec2a3f5f), + QFC(0x00426f36), QFC(0xffe6afed), QFC(0x05626209), QFC(0x4c2ca3df), + QFC(0xed50a31d), QFC(0x00504f41), QFC(0xffe65416), QFC(0x05950122), + QFC(0x4d83976d), QFC(0xee71b2fe), QFC(0x005d36df), QFC(0xffe681c6), + QFC(0x05c76fed), QFC(0x4ed62be3), QFC(0xef8d4d7b), QFC(0x006928a0), + QFC(0xffe66dd0), QFC(0x05f9c051), QFC(0x5024d70e), QFC(0xf0a3959f), + QFC(0x007400b8), QFC(0xffe66fab), QFC(0x062bf5ec), QFC(0x516eefb9), + QFC(0xf1b461ab), QFC(0x007e0393), QFC(0xffe69423), QFC(0x065dd56a), + QFC(0x52b449de), QFC(0xf2bf6ea4), QFC(0x00872c63), QFC(0xffe6fed4), + QFC(0x068f8b44), QFC(0x53f495aa), QFC(0xf3c4e887), QFC(0x008f87aa), + QFC(0xffe75361), QFC(0x06c0f0c0), QFC(0x552f8ff7), QFC(0xf4c473c5), + QFC(0x0096dcc2), QFC(0xffe80414), QFC(0x06f1825d), QFC(0x56654bdd), + QFC(0xf5be0fa9), QFC(0x009da526), QFC(0xffe85b4a), QFC(0x0721bf22), + QFC(0x579505f5), QFC(0xf6b1f3c3), QFC(0x00a3508f), QFC(0xffe954d0), + QFC(0x075112a2), QFC(0x58befacd), QFC(0xf79fa13a), QFC(0x00a85e94), + QFC(0xffea353a), QFC(0x077fedb3), QFC(0x59e2f69e), QFC(0xf887507c), + QFC(0x00acbd2f), QFC(0xffeb3849), QFC(0x07ad8c26), QFC(0x5b001db8), + QFC(0xf96916f5), QFC(0x00b06b68), QFC(0xffec8409), QFC(0x07da2b7f), + QFC(0x5c16d0ae), QFC(0xfa44a069), QFC(0x00b36acd), QFC(0xffedc418), + QFC(0x08061671), QFC(0x5d26be9b), QFC(0xfb19b7bd), QFC(0x00b58c8d), + QFC(0xffef2395), QFC(0x08303897), QFC(0x5e2f6367), QFC(0xfbe8f5bd), + QFC(0x00b73ab0), QFC(0xfff0e7ef), QFC(0x08594888), QFC(0x5f30ff5f), + QFC(0xfcb1d740), QFC(0x00b85f70), QFC(0xfff294c3), QFC(0x0880ffdd), + QFC(0x602b0c7f), QFC(0xfd7475d8), QFC(0x00b8c6b0), QFC(0xfff48700), + QFC(0x08a75da4), QFC(0x611d58a3), QFC(0xfe310657), QFC(0x00b8fe0d), + QFC(0xfff681d6), QFC(0x08cb4e23), QFC(0x6207f220), QFC(0xfee723c6), + QFC(0x00b8394b), QFC(0xfff91fc9), QFC(0x08edfeaa), QFC(0x62ea6474), + QFC(0xff96db8f), QFC(0x00b74c37), QFC(0xfffb42b0), QFC(0x090ec1fd), + QFC(0x63c45243), QFC(0x0040c497), QFC(0x00b5c867), QFC(0xfffdfa24), + QFC(0x092d7970), QFC(0x64964063), QFC(0x00e42fa2), QFC(0x00b3d15c), + QFC(0x00007134), QFC(0x0949eaac), QFC(0x655f63f2), QFC(0x01816e06), + QFC(0x00b1978d), QFC(0x00039609), QFC(0x0963ed46), QFC(0x661fd6b8), + QFC(0x02186a92), QFC(0x00af374c), QFC(0x0006b1cf), QFC(0x097c1ee9), + QFC(0x66d76725), QFC(0x02a99097), QFC(0x00abe79e), QFC(0x0009aa3f), + QFC(0x099140a7), QFC(0x6785c24d), QFC(0x03343534), QFC(0x00a8739d), + QFC(0x000d31b5), QFC(0x09a3e163), QFC(0x682b39a4), QFC(0x03b8f8dc), + QFC(0x00a520bb), QFC(0x0010bc63), QFC(0x09b3d780), QFC(0x68c7269c), + QFC(0x0437fb0a), QFC(0x00a1039c), QFC(0x001471f8), QFC(0x09c0e59f), + QFC(0x6959709d), QFC(0x04b0adcb), QFC(0x009d10bf), QFC(0x0018703f), + QFC(0x09cab9f2), QFC(0x69e29784), QFC(0x05237f9d), QFC(0x0098b855), + QFC(0x001c3549), QFC(0x09d19ca9), QFC(0x6a619c5e), QFC(0x0590a67d), + QFC(0x009424c6), QFC(0x002064f8), QFC(0x09d52709), QFC(0x6ad73e8e), + QFC(0x05f7fb90), QFC(0x008f4bfd), QFC(0x0024dd50), QFC(0x09d5560b), + QFC(0x6b42a864), QFC(0x06593912), QFC(0x008a7dd7), QFC(0x00293718), + QFC(0x09d1fa23), QFC(0x6ba4629f), QFC(0x06b559c3), QFC(0x0085c217), + QFC(0x002d8e42), QFC(0x09caeb0f), QFC(0x6bfbdd98), QFC(0x070bbf58), + QFC(0x00807994), QFC(0x00329ab6), QFC(0x09c018cf), QFC(0x6c492217), + QFC(0x075ca90c), QFC(0x007b3875), QFC(0x003745f9), QFC(0x09b18a1d), + QFC(0x6c8c4c7a), QFC(0x07a8127d), QFC(0x0075fded), QFC(0x003c1fa4), + QFC(0x099ec3dc), QFC(0x6cc59bab), QFC(0x07ee507c), QFC(0x0070c8a5), + QFC(0x004103f5), QFC(0x09881dc5), QFC(0x6cf4073e), QFC(0x082f552e), + QFC(0x006b47fa), QFC(0x00465348), QFC(0x096d0e22), QFC(0x6d18520e), + QFC(0x086b1eec), QFC(0x0065fde5), QFC(0x004b6c46), QFC(0x094d7ec2), + QFC(0x6d32730f), QFC(0x08a24899), QFC(0x006090c4), QFC(0x0050b177), + QFC(0x09299ead), QFC(0x6d41d964), QFC(0x08d3e41b), QFC(0x005b5371), + QFC(0x0055dba1), QFC(0x09015651), QFC(0x6d474e1d), QFC(0x09015651), + QFC(0x0055dba1), QFC(0xfe4d1be3), QFC(0xd1c58ace), QFC(0x2e3a7532), + QFC(0x01b2e41d), QFC(0x00000000), +}; + +/* This variant of the table above is used on platforms, that have vectorized + access to the table reading 4 filter sets (each of 5 coefficients) in a + block. Format: 1st row flt[0] of 4 sets (e.g. set 0, 1, 2, 3) 2nd row + flt[1] of 4 sets (e.g. set 0, 1, 2, 3) 3rd row flt[2] of 4 sets (e.g. set + 0, 1, 2, 3) 4th row flt[3] of 4 sets (e.g. set 0, 1, 2, 3) 5th row + flt[4] of 4 sets (e.g. set 0, 1, 2, 3) There are 32 blocks of 20 + coefficients, in total 640. Each of the rows must be at least 64-bit aligned + (see: RAM_ALIGN). +*/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_PFT qmf_pfilt640_vector[] = { + /*------------- 1 .. 4 ---------------*/ + QFC(0xFFEDE50E), + QFC(0xFFED978A), + QFC(0xFFEFC9B9), + QFC(0xFFF0065D), + QFC(0x01D78BFC), + QFC(0x01FD3BA0), + QFC(0x02244A25), + QFC(0x024BF7A1), + QFC(0x2FAA221C), + QFC(0x311AF3A4), + QFC(0x328CC6F0), + QFC(0x33FF670E), + QFC(0xD3337B3D), + QFC(0xD49FD55F), + QFC(0xD60A46E5), + QFC(0xD7722F04), + QFC(0xFE70B8D1), + QFC(0xFE933DC0), + QFC(0xFEB48D0D), + QFC(0xFED4BEC3), + /*------------- 5 .. 8 ---------------*/ + QFC(0xFFEFF6CA), + QFC(0xFFEF7B8B), + QFC(0xFFEEDFA4), + QFC(0xFFEE1650), + QFC(0x0274BA43), + QFC(0x029E35B4), + QFC(0x02C89901), + QFC(0x02F3E48D), + QFC(0x3572EC70), + QFC(0x36E69691), + QFC(0x385A49C4), + QFC(0x39CE0477), + QFC(0xD8D7F21F), + QFC(0xDA3B176A), + QFC(0xDB9B5B12), + QFC(0xDCF898FB), + QFC(0xFEF3F6AB), + QFC(0xFF120D70), + QFC(0xFF2EF725), + QFC(0xFF4AABC8), + /*------------- 9 .. 12 ---------------*/ + QFC(0xFFED651D), + QFC(0xFFECC31B), + QFC(0xFFEBE77B), + QFC(0xFFEB50B2), + QFC(0x03201116), + QFC(0x034D01F1), + QFC(0x037AD438), + QFC(0x03A966BC), + QFC(0x3B415115), + QFC(0x3CB41219), + QFC(0x3E25B17E), + QFC(0x3F962FB8), + QFC(0xDE529086), + QFC(0xDFA93AB5), + QFC(0xE0FC421E), + QFC(0xE24B8F66), + QFC(0xFF6542D1), + QFC(0xFF7EE3F1), + QFC(0xFF975C01), + QFC(0xFFAEA5D6), + /*------------- 13 .. 16 ---------------*/ + QFC(0xFFEA9192), + QFC(0xFFE9CA76), + QFC(0xFFE940F4), + QFC(0xFFE88BA8), + QFC(0x03D8AFE6), + QFC(0x04083FEC), + QFC(0x043889C6), + QFC(0x04694101), + QFC(0x41058BC6), + QFC(0x4272A385), + QFC(0x43DE620A), + QFC(0x4547DAEB), + QFC(0xE396A45D), + QFC(0xE4DE0CB0), + QFC(0xE620C476), + QFC(0xE75F8BB7), + QFC(0xFFC4E365), + QFC(0xFFDA17F2), + QFC(0xFFEE183B), + QFC(0x0000E790), + /*------------- 17 .. 20 ---------------*/ + QFC(0xFFE83A07), + QFC(0xFFE79E16), + QFC(0xFFE7746E), + QFC(0xFFE6D466), + QFC(0x049AA82F), + QFC(0x04CC2FCF), + QFC(0x04FE20BE), + QFC(0x05303F88), + QFC(0x46AEA856), + QFC(0x4812F848), + QFC(0x4973FEF2), + QFC(0x4AD237A2), + QFC(0xE89971B7), + QFC(0xE9CEA84A), + QFC(0xEAFEE7F1), + QFC(0xEC2A3F5F), + QFC(0x00131C75), + QFC(0x0023B989), + QFC(0x0033B927), + QFC(0x00426F36), + /*------------- 21 .. 24 ---------------*/ + QFC(0xFFE6AFED), + QFC(0xFFE65416), + QFC(0xFFE681C6), + QFC(0xFFE66DD0), + QFC(0x05626209), + QFC(0x05950122), + QFC(0x05C76FED), + QFC(0x05F9C051), + QFC(0x4C2CA3DF), + QFC(0x4D83976D), + QFC(0x4ED62BE3), + QFC(0x5024D70E), + QFC(0xED50A31D), + QFC(0xEE71B2FE), + QFC(0xEF8D4D7B), + QFC(0xF0A3959F), + QFC(0x00504F41), + QFC(0x005D36DF), + QFC(0x006928A0), + QFC(0x007400B8), + /*------------- 25 .. 28 ---------------*/ + QFC(0xFFE66FAB), + QFC(0xFFE69423), + QFC(0xFFE6FED4), + QFC(0xFFE75361), + QFC(0x062BF5EC), + QFC(0x065DD56A), + QFC(0x068F8B44), + QFC(0x06C0F0C0), + QFC(0x516EEFB9), + QFC(0x52B449DE), + QFC(0x53F495AA), + QFC(0x552F8FF7), + QFC(0xF1B461AB), + QFC(0xF2BF6EA4), + QFC(0xF3C4E887), + QFC(0xF4C473C5), + QFC(0x007E0393), + QFC(0x00872C63), + QFC(0x008F87AA), + QFC(0x0096DCC2), + /*------------- 29 .. 32 ---------------*/ + QFC(0xFFE80414), + QFC(0xFFE85B4A), + QFC(0xFFE954D0), + QFC(0xFFEA353A), + QFC(0x06F1825D), + QFC(0x0721BF22), + QFC(0x075112A2), + QFC(0x077FEDB3), + QFC(0x56654BDD), + QFC(0x579505F5), + QFC(0x58BEFACD), + QFC(0x59E2F69E), + QFC(0xF5BE0FA9), + QFC(0xF6B1F3C3), + QFC(0xF79FA13A), + QFC(0xF887507C), + QFC(0x009DA526), + QFC(0x00A3508F), + QFC(0x00A85E94), + QFC(0x00ACBD2F), + /*------------- 33 .. 36 ---------------*/ + QFC(0xFFEB3849), + QFC(0xFFEC8409), + QFC(0xFFEDC418), + QFC(0xFFEF2395), + QFC(0x07AD8C26), + QFC(0x07DA2B7F), + QFC(0x08061671), + QFC(0x08303897), + QFC(0x5B001DB8), + QFC(0x5C16D0AE), + QFC(0x5D26BE9B), + QFC(0x5E2F6367), + QFC(0xF96916F5), + QFC(0xFA44A069), + QFC(0xFB19B7BD), + QFC(0xFBE8F5BD), + QFC(0x00B06B68), + QFC(0x00B36ACD), + QFC(0x00B58C8D), + QFC(0x00B73AB0), + /*------------- 37 .. 40 ---------------*/ + QFC(0xFFF0E7EF), + QFC(0xFFF294C3), + QFC(0xFFF48700), + QFC(0xFFF681D6), + QFC(0x08594888), + QFC(0x0880FFDD), + QFC(0x08A75DA4), + QFC(0x08CB4E23), + QFC(0x5F30FF5F), + QFC(0x602B0C7F), + QFC(0x611D58A3), + QFC(0x6207F220), + QFC(0xFCB1D740), + QFC(0xFD7475D8), + QFC(0xFE310657), + QFC(0xFEE723C6), + QFC(0x00B85F70), + QFC(0x00B8C6B0), + QFC(0x00B8FE0D), + QFC(0x00B8394B), + /*------------- 41 .. 44 ---------------*/ + QFC(0xFFF91FC9), + QFC(0xFFFB42B0), + QFC(0xFFFDFA24), + QFC(0x00007134), + QFC(0x08EDFEAA), + QFC(0x090EC1FD), + QFC(0x092D7970), + QFC(0x0949EAAC), + QFC(0x62EA6474), + QFC(0x63C45243), + QFC(0x64964063), + QFC(0x655F63F2), + QFC(0xFF96DB8F), + QFC(0x0040C497), + QFC(0x00E42FA2), + QFC(0x01816E06), + QFC(0x00B74C37), + QFC(0x00B5C867), + QFC(0x00B3D15C), + QFC(0x00B1978D), + /*------------- 45 .. 48 ---------------*/ + QFC(0x00039609), + QFC(0x0006B1CF), + QFC(0x0009AA3F), + QFC(0x000D31B5), + QFC(0x0963ED46), + QFC(0x097C1EE9), + QFC(0x099140A7), + QFC(0x09A3E163), + QFC(0x661FD6B8), + QFC(0x66D76725), + QFC(0x6785C24D), + QFC(0x682B39A4), + QFC(0x02186A92), + QFC(0x02A99097), + QFC(0x03343534), + QFC(0x03B8F8DC), + QFC(0x00AF374C), + QFC(0x00ABE79E), + QFC(0x00A8739D), + QFC(0x00A520BB), + /*------------- 49 .. 52 ---------------*/ + QFC(0x0010BC63), + QFC(0x001471F8), + QFC(0x0018703F), + QFC(0x001C3549), + QFC(0x09B3D780), + QFC(0x09C0E59F), + QFC(0x09CAB9F2), + QFC(0x09D19CA9), + QFC(0x68C7269C), + QFC(0x6959709D), + QFC(0x69E29784), + QFC(0x6A619C5E), + QFC(0x0437FB0A), + QFC(0x04B0ADCB), + QFC(0x05237F9D), + QFC(0x0590A67D), + QFC(0x00A1039C), + QFC(0x009D10BF), + QFC(0x0098B855), + QFC(0x009424C6), + /*------------- 53 .. 56 ---------------*/ + QFC(0x002064F8), + QFC(0x0024DD50), + QFC(0x00293718), + QFC(0x002D8E42), + QFC(0x09D52709), + QFC(0x09D5560B), + QFC(0x09D1FA23), + QFC(0x09CAEB0F), + QFC(0x6AD73E8E), + QFC(0x6B42A864), + QFC(0x6BA4629F), + QFC(0x6BFBDD98), + QFC(0x05F7FB90), + QFC(0x06593912), + QFC(0x06B559C3), + QFC(0x070BBF58), + QFC(0x008F4BFD), + QFC(0x008A7DD7), + QFC(0x0085C217), + QFC(0x00807994), + /*------------- 57 .. 60 ---------------*/ + QFC(0x00329AB6), + QFC(0x003745F9), + QFC(0x003C1FA4), + QFC(0x004103F5), + QFC(0x09C018CF), + QFC(0x09B18A1D), + QFC(0x099EC3DC), + QFC(0x09881DC5), + QFC(0x6C492217), + QFC(0x6C8C4C7A), + QFC(0x6CC59BAB), + QFC(0x6CF4073E), + QFC(0x075CA90C), + QFC(0x07A8127D), + QFC(0x07EE507C), + QFC(0x082F552E), + QFC(0x007B3875), + QFC(0x0075FDED), + QFC(0x0070C8A5), + QFC(0x006B47FA), + /*------------- 61 .. 64 ---------------*/ + QFC(0x00465348), + QFC(0x004B6C46), + QFC(0x0050B177), + QFC(0x0055DBA1), + QFC(0x096D0E22), + QFC(0x094D7EC2), + QFC(0x09299EAD), + QFC(0x09015651), + QFC(0x6D18520E), + QFC(0x6D32730F), + QFC(0x6D41D964), + QFC(0x6D474E1D), + QFC(0x086B1EEC), + QFC(0x08A24899), + QFC(0x08D3E41B), + QFC(0x09015651), + QFC(0x0065FDE5), + QFC(0x006090C4), + QFC(0x005B5371), + QFC(0x0055DBA1), + /*------------- 63 .. 60 ---------------*/ + QFC(0x005B5371), + QFC(0x006090C4), + QFC(0x0065FDE5), + QFC(0x006B47FA), + QFC(0x08D3E41B), + QFC(0x08A24899), + QFC(0x086B1EEC), + QFC(0x082F552E), + QFC(0x6D41D964), + QFC(0x6D32730F), + QFC(0x6D18520E), + QFC(0x6CF4073E), + QFC(0x09299EAD), + QFC(0x094D7EC2), + QFC(0x096D0E22), + QFC(0x09881DC5), + QFC(0x0050B177), + QFC(0x004B6C46), + QFC(0x00465348), + QFC(0x004103F5), + /*------------- 59 .. 56 ---------------*/ + QFC(0x0070C8A5), + QFC(0x0075FDED), + QFC(0x007B3875), + QFC(0x00807994), + QFC(0x07EE507C), + QFC(0x07A8127D), + QFC(0x075CA90C), + QFC(0x070BBF58), + QFC(0x6CC59BAB), + QFC(0x6C8C4C7A), + QFC(0x6C492217), + QFC(0x6BFBDD98), + QFC(0x099EC3DC), + QFC(0x09B18A1D), + QFC(0x09C018CF), + QFC(0x09CAEB0F), + QFC(0x003C1FA4), + QFC(0x003745F9), + QFC(0x00329AB6), + QFC(0x002D8E42), + /*------------- 55 .. 52 ---------------*/ + QFC(0x0085C217), + QFC(0x008A7DD7), + QFC(0x008F4BFD), + QFC(0x009424C6), + QFC(0x06B559C3), + QFC(0x06593912), + QFC(0x05F7FB90), + QFC(0x0590A67D), + QFC(0x6BA4629F), + QFC(0x6B42A864), + QFC(0x6AD73E8E), + QFC(0x6A619C5E), + QFC(0x09D1FA23), + QFC(0x09D5560B), + QFC(0x09D52709), + QFC(0x09D19CA9), + QFC(0x00293718), + QFC(0x0024DD50), + QFC(0x002064F8), + QFC(0x001C3549), + /*------------- 51 .. 48 ---------------*/ + QFC(0x0098B855), + QFC(0x009D10BF), + QFC(0x00A1039C), + QFC(0x00A520BB), + QFC(0x05237F9D), + QFC(0x04B0ADCB), + QFC(0x0437FB0A), + QFC(0x03B8F8DC), + QFC(0x69E29784), + QFC(0x6959709D), + QFC(0x68C7269C), + QFC(0x682B39A4), + QFC(0x09CAB9F2), + QFC(0x09C0E59F), + QFC(0x09B3D780), + QFC(0x09A3E163), + QFC(0x0018703F), + QFC(0x001471F8), + QFC(0x0010BC63), + QFC(0x000D31B5), + /*------------- 47 .. 44 ---------------*/ + QFC(0x00A8739D), + QFC(0x00ABE79E), + QFC(0x00AF374C), + QFC(0x00B1978D), + QFC(0x03343534), + QFC(0x02A99097), + QFC(0x02186A92), + QFC(0x01816E06), + QFC(0x6785C24D), + QFC(0x66D76725), + QFC(0x661FD6B8), + QFC(0x655F63F2), + QFC(0x099140A7), + QFC(0x097C1EE9), + QFC(0x0963ED46), + QFC(0x0949EAAC), + QFC(0x0009AA3F), + QFC(0x0006B1CF), + QFC(0x00039609), + QFC(0x00007134), + /*------------- 43 .. 40 ---------------*/ + QFC(0x00B3D15C), + QFC(0x00B5C867), + QFC(0x00B74C37), + QFC(0x00B8394B), + QFC(0x00E42FA2), + QFC(0x0040C497), + QFC(0xFF96DB8F), + QFC(0xFEE723C6), + QFC(0x64964063), + QFC(0x63C45243), + QFC(0x62EA6474), + QFC(0x6207F220), + QFC(0x092D7970), + QFC(0x090EC1FD), + QFC(0x08EDFEAA), + QFC(0x08CB4E23), + QFC(0xFFFDFA24), + QFC(0xFFFB42B0), + QFC(0xFFF91FC9), + QFC(0xFFF681D6), + /*------------- 39 .. 36 ---------------*/ + QFC(0x00B8FE0D), + QFC(0x00B8C6B0), + QFC(0x00B85F70), + QFC(0x00B73AB0), + QFC(0xFE310657), + QFC(0xFD7475D8), + QFC(0xFCB1D740), + QFC(0xFBE8F5BD), + QFC(0x611D58A3), + QFC(0x602B0C7F), + QFC(0x5F30FF5F), + QFC(0x5E2F6367), + QFC(0x08A75DA4), + QFC(0x0880FFDD), + QFC(0x08594888), + QFC(0x08303897), + QFC(0xFFF48700), + QFC(0xFFF294C3), + QFC(0xFFF0E7EF), + QFC(0xFFEF2395), + /*------------- 35 .. 32 ---------------*/ + QFC(0x00B58C8D), + QFC(0x00B36ACD), + QFC(0x00B06B68), + QFC(0x00ACBD2F), + QFC(0xFB19B7BD), + QFC(0xFA44A069), + QFC(0xF96916F5), + QFC(0xF887507C), + QFC(0x5D26BE9B), + QFC(0x5C16D0AE), + QFC(0x5B001DB8), + QFC(0x59E2F69E), + QFC(0x08061671), + QFC(0x07DA2B7F), + QFC(0x07AD8C26), + QFC(0x077FEDB3), + QFC(0xFFEDC418), + QFC(0xFFEC8409), + QFC(0xFFEB3849), + QFC(0xFFEA353A), + /*------------- 31 .. 28 ---------------*/ + QFC(0x00A85E94), + QFC(0x00A3508F), + QFC(0x009DA526), + QFC(0x0096DCC2), + QFC(0xF79FA13A), + QFC(0xF6B1F3C3), + QFC(0xF5BE0FA9), + QFC(0xF4C473C5), + QFC(0x58BEFACD), + QFC(0x579505F5), + QFC(0x56654BDD), + QFC(0x552F8FF7), + QFC(0x075112A2), + QFC(0x0721BF22), + QFC(0x06F1825D), + QFC(0x06C0F0C0), + QFC(0xFFE954D0), + QFC(0xFFE85B4A), + QFC(0xFFE80414), + QFC(0xFFE75361), + /*------------- 27 .. 24 ---------------*/ + QFC(0x008F87AA), + QFC(0x00872C63), + QFC(0x007E0393), + QFC(0x007400B8), + QFC(0xF3C4E887), + QFC(0xF2BF6EA4), + QFC(0xF1B461AB), + QFC(0xF0A3959F), + QFC(0x53F495AA), + QFC(0x52B449DE), + QFC(0x516EEFB9), + QFC(0x5024D70E), + QFC(0x068F8B44), + QFC(0x065DD56A), + QFC(0x062BF5EC), + QFC(0x05F9C051), + QFC(0xFFE6FED4), + QFC(0xFFE69423), + QFC(0xFFE66FAB), + QFC(0xFFE66DD0), + /*------------- 23 .. 20 ---------------*/ + QFC(0x006928A0), + QFC(0x005D36DF), + QFC(0x00504F41), + QFC(0x00426F36), + QFC(0xEF8D4D7B), + QFC(0xEE71B2FE), + QFC(0xED50A31D), + QFC(0xEC2A3F5F), + QFC(0x4ED62BE3), + QFC(0x4D83976D), + QFC(0x4C2CA3DF), + QFC(0x4AD237A2), + QFC(0x05C76FED), + QFC(0x05950122), + QFC(0x05626209), + QFC(0x05303F88), + QFC(0xFFE681C6), + QFC(0xFFE65416), + QFC(0xFFE6AFED), + QFC(0xFFE6D466), + /*------------- 19 .. 16 ---------------*/ + QFC(0x0033B927), + QFC(0x0023B989), + QFC(0x00131C75), + QFC(0x0000E790), + QFC(0xEAFEE7F1), + QFC(0xE9CEA84A), + QFC(0xE89971B7), + QFC(0xE75F8BB7), + QFC(0x4973FEF2), + QFC(0x4812F848), + QFC(0x46AEA856), + QFC(0x4547DAEB), + QFC(0x04FE20BE), + QFC(0x04CC2FCF), + QFC(0x049AA82F), + QFC(0x04694101), + QFC(0xFFE7746E), + QFC(0xFFE79E16), + QFC(0xFFE83A07), + QFC(0xFFE88BA8), + /*------------- 15 .. 12 ---------------*/ + QFC(0xFFEE183B), + QFC(0xFFDA17F2), + QFC(0xFFC4E365), + QFC(0xFFAEA5D6), + QFC(0xE620C476), + QFC(0xE4DE0CB0), + QFC(0xE396A45D), + QFC(0xE24B8F66), + QFC(0x43DE620A), + QFC(0x4272A385), + QFC(0x41058BC6), + QFC(0x3F962FB8), + QFC(0x043889C6), + QFC(0x04083FEC), + QFC(0x03D8AFE6), + QFC(0x03A966BC), + QFC(0xFFE940F4), + QFC(0xFFE9CA76), + QFC(0xFFEA9192), + QFC(0xFFEB50B2), + /*------------- 11 .. 8 ---------------*/ + QFC(0xFF975C01), + QFC(0xFF7EE3F1), + QFC(0xFF6542D1), + QFC(0xFF4AABC8), + QFC(0xE0FC421E), + QFC(0xDFA93AB5), + QFC(0xDE529086), + QFC(0xDCF898FB), + QFC(0x3E25B17E), + QFC(0x3CB41219), + QFC(0x3B415115), + QFC(0x39CE0477), + QFC(0x037AD438), + QFC(0x034D01F1), + QFC(0x03201116), + QFC(0x02F3E48D), + QFC(0xFFEBE77B), + QFC(0xFFECC31B), + QFC(0xFFED651D), + QFC(0xFFEE1650), + /*------------- 7 .. 4 ---------------*/ + QFC(0xFF2EF725), + QFC(0xFF120D70), + QFC(0xFEF3F6AB), + QFC(0xFED4BEC3), + QFC(0xDB9B5B12), + QFC(0xDA3B176A), + QFC(0xD8D7F21F), + QFC(0xD7722F04), + QFC(0x385A49C4), + QFC(0x36E69691), + QFC(0x3572EC70), + QFC(0x33FF670E), + QFC(0x02C89901), + QFC(0x029E35B4), + QFC(0x0274BA43), + QFC(0x024BF7A1), + QFC(0xFFEEDFA4), + QFC(0xFFEF7B8B), + QFC(0xFFEFF6CA), + QFC(0xFFF0065D), + /*------------- 3 .. 0 ---------------*/ + QFC(0xFEB48D0D), + QFC(0xFE933DC0), + QFC(0xFE70B8D1), + QFC(0xFE4D1BE3), + QFC(0xD60A46E5), + QFC(0xD49FD55F), + QFC(0xD3337B3D), + QFC(0xD1C58ACE), + QFC(0x328CC6F0), + QFC(0x311AF3A4), + QFC(0x2FAA221C), + QFC(0x2E3A7532), + QFC(0x02244A25), + QFC(0x01FD3BA0), + QFC(0x01D78BFC), + QFC(0x01B2E41D), + QFC(0xFFEFC9B9), + QFC(0xFFED978A), + QFC(0xFFEDE50E), + QFC(0x00000000), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_cos64[] = { + QTC(0x7ff62182), QTC(0x7fa736b4), QTC(0x7f0991c4), QTC(0x7e1d93ea), + QTC(0x7ce3ceb2), QTC(0x7b5d039e), QTC(0x798a23b1), QTC(0x776c4edb), + QTC(0x7504d345), QTC(0x72552c85), QTC(0x6f5f02b2), QTC(0x6c242960), + QTC(0x68a69e81), QTC(0x64e88926), QTC(0x60ec3830), QTC(0x5cb420e0), + QTC(0x5842dd54), QTC(0x539b2af0), QTC(0x4ebfe8a5), QTC(0x49b41533), + QTC(0x447acd50), QTC(0x3f1749b8), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), + QTC(0x15e21445), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf), + QTC(0xfcdbd541), QTC(0xf6956fb7), QTC(0xf054d8d5), QTC(0xea1debbb), + QTC(0xe3f47d96), QTC(0xdddc5b3b), QTC(0xd7d946d8), QTC(0xd1eef59e), + QTC(0xcc210d79), QTC(0xc67322ce), QTC(0xc0e8b648), QTC(0xbb8532b0), + QTC(0xb64beacd), QTC(0xb140175b), QTC(0xac64d510), QTC(0xa7bd22ac), + QTC(0xa34bdf20), QTC(0x9f13c7d0), QTC(0x9b1776da), QTC(0x9759617f), + QTC(0x93dbd6a0), QTC(0x90a0fd4e), QTC(0x8daad37b), QTC(0x8afb2cbb), + QTC(0x8893b125), QTC(0x8675dc4f), QTC(0x84a2fc62), QTC(0x831c314e), + QTC(0x81e26c16), QTC(0x80f66e3c), QTC(0x8058c94c), QTC(0x8009de7e), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +const FIXP_QTW qmf_phaseshift_sin64[] = { + QTC(0x03242abf), QTC(0x096a9049), QTC(0x0fab272b), QTC(0x15e21445), + QTC(0x1c0b826a), QTC(0x2223a4c5), QTC(0x2826b928), QTC(0x2e110a62), + QTC(0x33def287), QTC(0x398cdd32), QTC(0x3f1749b8), QTC(0x447acd50), + QTC(0x49b41533), QTC(0x4ebfe8a5), QTC(0x539b2af0), QTC(0x5842dd54), + QTC(0x5cb420e0), QTC(0x60ec3830), QTC(0x64e88926), QTC(0x68a69e81), + QTC(0x6c242960), QTC(0x6f5f02b2), QTC(0x72552c85), QTC(0x7504d345), + QTC(0x776c4edb), QTC(0x798a23b1), QTC(0x7b5d039e), QTC(0x7ce3ceb2), + QTC(0x7e1d93ea), QTC(0x7f0991c4), QTC(0x7fa736b4), QTC(0x7ff62182), + QTC(0x7ff62182), QTC(0x7fa736b4), QTC(0x7f0991c4), QTC(0x7e1d93ea), + QTC(0x7ce3ceb2), QTC(0x7b5d039e), QTC(0x798a23b1), QTC(0x776c4edb), + QTC(0x7504d345), QTC(0x72552c85), QTC(0x6f5f02b2), QTC(0x6c242960), + QTC(0x68a69e81), QTC(0x64e88926), QTC(0x60ec3830), QTC(0x5cb420e0), + QTC(0x5842dd54), QTC(0x539b2af0), QTC(0x4ebfe8a5), QTC(0x49b41533), + QTC(0x447acd50), QTC(0x3f1749b8), QTC(0x398cdd32), QTC(0x33def287), + QTC(0x2e110a62), QTC(0x2826b928), QTC(0x2223a4c5), QTC(0x1c0b826a), + QTC(0x15e21445), QTC(0x0fab272b), QTC(0x096a9049), QTC(0x03242abf), +}; + +/* + * Low Delay QMF aka CLDFB + */ + +#if defined(QMF_COEFF_16BIT) +#define QTCFLLD(x) FL2FXCONST_SGL(x / (float)(1 << QMF_CLDFB_PFT_SCALE)) +#define QTCFLLDT(x) FL2FXCONST_SGL(x) +#else +#define QTCFLLD(x) FL2FXCONST_DBL(x / (float)(1 << QMF_CLDFB_PFT_SCALE)) +#define QTCFLLDT(x) FL2FXCONST_DBL(x) +#endif + +#ifndef LOW_POWER_SBR_ONLY +/*! + \name QMF-Twiddle + \brief QMF twiddle factors + + L=32, gain=2.0, angle = 0.75 +*/ +/* sin/cos (angle) / 2 */ +const FIXP_QTW qmf_phaseshift_cos32_cldfb_ana[32] = { + /* analysis twiddle table */ + QTCFLLDT(-7.071067e-01), QTCFLLDT(7.071070e-01), QTCFLLDT(7.071064e-01), + QTCFLLDT(-7.071073e-01), QTCFLLDT(-7.071061e-01), QTCFLLDT(7.071076e-01), + QTCFLLDT(7.071058e-01), QTCFLLDT(-7.071080e-01), QTCFLLDT(-7.071055e-01), + QTCFLLDT(7.071083e-01), QTCFLLDT(7.071052e-01), QTCFLLDT(-7.071086e-01), + QTCFLLDT(-7.071049e-01), QTCFLLDT(7.071089e-01), QTCFLLDT(7.071046e-01), + QTCFLLDT(-7.071092e-01), QTCFLLDT(-7.071042e-01), QTCFLLDT(7.071095e-01), + QTCFLLDT(7.071039e-01), QTCFLLDT(-7.071098e-01), QTCFLLDT(-7.071036e-01), + QTCFLLDT(7.071101e-01), QTCFLLDT(7.071033e-01), QTCFLLDT(-7.071104e-01), + QTCFLLDT(-7.071030e-01), QTCFLLDT(7.071107e-01), QTCFLLDT(7.071027e-01), + QTCFLLDT(-7.071111e-01), QTCFLLDT(-7.071024e-01), QTCFLLDT(7.071114e-01), + QTCFLLDT(7.071021e-01), QTCFLLDT(-7.071117e-01), +}; + +const FIXP_QTW qmf_phaseshift_cos32_cldfb_syn[32] = { + /* synthesis twiddle table */ + QTCFLLDT(7.071067e-01), QTCFLLDT(-7.071070e-01), QTCFLLDT(-7.071064e-01), + QTCFLLDT(7.071073e-01), QTCFLLDT(7.071061e-01), QTCFLLDT(-7.071076e-01), + QTCFLLDT(-7.071058e-01), QTCFLLDT(7.071080e-01), QTCFLLDT(7.071055e-01), + QTCFLLDT(-7.071083e-01), QTCFLLDT(-7.071052e-01), QTCFLLDT(7.071086e-01), + QTCFLLDT(7.071049e-01), QTCFLLDT(-7.071089e-01), QTCFLLDT(-7.071046e-01), + QTCFLLDT(7.071092e-01), QTCFLLDT(7.071042e-01), QTCFLLDT(-7.071095e-01), + QTCFLLDT(-7.071039e-01), QTCFLLDT(7.071098e-01), QTCFLLDT(7.071036e-01), + QTCFLLDT(-7.071101e-01), QTCFLLDT(-7.071033e-01), QTCFLLDT(7.071104e-01), + QTCFLLDT(7.071030e-01), QTCFLLDT(-7.071107e-01), QTCFLLDT(-7.071027e-01), + QTCFLLDT(7.071111e-01), QTCFLLDT(7.071024e-01), QTCFLLDT(-7.071114e-01), + QTCFLLDT(-7.071021e-01), QTCFLLDT(7.071117e-01), +}; + +const FIXP_QTW qmf_phaseshift_sin32_cldfb[32] = { + QTCFLLDT(7.071068e-01), QTCFLLDT(7.071065e-01), QTCFLLDT(-7.071072e-01), + QTCFLLDT(-7.071062e-01), QTCFLLDT(7.071075e-01), QTCFLLDT(7.071059e-01), + QTCFLLDT(-7.071078e-01), QTCFLLDT(-7.071056e-01), QTCFLLDT(7.071081e-01), + QTCFLLDT(7.071053e-01), QTCFLLDT(-7.071084e-01), QTCFLLDT(-7.071050e-01), + QTCFLLDT(7.071087e-01), QTCFLLDT(7.071047e-01), QTCFLLDT(-7.071090e-01), + QTCFLLDT(-7.071044e-01), QTCFLLDT(7.071093e-01), QTCFLLDT(7.071041e-01), + QTCFLLDT(-7.071096e-01), QTCFLLDT(-7.071038e-01), QTCFLLDT(7.071099e-01), + QTCFLLDT(7.071034e-01), QTCFLLDT(-7.071103e-01), QTCFLLDT(-7.071031e-01), + QTCFLLDT(7.071106e-01), QTCFLLDT(7.071028e-01), QTCFLLDT(-7.071109e-01), + QTCFLLDT(-7.071025e-01), QTCFLLDT(7.071112e-01), QTCFLLDT(7.071022e-01), + QTCFLLDT(-7.071115e-01), QTCFLLDT(-7.071019e-01), +}; + +/* twiddles for X=(8,16) band qmf are copied from float simpleplayer + * implementation: qmf_phaseshift_cosX_cldfb_ana = + * QMFlib_twiddle3RealX_SBRLD_A qmf_phaseshift_cosX_cldfb_syn = + * -(QMFlib_twiddle3RealX_SBRLD_A) qmf_phaseshift_sinX_cldfb = + * QMFlib_twiddle3ImagX_SBRLD_A + */ + +/* cos ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_cos16_cldfb_ana[16] = { + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), +}; + +/* cos ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_cos16_cldfb_syn[16] = { + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), +}; + +/* sin ((n + 0.5)*pi*angle/L) , order = 159, L=16 */ +const FIXP_QTW qmf_phaseshift_sin16_cldfb[16] = { + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), +}; + +/* cos ((n + 0.5)*pi*angle/L) , order = 79, L=8 */ +const FIXP_QTW qmf_phaseshift_cos8_cldfb_ana[8] = { + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), +}; + +const FIXP_QTW qmf_phaseshift_cos8_cldfb_syn[8] = { + QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), +}; + +/* sin ((n + 0.5)*pi*angle/L) , order = 79, L=8 */ +const FIXP_QTW qmf_phaseshift_sin8_cldfb[8] = { + QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(-0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(0.7071067812), QTCFLLDT(0.7071067812), + QTCFLLDT(-0.7071067812), QTCFLLDT(-0.7071067812), +}; + +/* sin/cos (angle) / 128 */ +const FIXP_QTW qmf_phaseshift_cos64_cldfb[64] = { + QTCFLLDT(7.071068e-01), QTCFLLDT(-7.071066e-01), QTCFLLDT(-7.071070e-01), + QTCFLLDT(7.071065e-01), QTCFLLDT(7.071072e-01), QTCFLLDT(-7.071063e-01), + QTCFLLDT(-7.071074e-01), QTCFLLDT(7.071061e-01), QTCFLLDT(7.071075e-01), + QTCFLLDT(-7.071059e-01), QTCFLLDT(-7.071078e-01), QTCFLLDT(7.071057e-01), + QTCFLLDT(7.071080e-01), QTCFLLDT(-7.071055e-01), QTCFLLDT(-7.071081e-01), + QTCFLLDT(7.071053e-01), QTCFLLDT(7.071083e-01), QTCFLLDT(-7.071052e-01), + QTCFLLDT(-7.071085e-01), QTCFLLDT(7.071050e-01), QTCFLLDT(7.071087e-01), + QTCFLLDT(-7.071048e-01), QTCFLLDT(-7.071089e-01), QTCFLLDT(7.071046e-01), + QTCFLLDT(7.071090e-01), QTCFLLDT(-7.071044e-01), QTCFLLDT(-7.071092e-01), + QTCFLLDT(7.071042e-01), QTCFLLDT(7.071095e-01), QTCFLLDT(-7.071040e-01), + QTCFLLDT(-7.071096e-01), QTCFLLDT(7.071038e-01), QTCFLLDT(7.071098e-01), + QTCFLLDT(-7.071037e-01), QTCFLLDT(-7.071100e-01), QTCFLLDT(7.071035e-01), + QTCFLLDT(7.071102e-01), QTCFLLDT(-7.071033e-01), QTCFLLDT(-7.071103e-01), + QTCFLLDT(7.071031e-01), QTCFLLDT(7.071105e-01), QTCFLLDT(-7.071030e-01), + QTCFLLDT(-7.071107e-01), QTCFLLDT(7.071028e-01), QTCFLLDT(7.071109e-01), + QTCFLLDT(-7.071025e-01), QTCFLLDT(-7.071111e-01), QTCFLLDT(7.071024e-01), + QTCFLLDT(7.071113e-01), QTCFLLDT(-7.071022e-01), QTCFLLDT(-7.071115e-01), + QTCFLLDT(7.071020e-01), QTCFLLDT(7.071117e-01), QTCFLLDT(-7.071018e-01), + QTCFLLDT(-7.071118e-01), QTCFLLDT(7.071016e-01), QTCFLLDT(7.071120e-01), + QTCFLLDT(-7.071015e-01), QTCFLLDT(-7.071122e-01), QTCFLLDT(7.071013e-01), + QTCFLLDT(7.071124e-01), QTCFLLDT(-7.071011e-01), QTCFLLDT(-7.071126e-01), + QTCFLLDT(7.071009e-01), +}; +const FIXP_QTW qmf_phaseshift_sin64_cldfb[64] = { + QTCFLLDT(7.071067e-01), QTCFLLDT(7.071069e-01), QTCFLLDT(-7.071065e-01), + QTCFLLDT(-7.071071e-01), QTCFLLDT(7.071064e-01), QTCFLLDT(7.071073e-01), + QTCFLLDT(-7.071062e-01), QTCFLLDT(-7.071075e-01), QTCFLLDT(7.071060e-01), + QTCFLLDT(7.071077e-01), QTCFLLDT(-7.071058e-01), QTCFLLDT(-7.071078e-01), + QTCFLLDT(7.071056e-01), QTCFLLDT(7.071080e-01), QTCFLLDT(-7.071055e-01), + QTCFLLDT(-7.071082e-01), QTCFLLDT(7.071053e-01), QTCFLLDT(7.071084e-01), + QTCFLLDT(-7.071050e-01), QTCFLLDT(-7.071086e-01), QTCFLLDT(7.071049e-01), + QTCFLLDT(7.071088e-01), QTCFLLDT(-7.071047e-01), QTCFLLDT(-7.071090e-01), + QTCFLLDT(7.071045e-01), QTCFLLDT(7.071092e-01), QTCFLLDT(-7.071043e-01), + QTCFLLDT(-7.071093e-01), QTCFLLDT(7.071041e-01), QTCFLLDT(7.071095e-01), + QTCFLLDT(-7.071040e-01), QTCFLLDT(-7.071097e-01), QTCFLLDT(7.071038e-01), + QTCFLLDT(7.071099e-01), QTCFLLDT(-7.071036e-01), QTCFLLDT(-7.071100e-01), + QTCFLLDT(7.071034e-01), QTCFLLDT(7.071103e-01), QTCFLLDT(-7.071032e-01), + QTCFLLDT(-7.071105e-01), QTCFLLDT(7.071030e-01), QTCFLLDT(7.071106e-01), + QTCFLLDT(-7.071028e-01), QTCFLLDT(-7.071108e-01), QTCFLLDT(7.071027e-01), + QTCFLLDT(7.071110e-01), QTCFLLDT(-7.071025e-01), QTCFLLDT(-7.071112e-01), + QTCFLLDT(7.071023e-01), QTCFLLDT(7.071114e-01), QTCFLLDT(-7.071021e-01), + QTCFLLDT(-7.071115e-01), QTCFLLDT(7.071019e-01), QTCFLLDT(7.071117e-01), + QTCFLLDT(-7.071017e-01), QTCFLLDT(-7.071120e-01), QTCFLLDT(7.071015e-01), + QTCFLLDT(7.071121e-01), QTCFLLDT(-7.071013e-01), QTCFLLDT(-7.071123e-01), + QTCFLLDT(7.071012e-01), QTCFLLDT(7.071125e-01), QTCFLLDT(-7.071010e-01), + QTCFLLDT(-7.071127e-01), +}; + +//@} + +#endif /* #ifdef LOW_POWER_SBR_ONLY */ + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, optimized by PE 010516 + + The coeffs are rearranged compared with the reference in the following + way: + sbr_qmf_64[0] = sbr_qmf_64_reference[0]; + sbr_qmf_64[1] = sbr_qmf_64_reference[128]; + sbr_qmf_64[2] = sbr_qmf_64_reference[256]; + sbr_qmf_64[3] = sbr_qmf_64_reference[384]; + sbr_qmf_64[4] = sbr_qmf_64_reference[512]; + + sbr_qmf_64[5] = sbr_qmf_64_reference[1]; + sbr_qmf_64[6] = sbr_qmf_64_reference[129]; + sbr_qmf_64[7] = sbr_qmf_64_reference[257]; + sbr_qmf_64[8] = sbr_qmf_64_reference[385]; + sbr_qmf_64[9] = sbr_qmf_64_reference[513]; + . + . + . + sbr_qmf_64[635] = sbr_qmf_64_reference[127] + sbr_qmf_64[636] = sbr_qmf_64_reference[255]; + sbr_qmf_64[637] = sbr_qmf_64_reference[383]; + sbr_qmf_64[638] = sbr_qmf_64_reference[511]; + sbr_qmf_64[639] = sbr_qmf_64_reference[639]; + + + Symmetric properties of qmf coeffs: + + Use point symmetry: + + sbr_qmf_64_640_qmf[320..634] = p_64_640_qmf[314..0] + + Max sum of all FIR filter absolute coefficients is: 0x7FF5B201 + thus, the filter output is not required to be scaled. + + \showinitializer +*/ +//@{ + +LNK_SECTION_CONSTDATA_L1 +RAM_ALIGN +const FIXP_PFT qmf_cldfb_640[QMF640_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.571760e-07), QTCFLLD(-8.010079e-06), QTCFLLD(-1.250743e-03), + QTCFLLD(8.996371e-03), QTCFLLD(5.128557e-01), QTCFLLD(4.118360e-07), + QTCFLLD(-1.469933e-05), QTCFLLD(-1.194743e-03), QTCFLLD(9.640299e-03), + QTCFLLD(5.299510e-01), QTCFLLD(8.109952e-07), QTCFLLD(4.840578e-06), + QTCFLLD(-1.151796e-03), QTCFLLD(1.033126e-02), QTCFLLD(5.470652e-01), + QTCFLLD(7.099633e-07), QTCFLLD(7.167101e-06), QTCFLLD(-1.099001e-03), + QTCFLLD(1.106959e-02), QTCFLLD(5.641523e-01), QTCFLLD(6.834210e-07), + QTCFLLD(1.088325e-05), QTCFLLD(-1.047655e-03), QTCFLLD(1.186211e-02), + QTCFLLD(5.811993e-01), QTCFLLD(4.292862e-07), QTCFLLD(1.013260e-05), + QTCFLLD(-9.862027e-04), QTCFLLD(1.270747e-02), QTCFLLD(5.981877e-01), + QTCFLLD(-5.426597e-09), QTCFLLD(5.869707e-06), QTCFLLD(-9.294665e-04), + QTCFLLD(1.361072e-02), QTCFLLD(6.151031e-01), QTCFLLD(6.355303e-08), + QTCFLLD(1.125135e-05), QTCFLLD(-9.767709e-04), QTCFLLD(1.456209e-02), + QTCFLLD(6.319284e-01), QTCFLLD(5.490570e-07), QTCFLLD(2.015445e-05), + QTCFLLD(-1.040598e-03), QTCFLLD(1.557759e-02), QTCFLLD(6.486438e-01), + QTCFLLD(1.620171e-06), QTCFLLD(2.800456e-05), QTCFLLD(-1.146268e-03), + QTCFLLD(1.665188e-02), QTCFLLD(6.652304e-01), QTCFLLD(-6.025110e-10), + QTCFLLD(8.975978e-06), QTCFLLD(-1.292866e-03), QTCFLLD(1.778249e-02), + QTCFLLD(6.816668e-01), QTCFLLD(-6.325664e-10), QTCFLLD(8.563820e-06), + QTCFLLD(-1.196638e-03), QTCFLLD(1.897506e-02), QTCFLLD(6.979337e-01), + QTCFLLD(-4.013525e-09), QTCFLLD(1.168895e-05), QTCFLLD(-9.726699e-04), + QTCFLLD(2.023525e-02), QTCFLLD(7.140087e-01), QTCFLLD(-4.244091e-09), + QTCFLLD(7.300589e-06), QTCFLLD(-8.029620e-04), QTCFLLD(2.156305e-02), + QTCFLLD(7.298746e-01), QTCFLLD(-1.846548e-08), QTCFLLD(3.965364e-06), + QTCFLLD(-6.754936e-04), QTCFLLD(2.296471e-02), QTCFLLD(7.455112e-01), + QTCFLLD(-3.870537e-09), QTCFLLD(1.374896e-06), QTCFLLD(-5.791145e-04), + QTCFLLD(2.443434e-02), QTCFLLD(7.609051e-01), QTCFLLD(-8.883499e-10), + QTCFLLD(3.798520e-07), QTCFLLD(-4.733148e-04), QTCFLLD(2.597957e-02), + QTCFLLD(7.760386e-01), QTCFLLD(5.303528e-08), QTCFLLD(4.469729e-06), + QTCFLLD(-2.998740e-04), QTCFLLD(2.760091e-02), QTCFLLD(7.908995e-01), + QTCFLLD(7.391974e-08), QTCFLLD(2.461877e-05), QTCFLLD(7.882620e-05), + QTCFLLD(2.931526e-02), QTCFLLD(8.054701e-01), QTCFLLD(1.723217e-09), + QTCFLLD(4.005269e-05), QTCFLLD(4.708010e-04), QTCFLLD(3.110861e-02), + QTCFLLD(8.197387e-01), QTCFLLD(2.443085e-07), QTCFLLD(5.272982e-05), + QTCFLLD(8.089812e-04), QTCFLLD(3.298151e-02), QTCFLLD(8.336864e-01), + QTCFLLD(1.387567e-08), QTCFLLD(4.939392e-05), QTCFLLD(1.127142e-03), + QTCFLLD(3.493300e-02), QTCFLLD(8.472987e-01), QTCFLLD(-5.690531e-06), + QTCFLLD(-4.256442e-05), QTCFLLD(1.417367e-03), QTCFLLD(3.696343e-02), + QTCFLLD(8.605543e-01), QTCFLLD(3.629067e-06), QTCFLLD(6.582328e-05), + QTCFLLD(1.725030e-03), QTCFLLD(3.907138e-02), QTCFLLD(8.734367e-01), + QTCFLLD(-5.393556e-08), QTCFLLD(6.481921e-05), QTCFLLD(1.948069e-03), + QTCFLLD(4.125570e-02), QTCFLLD(8.859232e-01), QTCFLLD(1.349944e-07), + QTCFLLD(3.367998e-05), QTCFLLD(2.033465e-03), QTCFLLD(4.355568e-02), + QTCFLLD(8.979959e-01), QTCFLLD(7.326611e-09), QTCFLLD(4.694252e-05), + QTCFLLD(2.239143e-03), QTCFLLD(4.599068e-02), QTCFLLD(9.096311e-01), + QTCFLLD(2.399696e-07), QTCFLLD(6.904415e-05), QTCFLLD(2.470456e-03), + QTCFLLD(4.849285e-02), QTCFLLD(9.208195e-01), QTCFLLD(3.330982e-07), + QTCFLLD(5.643103e-05), QTCFLLD(2.630472e-03), QTCFLLD(5.105621e-02), + QTCFLLD(9.315442e-01), QTCFLLD(4.767794e-07), QTCFLLD(7.095887e-05), + QTCFLLD(2.703019e-03), QTCFLLD(5.368313e-02), QTCFLLD(9.417976e-01), + QTCFLLD(3.428661e-07), QTCFLLD(7.872593e-05), QTCFLLD(2.729137e-03), + QTCFLLD(5.637219e-02), QTCFLLD(9.515675e-01), QTCFLLD(8.676848e-06), + QTCFLLD(2.666445e-04), QTCFLLD(2.719749e-03), QTCFLLD(5.911363e-02), + QTCFLLD(9.608520e-01), QTCFLLD(2.722296e-05), QTCFLLD(5.822201e-04), + QTCFLLD(2.530907e-03), QTCFLLD(6.192693e-02), QTCFLLD(9.696426e-01), + QTCFLLD(3.575651e-07), QTCFLLD(7.870355e-05), QTCFLLD(2.225524e-03), + QTCFLLD(6.480449e-02), QTCFLLD(9.779405e-01), QTCFLLD(6.293002e-07), + QTCFLLD(7.245096e-05), QTCFLLD(1.891972e-03), QTCFLLD(6.771675e-02), + QTCFLLD(9.857388e-01), QTCFLLD(1.070243e-06), QTCFLLD(7.194151e-05), + QTCFLLD(1.557112e-03), QTCFLLD(7.064948e-02), QTCFLLD(9.930380e-01), + QTCFLLD(-3.225913e-07), QTCFLLD(-7.679955e-05), QTCFLLD(1.194731e-03), + QTCFLLD(7.360559e-02), QTCFLLD(9.998286e-01), QTCFLLD(-9.597516e-09), + QTCFLLD(-6.093373e-05), QTCFLLD(6.415402e-04), QTCFLLD(7.657650e-02), + QTCFLLD(1.006109e+00), QTCFLLD(-8.908041e-08), QTCFLLD(-1.721347e-05), + QTCFLLD(1.092526e-04), QTCFLLD(7.955571e-02), QTCFLLD(1.011868e+00), + QTCFLLD(-2.285563e-05), QTCFLLD(-8.882305e-05), QTCFLLD(2.934876e-04), + QTCFLLD(8.251962e-02), QTCFLLD(1.017100e+00), QTCFLLD(1.013575e-05), + QTCFLLD(6.418658e-05), QTCFLLD(5.721223e-04), QTCFLLD(8.547716e-02), + QTCFLLD(1.021799e+00), QTCFLLD(-1.706941e-05), QTCFLLD(1.769262e-04), + QTCFLLD(6.976561e-04), QTCFLLD(8.841813e-02), QTCFLLD(1.025967e+00), + QTCFLLD(1.356728e-06), QTCFLLD(2.206341e-05), QTCFLLD(7.376101e-04), + QTCFLLD(9.133591e-02), QTCFLLD(1.029601e+00), QTCFLLD(-1.398913e-08), + QTCFLLD(-6.538879e-06), QTCFLLD(7.154124e-04), QTCFLLD(9.421624e-02), + QTCFLLD(1.032713e+00), QTCFLLD(3.552992e-08), QTCFLLD(-1.052707e-05), + QTCFLLD(7.139920e-04), QTCFLLD(9.705240e-02), QTCFLLD(1.035312e+00), + QTCFLLD(4.211177e-07), QTCFLLD(-9.075431e-06), QTCFLLD(6.944123e-04), + QTCFLLD(9.982958e-02), QTCFLLD(1.037422e+00), QTCFLLD(5.433719e-07), + QTCFLLD(-1.748285e-05), QTCFLLD(6.766320e-04), QTCFLLD(1.025398e-01), + QTCFLLD(1.039062e+00), QTCFLLD(8.226600e-08), QTCFLLD(-3.498286e-05), + QTCFLLD(6.887784e-04), QTCFLLD(1.051642e-01), QTCFLLD(1.040262e+00), + QTCFLLD(1.272705e-07), QTCFLLD(-4.489491e-05), QTCFLLD(6.673250e-04), + QTCFLLD(1.076972e-01), QTCFLLD(1.041043e+00), QTCFLLD(2.542598e-07), + QTCFLLD(-5.449816e-05), QTCFLLD(5.970697e-04), QTCFLLD(1.101216e-01), + QTCFLLD(1.041434e+00), QTCFLLD(6.322770e-07), QTCFLLD(-5.874199e-05), + QTCFLLD(4.749931e-04), QTCFLLD(1.124296e-01), QTCFLLD(1.041443e+00), + QTCFLLD(2.801882e-08), QTCFLLD(-7.934510e-05), QTCFLLD(3.189336e-04), + QTCFLLD(1.146042e-01), QTCFLLD(1.041087e+00), QTCFLLD(5.891904e-07), + QTCFLLD(-8.039232e-05), QTCFLLD(1.218226e-04), QTCFLLD(1.166399e-01), + QTCFLLD(1.040350e+00), QTCFLLD(7.301957e-07), QTCFLLD(-9.907631e-05), + QTCFLLD(-1.324292e-04), QTCFLLD(1.185243e-01), QTCFLLD(1.039228e+00), + QTCFLLD(-4.518603e-06), QTCFLLD(-2.217025e-04), QTCFLLD(-4.268575e-04), + QTCFLLD(1.202546e-01), QTCFLLD(1.037683e+00), QTCFLLD(-3.561585e-06), + QTCFLLD(-2.415166e-04), QTCFLLD(-7.804546e-04), QTCFLLD(1.218184e-01), + QTCFLLD(1.035694e+00), QTCFLLD(-1.074717e-07), QTCFLLD(-2.123672e-04), + QTCFLLD(-1.156680e-03), QTCFLLD(1.232132e-01), QTCFLLD(1.033206e+00), + QTCFLLD(1.323268e-06), QTCFLLD(-2.078299e-04), QTCFLLD(-1.525819e-03), + QTCFLLD(1.244270e-01), QTCFLLD(1.030199e+00), QTCFLLD(3.377815e-06), + QTCFLLD(-1.885286e-04), QTCFLLD(-1.914115e-03), QTCFLLD(1.254605e-01), + QTCFLLD(1.026616e+00), QTCFLLD(5.161607e-06), QTCFLLD(-1.728673e-04), + QTCFLLD(-2.292814e-03), QTCFLLD(1.262996e-01), QTCFLLD(1.022470e+00), + QTCFLLD(5.924001e-06), QTCFLLD(-1.744842e-04), QTCFLLD(-2.658042e-03), + QTCFLLD(1.269416e-01), QTCFLLD(1.017729e+00), QTCFLLD(6.310208e-06), + QTCFLLD(-1.784193e-04), QTCFLLD(-3.000423e-03), QTCFLLD(1.273648e-01), + QTCFLLD(1.012508e+00), QTCFLLD(3.357219e-06), QTCFLLD(-2.131406e-04), + QTCFLLD(-3.318858e-03), QTCFLLD(1.275561e-01), QTCFLLD(1.006893e+00), + QTCFLLD(5.189087e-06), QTCFLLD(-2.078886e-04), QTCFLLD(-3.597476e-03), + QTCFLLD(1.274568e-01), QTCFLLD(1.001463e+00), QTCFLLD(4.178050e-06), + QTCFLLD(-4.663778e-05), QTCFLLD(-3.870852e-03), QTCFLLD(1.273591e-01), + QTCFLLD(9.927544e-01), QTCFLLD(5.364807e-06), QTCFLLD(-5.889277e-06), + QTCFLLD(-4.135130e-03), QTCFLLD(1.272499e-01), QTCFLLD(9.807692e-01), + QTCFLLD(4.083719e-06), QTCFLLD(-1.774108e-05), QTCFLLD(-4.351668e-03), + QTCFLLD(1.268281e-01), QTCFLLD(9.690017e-01), QTCFLLD(3.567581e-06), + QTCFLLD(-2.599468e-08), QTCFLLD(-4.517190e-03), QTCFLLD(1.261262e-01), + QTCFLLD(9.568886e-01), QTCFLLD(3.262754e-06), QTCFLLD(1.260640e-05), + QTCFLLD(-4.636228e-03), QTCFLLD(1.251477e-01), QTCFLLD(9.443803e-01), + QTCFLLD(2.041128e-06), QTCFLLD(2.364519e-05), QTCFLLD(-4.704321e-03), + QTCFLLD(1.238869e-01), QTCFLLD(9.313874e-01), QTCFLLD(-2.567965e-08), + QTCFLLD(2.806963e-05), QTCFLLD(-4.722568e-03), QTCFLLD(1.223371e-01), + QTCFLLD(9.179666e-01), QTCFLLD(2.714879e-07), QTCFLLD(4.493916e-05), + QTCFLLD(-4.663276e-03), QTCFLLD(1.204854e-01), QTCFLLD(9.041286e-01), + QTCFLLD(2.150884e-06), QTCFLLD(5.408155e-05), QTCFLLD(-4.554811e-03), + QTCFLLD(1.183233e-01), QTCFLLD(8.899474e-01), QTCFLLD(5.818595e-06), + QTCFLLD(3.759630e-05), QTCFLLD(-4.369554e-03), QTCFLLD(1.158359e-01), + QTCFLLD(8.754641e-01), QTCFLLD(-1.686137e-09), QTCFLLD(2.515118e-05), + QTCFLLD(-4.091033e-03), QTCFLLD(1.130180e-01), QTCFLLD(8.607492e-01), + QTCFLLD(-1.775191e-09), QTCFLLD(2.406517e-05), QTCFLLD(-3.794425e-03), + QTCFLLD(1.098551e-01), QTCFLLD(8.458450e-01), QTCFLLD(-2.222072e-09), + QTCFLLD(3.628511e-05), QTCFLLD(-3.460363e-03), QTCFLLD(1.063455e-01), + QTCFLLD(8.308040e-01), QTCFLLD(-1.280675e-08), QTCFLLD(2.241546e-05), + QTCFLLD(-3.064311e-03), QTCFLLD(1.024805e-01), QTCFLLD(8.156523e-01), + QTCFLLD(-6.977078e-08), QTCFLLD(1.499170e-05), QTCFLLD(-2.621537e-03), + QTCFLLD(9.826251e-02), QTCFLLD(8.004165e-01), QTCFLLD(-1.409927e-08), + QTCFLLD(5.009913e-06), QTCFLLD(-2.124648e-03), QTCFLLD(9.368652e-02), + QTCFLLD(7.851012e-01), QTCFLLD(-2.986489e-09), QTCFLLD(1.277184e-06), + QTCFLLD(-1.594861e-03), QTCFLLD(8.875756e-02), QTCFLLD(7.697093e-01), + QTCFLLD(1.876022e-07), QTCFLLD(1.580189e-05), QTCFLLD(-1.061499e-03), + QTCFLLD(8.347151e-02), QTCFLLD(7.542294e-01), QTCFLLD(1.737277e-07), + QTCFLLD(5.533953e-05), QTCFLLD(-6.169855e-04), QTCFLLD(7.783300e-02), + QTCFLLD(7.386515e-01), QTCFLLD(3.818589e-09), QTCFLLD(8.870182e-05), + QTCFLLD(-2.004823e-04), QTCFLLD(7.184074e-02), QTCFLLD(7.229599e-01), + QTCFLLD(5.143615e-07), QTCFLLD(1.035783e-04), QTCFLLD(2.048499e-04), + QTCFLLD(6.550209e-02), QTCFLLD(7.071448e-01), QTCFLLD(2.820292e-08), + QTCFLLD(9.990758e-05), QTCFLLD(5.621721e-04), QTCFLLD(5.881297e-02), + QTCFLLD(6.911982e-01), QTCFLLD(4.677016e-06), QTCFLLD(1.181078e-04), + QTCFLLD(9.373975e-04), QTCFLLD(5.177965e-02), QTCFLLD(6.751199e-01), + QTCFLLD(3.361682e-06), QTCFLLD(2.126365e-05), QTCFLLD(1.344657e-03), + QTCFLLD(4.439684e-02), QTCFLLD(6.589149e-01), QTCFLLD(-4.880845e-08), + QTCFLLD(5.861800e-05), QTCFLLD(1.812176e-03), QTCFLLD(3.666943e-02), + QTCFLLD(6.425940e-01), QTCFLLD(2.267731e-07), QTCFLLD(5.021906e-05), + QTCFLLD(2.172866e-03), QTCFLLD(2.857528e-02), QTCFLLD(6.261725e-01), + QTCFLLD(5.158213e-09), QTCFLLD(4.150075e-05), QTCFLLD(1.985825e-03), + QTCFLLD(2.012237e-02), QTCFLLD(6.096690e-01), QTCFLLD(-2.066962e-07), + QTCFLLD(3.799972e-05), QTCFLLD(1.697653e-03), QTCFLLD(1.132324e-02), + QTCFLLD(5.930982e-01), QTCFLLD(4.883305e-07), QTCFLLD(6.606462e-05), + QTCFLLD(1.471167e-03), QTCFLLD(2.184257e-03), QTCFLLD(5.764735e-01), + QTCFLLD(8.254430e-07), QTCFLLD(9.755685e-05), QTCFLLD(1.232134e-03), + QTCFLLD(-7.298198e-03), QTCFLLD(5.598052e-01), QTCFLLD(9.464783e-07), + QTCFLLD(1.831121e-04), QTCFLLD(8.990256e-04), QTCFLLD(-1.711324e-02), + QTCFLLD(5.430990e-01), QTCFLLD(-1.232693e-05), QTCFLLD(-5.901618e-07), + QTCFLLD(6.150317e-04), QTCFLLD(-2.726484e-02), QTCFLLD(5.263554e-01), + QTCFLLD(3.867483e-05), QTCFLLD(-3.595054e-04), QTCFLLD(6.307841e-04), + QTCFLLD(-3.775928e-02), QTCFLLD(5.095721e-01), QTCFLLD(-9.870548e-07), + QTCFLLD(-1.815837e-04), QTCFLLD(4.366447e-04), QTCFLLD(-4.859006e-02), + QTCFLLD(4.927464e-01), QTCFLLD(-1.089501e-06), QTCFLLD(-9.204876e-05), + QTCFLLD(1.498232e-04), QTCFLLD(-5.973742e-02), QTCFLLD(4.758754e-01), + QTCFLLD(-1.569003e-06), QTCFLLD(-5.192444e-05), QTCFLLD(-9.099723e-05), + QTCFLLD(-7.120357e-02), QTCFLLD(4.589583e-01), QTCFLLD(-2.778618e-07), + QTCFLLD(6.487880e-05), QTCFLLD(-3.337967e-04), QTCFLLD(-8.298103e-02), + QTCFLLD(4.420014e-01), QTCFLLD(6.757015e-09), QTCFLLD(5.397065e-05), + QTCFLLD(-5.599348e-04), QTCFLLD(-9.506967e-02), QTCFLLD(4.250144e-01), + QTCFLLD(1.496436e-07), QTCFLLD(2.472024e-05), QTCFLLD(-7.677634e-04), + QTCFLLD(-1.074631e-01), QTCFLLD(4.080155e-01), QTCFLLD(2.068297e-05), + QTCFLLD(9.711682e-05), QTCFLLD(-9.730460e-04), QTCFLLD(-1.201629e-01), + QTCFLLD(3.910244e-01), QTCFLLD(-9.388963e-06), QTCFLLD(5.144969e-05), + QTCFLLD(-1.131860e-03), QTCFLLD(-1.331545e-01), QTCFLLD(3.740644e-01), + QTCFLLD(-1.402925e-05), QTCFLLD(-1.039264e-04), QTCFLLD(-1.283281e-03), + QTCFLLD(-1.464389e-01), QTCFLLD(3.571528e-01), QTCFLLD(-2.757611e-06), + QTCFLLD(2.853437e-06), QTCFLLD(-1.480543e-03), QTCFLLD(-1.600062e-01), + QTCFLLD(3.403074e-01), QTCFLLD(2.945239e-08), QTCFLLD(1.334091e-05), + QTCFLLD(-1.699161e-03), QTCFLLD(-1.738542e-01), QTCFLLD(3.235299e-01), + QTCFLLD(-7.873304e-08), QTCFLLD(2.443161e-05), QTCFLLD(-1.924845e-03), + QTCFLLD(-1.879712e-01), QTCFLLD(3.068187e-01), QTCFLLD(-9.897194e-07), + QTCFLLD(3.568555e-05), QTCFLLD(-2.152380e-03), QTCFLLD(-2.023548e-01), + QTCFLLD(2.901491e-01), QTCFLLD(-1.922074e-06), QTCFLLD(6.193370e-05), + QTCFLLD(-2.396404e-03), QTCFLLD(-2.169926e-01), QTCFLLD(2.734977e-01), + QTCFLLD(-2.765650e-07), QTCFLLD(1.176237e-04), QTCFLLD(-2.653819e-03), + QTCFLLD(-2.318815e-01), QTCFLLD(2.568176e-01), QTCFLLD(-4.636105e-07), + QTCFLLD(1.635906e-04), QTCFLLD(-2.927159e-03), QTCFLLD(-2.470098e-01), + QTCFLLD(2.400768e-01), QTCFLLD(-9.607069e-07), QTCFLLD(2.060394e-04), + QTCFLLD(-3.209093e-03), QTCFLLD(-2.623749e-01), QTCFLLD(2.232277e-01), + QTCFLLD(-1.907927e-06), QTCFLLD(2.346981e-04), QTCFLLD(-3.505531e-03), + QTCFLLD(-2.779638e-01), QTCFLLD(2.062605e-01), QTCFLLD(-1.551251e-08), + QTCFLLD(2.520607e-04), QTCFLLD(-3.811612e-03), QTCFLLD(-2.937725e-01), + QTCFLLD(1.891590e-01), QTCFLLD(-1.653464e-06), QTCFLLD(2.556450e-04), + QTCFLLD(-4.133640e-03), QTCFLLD(-3.097862e-01), QTCFLLD(1.719726e-01), + QTCFLLD(-2.043464e-06), QTCFLLD(3.157664e-04), QTCFLLD(-4.448993e-03), + QTCFLLD(-3.259994e-01), QTCFLLD(1.547461e-01), QTCFLLD(1.622786e-05), + QTCFLLD(6.205676e-04), QTCFLLD(-4.754192e-03), QTCFLLD(-3.423942e-01), + QTCFLLD(1.376150e-01), QTCFLLD(1.395221e-05), QTCFLLD(7.847840e-04), + QTCFLLD(-5.063851e-03), QTCFLLD(-3.589627e-01), QTCFLLD(1.206924e-01), + QTCFLLD(4.591010e-07), QTCFLLD(9.019129e-04), QTCFLLD(-5.394570e-03), + QTCFLLD(-3.756822e-01), QTCFLLD(1.042033e-01), QTCFLLD(-6.261944e-06), + QTCFLLD(1.054963e-03), QTCFLLD(-5.741103e-03), QTCFLLD(-3.925409e-01), + QTCFLLD(8.829745e-02), QTCFLLD(-1.606051e-05), QTCFLLD(1.089429e-03), + QTCFLLD(-6.109179e-03), QTCFLLD(-4.095160e-01), QTCFLLD(7.325979e-02), + QTCFLLD(-2.464228e-05), QTCFLLD(1.122503e-03), QTCFLLD(-6.500503e-03), + QTCFLLD(-4.265950e-01), QTCFLLD(5.918678e-02), QTCFLLD(-2.976824e-05), + QTCFLLD(1.177515e-03), QTCFLLD(-6.925141e-03), QTCFLLD(-4.437530e-01), + QTCFLLD(4.634696e-02), QTCFLLD(-3.177468e-05), QTCFLLD(1.226113e-03), + QTCFLLD(-7.380544e-03), QTCFLLD(-4.609829e-01), QTCFLLD(3.450719e-02), + QTCFLLD(-4.373302e-05), QTCFLLD(1.263569e-03), QTCFLLD(-7.876393e-03), + QTCFLLD(-4.782650e-01), QTCFLLD(2.353060e-02), QTCFLLD(-3.299004e-05), + QTCFLLD(1.287819e-03), QTCFLLD(-8.407749e-03), QTCFLLD(-4.956175e-01), + QTCFLLD(1.129580e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_320[QMF320_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(5.345060e-07), QTCFLLD(-1.135471e-05), QTCFLLD(-1.222743e-03), + QTCFLLD(9.318335e-03), QTCFLLD(5.214033e-01), QTCFLLD(7.604792e-07), + QTCFLLD(6.003839e-06), QTCFLLD(-1.125398e-03), QTCFLLD(1.070043e-02), + QTCFLLD(5.556087e-01), QTCFLLD(5.563536e-07), QTCFLLD(1.050792e-05), + QTCFLLD(-1.016929e-03), QTCFLLD(1.228479e-02), QTCFLLD(5.896935e-01), + QTCFLLD(2.906322e-08), QTCFLLD(8.560527e-06), QTCFLLD(-9.531187e-04), + QTCFLLD(1.408640e-02), QTCFLLD(6.235157e-01), QTCFLLD(1.084614e-06), + QTCFLLD(2.407951e-05), QTCFLLD(-1.093433e-03), QTCFLLD(1.611474e-02), + QTCFLLD(6.569371e-01), QTCFLLD(-6.175387e-10), QTCFLLD(8.769899e-06), + QTCFLLD(-1.244752e-03), QTCFLLD(1.837877e-02), QTCFLLD(6.898003e-01), + QTCFLLD(-4.128808e-09), QTCFLLD(9.494767e-06), QTCFLLD(-8.878160e-04), + QTCFLLD(2.089915e-02), QTCFLLD(7.219416e-01), QTCFLLD(-1.116801e-08), + QTCFLLD(2.670130e-06), QTCFLLD(-6.273041e-04), QTCFLLD(2.369952e-02), + QTCFLLD(7.532082e-01), QTCFLLD(2.607347e-08), QTCFLLD(2.424790e-06), + QTCFLLD(-3.865944e-04), QTCFLLD(2.679024e-02), QTCFLLD(7.834691e-01), + QTCFLLD(3.782148e-08), QTCFLLD(3.233573e-05), QTCFLLD(2.748136e-04), + QTCFLLD(3.021193e-02), QTCFLLD(8.126044e-01), QTCFLLD(1.290921e-07), + QTCFLLD(5.106187e-05), QTCFLLD(9.680615e-04), QTCFLLD(3.395726e-02), + QTCFLLD(8.404925e-01), QTCFLLD(-1.030732e-06), QTCFLLD(1.162943e-05), + QTCFLLD(1.571198e-03), QTCFLLD(3.801740e-02), QTCFLLD(8.669955e-01), + QTCFLLD(4.052940e-08), QTCFLLD(4.924960e-05), QTCFLLD(1.990767e-03), + QTCFLLD(4.240569e-02), QTCFLLD(8.919595e-01), QTCFLLD(1.236481e-07), + QTCFLLD(5.799333e-05), QTCFLLD(2.354800e-03), QTCFLLD(4.724177e-02), + QTCFLLD(9.152253e-01), QTCFLLD(4.049388e-07), QTCFLLD(6.369496e-05), + QTCFLLD(2.666746e-03), QTCFLLD(5.236967e-02), QTCFLLD(9.366709e-01), + QTCFLLD(4.509857e-06), QTCFLLD(1.726852e-04), QTCFLLD(2.724443e-03), + QTCFLLD(5.774291e-02), QTCFLLD(9.562097e-01), QTCFLLD(1.379026e-05), + QTCFLLD(3.304619e-04), QTCFLLD(2.378216e-03), QTCFLLD(6.336571e-02), + QTCFLLD(9.737916e-01), QTCFLLD(8.497715e-07), QTCFLLD(7.219624e-05), + QTCFLLD(1.724542e-03), QTCFLLD(6.918311e-02), QTCFLLD(9.893883e-01), + QTCFLLD(-1.660944e-07), QTCFLLD(-6.886664e-05), QTCFLLD(9.181354e-04), + QTCFLLD(7.509105e-02), QTCFLLD(1.002969e+00), QTCFLLD(-1.147235e-05), + QTCFLLD(-5.301826e-05), QTCFLLD(2.013701e-04), QTCFLLD(8.103766e-02), + QTCFLLD(1.014484e+00), QTCFLLD(-3.466829e-06), QTCFLLD(1.205564e-04), + QTCFLLD(6.348892e-04), QTCFLLD(8.694765e-02), QTCFLLD(1.023883e+00), + QTCFLLD(6.713692e-07), QTCFLLD(7.762268e-06), QTCFLLD(7.265112e-04), + QTCFLLD(9.277608e-02), QTCFLLD(1.031157e+00), QTCFLLD(2.283238e-07), + QTCFLLD(-9.801253e-06), QTCFLLD(7.042022e-04), QTCFLLD(9.844099e-02), + QTCFLLD(1.036367e+00), QTCFLLD(3.128189e-07), QTCFLLD(-2.623285e-05), + QTCFLLD(6.827052e-04), QTCFLLD(1.038520e-01), QTCFLLD(1.039662e+00), + QTCFLLD(1.907652e-07), QTCFLLD(-4.969654e-05), QTCFLLD(6.321974e-04), + QTCFLLD(1.089094e-01), QTCFLLD(1.041239e+00), QTCFLLD(3.301479e-07), + QTCFLLD(-6.904354e-05), QTCFLLD(3.969634e-04), QTCFLLD(1.135169e-01), + QTCFLLD(1.041265e+00), QTCFLLD(6.596931e-07), QTCFLLD(-8.973431e-05), + QTCFLLD(-5.303260e-06), QTCFLLD(1.175821e-01), QTCFLLD(1.039789e+00), + QTCFLLD(-4.040094e-06), QTCFLLD(-2.316096e-04), QTCFLLD(-6.036561e-04), + QTCFLLD(1.210365e-01), QTCFLLD(1.036689e+00), QTCFLLD(6.078980e-07), + QTCFLLD(-2.100985e-04), QTCFLLD(-1.341249e-03), QTCFLLD(1.238201e-01), + QTCFLLD(1.031702e+00), QTCFLLD(4.269711e-06), QTCFLLD(-1.806979e-04), + QTCFLLD(-2.103464e-03), QTCFLLD(1.258800e-01), QTCFLLD(1.024543e+00), + QTCFLLD(6.117105e-06), QTCFLLD(-1.764517e-04), QTCFLLD(-2.829232e-03), + QTCFLLD(1.271532e-01), QTCFLLD(1.015119e+00), QTCFLLD(4.273153e-06), + QTCFLLD(-2.105146e-04), QTCFLLD(-3.458167e-03), QTCFLLD(1.275064e-01), + QTCFLLD(1.004178e+00), QTCFLLD(4.771428e-06), QTCFLLD(-2.626353e-05), + QTCFLLD(-4.002991e-03), QTCFLLD(1.273045e-01), QTCFLLD(9.867618e-01), + QTCFLLD(3.825650e-06), QTCFLLD(-8.883540e-06), QTCFLLD(-4.434429e-03), + QTCFLLD(1.264771e-01), QTCFLLD(9.629451e-01), QTCFLLD(2.651941e-06), + QTCFLLD(1.812579e-05), QTCFLLD(-4.670274e-03), QTCFLLD(1.245173e-01), + QTCFLLD(9.378839e-01), QTCFLLD(1.229041e-07), QTCFLLD(3.650440e-05), + QTCFLLD(-4.692922e-03), QTCFLLD(1.214113e-01), QTCFLLD(9.110476e-01), + QTCFLLD(3.984739e-06), QTCFLLD(4.583892e-05), QTCFLLD(-4.462183e-03), + QTCFLLD(1.170796e-01), QTCFLLD(8.827057e-01), QTCFLLD(-1.730664e-09), + QTCFLLD(2.460818e-05), QTCFLLD(-3.942729e-03), QTCFLLD(1.114366e-01), + QTCFLLD(8.532971e-01), QTCFLLD(-7.514413e-09), QTCFLLD(2.935029e-05), + QTCFLLD(-3.262337e-03), QTCFLLD(1.044130e-01), QTCFLLD(8.232281e-01), + QTCFLLD(-4.193503e-08), QTCFLLD(1.000081e-05), QTCFLLD(-2.373092e-03), + QTCFLLD(9.597452e-02), QTCFLLD(7.927589e-01), QTCFLLD(9.230786e-08), + QTCFLLD(8.539538e-06), QTCFLLD(-1.328180e-03), QTCFLLD(8.611453e-02), + QTCFLLD(7.619694e-01), QTCFLLD(8.877312e-08), QTCFLLD(7.202067e-05), + QTCFLLD(-4.087339e-04), QTCFLLD(7.483687e-02), QTCFLLD(7.308058e-01), + QTCFLLD(2.712822e-07), QTCFLLD(1.017429e-04), QTCFLLD(3.835110e-04), + QTCFLLD(6.215753e-02), QTCFLLD(6.991715e-01), QTCFLLD(4.019349e-06), + QTCFLLD(6.968570e-05), QTCFLLD(1.141027e-03), QTCFLLD(4.808825e-02), + QTCFLLD(6.670174e-01), QTCFLLD(8.898233e-08), QTCFLLD(5.441853e-05), + QTCFLLD(1.992521e-03), QTCFLLD(3.262236e-02), QTCFLLD(6.343833e-01), + QTCFLLD(-1.007690e-07), QTCFLLD(3.975024e-05), QTCFLLD(1.841739e-03), + QTCFLLD(1.572281e-02), QTCFLLD(6.013836e-01), QTCFLLD(6.568868e-07), + QTCFLLD(8.181074e-05), QTCFLLD(1.351651e-03), QTCFLLD(-2.556970e-03), + QTCFLLD(5.681393e-01), QTCFLLD(-5.690228e-06), QTCFLLD(9.126098e-05), + QTCFLLD(7.570286e-04), QTCFLLD(-2.218904e-02), QTCFLLD(5.347272e-01), + QTCFLLD(1.884389e-05), QTCFLLD(-2.705446e-04), QTCFLLD(5.337144e-04), + QTCFLLD(-4.317467e-02), QTCFLLD(5.011593e-01), QTCFLLD(-1.329252e-06), + QTCFLLD(-7.198660e-05), QTCFLLD(2.941296e-05), QTCFLLD(-6.547049e-02), + QTCFLLD(4.674168e-01), QTCFLLD(-1.355524e-07), QTCFLLD(5.942472e-05), + QTCFLLD(-4.468657e-04), QTCFLLD(-8.902535e-02), QTCFLLD(4.335079e-01), + QTCFLLD(1.041631e-05), QTCFLLD(6.091853e-05), QTCFLLD(-8.704047e-04), + QTCFLLD(-1.138130e-01), QTCFLLD(3.995200e-01), QTCFLLD(-1.170911e-05), + QTCFLLD(-2.623833e-05), QTCFLLD(-1.207570e-03), QTCFLLD(-1.397967e-01), + QTCFLLD(3.656086e-01), QTCFLLD(-1.364079e-06), QTCFLLD(8.097173e-06), + QTCFLLD(-1.589852e-03), QTCFLLD(-1.669302e-01), QTCFLLD(3.319187e-01), + QTCFLLD(-5.342262e-07), QTCFLLD(3.005858e-05), QTCFLLD(-2.038612e-03), + QTCFLLD(-1.951630e-01), QTCFLLD(2.984839e-01), QTCFLLD(-1.099320e-06), + QTCFLLD(8.977871e-05), QTCFLLD(-2.525111e-03), QTCFLLD(-2.244371e-01), + QTCFLLD(2.651577e-01), QTCFLLD(-7.121587e-07), QTCFLLD(1.848150e-04), + QTCFLLD(-3.068126e-03), QTCFLLD(-2.546924e-01), QTCFLLD(2.316523e-01), + QTCFLLD(-9.617199e-07), QTCFLLD(2.433794e-04), QTCFLLD(-3.658572e-03), + QTCFLLD(-2.858681e-01), QTCFLLD(1.977098e-01), QTCFLLD(-1.848464e-06), + QTCFLLD(2.857057e-04), QTCFLLD(-4.291316e-03), QTCFLLD(-3.178928e-01), + QTCFLLD(1.633594e-01), QTCFLLD(1.509004e-05), QTCFLLD(7.026758e-04), + QTCFLLD(-4.909021e-03), QTCFLLD(-3.506784e-01), QTCFLLD(1.291537e-01), + QTCFLLD(-2.901422e-06), QTCFLLD(9.784381e-04), QTCFLLD(-5.567837e-03), + QTCFLLD(-3.841116e-01), QTCFLLD(9.625038e-02), QTCFLLD(-2.035140e-05), + QTCFLLD(1.105966e-03), QTCFLLD(-6.304841e-03), QTCFLLD(-4.180555e-01), + QTCFLLD(6.622328e-02), QTCFLLD(-3.077146e-05), QTCFLLD(1.201814e-03), + QTCFLLD(-7.152842e-03), QTCFLLD(-4.523680e-01), QTCFLLD(4.042707e-02), + QTCFLLD(-3.836153e-05), QTCFLLD(1.275694e-03), QTCFLLD(-8.142071e-03), + QTCFLLD(-4.869413e-01), QTCFLLD(1.741320e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_160[QMF160_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.114156e-07), QTCFLLD(-4.929378e-06), QTCFLLD(-1.173270e-03), + QTCFLLD(9.985781e-03), QTCFLLD(5.385081e-01), QTCFLLD(2.119298e-07), + QTCFLLD(8.001152e-06), QTCFLLD(-9.578346e-04), QTCFLLD(1.315910e-02), + QTCFLLD(6.066454e-01), QTCFLLD(8.097845e-07), QTCFLLD(1.849027e-05), + QTCFLLD(-1.219567e-03), QTCFLLD(1.721718e-02), QTCFLLD(6.734486e-01), + QTCFLLD(-1.135478e-08), QTCFLLD(5.632976e-06), QTCFLLD(-7.392278e-04), + QTCFLLD(2.226388e-02), QTCFLLD(7.376929e-01), QTCFLLD(6.347751e-08), + QTCFLLD(1.454425e-05), QTCFLLD(-1.105239e-04), QTCFLLD(2.845808e-02), + QTCFLLD(7.981848e-01), QTCFLLD(-2.838328e-06), QTCFLLD(3.414749e-06), + QTCFLLD(1.272254e-03), QTCFLLD(3.594821e-02), QTCFLLD(8.539265e-01), + QTCFLLD(7.116049e-08), QTCFLLD(4.031125e-05), QTCFLLD(2.136304e-03), + QTCFLLD(4.477318e-02), QTCFLLD(9.038135e-01), QTCFLLD(4.098227e-07), + QTCFLLD(7.484240e-05), QTCFLLD(2.716078e-03), QTCFLLD(5.502766e-02), + QTCFLLD(9.466825e-01), QTCFLLD(4.934327e-07), QTCFLLD(7.557725e-05), + QTCFLLD(2.058748e-03), QTCFLLD(6.626062e-02), QTCFLLD(9.818396e-01), + QTCFLLD(-4.933896e-08), QTCFLLD(-3.907360e-05), QTCFLLD(3.753964e-04), + QTCFLLD(7.806610e-02), QTCFLLD(1.008988e+00), QTCFLLD(-7.856341e-06), + QTCFLLD(9.949480e-05), QTCFLLD(7.176331e-04), QTCFLLD(8.987702e-02), + QTCFLLD(1.027784e+00), QTCFLLD(4.822448e-07), QTCFLLD(-1.327914e-05), + QTCFLLD(6.855222e-04), QTCFLLD(1.011847e-01), QTCFLLD(1.038242e+00), + QTCFLLD(4.432684e-07), QTCFLLD(-5.662008e-05), QTCFLLD(5.360314e-04), + QTCFLLD(1.112756e-01), QTCFLLD(1.041439e+00), QTCFLLD(-1.894204e-06), + QTCFLLD(-1.603894e-04), QTCFLLD(-2.796433e-04), QTCFLLD(1.193894e-01), + QTCFLLD(1.038456e+00), QTCFLLD(2.350541e-06), QTCFLLD(-1.981793e-04), + QTCFLLD(-1.719967e-03), QTCFLLD(1.249437e-01), QTCFLLD(1.028407e+00), + QTCFLLD(4.833713e-06), QTCFLLD(-1.957799e-04), QTCFLLD(-3.159640e-03), + QTCFLLD(1.274605e-01), QTCFLLD(1.009701e+00), QTCFLLD(4.724263e-06), + QTCFLLD(-1.181518e-05), QTCFLLD(-4.243399e-03), QTCFLLD(1.270390e-01), + QTCFLLD(9.748854e-01), QTCFLLD(1.007724e-06), QTCFLLD(2.585741e-05), + QTCFLLD(-4.713445e-03), QTCFLLD(1.231120e-01), QTCFLLD(9.246770e-01), + QTCFLLD(2.908454e-06), QTCFLLD(3.137374e-05), QTCFLLD(-4.230293e-03), + QTCFLLD(1.144269e-01), QTCFLLD(8.681067e-01), QTCFLLD(-4.128877e-08), + QTCFLLD(1.870358e-05), QTCFLLD(-2.842924e-03), QTCFLLD(1.003715e-01), + QTCFLLD(8.080344e-01), QTCFLLD(1.806649e-07), QTCFLLD(3.557071e-05), + QTCFLLD(-8.392422e-04), QTCFLLD(8.065225e-02), QTCFLLD(7.464405e-01), + QTCFLLD(2.352609e-06), QTCFLLD(1.090077e-04), QTCFLLD(7.497848e-04), + QTCFLLD(5.529631e-02), QTCFLLD(6.831591e-01), QTCFLLD(1.159657e-07), + QTCFLLD(4.585990e-05), QTCFLLD(2.079346e-03), QTCFLLD(2.434883e-02), + QTCFLLD(6.179208e-01), QTCFLLD(8.859606e-07), QTCFLLD(1.403345e-04), + QTCFLLD(1.065580e-03), QTCFLLD(-1.220572e-02), QTCFLLD(5.514521e-01), + QTCFLLD(-1.038278e-06), QTCFLLD(-1.368162e-04), QTCFLLD(2.932339e-04), + QTCFLLD(-5.416374e-02), QTCFLLD(4.843109e-01), QTCFLLD(7.820030e-08), + QTCFLLD(3.934544e-05), QTCFLLD(-6.638491e-04), QTCFLLD(-1.012664e-01), + QTCFLLD(4.165150e-01), QTCFLLD(-8.393432e-06), QTCFLLD(-5.053646e-05), + QTCFLLD(-1.381912e-03), QTCFLLD(-1.532225e-01), QTCFLLD(3.487301e-01), + QTCFLLD(-1.455897e-06), QTCFLLD(4.880962e-05), QTCFLLD(-2.274392e-03), + QTCFLLD(-2.096737e-01), QTCFLLD(2.818234e-01), QTCFLLD(-1.434317e-06), + QTCFLLD(2.203687e-04), QTCFLLD(-3.357312e-03), QTCFLLD(-2.701693e-01), + QTCFLLD(2.147441e-01), QTCFLLD(7.092199e-06), QTCFLLD(4.681670e-04), + QTCFLLD(-4.601593e-03), QTCFLLD(-3.341968e-01), QTCFLLD(1.461805e-01), + QTCFLLD(-1.116123e-05), QTCFLLD(1.072196e-03), QTCFLLD(-5.925141e-03), + QTCFLLD(-4.010285e-01), QTCFLLD(8.077862e-02), QTCFLLD(-3.775385e-05), + QTCFLLD(1.244841e-03), QTCFLLD(-7.628469e-03), QTCFLLD(-4.696240e-01), + QTCFLLD(2.901889e-02), +}; + +RAM_ALIGN +const FIXP_PFT qmf_cldfb_80[QMF80_CLDFB_PFT_TABLE_SIZE] = { + QTCFLLD(6.966921e-07), QTCFLLD(9.025176e-06), QTCFLLD(-1.073328e-03), + QTCFLLD(1.146585e-02), QTCFLLD(5.726758e-01), QTCFLLD(-2.323046e-09), + QTCFLLD(1.012638e-05), QTCFLLD(-1.084654e-03), QTCFLLD(1.960515e-02), + QTCFLLD(7.059712e-01), QTCFLLD(1.230159e-07), QTCFLLD(4.639126e-05), + QTCFLLD(6.398911e-04), QTCFLLD(3.204506e-02), QTCFLLD(8.267125e-01), + QTCFLLD(2.865339e-07), QTCFLLD(6.273759e-05), QTCFLLD(2.550464e-03), + QTCFLLD(4.977453e-02), QTCFLLD(9.261818e-01), QTCFLLD(3.738257e-07), + QTCFLLD(-2.429021e-06), QTCFLLD(1.375921e-03), QTCFLLD(7.212754e-02), + QTCFLLD(9.964333e-01), QTCFLLD(1.077039e-08), QTCFLLD(-8.532976e-06), + QTCFLLD(7.147022e-04), QTCFLLD(9.563432e-02), QTCFLLD(1.034012e+00), + QTCFLLD(3.086046e-07), QTCFLLD(-7.986870e-05), QTCFLLD(2.203781e-04), + QTCFLLD(1.156221e-01), QTCFLLD(1.040718e+00), QTCFLLD(5.542804e-06), + QTCFLLD(-1.736757e-04), QTCFLLD(-2.475428e-03), QTCFLLD(1.266206e-01), + QTCFLLD(1.020100e+00), QTCFLLD(3.415168e-06), QTCFLLD(6.290201e-06), + QTCFLLD(-4.576709e-03), QTCFLLD(1.256370e-01), QTCFLLD(9.506344e-01), + QTCFLLD(-1.998632e-09), QTCFLLD(3.017514e-05), QTCFLLD(-3.627394e-03), + QTCFLLD(1.081003e-01), QTCFLLD(8.383245e-01), QTCFLLD(2.590900e-07), + QTCFLLD(9.614004e-05), QTCFLLD(2.183786e-06), QTCFLLD(6.867141e-02), + QTCFLLD(7.150523e-01), QTCFLLD(1.408172e-07), QTCFLLD(5.203217e-05), + QTCFLLD(1.584410e-03), QTCFLLD(6.753749e-03), QTCFLLD(5.847858e-01), + QTCFLLD(-9.234326e-07), QTCFLLD(6.477183e-06), QTCFLLD(-2.123969e-04), + QTCFLLD(-7.709230e-02), QTCFLLD(4.504798e-01), QTCFLLD(-2.464033e-08), + QTCFLLD(1.888626e-05), QTCFLLD(-1.812003e-03), QTCFLLD(-1.809127e-01), + QTCFLLD(3.151743e-01), QTCFLLD(-8.344882e-07), QTCFLLD(2.538528e-04), + QTCFLLD(-3.972626e-03), QTCFLLD(-3.017793e-01), QTCFLLD(1.805658e-01), + QTCFLLD(-2.720526e-05), QTCFLLD(1.150009e-03), QTCFLLD(-6.712822e-03), + QTCFLLD(-4.351740e-01), QTCFLLD(5.276687e-02), +}; + +#if defined(QMF_COEFF_16BIT) +#define QTMFLLD(x) FL2FXCONST_SGL(x / (float)(1 << QMF_MPSLDFB_PFT_SCALE)) +#define QTMFLLDT(x) FX_DBL2FXCONST_SGL(x) +#else +#define QTMFLLD(x) FL2FXCONST_DBL(x / (float)(1 << QMF_MPSLDFB_PFT_SCALE)) +#define QTMFLLDT(x) (FIXP_DBL)(x) +#endif + +/*! + \name QMF + \brief QMF-Table + 32 channels, N = 320, + + The coefficients are derived from the MPS Low Delay coefficient set + with 640 samples. The coefficients are interpolated and rearranged + in the following way compared to the reference: + + qmf_mpsldfb_320[0] = (qmf_64_reference[ 0] + qmf_64_reference[ 1])/2.0; + qmf_mpsldfb_320[1] = (qmf_64_reference[128] + qmf_64_reference[129])/2.0; + qmf_mpsldfb_320[2] = (qmf_64_reference[256] + qmf_64_reference[257])/2.0; + qmf_mpsldfb_320[3] = (qmf_64_reference[384] + qmf_64_reference[385])/2.0; + qmf_mpsldfb_320[4] = (qmf_64_reference[512] + qmf_64_reference[513])/2.0; + + qmf_mpsldfb_320[5] = (qmf_64_reference[ 2] + qmf_64_reference[ 3])/2.0; + qmf_mpsldfb_320[6] = (qmf_64_reference[130] + qmf_64_reference[131])/2.0; + qmf_mpsldfb_320[7] = (qmf_64_reference[258] + qmf_64_reference[259])/2.0; + qmf_mpsldfb_320[8] = (qmf_64_reference[386] + qmf_64_reference[387])/2.0; + qmf_mpsldfb_320[9] = (qmf_64_reference[514] + qmf_64_reference[515])/2.0; + . + . + . + qmf_mpsldfb_320[315] = (qmf_64_reference[126] + qmf_64_reference[127])/2.0; + qmf_mpsldfb_320[316] = (qmf_64_reference[254] + qmf_64_reference[255])/2.0; + qmf_mpsldfb_320[317] = (qmf_64_reference[382] + qmf_64_reference[383])/2.0; + qmf_mpsldfb_320[318] = (qmf_64_reference[510] + qmf_64_reference[511])/2.0; + qmf_mpsldfb_320[319] = (qmf_64_reference[638] + qmf_64_reference[639])/2.0; + + The filter output is required to be scaled by 1 bit. + + \showinitializer +*/ +//@{ +const FIXP_PFT qmf_mpsldfb_320[QMF320_MPSLDFB_PFT_TABLE_SIZE] = { + QTMFLLD(1.0777725402e-004), QTMFLLD(-9.4703806099e-004), + QTMFLLD(6.1286436394e-003), QTMFLLD(-9.0161964297e-002), + QTMFLLD(5.5554401875e-001), QTMFLLD(1.2731316383e-004), + QTMFLLD(-1.2311334722e-003), QTMFLLD(4.9468209036e-003), + QTMFLLD(-1.1305026710e-001), QTMFLLD(5.2990418673e-001), + QTMFLLD(1.1927412561e-004), QTMFLLD(-1.5128203668e-003), + QTMFLLD(3.5794533323e-003), QTMFLLD(-1.3681203127e-001), + QTMFLLD(5.0423312187e-001), QTMFLLD(1.0006380762e-004), + QTMFLLD(-1.7925058492e-003), QTMFLLD(2.0164034795e-003), + QTMFLLD(-1.6139641404e-001), QTMFLLD(4.7861024737e-001), + QTMFLLD(7.2826202086e-005), QTMFLLD(-2.0697340369e-003), + QTMFLLD(2.4838969694e-004), QTMFLLD(-1.8674756587e-001), + QTMFLLD(4.5311337709e-001), QTMFLLD(3.8808015233e-005), + QTMFLLD(-2.3429044522e-003), QTMFLLD(-1.7331546405e-003), + QTMFLLD(-2.1280488372e-001), QTMFLLD(4.2781800032e-001), + QTMFLLD(-5.4359588830e-007), QTMFLLD(-2.6112669148e-003), + QTMFLLD(-3.9357249625e-003), QTMFLLD(-2.3950359225e-001), + QTMFLLD(4.0279802680e-001), QTMFLLD(-4.3614549213e-005), + QTMFLLD(-2.8741455171e-003), QTMFLLD(-6.3655078411e-003), + QTMFLLD(-2.6677471399e-001), QTMFLLD(3.7812507153e-001), + QTMFLLD(-8.9040157036e-005), QTMFLLD(-3.1308881007e-003), + QTMFLLD(-9.0275555849e-003), QTMFLLD(-2.9454550147e-001), + QTMFLLD(3.5386830568e-001), QTMFLLD(-1.3519046479e-004), + QTMFLLD(-3.3808732405e-003), QTMFLLD(-1.1925406754e-002), + QTMFLLD(-3.2273942232e-001), QTMFLLD(3.3009397984e-001), + QTMFLLD(-1.8045579782e-004), QTMFLLD(-3.6236830056e-003), + QTMFLLD(-1.5061311424e-002), QTMFLLD(-3.5127705336e-001), + QTMFLLD(3.0686509609e-001), QTMFLLD(-2.2396800341e-004), + QTMFLLD(-3.8587960880e-003), QTMFLLD(-1.8435835838e-002), + QTMFLLD(-3.8007527590e-001), QTMFLLD(2.8424069285e-001), + QTMFLLD(-2.6416976471e-004), QTMFLLD(-4.0859002620e-003), + QTMFLLD(-2.2048022598e-002), QTMFLLD(-4.0904915333e-001), + QTMFLLD(2.6227575541e-001), QTMFLLD(-3.0001887353e-004), + QTMFLLD(-4.3045589700e-003), QTMFLLD(-2.5894984603e-002), + QTMFLLD(-4.3811064959e-001), QTMFLLD(2.4102044106e-001), + QTMFLLD(-3.3083156450e-004), QTMFLLD(-4.5145484619e-003), + QTMFLLD(-2.9972121119e-002), QTMFLLD(-4.6717000008e-001), + QTMFLLD(2.2052007914e-001), QTMFLLD(-3.5614447552e-004), + QTMFLLD(-4.7155953944e-003), QTMFLLD(-3.4272894263e-002), + QTMFLLD(-4.9613577127e-001), QTMFLLD(2.0081442595e-001), + QTMFLLD(-3.7579826312e-004), QTMFLLD(-4.9072988331e-003), + QTMFLLD(-3.8788780570e-002), QTMFLLD(-5.2491527796e-001), + QTMFLLD(1.8193808198e-001), QTMFLLD(-3.8993739872e-004), + QTMFLLD(-5.0893351436e-003), QTMFLLD(-4.3509010226e-002), + QTMFLLD(-5.5341482162e-001), QTMFLLD(1.6391974688e-001), + QTMFLLD(-3.9912899956e-004), QTMFLLD(-5.2615385503e-003), + QTMFLLD(-4.8421185464e-002), QTMFLLD(-5.8154034615e-001), + QTMFLLD(1.4678207040e-001), QTMFLLD(-4.0421969607e-004), + QTMFLLD(-5.4236799479e-003), QTMFLLD(-5.3510606289e-002), + QTMFLLD(-6.0919785500e-001), QTMFLLD(1.3054165244e-001), + QTMFLLD(-4.0645478293e-004), QTMFLLD(-5.5756671354e-003), + QTMFLLD(-5.8760054410e-002), QTMFLLD(-6.3629388809e-001), + QTMFLLD(1.1520925164e-001), QTMFLLD(-4.0720938705e-004), + QTMFLLD(-5.7173836976e-003), QTMFLLD(-6.4149998128e-002), + QTMFLLD(-6.6273581982e-001), QTMFLLD(1.0078965127e-001), + QTMFLLD(-4.0812738007e-004), QTMFLLD(-5.8488911018e-003), + QTMFLLD(-6.9658569992e-002), QTMFLLD(-6.8843221664e-001), + QTMFLLD(8.7281554937e-002), QTMFLLD(-4.1120912647e-004), + QTMFLLD(-5.9703430161e-003), QTMFLLD(-7.5261354446e-002), + QTMFLLD(-7.1329379082e-001), QTMFLLD(7.4678033590e-002), + QTMFLLD(-4.1838851757e-004), QTMFLLD(-6.0821287334e-003), + QTMFLLD(-8.0931767821e-002), QTMFLLD(-7.3723363876e-001), + QTMFLLD(6.2966249883e-002), QTMFLLD(-4.3148122495e-004), + QTMFLLD(-6.1847940087e-003), QTMFLLD(-8.6640790105e-002), + QTMFLLD(-7.6016783714e-001), QTMFLLD(5.2128262818e-002), + QTMFLLD(-4.5229538227e-004), QTMFLLD(-6.2791546807e-003), + QTMFLLD(-9.2357128859e-002), QTMFLLD(-7.8201586008e-001), + QTMFLLD(4.2139917612e-002), QTMFLLD(-4.8211280955e-004), + QTMFLLD(-6.3661932945e-003), QTMFLLD(-9.8047181964e-002), + QTMFLLD(-8.0270123482e-001), QTMFLLD(3.2972395420e-002), + QTMFLLD(-5.2196672186e-004), QTMFLLD(-6.4471233636e-003), + QTMFLLD(-1.0367526114e-001), QTMFLLD(-8.2215231657e-001), + QTMFLLD(2.4589803070e-002), QTMFLLD(-5.7247944642e-004), + QTMFLLD(-6.5232971683e-003), QTMFLLD(-1.0920339823e-001), + QTMFLLD(-8.4030228853e-001), QTMFLLD(1.6952158883e-002), + QTMFLLD(-6.3343788497e-004), QTMFLLD(-6.5963375382e-003), + QTMFLLD(-1.1459194124e-001), QTMFLLD(-8.5709118843e-001), + QTMFLLD(1.0006074794e-002), QTMFLLD(-7.0449430496e-004), + QTMFLLD(-6.6681848839e-003), QTMFLLD(-1.1979964375e-001), + QTMFLLD(-8.7246519327e-001), QTMFLLD(3.6968050990e-003), + QTMFLLD(-7.9609593377e-004), QTMFLLD(-6.7403013818e-003), + QTMFLLD(-1.2478165329e-001), QTMFLLD(-8.8632321358e-001), + QTMFLLD(-1.6344460892e-003), QTMFLLD(-9.0200459817e-004), + QTMFLLD(-6.8151149899e-003), QTMFLLD(-1.2949258089e-001), + QTMFLLD(-8.9860773087e-001), QTMFLLD(-5.9283543378e-003), + QTMFLLD(-1.0116943158e-003), QTMFLLD(-6.8955891766e-003), + QTMFLLD(-1.3388808072e-001), QTMFLLD(-9.0933418274e-001), + QTMFLLD(-9.6466485411e-003), QTMFLLD(-1.1244935449e-003), + QTMFLLD(-6.9835213944e-003), QTMFLLD(-1.3791990280e-001), + QTMFLLD(-9.1846722364e-001), QTMFLLD(-1.2838950381e-002), + QTMFLLD(-1.2393904617e-003), QTMFLLD(-7.0809246972e-003), + QTMFLLD(-1.4153905213e-001), QTMFLLD(-9.2597639561e-001), + QTMFLLD(-1.5539921820e-002), QTMFLLD(-1.3542033266e-003), + QTMFLLD(-7.1895248257e-003), QTMFLLD(-1.4469626546e-001), + QTMFLLD(-9.3183851242e-001), QTMFLLD(-1.7783239484e-002), + QTMFLLD(-1.4669501688e-003), QTMFLLD(-7.3110014200e-003), + QTMFLLD(-1.4734169841e-001), QTMFLLD(-9.3603670597e-001), + QTMFLLD(-1.9597738981e-002), QTMFLLD(-1.5753224725e-003), + QTMFLLD(-7.4466220103e-003), QTMFLLD(-1.4942565560e-001), + QTMFLLD(-9.3856132030e-001), QTMFLLD(-2.1011535078e-002), + QTMFLLD(-1.6771152150e-003), QTMFLLD(-7.5972955674e-003), + QTMFLLD(-1.5089863539e-001), QTMFLLD(-9.3940949440e-001), + QTMFLLD(-2.2049814463e-002), QTMFLLD(-1.7698677257e-003), + QTMFLLD(-7.7634919435e-003), QTMFLLD(-1.5171185136e-001), + QTMFLLD(-9.3858534098e-001), QTMFLLD(-2.2738276049e-002), + QTMFLLD(-1.8512960523e-003), QTMFLLD(-7.9450644553e-003), + QTMFLLD(-1.5181747079e-001), QTMFLLD(-9.3610012531e-001), + QTMFLLD(-2.3101080209e-002), QTMFLLD(-1.9192657201e-003), + QTMFLLD(-8.1413704902e-003), QTMFLLD(-1.5116891265e-001), + QTMFLLD(-9.3197190762e-001), QTMFLLD(-2.3163486272e-002), + QTMFLLD(-1.9716904499e-003), QTMFLLD(-8.3509404212e-003), + QTMFLLD(-1.4972095191e-001), QTMFLLD(-9.2622530460e-001), + QTMFLLD(-2.2950030863e-002), QTMFLLD(-2.0066620782e-003), + QTMFLLD(-8.5715763271e-003), QTMFLLD(-1.4743055403e-001), + QTMFLLD(-9.1889131069e-001), QTMFLLD(-2.2486699745e-002), + QTMFLLD(-2.0227057394e-003), QTMFLLD(-8.8005559519e-003), + QTMFLLD(-1.4425669611e-001), QTMFLLD(-9.1000711918e-001), + QTMFLLD(-2.1799135953e-002), QTMFLLD(-2.0185527392e-003), + QTMFLLD(-9.0341167524e-003), QTMFLLD(-1.4016106725e-001), + QTMFLLD(-8.9961612225e-001), QTMFLLD(-2.0914383233e-002), + QTMFLLD(-1.9932338037e-003), QTMFLLD(-9.2674419284e-003), + QTMFLLD(-1.3510815799e-001), QTMFLLD(-8.8776648045e-001), + QTMFLLD(-1.9859094173e-002), QTMFLLD(-1.9461065531e-003), + QTMFLLD(-9.4948727638e-003), QTMFLLD(-1.2906542420e-001), + QTMFLLD(-8.7451159954e-001), QTMFLLD(-1.8660902977e-002), + QTMFLLD(-1.8770052120e-003), QTMFLLD(-9.7100129351e-003), + QTMFLLD(-1.2200380862e-001), QTMFLLD(-8.5991013050e-001), + QTMFLLD(-1.7346922308e-002), QTMFLLD(-1.7859865911e-003), + QTMFLLD(-9.9056493491e-003), QTMFLLD(-1.1389782280e-001), + QTMFLLD(-8.4402561188e-001), QTMFLLD(-1.5944939107e-002), + QTMFLLD(-1.6734169330e-003), QTMFLLD(-1.0073989630e-002), + QTMFLLD(-1.0472598672e-001), QTMFLLD(-8.2692527771e-001), + QTMFLLD(-1.4481747523e-002), QTMFLLD(-1.5399802942e-003), + QTMFLLD(-1.0205906816e-002), QTMFLLD(-9.4470888376e-002), + QTMFLLD(-8.0868041515e-001), QTMFLLD(-1.2984249741e-002), + QTMFLLD(-1.3865872752e-003), QTMFLLD(-1.0291703977e-002), + QTMFLLD(-8.3119556308e-002), QTMFLLD(-7.8936588764e-001), + QTMFLLD(-1.1477986351e-002), QTMFLLD(-1.2144348584e-003), + QTMFLLD(-1.0320962407e-002), QTMFLLD(-7.0663399994e-002), + QTMFLLD(-7.6905936003e-001), QTMFLLD(-9.9884867668e-003), + QTMFLLD(-1.0248266626e-003), QTMFLLD(-1.0282764211e-002), + QTMFLLD(-5.7098604739e-002), QTMFLLD(-7.4784147739e-001), + QTMFLLD(-8.5393209010e-003), QTMFLLD(-8.1919803051e-004), + QTMFLLD(-1.0165717453e-002), QTMFLLD(-4.2426198721e-002), + QTMFLLD(-7.2579479218e-001), QTMFLLD(-7.1533406153e-003), + QTMFLLD(-5.9914286248e-004), QTMFLLD(-9.9579729140e-003), + QTMFLLD(-2.6652012020e-002), QTMFLLD(-7.0300412178e-001), + QTMFLLD(-5.8508114889e-003), QTMFLLD(-3.6626873771e-004), + QTMFLLD(-9.6475090832e-003), QTMFLLD(-9.7871217877e-003), + QTMFLLD(-6.7955517769e-001), QTMFLLD(-4.6512838453e-003), + QTMFLLD(-1.2227181287e-004), QTMFLLD(-9.2221321538e-003), + QTMFLLD(8.1523396075e-003), QTMFLLD(-6.5553492308e-001), + QTMFLLD(-3.5699680448e-003), QTMFLLD(1.3090072025e-004), + QTMFLLD(-8.6695179343e-003), QTMFLLD(2.7145106345e-002), + QTMFLLD(-6.3103044033e-001), QTMFLLD(-2.6181070134e-003), + QTMFLLD(3.9128778735e-004), QTMFLLD(-7.9773496836e-003), + QTMFLLD(4.7164849937e-002), QTMFLLD(-6.0613000393e-001), + QTMFLLD(-1.7908872105e-003), QTMFLLD(6.5761915175e-004), + QTMFLLD(-7.1337916888e-003), QTMFLLD(6.8181537092e-002), + QTMFLLD(-5.8092808723e-001), QTMFLLD(-1.0135001503e-003)}; + +/*! + \name QMF + \brief QMF-Table + 64 channels, N = 640, + + The coeffs are rearranged compared with the reference in the following + way: + + qmf_64[0] = qmf_64_reference[0]; + qmf_64[1] = qmf_64_reference[128]; + qmf_64[2] = qmf_64_reference[256]; + qmf_64[3] = qmf_64_reference[384]; + qmf_64[4] = qmf_64_reference[512]; + + qmf_64[5] = qmf_64_reference[1]; + qmf_64[6] = qmf_64_reference[129]; + qmf_64[7] = qmf_64_reference[257]; + qmf_64[8] = qmf_64_reference[385]; + qmf_64[9] = qmf_64_reference[513]; + . + . + . + qmf_64[635] = qmf_64_reference[127] + qmf_64[636] = qmf_64_reference[255]; + qmf_64[637] = qmf_64_reference[383]; + qmf_64[638] = qmf_64_reference[511]; + qmf_64[639] = qmf_64_reference[639]; + + The filter output is required to be scaled by 1 bit. + + \showinitializer +*/ +//@{ +LNK_SECTION_CONSTDATA_L1 +RAM_ALIGN +const FIXP_PFT qmf_mpsldfb_640[QMF640_MPSLDFB_PFT_TABLE_SIZE] = { + QTMFLLD(9.3863010989e-005), QTMFLLD(-8.7536586216e-004), + QTMFLLD(6.4016343094e-003), QTMFLLD(-8.4552817047e-002), + QTMFLLD(5.6194400787e-001), QTMFLLD(1.2169149704e-004), + QTMFLLD(-1.0187102016e-003), QTMFLLD(5.8556534350e-003), + QTMFLLD(-9.5771118999e-002), QTMFLLD(5.4914402962e-001), + QTMFLLD(1.2793767382e-004), QTMFLLD(-1.1605311884e-003), + QTMFLLD(5.2649765275e-003), QTMFLLD(-1.0721673071e-001), + QTMFLLD(5.3632181883e-001), QTMFLLD(1.2668863928e-004), + QTMFLLD(-1.3017356396e-003), QTMFLLD(4.6286652796e-003), + QTMFLLD(-1.1888379604e-001), QTMFLLD(5.2348655462e-001), + QTMFLLD(1.2296593923e-004), QTMFLLD(-1.4426353155e-003), + QTMFLLD(3.9453012869e-003), QTMFLLD(-1.3076621294e-001), + QTMFLLD(5.1064836979e-001), QTMFLLD(1.1558231199e-004), + QTMFLLD(-1.5830053017e-003), QTMFLLD(3.2136053778e-003), + QTMFLLD(-1.4285783470e-001), QTMFLLD(4.9781781435e-001), + QTMFLLD(1.0582985124e-004), QTMFLLD(-1.7228506040e-003), + QTMFLLD(2.4323666003e-003), QTMFLLD(-1.5515175462e-001), + QTMFLLD(4.8500382900e-001), QTMFLLD(9.4297764008e-005), + QTMFLLD(-1.8621610943e-003), QTMFLLD(1.6004402423e-003), + QTMFLLD(-1.6764105856e-001), QTMFLLD(4.7221666574e-001), + QTMFLLD(8.0514568253e-005), QTMFLLD(-2.0008818246e-003), + QTMFLLD(7.1672687773e-004), QTMFLLD(-1.8031860888e-001), + QTMFLLD(4.5946595073e-001), QTMFLLD(6.5137835918e-005), + QTMFLLD(-2.1385864820e-003), QTMFLLD(-2.1994746930e-004), + QTMFLLD(-1.9317652285e-001), QTMFLLD(4.4676083326e-001), + QTMFLLD(4.8101064749e-005), QTMFLLD(-2.2751907818e-003), + QTMFLLD(-1.2104592752e-003), QTMFLLD(-2.0620720088e-001), + QTMFLLD(4.3411090970e-001), QTMFLLD(2.9514967537e-005), + QTMFLLD(-2.4106178898e-003), QTMFLLD(-2.2558500059e-003), + QTMFLLD(-2.1940255165e-001), QTMFLLD(4.2152509093e-001), + QTMFLLD(9.8814107332e-006), QTMFLLD(-2.5448307861e-003), + QTMFLLD(-3.3569468651e-003), QTMFLLD(-2.3275400698e-001), + QTMFLLD(4.0901294351e-001), QTMFLLD(-1.0968602510e-005), + QTMFLLD(-2.6777030434e-003), QTMFLLD(-4.5145032927e-003), + QTMFLLD(-2.4625316262e-001), QTMFLLD(3.9658311009e-001), + QTMFLLD(-3.2559255487e-005), QTMFLLD(-2.8091520071e-003), + QTMFLLD(-5.7292259298e-003), QTMFLLD(-2.5989097357e-001), + QTMFLLD(3.8424444199e-001), QTMFLLD(-5.4669842939e-005), + QTMFLLD(-2.9391390271e-003), QTMFLLD(-7.0017897524e-003), + QTMFLLD(-2.7365845442e-001), QTMFLLD(3.7200567126e-001), + QTMFLLD(-7.7506563684e-005), QTMFLLD(-3.0675258022e-003), + QTMFLLD(-8.3327051252e-003), QTMFLLD(-2.8754624724e-001), + QTMFLLD(3.5987523198e-001), QTMFLLD(-1.0057374311e-004), + QTMFLLD(-3.1942503992e-003), QTMFLLD(-9.7224051133e-003), + QTMFLLD(-3.0154475570e-001), QTMFLLD(3.4786140919e-001), + QTMFLLD(-1.2368557509e-004), QTMFLLD(-3.3192564733e-003), + QTMFLLD(-1.1171258055e-002), QTMFLLD(-3.1564420462e-001), + QTMFLLD(3.3597227931e-001), QTMFLLD(-1.4669535449e-004), + QTMFLLD(-3.4424900077e-003), QTMFLLD(-1.2679555453e-002), + QTMFLLD(-3.2983466983e-001), QTMFLLD(3.2421571016e-001), + QTMFLLD(-1.6928518016e-004), QTMFLLD(-3.5639149137e-003), + QTMFLLD(-1.4247507788e-002), QTMFLLD(-3.4410607815e-001), + QTMFLLD(3.1259948015e-001), QTMFLLD(-1.9162640092e-004), + QTMFLLD(-3.6834510975e-003), QTMFLLD(-1.5875114128e-002), + QTMFLLD(-3.5844799876e-001), QTMFLLD(3.0113074183e-001), + QTMFLLD(-2.1345751884e-004), QTMFLLD(-3.8009947166e-003), + QTMFLLD(-1.7562393099e-002), QTMFLLD(-3.7284970284e-001), + QTMFLLD(2.8981682658e-001), QTMFLLD(-2.3447850253e-004), + QTMFLLD(-3.9165974595e-003), QTMFLLD(-1.9309276715e-002), + QTMFLLD(-3.8730087876e-001), QTMFLLD(2.7866455913e-001), + QTMFLLD(-2.5462667691e-004), QTMFLLD(-4.0301652625e-003), + QTMFLLD(-2.1115457639e-002), QTMFLLD(-4.0179058909e-001), + QTMFLLD(2.6768052578e-001), QTMFLLD(-2.7371285250e-004), + QTMFLLD(-4.1416347958e-003), QTMFLLD(-2.2980585694e-002), + QTMFLLD(-4.1630774736e-001), QTMFLLD(2.5687095523e-001), + QTMFLLD(-2.9165804153e-004), QTMFLLD(-4.2509674095e-003), + QTMFLLD(-2.4904217571e-002), QTMFLLD(-4.3084129691e-001), + QTMFLLD(2.4624188244e-001), QTMFLLD(-3.0837973463e-004), + QTMFLLD(-4.3581505306e-003), QTMFLLD(-2.6885753497e-002), + QTMFLLD(-4.4538003206e-001), QTMFLLD(2.3579898477e-001), + QTMFLLD(-3.2378203468e-004), QTMFLLD(-4.4631510973e-003), + QTMFLLD(-2.8924530372e-002), QTMFLLD(-4.5991250873e-001), + QTMFLLD(2.2554755211e-001), QTMFLLD(-3.3788106521e-004), + QTMFLLD(-4.5659458265e-003), QTMFLLD(-3.1019711867e-002), + QTMFLLD(-4.7442746162e-001), QTMFLLD(2.1549259126e-001), + QTMFLLD(-3.5053401371e-004), QTMFLLD(-4.6664695255e-003), + QTMFLLD(-3.3170353621e-002), QTMFLLD(-4.8891320825e-001), + QTMFLLD(2.0563863218e-001), QTMFLLD(-3.6175493733e-004), + QTMFLLD(-4.7647207975e-003), QTMFLLD(-3.5375438631e-002), + QTMFLLD(-5.0335830450e-001), QTMFLLD(1.9599021971e-001), + QTMFLLD(-3.7159718340e-004), QTMFLLD(-4.8605888151e-003), + QTMFLLD(-3.7633713335e-002), QTMFLLD(-5.1775097847e-001), + QTMFLLD(1.8655113876e-001), QTMFLLD(-3.7999937194e-004), + QTMFLLD(-4.9540083855e-003), QTMFLLD(-3.9943847805e-002), + QTMFLLD(-5.3207957745e-001), QTMFLLD(1.7732504010e-001), + QTMFLLD(-3.8705617771e-004), QTMFLLD(-5.0450465642e-003), + QTMFLLD(-4.2304381728e-002), QTMFLLD(-5.4633224010e-001), + QTMFLLD(1.6831515729e-001), QTMFLLD(-3.9281861973e-004), + QTMFLLD(-5.1336232573e-003), QTMFLLD(-4.4713638723e-002), + QTMFLLD(-5.6049734354e-001), QTMFLLD(1.5952435136e-001), + QTMFLLD(-3.9737694897e-004), QTMFLLD(-5.2197398618e-003), + QTMFLLD(-4.7170232981e-002), QTMFLLD(-5.7456302643e-001), + QTMFLLD(1.5095503628e-001), QTMFLLD(-4.0088107926e-004), + QTMFLLD(-5.3033372387e-003), QTMFLLD(-4.9672137946e-002), + QTMFLLD(-5.8851766586e-001), QTMFLLD(1.4260910451e-001), + QTMFLLD(-4.0338383405e-004), QTMFLLD(-5.3843962960e-003), + QTMFLLD(-5.2217379212e-002), QTMFLLD(-6.0234934092e-001), + QTMFLLD(1.3448855281e-001), QTMFLLD(-4.0505555808e-004), + QTMFLLD(-5.4629631341e-003), QTMFLLD(-5.4803829640e-002), + QTMFLLD(-6.1604642868e-001), QTMFLLD(1.2659475207e-001), + QTMFLLD(-4.0614881436e-004), QTMFLLD(-5.5389581248e-003), + QTMFLLD(-5.7429198176e-002), QTMFLLD(-6.2959736586e-001), + QTMFLLD(1.1892842501e-001), QTMFLLD(-4.0676075150e-004), + QTMFLLD(-5.6123761460e-003), QTMFLLD(-6.0090914369e-002), + QTMFLLD(-6.4299046993e-001), QTMFLLD(1.1149007827e-001), + QTMFLLD(-4.0709332097e-004), QTMFLLD(-5.6832311675e-003), + QTMFLLD(-6.2786586583e-002), QTMFLLD(-6.5621429682e-001), + QTMFLLD(1.0428040475e-001), QTMFLLD(-4.0732545312e-004), + QTMFLLD(-5.7515366934e-003), QTMFLLD(-6.5513409674e-002), + QTMFLLD(-6.6925734282e-001), QTMFLLD(9.7298897803e-002), + QTMFLLD(-4.0770808118e-004), QTMFLLD(-5.8172862045e-003), + QTMFLLD(-6.8268470466e-002), QTMFLLD(-6.8210834265e-001), + QTMFLLD(9.0545162559e-002), QTMFLLD(-4.0854664985e-004), + QTMFLLD(-5.8804959990e-003), QTMFLLD(-7.1048669517e-002), + QTMFLLD(-6.9475615025e-001), QTMFLLD(8.4017947316e-002), + QTMFLLD(-4.1002241778e-004), QTMFLLD(-5.9412117116e-003), + QTMFLLD(-7.3850922287e-002), QTMFLLD(-7.0718955994e-001), + QTMFLLD(7.7716566622e-002), QTMFLLD(-4.1239586426e-004), + QTMFLLD(-5.9994738549e-003), QTMFLLD(-7.6671779156e-002), + QTMFLLD(-7.1939796209e-001), QTMFLLD(7.1639508009e-002), + QTMFLLD(-4.1594370850e-004), QTMFLLD(-6.0553550720e-003), + QTMFLLD(-7.9507902265e-002), QTMFLLD(-7.3137050867e-001), + QTMFLLD(6.5784148872e-002), QTMFLLD(-4.2083335575e-004), + QTMFLLD(-6.1089023948e-003), QTMFLLD(-8.2355625927e-002), + QTMFLLD(-7.4309676886e-001), QTMFLLD(6.0148354620e-002), + QTMFLLD(-4.2732476140e-004), QTMFLLD(-6.1602159403e-003), + QTMFLLD(-8.5211075842e-002), QTMFLLD(-7.5456637144e-001), + QTMFLLD(5.4730266333e-002), QTMFLLD(-4.3563771760e-004), + QTMFLLD(-6.2093720771e-003), QTMFLLD(-8.8070511818e-002), + QTMFLLD(-7.6576924324e-001), QTMFLLD(4.9526259303e-002), + QTMFLLD(-4.4600359979e-004), QTMFLLD(-6.2565426342e-003), + QTMFLLD(-9.0929701924e-002), QTMFLLD(-7.7669566870e-001), + QTMFLLD(4.4533081353e-002), QTMFLLD(-4.5858716476e-004), + QTMFLLD(-6.3017667271e-003), QTMFLLD(-9.3784548342e-002), + QTMFLLD(-7.8733605146e-001), QTMFLLD(3.9746750146e-002), + QTMFLLD(-4.7345875646e-004), QTMFLLD(-6.3452622853e-003), + QTMFLLD(-9.6630692482e-002), QTMFLLD(-7.9768097401e-001), + QTMFLLD(3.5163912922e-002), QTMFLLD(-4.9076689174e-004), + QTMFLLD(-6.3871243037e-003), QTMFLLD(-9.9463671446e-002), + QTMFLLD(-8.0772149563e-001), QTMFLLD(3.0780877918e-002), + QTMFLLD(-5.1067111781e-004), QTMFLLD(-6.4275567420e-003), + QTMFLLD(-1.0227891803e-001), QTMFLLD(-8.1744915247e-001), + QTMFLLD(2.6590615511e-002), QTMFLLD(-5.3326232592e-004), + QTMFLLD(-6.4666904509e-003), QTMFLLD(-1.0507161170e-001), + QTMFLLD(-8.2685548067e-001), QTMFLLD(2.2588992491e-002), + QTMFLLD(-5.5855646497e-004), QTMFLLD(-6.5047293901e-003), + QTMFLLD(-1.0783691704e-001), QTMFLLD(-8.3593225479e-001), + QTMFLLD(1.8772648647e-002), QTMFLLD(-5.8640236966e-004), + QTMFLLD(-6.5418654121e-003), QTMFLLD(-1.1056987941e-001), + QTMFLLD(-8.4467232227e-001), QTMFLLD(1.5131668188e-002), + QTMFLLD(-6.1692652525e-004), QTMFLLD(-6.5783206373e-003), + QTMFLLD(-1.1326543987e-001), QTMFLLD(-8.5306841135e-001), + QTMFLLD(1.1661184952e-002), QTMFLLD(-6.4994930290e-004), + QTMFLLD(-6.6143544391e-003), QTMFLLD(-1.1591844261e-001), + QTMFLLD(-8.6111402512e-001), QTMFLLD(8.3509646356e-003), + QTMFLLD(-6.8494328298e-004), QTMFLLD(-6.6502285190e-003), + QTMFLLD(-1.1852371693e-001), QTMFLLD(-8.6880439520e-001), + QTMFLLD(5.1832948811e-003), QTMFLLD(-7.2404538514e-004), + QTMFLLD(-6.6861407831e-003), QTMFLLD(-1.2107557058e-001), + QTMFLLD(-8.7612599134e-001), QTMFLLD(2.2103153169e-003), + QTMFLLD(-7.7061145566e-004), QTMFLLD(-6.7221261561e-003), + QTMFLLD(-1.2356808037e-001), QTMFLLD(-8.8305824995e-001), + QTMFLLD(-4.6855807886e-004), QTMFLLD(-8.2158041187e-004), + QTMFLLD(-6.7584766075e-003), QTMFLLD(-1.2599521875e-001), + QTMFLLD(-8.8958823681e-001), QTMFLLD(-2.8003340121e-003), + QTMFLLD(-8.7498105131e-004), QTMFLLD(-6.7957863212e-003), + QTMFLLD(-1.2835204601e-001), QTMFLLD(-8.9572954178e-001), + QTMFLLD(-4.9293786287e-003), QTMFLLD(-9.2902814504e-004), + QTMFLLD(-6.8344431929e-003), QTMFLLD(-1.3063311577e-001), + QTMFLLD(-9.0148586035e-001), QTMFLLD(-6.9273295812e-003), + QTMFLLD(-9.8383461591e-004), QTMFLLD(-6.8746237084e-003), + QTMFLLD(-1.3283239305e-001), QTMFLLD(-9.0685033798e-001), + QTMFLLD(-8.7857460603e-003), QTMFLLD(-1.0395538993e-003), + QTMFLLD(-6.9165546447e-003), QTMFLLD(-1.3494376838e-001), + QTMFLLD(-9.1181802750e-001), QTMFLLD(-1.0507551953e-002), + QTMFLLD(-1.0959620122e-003), QTMFLLD(-6.9604511373e-003), + QTMFLLD(-1.3696120679e-001), QTMFLLD(-9.1638565063e-001), + QTMFLLD(-1.2103702873e-002), QTMFLLD(-1.1530250777e-003), + QTMFLLD(-7.0065916516e-003), QTMFLLD(-1.3887859881e-001), + QTMFLLD(-9.2054879665e-001), QTMFLLD(-1.3574197888e-002), + QTMFLLD(-1.2105966453e-003), QTMFLLD(-7.0552495308e-003), + QTMFLLD(-1.4068968594e-001), QTMFLLD(-9.2430406809e-001), + QTMFLLD(-1.4923358336e-002), QTMFLLD(-1.2681842782e-003), + QTMFLLD(-7.1066003293e-003), QTMFLLD(-1.4238841832e-001), + QTMFLLD(-9.2764878273e-001), QTMFLLD(-1.6156485304e-002), + QTMFLLD(-1.3256429229e-003), QTMFLLD(-7.1608433500e-003), + QTMFLLD(-1.4396859705e-001), QTMFLLD(-9.3058031797e-001), + QTMFLLD(-1.7277117819e-002), QTMFLLD(-1.3827638468e-003), + QTMFLLD(-7.2182063013e-003), QTMFLLD(-1.4542391896e-001), + QTMFLLD(-9.3309664726e-001), QTMFLLD(-1.8289361149e-002), + QTMFLLD(-1.4391905861e-003), QTMFLLD(-7.2789187543e-003), + QTMFLLD(-1.4674818516e-001), QTMFLLD(-9.3519610167e-001), + QTMFLLD(-1.9195662811e-002), QTMFLLD(-1.4947097516e-003), + QTMFLLD(-7.3430840857e-003), QTMFLLD(-1.4793521166e-001), + QTMFLLD(-9.3687731028e-001), QTMFLLD(-1.9999813288e-002), + QTMFLLD(-1.5489540529e-003), QTMFLLD(-7.4108825065e-003), + QTMFLLD(-1.4897871017e-001), QTMFLLD(-9.3813979626e-001), + QTMFLLD(-2.0706148818e-002), QTMFLLD(-1.6016908921e-003), + QTMFLLD(-7.4823615141e-003), QTMFLLD(-1.4987260103e-001), + QTMFLLD(-9.3898290396e-001), QTMFLLD(-2.1316919476e-002), + QTMFLLD(-1.6526894178e-003), QTMFLLD(-7.5576924719e-003), + QTMFLLD(-1.5061059594e-001), QTMFLLD(-9.3940681219e-001), + QTMFLLD(-2.1835187450e-002), QTMFLLD(-1.7015410122e-003), + QTMFLLD(-7.6368991286e-003), QTMFLLD(-1.5118667483e-001), + QTMFLLD(-9.3941211700e-001), QTMFLLD(-2.2264443338e-002), + QTMFLLD(-1.7479787348e-003), QTMFLLD(-7.7200052328e-003), + QTMFLLD(-1.5159477293e-001), QTMFLLD(-9.3899971247e-001), + QTMFLLD(-2.2607907653e-002), QTMFLLD(-1.7917567166e-003), + QTMFLLD(-7.8069791198e-003), QTMFLLD(-1.5182891488e-001), + QTMFLLD(-9.3817096949e-001), QTMFLLD(-2.2868644446e-002), + QTMFLLD(-1.8325200072e-003), QTMFLLD(-7.8977877274e-003), + QTMFLLD(-1.5188319981e-001), QTMFLLD(-9.3692785501e-001), + QTMFLLD(-2.3049183190e-002), QTMFLLD(-1.8700722139e-003), + QTMFLLD(-7.9923402518e-003), QTMFLLD(-1.5175175667e-001), + QTMFLLD(-9.3527245522e-001), QTMFLLD(-2.3152977228e-002), + QTMFLLD(-1.9041235792e-003), QTMFLLD(-8.0905584618e-003), + QTMFLLD(-1.5142890811e-001), QTMFLLD(-9.3320751190e-001), + QTMFLLD(-2.3183524609e-002), QTMFLLD(-1.9344078610e-003), + QTMFLLD(-8.1921815872e-003), QTMFLLD(-1.5090890229e-001), + QTMFLLD(-9.3073624372e-001), QTMFLLD(-2.3143447936e-002), + QTMFLLD(-1.9606938586e-003), QTMFLLD(-8.2970457152e-003), + QTMFLLD(-1.5018628538e-001), QTMFLLD(-9.2786192894e-001), + QTMFLLD(-2.3035895079e-002), QTMFLLD(-1.9826870412e-003), + QTMFLLD(-8.4048351273e-003), QTMFLLD(-1.4925561845e-001), + QTMFLLD(-9.2458862066e-001), QTMFLLD(-2.2864164785e-002), + QTMFLLD(-2.0002126694e-003), QTMFLLD(-8.5152359679e-003), + QTMFLLD(-1.4811170101e-001), QTMFLLD(-9.2092043161e-001), + QTMFLLD(-2.2631708533e-002), QTMFLLD(-2.0131117199e-003), + QTMFLLD(-8.6279176176e-003), QTMFLLD(-1.4674940705e-001), + QTMFLLD(-9.1686213017e-001), QTMFLLD(-2.2341690958e-002), + QTMFLLD(-2.0211567171e-003), QTMFLLD(-8.7425475940e-003), + QTMFLLD(-1.4516362548e-001), QTMFLLD(-9.1241872311e-001), + QTMFLLD(-2.1996961907e-002), QTMFLLD(-2.0242547616e-003), + QTMFLLD(-8.8585643098e-003), QTMFLLD(-1.4334976673e-001), + QTMFLLD(-9.0759557486e-001), QTMFLLD(-2.1601308137e-002), + QTMFLLD(-2.0221893210e-003), QTMFLLD(-8.9755039662e-003), + QTMFLLD(-1.4130303264e-001), QTMFLLD(-9.0239852667e-001), + QTMFLLD(-2.1158147603e-002), QTMFLLD(-2.0149163902e-003), + QTMFLLD(-9.0927295387e-003), QTMFLLD(-1.3901908696e-001), + QTMFLLD(-8.9683371782e-001), QTMFLLD(-2.0670616999e-002), + QTMFLLD(-2.0022888202e-003), QTMFLLD(-9.2095714062e-003), + QTMFLLD(-1.3649365306e-001), QTMFLLD(-8.9090716839e-001), + QTMFLLD(-2.0142132416e-002), QTMFLLD(-1.9841785543e-003), + QTMFLLD(-9.3253115192e-003), QTMFLLD(-1.3372266293e-001), + QTMFLLD(-8.8462579250e-001), QTMFLLD(-1.9576057792e-002), + QTMFLLD(-1.9606270362e-003), QTMFLLD(-9.4392402098e-003), + QTMFLLD(-1.3070219755e-001), QTMFLLD(-8.7799650431e-001), + QTMFLLD(-1.8976125866e-002), QTMFLLD(-1.9315859536e-003), + QTMFLLD(-9.5505062491e-003), QTMFLLD(-1.2742865086e-001), + QTMFLLD(-8.7102663517e-001), QTMFLLD(-1.8345680088e-002), + QTMFLLD(-1.8970289966e-003), QTMFLLD(-9.6583357081e-003), + QTMFLLD(-1.2389861047e-001), QTMFLLD(-8.6372399330e-001), + QTMFLLD(-1.7687706277e-002), QTMFLLD(-1.8569815438e-003), + QTMFLLD(-9.7616901621e-003), QTMFLLD(-1.2010899931e-001), + QTMFLLD(-8.5609632730e-001), QTMFLLD(-1.7006140202e-002), + QTMFLLD(-1.8114587292e-003), QTMFLLD(-9.8597351462e-003), + QTMFLLD(-1.1605655402e-001), QTMFLLD(-8.4815198183e-001), + QTMFLLD(-1.6304368153e-002), QTMFLLD(-1.7605143366e-003), + QTMFLLD(-9.9515644833e-003), QTMFLLD(-1.1173909158e-001), + QTMFLLD(-8.3989918232e-001), QTMFLLD(-1.5585509129e-002), + QTMFLLD(-1.7042002873e-003), QTMFLLD(-1.0036026128e-002), + QTMFLLD(-1.0715358704e-001), QTMFLLD(-8.3134686947e-001), + QTMFLLD(-1.4853162691e-002), QTMFLLD(-1.6426335787e-003), + QTMFLLD(-1.0111952201e-002), QTMFLLD(-1.0229838639e-001), + QTMFLLD(-8.2250368595e-001), QTMFLLD(-1.4110331424e-002), + QTMFLLD(-1.5758809168e-003), QTMFLLD(-1.0178210214e-002), + QTMFLLD(-9.7171187401e-002), QTMFLLD(-8.1337898970e-001), + QTMFLLD(-1.3360806741e-002), QTMFLLD(-1.5040797880e-003), + QTMFLLD(-1.0233603418e-002), QTMFLLD(-9.1770596802e-002), + QTMFLLD(-8.0398184061e-001), QTMFLLD(-1.2607692741e-002), + QTMFLLD(-1.4273397392e-003), QTMFLLD(-1.0276827961e-002), + QTMFLLD(-8.6095176637e-002), QTMFLLD(-7.9432225227e-001), + QTMFLLD(-1.1853585951e-002), QTMFLLD(-1.3458349276e-003), + QTMFLLD(-1.0306579992e-002), QTMFLLD(-8.0143928528e-002), + QTMFLLD(-7.8440952301e-001), QTMFLLD(-1.1102385819e-002), + QTMFLLD(-1.2597256573e-003), QTMFLLD(-1.0321546346e-002), + QTMFLLD(-7.3915921152e-002), QTMFLLD(-7.7425378561e-001), + QTMFLLD(-1.0356968269e-002), QTMFLLD(-1.1691439431e-003), + QTMFLLD(-1.0320378467e-002), QTMFLLD(-6.7410878837e-002), + QTMFLLD(-7.6386493444e-001), QTMFLLD(-9.6200043336e-003), + QTMFLLD(-1.0743001476e-003), QTMFLLD(-1.0301630013e-002), + QTMFLLD(-6.0628447682e-002), QTMFLLD(-7.5325345993e-001), + QTMFLLD(-8.8949296623e-003), QTMFLLD(-9.7535311943e-004), + QTMFLLD(-1.0263898410e-002), QTMFLLD(-5.3568758070e-002), + QTMFLLD(-7.4242949486e-001), QTMFLLD(-8.1837112084e-003), + QTMFLLD(-8.7248592172e-004), QTMFLLD(-1.0205759667e-002), + QTMFLLD(-4.6232450753e-002), QTMFLLD(-7.3140352964e-001), + QTMFLLD(-7.4901022017e-003), QTMFLLD(-7.6591013931e-004), + QTMFLLD(-1.0125675239e-002), QTMFLLD(-3.8619950414e-002), + QTMFLLD(-7.2018599510e-001), QTMFLLD(-6.8165790290e-003), + QTMFLLD(-6.5580842784e-004), QTMFLLD(-1.0022218339e-002), + QTMFLLD(-3.0732547864e-002), QTMFLLD(-7.0878815651e-001), + QTMFLLD(-6.1642420478e-003), QTMFLLD(-5.4247735534e-004), + QTMFLLD(-9.8937284201e-003), QTMFLLD(-2.2571478039e-002), + QTMFLLD(-6.9722014666e-001), QTMFLLD(-5.5373813957e-003), + QTMFLLD(-4.2596619460e-004), QTMFLLD(-9.7389295697e-003), + QTMFLLD(-1.4138570987e-002), QTMFLLD(-6.8549299240e-001), + QTMFLLD(-4.9372608773e-003), QTMFLLD(-3.0657128082e-004), + QTMFLLD(-9.5560895279e-003), QTMFLLD(-5.4356725886e-003), + QTMFLLD(-6.7361742258e-001), QTMFLLD(-4.3653072789e-003), + QTMFLLD(-1.8451632059e-004), QTMFLLD(-9.3438196927e-003), + QTMFLLD(3.5346730147e-003), QTMFLLD(-6.6160440445e-001), + QTMFLLD(-3.8251809310e-003), QTMFLLD(-6.0027297877e-005), + QTMFLLD(-9.1004446149e-003), QTMFLLD(1.2770005502e-002), + QTMFLLD(-6.4946544170e-001), QTMFLLD(-3.3147553913e-003), + QTMFLLD(6.6618180426e-005), QTMFLLD(-8.8245263323e-003), + QTMFLLD(2.2267201915e-002), QTMFLLD(-6.3721030951e-001), + QTMFLLD(-2.8387091588e-003), QTMFLLD(1.9518326735e-004), + QTMFLLD(-8.5145104676e-003), QTMFLLD(3.2023012638e-002), + QTMFLLD(-6.2485051155e-001), QTMFLLD(-2.3975048680e-003), + QTMFLLD(3.2545044087e-004), QTMFLLD(-8.1687811762e-003), + QTMFLLD(4.2033810169e-002), QTMFLLD(-6.1239802837e-001), + QTMFLLD(-1.9807203207e-003), QTMFLLD(4.5712510473e-004), + QTMFLLD(-7.7859172598e-003), QTMFLLD(5.2295893431e-002), + QTMFLLD(-5.9986191988e-001), QTMFLLD(-1.6010539839e-003), + QTMFLLD(5.9015140869e-004), QTMFLLD(-7.3645371012e-003), + QTMFLLD(6.2805138528e-002), QTMFLLD(-5.8725595474e-001), + QTMFLLD(-1.2320743408e-003), QTMFLLD(7.2508689482e-004), + QTMFLLD(-6.9030462764e-003), QTMFLLD(7.3557935655e-002), + QTMFLLD(-5.7460016012e-001), QTMFLLD(-7.9492607620e-004)}; + +//@{ +/*! + \name DCT_II twiddle factors, L=64 +*/ +/*! sin (3.14159265358979323 / (2*L) * n) , L=64*/ +LNK_SECTION_CONSTDATA +RAM_ALIGN +const FIXP_WTP sin_twiddle_L64[] = { + WTCP(0x7fffffff, 0x00000000), WTCP(0x7ff62182, 0x03242abf), + WTCP(0x7fd8878e, 0x0647d97c), WTCP(0x7fa736b4, 0x096a9049), + WTCP(0x7f62368f, 0x0c8bd35e), WTCP(0x7f0991c4, 0x0fab272b), + WTCP(0x7e9d55fc, 0x12c8106f), WTCP(0x7e1d93ea, 0x15e21445), + WTCP(0x7d8a5f40, 0x18f8b83c), WTCP(0x7ce3ceb2, 0x1c0b826a), + WTCP(0x7c29fbee, 0x1f19f97b), WTCP(0x7b5d039e, 0x2223a4c5), + WTCP(0x7a7d055b, 0x25280c5e), WTCP(0x798a23b1, 0x2826b928), + WTCP(0x78848414, 0x2b1f34eb), WTCP(0x776c4edb, 0x2e110a62), + WTCP(0x7641af3d, 0x30fbc54d), WTCP(0x7504d345, 0x33def287), + WTCP(0x73b5ebd1, 0x36ba2014), WTCP(0x72552c85, 0x398cdd32), + WTCP(0x70e2cbc6, 0x3c56ba70), WTCP(0x6f5f02b2, 0x3f1749b8), + WTCP(0x6dca0d14, 0x41ce1e65), WTCP(0x6c242960, 0x447acd50), + WTCP(0x6a6d98a4, 0x471cece7), WTCP(0x68a69e81, 0x49b41533), + WTCP(0x66cf8120, 0x4c3fdff4), WTCP(0x64e88926, 0x4ebfe8a5), + WTCP(0x62f201ac, 0x5133cc94), WTCP(0x60ec3830, 0x539b2af0), + WTCP(0x5ed77c8a, 0x55f5a4d2), WTCP(0x5cb420e0, 0x5842dd54), + WTCP(0x5a82799a, 0x5a82799a), WTCP(0x5842dd54, 0x5cb420e0), + WTCP(0x55f5a4d2, 0x5ed77c8a), WTCP(0x539b2af0, 0x60ec3830), + WTCP(0x5133cc94, 0x62f201ac), WTCP(0x4ebfe8a5, 0x64e88926), + WTCP(0x4c3fdff4, 0x66cf8120), WTCP(0x49b41533, 0x68a69e81), + WTCP(0x471cece7, 0x6a6d98a4), WTCP(0x447acd50, 0x6c242960), + WTCP(0x41ce1e65, 0x6dca0d14), WTCP(0x3f1749b8, 0x6f5f02b2), + WTCP(0x3c56ba70, 0x70e2cbc6), WTCP(0x398cdd32, 0x72552c85), + WTCP(0x36ba2014, 0x73b5ebd1), WTCP(0x33def287, 0x7504d345), + WTCP(0x30fbc54d, 0x7641af3d), WTCP(0x2e110a62, 0x776c4edb), + WTCP(0x2b1f34eb, 0x78848414), WTCP(0x2826b928, 0x798a23b1), + WTCP(0x25280c5e, 0x7a7d055b), WTCP(0x2223a4c5, 0x7b5d039e), + WTCP(0x1f19f97b, 0x7c29fbee), WTCP(0x1c0b826a, 0x7ce3ceb2), + WTCP(0x18f8b83c, 0x7d8a5f40), WTCP(0x15e21445, 0x7e1d93ea), + WTCP(0x12c8106f, 0x7e9d55fc), WTCP(0x0fab272b, 0x7f0991c4), + WTCP(0x0c8bd35e, 0x7f62368f), WTCP(0x096a9049, 0x7fa736b4), + WTCP(0x0647d97c, 0x7fd8878e), WTCP(0x03242abf, 0x7ff62182)}; + +const USHORT sqrt_tab[49] = { + 0x5a82, 0x5d4b, 0x6000, 0x62a1, 0x6531, 0x67b1, 0x6a21, 0x6c84, 0x6ed9, + 0x7123, 0x7360, 0x7593, 0x77bb, 0x79da, 0x7bef, 0x7dfb, 0x8000, 0x81fc, + 0x83f0, 0x85dd, 0x87c3, 0x89a3, 0x8b7c, 0x8d4e, 0x8f1b, 0x90e2, 0x92a4, + 0x9460, 0x9617, 0x97ca, 0x9977, 0x9b20, 0x9cc4, 0x9e64, 0xa000, 0xa197, + 0xa32b, 0xa4ba, 0xa646, 0xa7cf, 0xa953, 0xaad5, 0xac53, 0xadcd, 0xaf45, + 0xb0b9, 0xb22b, 0xb399, 0xb504}; + +LNK_SECTION_CONSTDATA_L1 +const FIXP_DBL invCount[80] = /* This could be 16-bit wide */ + {0x00000000, 0x7fffffff, 0x40000000, 0x2aaaaaab, 0x20000000, 0x1999999a, + 0x15555555, 0x12492492, 0x10000000, 0x0e38e38e, 0x0ccccccd, 0x0ba2e8ba, + 0x0aaaaaab, 0x09d89d8a, 0x09249249, 0x08888889, 0x08000000, 0x07878788, + 0x071c71c7, 0x06bca1af, 0x06666666, 0x06186186, 0x05d1745d, 0x0590b216, + 0x05555555, 0x051eb852, 0x04ec4ec5, 0x04bda12f, 0x04924925, 0x0469ee58, + 0x04444444, 0x04210842, 0x04000000, 0x03e0f83e, 0x03c3c3c4, 0x03a83a84, + 0x038e38e4, 0x03759f23, 0x035e50d8, 0x03483483, 0x03333333, 0x031f3832, + 0x030c30c3, 0x02fa0be8, 0x02e8ba2f, 0x02d82d83, 0x02c8590b, 0x02b93105, + 0x02aaaaab, 0x029cbc15, 0x028f5c29, 0x02828283, 0x02762762, 0x026a439f, + 0x025ed098, 0x0253c825, 0x02492492, 0x023ee090, 0x0234f72c, 0x022b63cc, + 0x02222222, 0x02192e2a, 0x02108421, 0x02082082, 0x02000000, 0x01f81f82, + 0x01f07c1f, 0x01e9131b, 0x01e1e1e2, 0x01dae607, 0x01d41d42, 0x01cd8569, + 0x01c71c72, 0x01c0e070, 0x01bacf91, 0x01b4e81b, 0x01af286c, 0x01a98ef6, + 0x01a41a42, 0x019ec8e9}; + +/* + * Bitstream data lists + */ + +/* + * AOT {2,5,29} + * epConfig = -1 + */ + +static const rbd_id_t el_aac_sce[] = { + adtscrc_start_reg1, element_instance_tag, global_gain, ics_info, + section_data, scale_factor_data, pulse, tns_data_present, tns_data, + gain_control_data_present, + /* gain_control_data, */ + spectral_data, adtscrc_end_reg1, end_of_sequence}; + +static const struct element_list node_aac_sce = {el_aac_sce, {NULL, NULL}}; + +/* CCE */ +static const rbd_id_t el_aac_cce[] = { + adtscrc_start_reg1, element_instance_tag, + coupled_elements, /* CCE specific */ + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /* gain_control_data, */ + spectral_data, gain_element_lists, /* CCE specific */ + adtscrc_end_reg1, end_of_sequence}; + +static const struct element_list node_aac_cce = {el_aac_cce, {NULL, NULL}}; + +static const rbd_id_t el_aac_cpe[] = {adtscrc_start_reg1, element_instance_tag, + common_window, link_sequence}; + +static const rbd_id_t el_aac_cpe0[] = { + /*common_window = 0*/ + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, next_channel, + + adtscrc_start_reg2, global_gain, ics_info, section_data, scale_factor_data, + pulse, tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, adtscrc_end_reg1, adtscrc_end_reg2, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1[] = { + /* common_window = 1 */ + ics_info, ms, + + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, next_channel, + + adtscrc_start_reg2, global_gain, section_data, scale_factor_data, pulse, + tns_data_present, tns_data, gain_control_data_present, + /*gain_control_data,*/ + spectral_data, adtscrc_end_reg1, adtscrc_end_reg2, end_of_sequence}; + +static const struct element_list node_aac_cpe0 = {el_aac_cpe0, {NULL, NULL}}; + +static const struct element_list node_aac_cpe1 = {el_aac_cpe1, {NULL, NULL}}; + +static const element_list_t node_aac_cpe = {el_aac_cpe, + {&node_aac_cpe0, &node_aac_cpe1}}; + +/* + * AOT C- {17,23} + * epConfig = 0,1 + */ +static const rbd_id_t el_aac_sce_epc0[] = { + element_instance_tag, + global_gain, + ics_info, + section_data, + scale_factor_data, + pulse, + tns_data_present, + gain_control_data_present, + gain_control_data, + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + tns_data, + spectral_data, + end_of_sequence}; + +static const struct element_list node_aac_sce_epc0 = {el_aac_sce_epc0, + {NULL, NULL}}; + +static const rbd_id_t el_aac_sce_epc1[] = { + element_instance_tag, global_gain, ics_info, section_data, + scale_factor_data, pulse, tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + tns_data, spectral_data, end_of_sequence}; + +static const struct element_list node_aac_sce_epc1 = {el_aac_sce_epc1, + {NULL, NULL}}; + +static const rbd_id_t el_aac_cpe_epc0[] = {element_instance_tag, common_window, + link_sequence}; + +static const rbd_id_t el_aac_cpe0_epc0[] = { + /* common_window = 0 */ + /* ESC 1: */ + global_gain, ics_info, + /* ltp_data_present, + ltp_data, + */ + section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, next_channel, + + /* ESC 1: */ + global_gain, ics_info, + /* ltp_data_present, + ltp_data, + */ + section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1_epc0[] = { + /* common_window = 1 */ + /* ESC 0: */ + ics_info, + /* ltp_data_present, + ltp_data, + next_channel, + ltp_data_present, + ltp_data, + next_channel, + */ + ms, + + /* ESC 1: */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /* length_of_reordered_spectral_data, length_of_longest_codeword + */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, next_channel, + + /* ESC 1: */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + esc1_hcr, /* length_of_reordered_spectral_data, length_of_longest_codeword + */ + /* ESC 2: */ + esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + /* ESC 3: */ + tns_data, + /* ESC 4: */ + spectral_data, end_of_sequence}; + +static const struct element_list node_aac_cpe0_epc0 = {el_aac_cpe0_epc0, + {NULL, NULL}}; + +static const struct element_list node_aac_cpe1_epc0 = {el_aac_cpe1_epc0, + {NULL, NULL}}; + +static const element_list_t node_aac_cpe_epc0 = { + el_aac_cpe_epc0, {&node_aac_cpe0_epc0, &node_aac_cpe1_epc0}}; + +static const rbd_id_t el_aac_cpe0_epc1[] = { + global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + next_channel, global_gain, ics_info, section_data, scale_factor_data, pulse, + tns_data_present, gain_control_data_present, + /*gain_control_data,*/ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, tns_data, next_channel, tns_data, next_channel, spectral_data, + next_channel, spectral_data, end_of_sequence}; + +static const rbd_id_t el_aac_cpe1_epc1[] = { + ics_info, ms, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + next_channel, + + ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, pulse, tns_data_present, + gain_control_data_present, + /*gain_control_data,*/ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc1_hcr, /*length_of_rvlc_escapes, length_of_rvlc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + next_channel, esc2_rvlc, /* rvlc_cod_sf, rvlc_esc_sf */ + + next_channel, tns_data, next_channel, tns_data, next_channel, spectral_data, + next_channel, spectral_data, end_of_sequence}; + +static const struct element_list node_aac_cpe0_epc1 = {el_aac_cpe0_epc1, + {NULL, NULL}}; + +static const struct element_list node_aac_cpe1_epc1 = {el_aac_cpe1_epc1, + {NULL, NULL}}; + +static const element_list_t node_aac_cpe_epc1 = { + el_aac_cpe, {&node_aac_cpe0_epc1, &node_aac_cpe1_epc1}}; + +/* + * AOT = 20 + * epConfig = 0 + */ +static const rbd_id_t el_scal_sce_epc0[] = {ics_info, /* ESC 1 */ + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, + scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 */ + tns_data, /* ESC 3 */ + spectral_data, /* ESC 4 */ + end_of_sequence}; + +static const struct element_list node_scal_sce_epc0 = {el_scal_sce_epc0, + {NULL, NULL}}; + +static const rbd_id_t el_scal_cpe_epc0[] = { + ics_info, /* ESC 0 */ + ms, tns_data_present, /* ESC 1 (ch 0) */ + ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 0) */ + tns_data, /* ESC 3 (ch 0) */ + spectral_data, /* ESC 4 (ch 0) */ + next_channel, tns_data_present, /* ESC 1 (ch 1) */ + ltp_data_present, global_gain, section_data, scale_factor_data, esc1_hcr, + esc2_rvlc, /* ESC 2 (ch 1) */ + tns_data, /* ESC 3 (ch 1) */ + spectral_data, /* ESC 4 (ch 1) */ + end_of_sequence}; + +static const struct element_list node_scal_cpe_epc0 = {el_scal_cpe_epc0, + {NULL, NULL}}; + +/* + * AOT = 20 + * epConfig = 1 + */ +static const rbd_id_t el_scal_sce_epc1[] = { + ics_info, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, tns_data, + spectral_data, end_of_sequence}; + +static const struct element_list node_scal_sce_epc1 = {el_scal_sce_epc1, + {NULL, NULL}}; + +static const rbd_id_t el_scal_cpe_epc1[] = { + ics_info, ms, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data, next_channel, tns_data, next_channel, spectral_data, next_channel, + spectral_data, end_of_sequence}; + +static const struct element_list node_scal_cpe_epc1 = {el_scal_cpe_epc1, + {NULL, NULL}}; + +/* + * Pseudo AOT for DRM/DRM+ (similar to AOT 20) + */ +static const rbd_id_t el_drm_sce[] = { + drmcrc_start_reg, ics_info, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, tns_data, + drmcrc_end_reg, spectral_data, end_of_sequence}; + +static const struct element_list node_drm_sce = {el_drm_sce, {NULL, NULL}}; + +static const rbd_id_t el_drm_cpe[] = { + drmcrc_start_reg, ics_info, ms, tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data_present, ltp_data_present, + /* ltp_data, */ + global_gain, section_data, scale_factor_data, esc1_hcr, next_channel, + tns_data, next_channel, tns_data, drmcrc_end_reg, next_channel, + spectral_data, next_channel, spectral_data, end_of_sequence}; + +static const struct element_list node_drm_cpe = {el_drm_cpe, {NULL, NULL}}; + +/* + * AOT = 39 + * epConfig = 0 + */ +static const rbd_id_t el_eld_sce_epc0[] = { + global_gain, ics_info, section_data, scale_factor_data, tns_data_present, + tns_data, esc1_hcr, esc2_rvlc, spectral_data, end_of_sequence}; + +static const struct element_list node_eld_sce_epc0 = {el_eld_sce_epc0, + {NULL, NULL}}; + +#define node_eld_sce_epc1 node_eld_sce_epc0 + +static const rbd_id_t el_eld_cpe_epc0[] = {ics_info, ms, + global_gain, section_data, + scale_factor_data, tns_data_present, + tns_data, esc1_hcr, + esc2_rvlc, spectral_data, + next_channel, global_gain, + section_data, scale_factor_data, + tns_data_present, tns_data, + esc1_hcr, esc2_rvlc, + spectral_data, end_of_sequence}; + +static const rbd_id_t el_eld_cpe_epc1[] = {ics_info, ms, + global_gain, section_data, + scale_factor_data, tns_data_present, + next_channel, global_gain, + section_data, scale_factor_data, + tns_data_present, next_channel, + tns_data, next_channel, + tns_data, next_channel, + esc1_hcr, esc2_rvlc, + spectral_data, next_channel, + esc1_hcr, esc2_rvlc, + spectral_data, end_of_sequence}; + +static const struct element_list node_eld_cpe_epc0 = {el_eld_cpe_epc0, + {NULL, NULL}}; + +static const struct element_list node_eld_cpe_epc1 = {el_eld_cpe_epc1, + {NULL, NULL}}; + +/* + * AOT = 42 + * epConfig = 0 + */ + +static const rbd_id_t el_usac_coremode[] = {core_mode, next_channel, + link_sequence}; + +static const rbd_id_t el_usac_sce0_epc0[] = { + tns_data_present, + /* fd_channel_stream */ + global_gain, noise, ics_info, tw_data, scale_factor_data_usac, tns_data, + ac_spectral_data, fac_data, end_of_sequence}; + +static const rbd_id_t el_usac_lfe_epc0[] = { + /* fd_channel_stream */ + global_gain, ics_info, scale_factor_data_usac, + ac_spectral_data, fac_data, end_of_sequence}; + +static const rbd_id_t el_usac_lpd_epc0[] = {lpd_channel_stream, + end_of_sequence}; + +static const struct element_list node_usac_sce0_epc0 = {el_usac_sce0_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_sce1_epc0 = {el_usac_lpd_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_sce_epc0 = { + el_usac_coremode, {&node_usac_sce0_epc0, &node_usac_sce1_epc0}}; + +static const rbd_id_t list_usac_cpe00_epc0[] = {tns_active, common_window, + link_sequence}; + +static const rbd_id_t el_usac_common_tw[] = {common_tw, link_sequence}; + +static const rbd_id_t list_usac_cpe0000_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 0 */ + tns_data_present_usac, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe0001_epc0[] = { + /* + core_mode0 = 0 + core_mode1 = 0 + common_window = 0 + common_tw = 1 + */ + tw_data, tns_data_present_usac, global_gain, noise, + ics_info, scale_factor_data_usac, tns_data, ac_spectral_data, + fac_data, next_channel, global_gain, noise, + ics_info, scale_factor_data_usac, tns_data, ac_spectral_data, + fac_data, end_of_sequence}; + +static const rbd_id_t list_usac_cpe001_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + ics_info, common_max_sfb, ms, common_tw, link_sequence}; + +static const rbd_id_t list_usac_cpe0010_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 0 */ + tns_data_present_usac, + global_gain, + noise, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe0011_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 1 */ + tw_data, + tns_data_present_usac, + global_gain, + noise, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + global_gain, + noise, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe10_epc0[] = { + /* core_mode0 = 1 */ + /* core_mode1 = 0 */ + lpd_channel_stream, + next_channel, + tns_data_present, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe01_epc0[] = { + /* core_mode0 = 0 */ + /* core_mode1 = 1 */ + tns_data_present, + global_gain, + noise, + ics_info, + tw_data, + scale_factor_data_usac, + tns_data, + ac_spectral_data, + fac_data, + next_channel, + lpd_channel_stream, + end_of_sequence}; + +static const rbd_id_t list_usac_cpe11_epc0[] = { + /* core_mode0 = 1 */ + /* core_mode1 = 1 */ + lpd_channel_stream, next_channel, lpd_channel_stream, end_of_sequence}; + +static const struct element_list node_usac_cpe0000_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 0 */ + list_usac_cpe0000_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0010_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 0 */ + list_usac_cpe0010_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0001_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + /* common_tw = 1 */ + list_usac_cpe0001_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0011_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 1 */ + /* common_tw = 1 */ + list_usac_cpe0011_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe000_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + /* common_window = 0 */ + el_usac_common_tw, + {&node_usac_cpe0000_epc0, &node_usac_cpe0001_epc0}}; + +static const struct element_list node_usac_cpe001_epc0 = { + list_usac_cpe001_epc0, {&node_usac_cpe0010_epc0, &node_usac_cpe0011_epc0}}; + +static const struct element_list node_usac_cpe00_epc0 = { + /* core_mode0 = 0 */ + /* core_mode1 = 0 */ + list_usac_cpe00_epc0, + {&node_usac_cpe000_epc0, &node_usac_cpe001_epc0}}; + +static const struct element_list node_usac_cpe10_epc0 = { + /* core_mode0 = 1 */ + /* core_mode1 = 0 */ + list_usac_cpe10_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe01_epc0 = {list_usac_cpe01_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe11_epc0 = {list_usac_cpe11_epc0, + {NULL, NULL}}; + +static const struct element_list node_usac_cpe0_epc0 = { + /* core_mode0 = 0 */ + el_usac_coremode, + {&node_usac_cpe00_epc0, &node_usac_cpe01_epc0}}; + +static const struct element_list node_usac_cpe1_epc0 = { + /* core_mode0 = 1 */ + el_usac_coremode, + {&node_usac_cpe10_epc0, &node_usac_cpe11_epc0}}; + +static const struct element_list node_usac_cpe_epc0 = { + el_usac_coremode, {&node_usac_cpe0_epc0, &node_usac_cpe1_epc0}}; + +static const struct element_list node_usac_lfe_epc0 = {el_usac_lfe_epc0, + {NULL, NULL}}; + +const element_list_t *getBitstreamElementList(AUDIO_OBJECT_TYPE aot, + SCHAR epConfig, UCHAR nChannels, + UCHAR layer, UINT elFlags) { + switch (aot) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_DABPLUS_AAC_LC: + case AOT_DABPLUS_SBR: + case AOT_DABPLUS_PS: + FDK_ASSERT(epConfig == -1); + if (elFlags & AC_EL_GA_CCE) { + return &node_aac_cce; + } else { + if (nChannels == 1) { + return &node_aac_sce; + } else { + return &node_aac_cpe; + } + } + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + if (nChannels == 1) { + if (epConfig == 0) { + return &node_aac_sce_epc0; + } else { + return &node_aac_sce_epc1; + } + } else { + if (epConfig == 0) + return &node_aac_cpe_epc0; + else + return &node_aac_cpe_epc1; + } + case AOT_USAC: + if (elFlags & AC_EL_USAC_LFE) { + FDK_ASSERT(nChannels == 1); + return &node_usac_lfe_epc0; + } + if (nChannels == 1) { + return &node_usac_sce_epc0; + } else { + return &node_usac_cpe_epc0; + } + case AOT_ER_AAC_SCAL: + if (nChannels == 1) { + if (epConfig <= 0) + return &node_scal_sce_epc0; + else + return &node_scal_sce_epc1; + } else { + if (epConfig <= 0) + return &node_scal_cpe_epc0; + else + return &node_scal_cpe_epc1; + } + case AOT_ER_AAC_ELD: + if (nChannels == 1) { + if (epConfig <= 0) + return &node_eld_sce_epc0; + else + return &node_eld_sce_epc1; + } else { + if (epConfig <= 0) + return &node_eld_cpe_epc0; + else + return &node_eld_cpe_epc1; + } + case AOT_DRM_AAC: + case AOT_DRM_SBR: + case AOT_DRM_MPEG_PS: + case AOT_DRM_SURROUND: + FDK_ASSERT(epConfig == 1); + if (nChannels == 1) { + return &node_drm_sce; + } else { + return &node_drm_cpe; + } + default: + break; + } + return NULL; +} + +/* Inverse square root table for operands running from 0.5 to ~1.0 */ +/* (INT) (0.5 + 1.0/sqrt((op)/FDKpow(2.0,31))); */ +/* Note: First value is rnot rounded for accuracy reasons */ +/* Implicit exponent is 1. */ +/* Examples: 0x5A82799A = invSqrtNorm2 (0x4000.0000), exp=1 */ +/* 0x5A82799A = invSqrtNorm2 (0x4000.0000), exp=1 */ + +LNK_SECTION_CONSTDATA_L1 +const FIXP_DBL invSqrtTab[SQRT_VALUES] = { + 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 */ +}; + +/* number of channels of the formats */ + +const INT format_nchan[FDK_NFORMATS + 9 - 2] = { + 0, /* any set-up, ChConfIdx = 0 */ + 1, /* mono ChConfIdx = 1 */ + 2, /* stereo ChConfIdx = 2 */ + 3, /* 3/0.0 ChConfIdx = 3 */ + 4, /* 3/1.0 ChConfIdx = 4 */ + 5, /* 3/2.0 ChConfIdx = 5 */ + 6, /* 5.1 ChConfIdx = 6 */ + 8, /* 5/2.1 ALT ChConfIdx = 7 */ + 0, /* Empty n.a. ChConfIdx = 8 */ + 3, /* 2/1.0 ChConfIdx = 9 */ + 4, /* 2/2.0 ChConfIdx = 10 */ + 7, /* 3/3.1 ChConfIdx = 11 */ + 8, /* 3/4.1 ChConfIdx = 12 */ + 24, /* 22.2 ChConfIdx = 13 */ + 8, /* 5/2.1 ChConfIdx = 14 */ + 12, /* 5/5.2 ChConfIdx = 15 */ + 10, /* 5/4.1 ChConfIdx = 16 */ + 12, /* 6/5.1 ChConfIdx = 17 */ + 14, /* 6/7.1 ChConfIdx = 18 */ + 12, /* 5/6.1 ChConfIdx = 19 */ + 14 /* 7/6.1 ChConfIdx = 20 */ +}; diff --git a/fdk-aac/libFDK/src/FDK_trigFcts.cpp b/fdk-aac/libFDK/src/FDK_trigFcts.cpp new file mode 100644 index 0000000..4bb6262 --- /dev/null +++ b/fdk-aac/libFDK/src/FDK_trigFcts.cpp @@ -0,0 +1,340 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Haricharan Lakshman, Manuel Jander + + Description: Trigonometric functions fixed point fractional implementation. + +*******************************************************************************/ + +#include "FDK_trigFcts.h" + +#include "fixpoint_math.h" + +#define IMPROVE_ATAN2_ACCURACY 1 /* 0 --> 59 dB SNR 1 --> 65 dB SNR */ +#define MINSFTAB 7 +#define MAXSFTAB 25 + +#if IMPROVE_ATAN2_ACCURACY +static const FIXP_DBL f_atan_expand_range[MAXSFTAB - (MINSFTAB - 1)] = { + /***************************************************************************** + * + * Table holds fixp_atan() output values which are outside of input range + * of fixp_atan() to improve SNR of fixp_atan2(). + * + * This Table might also be used in fixp_atan() so there a wider input + * range can be covered, too. + * + *****************************************************************************/ + FL2FXCONST_DBL(7.775862990872099e-001), + FL2FXCONST_DBL(7.814919928673978e-001), + FL2FXCONST_DBL(7.834450483314648e-001), + FL2FXCONST_DBL(7.844216021392089e-001), + FL2FXCONST_DBL(7.849098823026687e-001), + FL2FXCONST_DBL(7.851540227918509e-001), + FL2FXCONST_DBL(7.852760930873737e-001), + FL2FXCONST_DBL(7.853371282415015e-001), + FL2FXCONST_DBL(7.853676458193612e-001), + FL2FXCONST_DBL(7.853829046083906e-001), + FL2FXCONST_DBL(7.853905340029177e-001), + FL2FXCONST_DBL(7.853943487001828e-001), + FL2FXCONST_DBL(7.853962560488155e-001), + FL2FXCONST_DBL(7.853972097231319e-001), + FL2FXCONST_DBL(7.853976865602901e-001), + FL2FXCONST_DBL(7.853979249788692e-001), + FL2FXCONST_DBL(7.853980441881587e-001), + FL2FXCONST_DBL(7.853981037928035e-001), + FL2FXCONST_DBL(7.853981335951259e-001) + /* pi/4 = 0.785398163397448 = pi/2/ATO_SCALE */ +}; +#endif + +FIXP_DBL fixp_atan2(FIXP_DBL y, FIXP_DBL x) { + FIXP_DBL q; + FIXP_DBL at; /* atan out */ + FIXP_DBL at2; /* atan2 out */ + FIXP_DBL ret = FL2FXCONST_DBL(-1.0f); + INT sf, sfo, stf; + + /* --- division */ + + if (y > FL2FXCONST_DBL(0.0f)) { + if (x > FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec(y, x, &sf); /* both pos. */ + } else if (x < FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec(y, -x, &sf); /* x neg. */ + } else { /* (x == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(+1.0f); /* y/x = pos/zero = +Inf */ + sf = 0; + } + } else if (y < FL2FXCONST_DBL(0.0f)) { + if (x > FL2FXCONST_DBL(0.0f)) { + q = -fDivNormHighPrec(-y, x, &sf); /* y neg. */ + } else if (x < FL2FXCONST_DBL(0.0f)) { + q = fDivNormHighPrec(-y, -x, &sf); /* both neg. */ + } else { /* (x == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(-1.0f); /* y/x = neg/zero = -Inf */ + sf = 0; + } + } else { /* (y == FL2FXCONST_DBL(0.0f)) */ + q = FL2FXCONST_DBL(0.0f); + sf = 0; + } + sfo = sf; + + /* --- atan() */ + + if (sfo > ATI_SF) { + /* --- could not calc fixp_atan() here bec of input data out of range */ + /* ==> therefore give back boundary values */ + +#if IMPROVE_ATAN2_ACCURACY + if (sfo > MAXSFTAB) sfo = MAXSFTAB; +#endif + + if (q > FL2FXCONST_DBL(0.0f)) { +#if IMPROVE_ATAN2_ACCURACY + at = +f_atan_expand_range[sfo - ATI_SF - 1]; +#else + at = FL2FXCONST_DBL(+M_PI / 2 / ATO_SCALE); +#endif + } else if (q < FL2FXCONST_DBL(0.0f)) { +#if IMPROVE_ATAN2_ACCURACY + at = -f_atan_expand_range[sfo - ATI_SF - 1]; +#else + at = FL2FXCONST_DBL(-M_PI / 2 / ATO_SCALE); +#endif + } else { /* q == FL2FXCONST_DBL(0.0f) */ + at = FL2FXCONST_DBL(0.0f); + } + } else { + /* --- calc of fixp_atan() is possible; input data within range */ + /* ==> set q on fixed scale level as desired from fixp_atan() */ + stf = sfo - ATI_SF; + if (stf > 0) + q = q << (INT)fMin(stf, DFRACT_BITS - 1); + else + q = q >> (INT)fMin(-stf, DFRACT_BITS - 1); + at = fixp_atan(q); /* ATO_SF */ + } + + // --- atan2() + + at2 = at >> (AT2O_SF - ATO_SF); // now AT2O_SF for atan2 + if (x > FL2FXCONST_DBL(0.0f)) { + ret = at2; + } else if (x < FL2FXCONST_DBL(0.0f)) { + if (y >= FL2FXCONST_DBL(0.0f)) { + ret = at2 + FL2FXCONST_DBL(M_PI / AT2O_SCALE); + } else { + ret = at2 - FL2FXCONST_DBL(M_PI / AT2O_SCALE); + } + } else { + // x == 0 + if (y > FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(+M_PI / 2 / AT2O_SCALE); + } else if (y < FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(-M_PI / 2 / AT2O_SCALE); + } else if (y == FL2FXCONST_DBL(0.0f)) { + ret = FL2FXCONST_DBL(0.0f); + } + } + return ret; +} + +FIXP_DBL fixp_atan(FIXP_DBL x) { + INT sign; + FIXP_DBL result, temp; + + /* SNR of fixp_atan() = 56 dB */ + FIXP_DBL P281 = (FIXP_DBL)0x00013000; // 0.281 in q18 + FIXP_DBL ONEP571 = (FIXP_DBL)0x6487ef00; // 1.571 in q30 + + if (x < FIXP_DBL(0)) { + sign = 1; + x = -x; + } else { + sign = 0; + } + FDK_ASSERT(FL2FXCONST_DBL(1.0 / 64.0) == Q(Q_ATANINP)); + /* calc of arctan */ + if (x < FL2FXCONST_DBL(1.0 / 64.0)) + /* + Chebyshev polynomial approximation of atan(x) + 5th-order approximation: atan(x) = a1*x + a2*x^3 + a3*x^5 = x(a1 + x^2*(a2 + + a3*x^2)); a1 = 0.9949493661166540f, a2 = 0.2870606355326520f, a3 = + 0.0780371764464410f; 7th-order approximation: atan(x) = a1*x + a2*x^3 + + a3*x^5 + a3*x^7 = x(a1 + x^2*(a2 + x^2*(a3 + a4*x^2))); a1 = + 0.9991334482227801, a2 = -0.3205332923816640, a3 = 0.1449824901444650, a4 = + -0.0382544649702990; 7th-order approximation in use (the most accurate + solution) + */ + { + x <<= ATI_SF; + FIXP_DBL x2 = fPow2(x); + temp = fMultAddDiv2((FL2FXCONST_DBL(0.1449824901444650f) >> 1), x2, + FL2FXCONST_DBL(-0.0382544649702990)); + temp = fMultAddDiv2((FL2FXCONST_DBL(-0.3205332923816640f) >> 2), x2, temp); + temp = fMultAddDiv2((FL2FXCONST_DBL(0.9991334482227801f) >> 3), x2, temp); + result = fMult(x, (temp << 2)); + } else if (x < FL2FXCONST_DBL(1.28 / 64.0)) { + FIXP_DBL delta_fix; + FIXP_DBL PI_BY_4 = FL2FXCONST_DBL(3.1415926 / 4.0) >> 1; /* pi/4 in q30 */ + + delta_fix = (x - FL2FXCONST_DBL(1.0 / 64.0)) << 5; /* q30 */ + result = PI_BY_4 + (delta_fix >> 1) - (fPow2Div2(delta_fix)); + } else { + /* Other approximation for |x| > 1.28 */ + INT res_e; + + temp = fPow2Div2(x); /* q25 * q25 - (DFRACT_BITS-1) - 1 = q18 */ + temp = temp + P281; /* q18 + q18 = q18 */ + result = fDivNorm(x, temp, &res_e); + result = scaleValue(result, + (Q_ATANOUT - Q_ATANINP + 18 - DFRACT_BITS + 1) + res_e); + result = ONEP571 - result; /* q30 + q30 = q30 */ + } + if (sign) { + result = -result; + } + + return (result); +} + +#include "FDK_tools_rom.h" + +FIXP_DBL fixp_cos(FIXP_DBL x, int scale) { + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(sine, residual); + +#ifdef SINETABLE_16BIT + return cosine - error; +#else + /* Undo downscaling by 1 which was done at fixp_sin_cos_residual_inline */ + return SATURATE_LEFT_SHIFT(cosine - error, 1, DFRACT_BITS); +#endif +} + +FIXP_DBL fixp_sin(FIXP_DBL x, int scale) { + FIXP_DBL residual, error, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error = fMult(cosine, residual); + +#ifdef SINETABLE_16BIT + return sine + error; +#else + return SATURATE_LEFT_SHIFT(sine + error, 1, DFRACT_BITS); +#endif +} + +void fixp_cos_sin(FIXP_DBL x, int scale, FIXP_DBL *cos, FIXP_DBL *sin) { + FIXP_DBL residual, error0, error1, sine, cosine; + + residual = fixp_sin_cos_residual_inline(x, scale, &sine, &cosine); + error0 = fMult(sine, residual); + error1 = fMult(cosine, residual); + +#ifdef SINETABLE_16BIT + *cos = cosine - error0; + *sin = sine + error1; +#else + *cos = SATURATE_LEFT_SHIFT(cosine - error0, 1, DFRACT_BITS); + *sin = SATURATE_LEFT_SHIFT(sine + error1, 1, DFRACT_BITS); +#endif +} diff --git a/fdk-aac/libFDK/src/arm/fft_rad2_arm.cpp b/fdk-aac/libFDK/src/arm/fft_rad2_arm.cpp new file mode 100644 index 0000000..2c03b11 --- /dev/null +++ b/fdk-aac/libFDK/src/arm/fft_rad2_arm.cpp @@ -0,0 +1,321 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: dit_fft ARM assembler replacements. + +*******************************************************************************/ + +#ifndef __FFT_RAD2_CPP__ +#error \ + "Do not compile this file separately. It is included on demand from fft_rad2.cpp" +#endif + +#ifndef FUNCTION_dit_fft +#if defined(SINETABLE_16BIT) + +#define FUNCTION_dit_fft +#if defined(FUNCTION_dit_fft) + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + const INT n = 1 << ldn; + INT i; + + scramble(x, n); + /* + * 1+2 stage radix 4 + */ + + for (i = 0; i < n * 2; i += 8) { + FIXP_DBL a00, a10, a20, a30; + a00 = (x[i + 0] + x[i + 2]) >> 1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6]) >> 1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3]) >> 1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7]) >> 1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + INT mh = 1 << 1; + INT ldm = ldn - 2; + INT trigstep = trigDataSize; + + do { + const FIXP_STP *pTrigData = trigdata; + INT j; + + mh <<= 1; + trigstep >>= 1; + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to + much precision. Beware: The impact on the overal FFT precision is rather + large. */ + { + FIXP_DBL *xt1 = x; + int r = n; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + /* + FIXP_DBL *xt1 = x+ ((r)<<1); + FIXP_DBL *xt2 = xt1 + (mh<<1); + */ + FIXP_DBL vr, vi, ur, ui; + + // cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vi = xt2[1] >> 1; + vr = xt2[0] >> 1; + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + // cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = xt2[1] >> 1; + vi = xt2[0] >> 1; + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 = xt2 + mh; + } while ((r = r - (mh << 1)) != 0); + } + for (j = 4; j < mh; j += 4) { + FIXP_DBL *xt1 = x + (j >> 1); + FIXP_SPK cs; + int r = n; + + pTrigData += trigstep; + cs = *pTrigData; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + xt1 = xt1 - (j); + xt2 = xt1 + (mh << 1); + + cplxMultDiv2(&vi, &vr, xt2[0], xt2[1], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[0], xt2[1], cs); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur - vr; + xt1[1] = ui - vi; + + xt2[0] = ur + vr; + xt2[1] = ui + vi; + + xt1 = xt2 + (j); + } while ((r = r - (mh << 1)) != 0); + } + { + FIXP_DBL *xt1 = x + (mh >> 1); + int r = n; + + do { + FIXP_DBL *xt2 = xt1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, xt2[1], xt2[0], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui + vi; + + xt2[0] = ur - vr; + xt2[1] = ui - vi; + + xt1 += mh; + xt2 += mh; + + cplxMultDiv2(&vr, &vi, xt2[1], xt2[0], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = xt1[0] >> 1; + ui = xt1[1] >> 1; + + xt1[0] = ur + vr; + xt1[1] = ui - vi; + + xt2[0] = ur - vr; + xt2[1] = ui + vi; + + xt1 = xt2 + mh; + } while ((r = r - (mh << 1)) != 0); + } + } while (--ldm != 0); +} + +#endif /* if defined(FUNCTION_dit_fft) */ + +#endif /* if defined(SINETABLE_16BIT) */ + +#endif /* ifndef FUNCTION_dit_fft */ diff --git a/fdk-aac/libFDK/src/arm/scale_arm.cpp b/fdk-aac/libFDK/src/arm/scale_arm.cpp new file mode 100644 index 0000000..92c9edc --- /dev/null +++ b/fdk-aac/libFDK/src/arm/scale_arm.cpp @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Arthur Tritthart + + Description: Scaling operations for ARM + +*******************************************************************************/ + +/* prevent multiple inclusion with re-definitions */ +#ifndef __INCLUDE_SCALE_ARM__ +#define __INCLUDE_SCALE_ARM__ + +#if !defined(FUNCTION_scaleValuesWithFactor_DBL) +#define FUNCTION_scaleValuesWithFactor_DBL +SCALE_INLINE +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor) { + /* This code combines the fMult with the scaling */ + /* It performs a fMultDiv2 and increments shift by 1 */ + int shift = scalefactor + 1; + FIXP_DBL *mySpec = vector; + + shift = fixmin_I(shift, (INT)DFRACT_BITS - 1); + + if (shift >= 0) { + for (int i = 0; i < (len >> 2); i++) { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 <<= shift; + tmp1 <<= shift; + tmp2 <<= shift; + tmp3 <<= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i = len & 3; i--;) { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 <<= shift; + *mySpec++ = tmp0; + } + } else { + shift = -shift; + for (int i = 0; i < (len >> 2); i++) { + FIXP_DBL tmp0 = mySpec[0]; + FIXP_DBL tmp1 = mySpec[1]; + FIXP_DBL tmp2 = mySpec[2]; + FIXP_DBL tmp3 = mySpec[3]; + tmp0 = fMultDiv2(tmp0, factor); + tmp1 = fMultDiv2(tmp1, factor); + tmp2 = fMultDiv2(tmp2, factor); + tmp3 = fMultDiv2(tmp3, factor); + tmp0 >>= shift; + tmp1 >>= shift; + tmp2 >>= shift; + tmp3 >>= shift; + *mySpec++ = tmp0; + *mySpec++ = tmp1; + *mySpec++ = tmp2; + *mySpec++ = tmp3; + } + for (int i = len & 3; i--;) { + FIXP_DBL tmp0 = mySpec[0]; + tmp0 = fMultDiv2(tmp0, factor); + tmp0 >>= shift; + *mySpec++ = tmp0; + } + } +} +#endif /* #if !defined(FUNCTION_scaleValuesWithFactor_DBL) */ + +#endif /* #ifndef __INCLUDE_SCALE_ARM__ */ diff --git a/fdk-aac/libFDK/src/autocorr2nd.cpp b/fdk-aac/libFDK/src/autocorr2nd.cpp new file mode 100644 index 0000000..718a555 --- /dev/null +++ b/fdk-aac/libFDK/src/autocorr2nd.cpp @@ -0,0 +1,293 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser + + Description: auto-correlation functions + +*******************************************************************************/ + +#include "autocorr2nd.h" + +/* If the accumulator does not provide enough overflow bits, + products have to be shifted down in the autocorrelation below. */ +#define SHIFT_FACTOR (5) +#define SHIFT >> (SHIFT_FACTOR) + +/*! + * + * \brief Calculate second order autocorrelation using 2 accumulators + * + */ +#if !defined(FUNCTION_autoCorr2nd_real) +INT autoCorr2nd_real( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to to real part of input samples */ + const int len /*!< Number input samples */ +) { + int j, autoCorrScaling, mScale; + + FIXP_DBL accu1, accu2, accu3, accu4, accu5; + + const FIXP_DBL *pReBuf; + + const FIXP_DBL *realBuf = reBuffer; + + /* + r11r,r22r + r01r,r12r + r02r + */ + pReBuf = realBuf - 2; + accu5 = ((fMultDiv2(pReBuf[0], pReBuf[2]) + fMultDiv2(pReBuf[1], pReBuf[3])) + SHIFT); + pReBuf++; + + /* len must be even */ + accu1 = fPow2Div2(pReBuf[0]) SHIFT; + accu3 = fMultDiv2(pReBuf[0], pReBuf[1]) SHIFT; + pReBuf++; + + for (j = (len - 2) >> 1; j != 0; j--, pReBuf += 2) { + accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pReBuf[1])) SHIFT); + + accu3 += ((fMultDiv2(pReBuf[0], pReBuf[1]) + + fMultDiv2(pReBuf[1], pReBuf[2])) SHIFT); + + accu5 += ((fMultDiv2(pReBuf[0], pReBuf[2]) + + fMultDiv2(pReBuf[1], pReBuf[3])) SHIFT); + } + + accu2 = (fPow2Div2(realBuf[-2]) SHIFT); + accu2 += accu1; + + accu1 += (fPow2Div2(realBuf[len - 2]) SHIFT); + + accu4 = (fMultDiv2(realBuf[-1], realBuf[-2]) SHIFT); + accu4 += accu3; + + accu3 += (fMultDiv2(realBuf[len - 1], realBuf[len - 2]) SHIFT); + + mScale = CntLeadingZeros( + (accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | fAbs(accu5))) - + 1; + autoCorrScaling = mScale - 1 - SHIFT_FACTOR; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r11r = accu1 << mScale; + ac->r22r = accu2 << mScale; + ac->r01r = accu3 << mScale; + ac->r12r = accu4 << mScale; + ac->r02r = accu5 << mScale; + + ac->det = (fMultDiv2(ac->r11r, ac->r22r) - fMultDiv2(ac->r12r, ac->r12r)); + mScale = CountLeadingBits(fAbs(ac->det)); + + ac->det <<= mScale; + ac->det_scale = mScale - 1; + + return autoCorrScaling; +} +#endif + +#if !defined(FUNCTION_autoCorr2nd_cplx) +INT autoCorr2nd_cplx( + ACORR_COEFS *ac, /*!< Pointer to autocorrelation coeffs */ + const FIXP_DBL *reBuffer, /*!< Pointer to real part of input samples */ + const FIXP_DBL *imBuffer, /*!< Pointer to imag part of input samples */ + const int len /*!< Number of input samples (should be smaller than 128) */ +) { + int j, autoCorrScaling, mScale, len_scale; + + FIXP_DBL accu0, accu1, accu2, accu3, accu4, accu5, accu6, accu7, accu8; + + const FIXP_DBL *pReBuf, *pImBuf; + + const FIXP_DBL *realBuf = reBuffer; + const FIXP_DBL *imagBuf = imBuffer; + + (len > 64) ? (len_scale = 6) : (len_scale = 5); + /* + r00r, + r11r,r22r + r01r,r12r + r01i,r12i + r02r,r02i + */ + accu1 = accu3 = accu5 = accu7 = accu8 = FL2FXCONST_DBL(0.0f); + + pReBuf = realBuf - 2, pImBuf = imagBuf - 2; + accu7 += + ((fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> + len_scale); + accu8 += + ((fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> + len_scale); + + pReBuf = realBuf - 1, pImBuf = imagBuf - 1; + for (j = (len - 1); j != 0; j--, pReBuf++, pImBuf++) { + accu1 += ((fPow2Div2(pReBuf[0]) + fPow2Div2(pImBuf[0])) >> len_scale); + accu3 += + ((fMultDiv2(pReBuf[0], pReBuf[1]) + fMultDiv2(pImBuf[0], pImBuf[1])) >> + len_scale); + accu5 += + ((fMultDiv2(pImBuf[1], pReBuf[0]) - fMultDiv2(pReBuf[1], pImBuf[0])) >> + len_scale); + accu7 += + ((fMultDiv2(pReBuf[2], pReBuf[0]) + fMultDiv2(pImBuf[2], pImBuf[0])) >> + len_scale); + accu8 += + ((fMultDiv2(pImBuf[2], pReBuf[0]) - fMultDiv2(pReBuf[2], pImBuf[0])) >> + len_scale); + } + + accu2 = ((fPow2Div2(realBuf[-2]) + fPow2Div2(imagBuf[-2])) >> len_scale); + accu2 += accu1; + + accu1 += ((fPow2Div2(realBuf[len - 2]) + fPow2Div2(imagBuf[len - 2])) >> + len_scale); + accu0 = ((fPow2Div2(realBuf[len - 1]) + fPow2Div2(imagBuf[len - 1])) >> + len_scale) - + ((fPow2Div2(realBuf[-1]) + fPow2Div2(imagBuf[-1])) >> len_scale); + accu0 += accu1; + + accu4 = ((fMultDiv2(realBuf[-1], realBuf[-2]) + + fMultDiv2(imagBuf[-1], imagBuf[-2])) >> + len_scale); + accu4 += accu3; + + accu3 += ((fMultDiv2(realBuf[len - 1], realBuf[len - 2]) + + fMultDiv2(imagBuf[len - 1], imagBuf[len - 2])) >> + len_scale); + + accu6 = ((fMultDiv2(imagBuf[-1], realBuf[-2]) - + fMultDiv2(realBuf[-1], imagBuf[-2])) >> + len_scale); + accu6 += accu5; + + accu5 += ((fMultDiv2(imagBuf[len - 1], realBuf[len - 2]) - + fMultDiv2(realBuf[len - 1], imagBuf[len - 2])) >> + len_scale); + + mScale = + CntLeadingZeros((accu0 | accu1 | accu2 | fAbs(accu3) | fAbs(accu4) | + fAbs(accu5) | fAbs(accu6) | fAbs(accu7) | fAbs(accu8))) - + 1; + autoCorrScaling = mScale - 1 - len_scale; /* -1 because of fMultDiv2*/ + + /* Scale to common scale factor */ + ac->r00r = (FIXP_DBL)accu0 << mScale; + ac->r11r = (FIXP_DBL)accu1 << mScale; + ac->r22r = (FIXP_DBL)accu2 << mScale; + ac->r01r = (FIXP_DBL)accu3 << mScale; + ac->r12r = (FIXP_DBL)accu4 << mScale; + ac->r01i = (FIXP_DBL)accu5 << mScale; + ac->r12i = (FIXP_DBL)accu6 << mScale; + ac->r02r = (FIXP_DBL)accu7 << mScale; + ac->r02i = (FIXP_DBL)accu8 << mScale; + + ac->det = + (fMultDiv2(ac->r11r, ac->r22r) >> 1) - + ((fMultDiv2(ac->r12r, ac->r12r) + fMultDiv2(ac->r12i, ac->r12i)) >> 1); + mScale = CntLeadingZeros(fAbs(ac->det)) - 1; + + ac->det <<= mScale; + ac->det_scale = mScale - 2; + + return autoCorrScaling; +} + +#endif /* FUNCTION_autoCorr2nd_cplx */ diff --git a/fdk-aac/libFDK/src/dct.cpp b/fdk-aac/libFDK/src/dct.cpp new file mode 100644 index 0000000..776493e --- /dev/null +++ b/fdk-aac/libFDK/src/dct.cpp @@ -0,0 +1,568 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file dct.cpp + \brief DCT Implementations + Library functions to calculate standard DCTs. This will most likely be + replaced by hand-optimized functions for the specific target processor. + + Three different implementations of the dct type II and the dct type III + transforms are provided. + + By default implementations which are based on a single, standard complex + FFT-kernel are used (dctII_f() and dctIII_f()). These are specifically helpful + in cases where optimized FFT libraries are already available. The FFT used in + these implementation is FFT rad2 from FDK_tools. + + Of course, one might also use DCT-libraries should they be available. The DCT + and DST type IV implementations are only available in a version based on a + complex FFT kernel. +*/ + +#include "dct.h" + +#include "FDK_tools_rom.h" +#include "fft.h" + +void dct_getTables(const FIXP_WTP **ptwiddle, const FIXP_STP **sin_twiddle, + int *sin_step, int length) { + const FIXP_WTP *twiddle; + int ld2_length; + + /* Get ld2 of length - 2 + 1 + -2: because first table entry is window of size 4 + +1: because we already include +1 because of ceil(log2(length)) */ + ld2_length = DFRACT_BITS - 1 - fNormz((FIXP_DBL)length) - 1; + + /* Extract sort of "eigenvalue" (the 4 left most bits) of length. */ + switch ((length) >> (ld2_length - 1)) { + case 0x4: /* radix 2 */ + *sin_twiddle = SineTable1024; + *sin_step = 1 << (10 - ld2_length); + twiddle = windowSlopes[0][0][ld2_length - 1]; + break; + case 0x7: /* 10 ms */ + *sin_twiddle = SineTable480; + *sin_step = 1 << (8 - ld2_length); + twiddle = windowSlopes[0][1][ld2_length]; + break; + case 0x6: /* 3/4 of radix 2 */ + *sin_twiddle = SineTable384; + *sin_step = 1 << (8 - ld2_length); + twiddle = windowSlopes[0][2][ld2_length]; + break; + case 0x5: /* 5/16 of radix 2*/ + *sin_twiddle = SineTable80; + *sin_step = 1 << (6 - ld2_length); + twiddle = windowSlopes[0][3][ld2_length]; + break; + default: + *sin_twiddle = NULL; + *sin_step = 0; + twiddle = NULL; + break; + } + + if (ptwiddle != NULL) { + FDK_ASSERT(twiddle != NULL); + *ptwiddle = twiddle; + } + + FDK_ASSERT(*sin_step > 0); +} + +#if !defined(FUNCTION_dct_III) +void dct_III(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e) { + const FIXP_WTP *sin_twiddle; + int i; + FIXP_DBL xr, accu1, accu2; + int inc, index; + int M = L >> 1; + + FDK_ASSERT(L % 4 == 0); + dct_getTables(NULL, &sin_twiddle, &inc, L); + inc >>= 1; + + FIXP_DBL *pTmp_0 = &tmp[2]; + FIXP_DBL *pTmp_1 = &tmp[(M - 1) * 2]; + + index = 4 * inc; + + /* This loop performs multiplication for index i (i*inc) */ + for (i = 1; i> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) { + FIXP_DBL accu3, accu4, accu5, accu6; + + cplxMultDiv2(&accu2, &accu1, pDat[L - i], pDat[i], sin_twiddle[i * inc]); + cplxMultDiv2(&accu4, &accu3, pDat[M + i], pDat[M - i], + sin_twiddle[(M - i) * inc]); + accu3 >>= 1; + accu4 >>= 1; + + /* This method is better for ARM926, that uses operand2 shifted right by 1 + * always */ + if (2 * i < (M / 2)) { + cplxMultDiv2(&accu6, &accu5, (accu3 - (accu1 >> 1)), + ((accu2 >> 1) + accu4), sin_twiddle[index]); + } else { + cplxMultDiv2(&accu6, &accu5, ((accu2 >> 1) + accu4), + (accu3 - (accu1 >> 1)), sin_twiddle[index]); + accu6 = -accu6; + } + xr = (accu1 >> 1) + accu3; + pTmp_0[0] = (xr >> 1) - accu5; + pTmp_1[0] = (xr >> 1) + accu5; + + xr = (accu2 >> 1) - accu4; + pTmp_0[1] = (xr >> 1) - accu6; + pTmp_1[1] = -((xr >> 1) + accu6); + + /* Create index helper variables for (4*i)*inc indexed equivalent values of + * short tables. */ + if (2 * i < ((M / 2) - 1)) { + index += 4 * inc; + } else if (2 * i >= ((M / 2))) { + index -= 4 * inc; + } + } + + xr = fMultDiv2(pDat[M], sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */ + tmp[0] = ((pDat[0] >> 1) + xr) >> 1; + tmp[1] = ((pDat[0] >> 1) - xr) >> 1; + + cplxMultDiv2(&accu2, &accu1, pDat[L - (M / 2)], pDat[M / 2], + sin_twiddle[M * inc / 2]); + tmp[M] = accu1 >> 1; + tmp[M + 1] = accu2 >> 1; + + /* dit_fft expects 1 bit scaled input values */ + fft(M, tmp, pDat_e); + + /* ARM926: 12 cycles per 2-iteration, no overhead code by compiler */ + pTmp_1 = &tmp[L]; + for (i = M >> 1; i--;) { + FIXP_DBL tmp1, tmp2, tmp3, tmp4; + tmp1 = *tmp++; + tmp2 = *tmp++; + tmp3 = *--pTmp_1; + tmp4 = *--pTmp_1; + *pDat++ = tmp1; + *pDat++ = tmp3; + *pDat++ = tmp2; + *pDat++ = tmp4; + } + + *pDat_e += 2; +} + +void dst_III(FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform */ + int *pDat_e) { + int L2 = L >> 1; + int i; + FIXP_DBL t; + + /* note: DCT III is reused here, direct DST III implementation might be more + * efficient */ + + /* mirror input */ + for (i = 0; i < L2; i++) { + t = pDat[i]; + pDat[i] = pDat[L - 1 - i]; + pDat[L - 1 - i] = t; + } + + /* DCT-III */ + dct_III(pDat, tmp, L, pDat_e); + + /* flip signs at odd indices */ + for (i = 1; i < L; i += 2) pDat[i] = -pDat[i]; +} + +#endif + +#if !defined(FUNCTION_dct_II) +void dct_II( + FIXP_DBL *pDat, /*!< pointer to input/output */ + FIXP_DBL *tmp, /*!< pointer to temporal working buffer */ + int L, /*!< lenght of transform (has to be a multiple of 8 (or 4 in case + DCT_II_L_MULTIPLE_OF_4_SUPPORT is defined) */ + int *pDat_e) { + const FIXP_WTP *sin_twiddle; + FIXP_DBL accu1, accu2; + FIXP_DBL *pTmp_0, *pTmp_1; + + int i; + int inc, index = 0; + int M = L >> 1; + + FDK_ASSERT(L % 4 == 0); + dct_getTables(NULL, &sin_twiddle, &inc, L); + inc >>= 1; + + { + for (i = 0; i < M; i++) { + tmp[i] = pDat[2 * i] >> 1; /* dit_fft expects 1 bit scaled input values */ + tmp[L - 1 - i] = + pDat[2 * i + 1] >> 1; /* dit_fft expects 1 bit scaled input values */ + } + } + + fft(M, tmp, pDat_e); + + pTmp_0 = &tmp[2]; + pTmp_1 = &tmp[(M - 1) * 2]; + + index = inc * 4; + + for (i = 1; i> 1; i++, pTmp_0 += 2, pTmp_1 -= 2) { + FIXP_DBL a1, a2; + FIXP_DBL accu3, accu4; + + a1 = ((pTmp_0[1] >> 1) + (pTmp_1[1] >> 1)); + a2 = ((pTmp_1[0] >> 1) - (pTmp_0[0] >> 1)); + + if (2 * i < (M / 2)) { + cplxMultDiv2(&accu1, &accu2, a2, a1, sin_twiddle[index]); + } else { + cplxMultDiv2(&accu1, &accu2, a1, a2, sin_twiddle[index]); + accu1 = -accu1; + } + accu1 <<= 1; + accu2 <<= 1; + + a1 = ((pTmp_0[0] >> 1) + (pTmp_1[0] >> 1)); + a2 = ((pTmp_0[1] >> 1) - (pTmp_1[1] >> 1)); + + cplxMultDiv2(&accu3, &accu4, (a1 + accu2), -(accu1 + a2), + sin_twiddle[i * inc]); + pDat[L - i] = accu4; + pDat[i] = accu3; + + cplxMultDiv2(&accu3, &accu4, (a1 - accu2), -(accu1 - a2), + sin_twiddle[(M - i) * inc]); + pDat[M + i] = accu4; + pDat[M - i] = accu3; + + /* Create index helper variables for (4*i)*inc indexed equivalent values of + * short tables. */ + if (2 * i < ((M / 2) - 1)) { + index += 4 * inc; + } else if (2 * i >= ((M / 2))) { + index -= 4 * inc; + } + } + + cplxMultDiv2(&accu1, &accu2, tmp[M], tmp[M + 1], sin_twiddle[(M / 2) * inc]); + pDat[L - (M / 2)] = accu2; + pDat[M / 2] = accu1; + + pDat[0] = (tmp[0] >> 1) + (tmp[1] >> 1); + pDat[M] = fMult(((tmp[0] >> 1) - (tmp[1] >> 1)), + sin_twiddle[M * inc].v.re); /* cos((PI/(2*L))*M); */ + + *pDat_e += 2; +} +#endif + +#if !defined(FUNCTION_dct_IV) + +void dct_IV(FIXP_DBL *pDat, int L, int *pDat_e) { + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + + FDK_ASSERT(L >= 4); + + FDK_ASSERT(L >= 4); + + dct_getTables(&twiddle, &sin_twiddle, &sin_step, L); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + int i; + + /* 29 cycles on ARM926 */ + for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) { + FIXP_DBL accu1, accu2, accu3, accu4; + + accu1 = pDat_1[1]; + accu2 = pDat_0[0]; + accu3 = pDat_0[1]; + accu4 = pDat_1[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + pDat_1[0] = accu4 >> 1; + pDat_1[1] = -(accu3 >> 1); + } + if (M & 1) { + FIXP_DBL accu1, accu2; + + accu1 = pDat_1[1]; + accu2 = pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + } + } + + fft(M, pDat, pDat_e); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + FIXP_DBL accu1, accu2, accu3, accu4; + int idx, i; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -pDat_0[1]; + + /* 28 cycles for ARM926 */ + for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) { + FIXP_STP twd = sin_twiddle[idx]; + cplxMult(&accu3, &accu4, accu1, accu2, twd); + pDat_0[1] = accu3; + pDat_1[0] = accu4; + + pDat_0 += 2; + pDat_1 -= 2; + + cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -accu3; + pDat_0[0] = accu4; + } + + if ((M & 1) == 0) { + /* Last Sin and Cos value pair are the same */ + accu1 = fMult(accu1, WTC(0x5a82799a)); + accu2 = fMult(accu2, WTC(0x5a82799a)); + + pDat_1[0] = accu1 + accu2; + pDat_0[1] = accu1 - accu2; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* defined (FUNCTION_dct_IV) */ + +#if !defined(FUNCTION_dst_IV) +void dst_IV(FIXP_DBL *pDat, int L, int *pDat_e) { + int sin_step = 0; + int M = L >> 1; + + const FIXP_WTP *twiddle; + const FIXP_STP *sin_twiddle; + + FDK_ASSERT(L >= 4); + + FDK_ASSERT(L >= 4); + + dct_getTables(&twiddle, &sin_twiddle, &sin_step, L); + + { + FIXP_DBL *RESTRICT pDat_0 = &pDat[0]; + FIXP_DBL *RESTRICT pDat_1 = &pDat[L - 2]; + int i; + + /* 34 cycles on ARM926 */ + for (i = 0; i < M - 1; i += 2, pDat_0 += 2, pDat_1 -= 2) { + FIXP_DBL accu1, accu2, accu3, accu4; + + accu1 = pDat_1[1]; + accu2 = -pDat_0[0]; + accu3 = pDat_0[1]; + accu4 = -pDat_1[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + cplxMultDiv2(&accu3, &accu4, accu4, accu3, twiddle[i + 1]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + pDat_1[0] = accu4 >> 1; + pDat_1[1] = -(accu3 >> 1); + } + if (M & 1) { + FIXP_DBL accu1, accu2; + + accu1 = pDat_1[1]; + accu2 = -pDat_0[0]; + + cplxMultDiv2(&accu1, &accu2, accu1, accu2, twiddle[i]); + + pDat_0[0] = accu2 >> 1; + pDat_0[1] = accu1 >> 1; + } + } + + fft(M, pDat, pDat_e); + + { + FIXP_DBL *RESTRICT pDat_0; + FIXP_DBL *RESTRICT pDat_1; + FIXP_DBL accu1, accu2, accu3, accu4; + int idx, i; + + pDat_0 = &pDat[0]; + pDat_1 = &pDat[L - 2]; + + /* Sin and Cos values are 0.0f and 1.0f */ + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_1[1] = -pDat_0[0]; + pDat_0[0] = pDat_0[1]; + + for (idx = sin_step, i = 1; i<(M + 1)>> 1; i++, idx += sin_step) { + FIXP_STP twd = sin_twiddle[idx]; + + cplxMult(&accu3, &accu4, accu1, accu2, twd); + pDat_1[0] = -accu3; + pDat_0[1] = -accu4; + + pDat_0 += 2; + pDat_1 -= 2; + + cplxMult(&accu3, &accu4, pDat_0[1], pDat_0[0], twd); + + accu1 = pDat_1[0]; + accu2 = pDat_1[1]; + + pDat_0[0] = accu3; + pDat_1[1] = -accu4; + } + + if ((M & 1) == 0) { + /* Last Sin and Cos value pair are the same */ + accu1 = fMult(accu1, WTC(0x5a82799a)); + accu2 = fMult(accu2, WTC(0x5a82799a)); + + pDat_0[1] = -accu1 - accu2; + pDat_1[0] = accu2 - accu1; + } + } + + /* Add twiddeling scale. */ + *pDat_e += 2; +} +#endif /* !defined(FUNCTION_dst_IV) */ diff --git a/fdk-aac/libFDK/src/fft.cpp b/fdk-aac/libFDK/src/fft.cpp new file mode 100644 index 0000000..4e6fdd2 --- /dev/null +++ b/fdk-aac/libFDK/src/fft.cpp @@ -0,0 +1,1922 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, DSP Solutions + + Description: Fix point FFT + +*******************************************************************************/ + +#include "fft_rad2.h" +#include "FDK_tools_rom.h" + +#define W_PiFOURTH STC(0x5a82799a) +//#define W_PiFOURTH ((FIXP_DBL)(0x5a82799a)) +#ifndef SUMDIFF_PIFOURTH +#define SUMDIFF_PIFOURTH(diff, sum, a, b) \ + { \ + FIXP_DBL wa, wb; \ + wa = fMultDiv2(a, W_PiFOURTH); \ + wb = fMultDiv2(b, W_PiFOURTH); \ + diff = wb - wa; \ + sum = wb + wa; \ + } +#define SUMDIFF_PIFOURTH16(diff, sum, a, b) \ + { \ + FIXP_SGL wa, wb; \ + wa = FX_DBL2FX_SGL(fMultDiv2(a, W_PiFOURTH)); \ + wb = FX_DBL2FX_SGL(fMultDiv2(b, W_PiFOURTH)); \ + diff = wb - wa; \ + sum = wb + wa; \ + } +#endif + +#define SCALEFACTOR2048 10 +#define SCALEFACTOR1024 9 +#define SCALEFACTOR512 8 +#define SCALEFACTOR256 7 +#define SCALEFACTOR128 6 +#define SCALEFACTOR64 5 +#define SCALEFACTOR32 4 +#define SCALEFACTOR16 3 +#define SCALEFACTOR8 2 +#define SCALEFACTOR4 1 +#define SCALEFACTOR2 1 + +#define SCALEFACTOR3 1 +#define SCALEFACTOR5 1 +#define SCALEFACTOR6 (SCALEFACTOR2 + SCALEFACTOR3 + 2) +#define SCALEFACTOR7 2 +#define SCALEFACTOR9 2 +#define SCALEFACTOR10 5 +#define SCALEFACTOR12 3 +#define SCALEFACTOR15 3 +#define SCALEFACTOR18 (SCALEFACTOR2 + SCALEFACTOR9 + 2) +#define SCALEFACTOR20 (SCALEFACTOR4 + SCALEFACTOR5 + 2) +#define SCALEFACTOR21 (SCALEFACTOR3 + SCALEFACTOR7 + 2) +#define SCALEFACTOR24 (SCALEFACTOR2 + SCALEFACTOR12 + 2) +#define SCALEFACTOR30 (SCALEFACTOR2 + SCALEFACTOR15 + 2) +#define SCALEFACTOR40 (SCALEFACTOR5 + SCALEFACTOR8 + 2) +#define SCALEFACTOR48 (SCALEFACTOR4 + SCALEFACTOR12 + 2) +#define SCALEFACTOR60 (SCALEFACTOR4 + SCALEFACTOR15 + 2) +#define SCALEFACTOR80 (SCALEFACTOR5 + SCALEFACTOR16 + 2) +#define SCALEFACTOR96 (SCALEFACTOR3 + SCALEFACTOR32 + 2) +#define SCALEFACTOR120 (SCALEFACTOR8 + SCALEFACTOR15 + 2) +#define SCALEFACTOR160 (SCALEFACTOR10 + SCALEFACTOR16 + 2) +#define SCALEFACTOR168 (SCALEFACTOR21 + SCALEFACTOR8 + 2) +#define SCALEFACTOR192 (SCALEFACTOR12 + SCALEFACTOR16 + 2) +#define SCALEFACTOR240 (SCALEFACTOR16 + SCALEFACTOR15 + 2) +#define SCALEFACTOR320 (SCALEFACTOR10 + SCALEFACTOR32 + 2) +#define SCALEFACTOR336 (SCALEFACTOR21 + SCALEFACTOR16 + 2) +#define SCALEFACTOR384 (SCALEFACTOR12 + SCALEFACTOR32 + 2) +#define SCALEFACTOR480 (SCALEFACTOR32 + SCALEFACTOR15 + 2) + +#include "fft.h" + +#ifndef FUNCTION_fft2 + +/* Performs the FFT of length 2. Input vector unscaled, output vector scaled + * with factor 0.5 */ +static FDK_FORCEINLINE void fft2(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, i1; + FIXP_DBL r2, i2; + + /* real part */ + r1 = pDat[2]; + r2 = pDat[0]; + + /* imaginary part */ + i1 = pDat[3]; + i2 = pDat[1]; + + /* real part */ + pDat[0] = (r2 + r1) >> 1; + pDat[2] = (r2 - r1) >> 1; + + /* imaginary part */ + pDat[1] = (i2 + i1) >> 1; + pDat[3] = (i2 - i1) >> 1; +} +#endif /* FUNCTION_fft2 */ + +#define C31 (STC(0x91261468)) /* FL2FXCONST_DBL(-0.86602540) = -sqrt(3)/2 */ + +#ifndef FUNCTION_fft3 +/* Performs the FFT of length 3 according to the algorithm after winograd. */ +static FDK_FORCEINLINE void fft3(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, r2; + FIXP_DBL s1, s2; + FIXP_DBL pD; + + /* real part */ + r1 = pDat[2] + pDat[4]; + r2 = fMultDiv2((pDat[2] - pDat[4]), C31); + pD = pDat[0] >> 1; + pDat[0] = pD + (r1 >> 1); + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pDat[3] + pDat[5]; + s2 = fMultDiv2((pDat[3] - pDat[5]), C31); + pD = pDat[1] >> 1; + pDat[1] = pD + (s1 >> 1); + s1 = pD - (s1 >> 2); + + /* combination */ + pDat[2] = r1 - s2; + pDat[4] = r1 + s2; + pDat[3] = s1 + r2; + pDat[5] = s1 - r2; +} +#endif /* #ifndef FUNCTION_fft3 */ + +#define F5C(x) STC(x) + +#define C51 (F5C(0x79bc3854)) /* FL2FXCONST_DBL( 0.95105652) */ +#define C52 (F5C(0x9d839db0)) /* FL2FXCONST_DBL(-1.53884180/2) */ +#define C53 (F5C(0xd18053ce)) /* FL2FXCONST_DBL(-0.36327126) */ +#define C54 (F5C(0x478dde64)) /* FL2FXCONST_DBL( 0.55901699) */ +#define C55 (F5C(0xb0000001)) /* FL2FXCONST_DBL(-1.25/2) */ + +/* performs the FFT of length 5 according to the algorithm after winograd */ +/* This version works with a prescale of 2 instead of 3 */ +static FDK_FORCEINLINE void fft5(FIXP_DBL *RESTRICT pDat) { + FIXP_DBL r1, r2, r3, r4; + FIXP_DBL s1, s2, s3, s4; + FIXP_DBL t; + + /* real part */ + r1 = (pDat[2] + pDat[8]) >> 1; + r4 = (pDat[2] - pDat[8]) >> 1; + r3 = (pDat[4] + pDat[6]) >> 1; + r2 = (pDat[4] - pDat[6]) >> 1; + t = fMult((r1 - r3), C54); + r1 = r1 + r3; + pDat[0] = (pDat[0] >> 1) + r1; + /* 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 = pDat[0] + (fMultDiv2(r1, C55) << (2)); + r3 = r1 - t; + r1 = r1 + t; + t = fMult((r4 + r2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + r4 = t + (fMultDiv2(r4, C52) << (2)); + r2 = t + fMult(r2, C53); + + /* imaginary part */ + s1 = (pDat[3] + pDat[9]) >> 1; + s4 = (pDat[3] - pDat[9]) >> 1; + s3 = (pDat[5] + pDat[7]) >> 1; + s2 = (pDat[5] - pDat[7]) >> 1; + t = fMult((s1 - s3), C54); + s1 = s1 + s3; + pDat[1] = (pDat[1] >> 1) + s1; + /* 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 = pDat[1] + (fMultDiv2(s1, C55) << (2)); + s3 = s1 - t; + s1 = s1 + t; + t = fMult((s4 + s2), C51); + /* Bit shift left because of the constant C55 which was scaled with the factor + 0.5 because of the representation of the values as fracts */ + s4 = t + (fMultDiv2(s4, C52) << (2)); + s2 = t + fMult(s2, C53); + + /* combination */ + pDat[2] = r1 + s2; + pDat[8] = r1 - s2; + pDat[4] = r3 - s4; + pDat[6] = r3 + s4; + + pDat[3] = s1 - r2; + pDat[9] = s1 + r2; + pDat[5] = s3 + r4; + pDat[7] = s3 - r4; +} + +#define F5C(x) STC(x) + +#define C51 (F5C(0x79bc3854)) /* FL2FXCONST_DBL( 0.95105652) */ +#define C52 (F5C(0x9d839db0)) /* FL2FXCONST_DBL(-1.53884180/2) */ +#define C53 (F5C(0xd18053ce)) /* FL2FXCONST_DBL(-0.36327126) */ +#define C54 (F5C(0x478dde64)) /* FL2FXCONST_DBL( 0.55901699) */ +#define C55 (F5C(0xb0000001)) /* FL2FXCONST_DBL(-1.25/2) */ +/** + * \brief Function performs a complex 10-point FFT + * The FFT is performed inplace. The result of the FFT + * is scaled by SCALEFACTOR10 bits. + * + * WOPS FLC version: 1093 cycles + * WOPS with 32x16 bit multiplications: 196 cycles + * + * \param [i/o] re real input / output + * \param [i/o] im imag input / output + * \param [i ] s stride real and imag input / output + * + * \return void + */ +static void fft10(FIXP_DBL *x) // FIXP_DBL *re, FIXP_DBL *im, FIXP_SGL s) +{ + FIXP_DBL t; + FIXP_DBL x0, x1, x2, x3, x4; + FIXP_DBL r1, r2, r3, r4; + FIXP_DBL s1, s2, s3, s4; + FIXP_DBL y00, y01, y02, y03, y04, y05, y06, y07, y08, y09; + FIXP_DBL y10, y11, y12, y13, y14, y15, y16, y17, y18, y19; + + const int s = 1; // stride factor + + /* 2 fft5 stages */ + + /* real part */ + x0 = (x[s * 0] >> SCALEFACTOR10); + x1 = (x[s * 4] >> SCALEFACTOR10); + x2 = (x[s * 8] >> SCALEFACTOR10); + x3 = (x[s * 12] >> SCALEFACTOR10); + x4 = (x[s * 16] >> SCALEFACTOR10); + + r1 = (x3 + x2); + r4 = (x3 - x2); + r3 = (x1 + x4); + r2 = (x1 - x4); + t = fMult((r1 - r3), C54); + r1 = (r1 + r3); + y00 = (x0 + r1); + r1 = (y00 + ((fMult(r1, C55) << 1))); + r3 = (r1 - t); + r1 = (r1 + t); + t = fMult((r4 + r2), C51); + r4 = (t + (fMult(r4, C52) << 1)); + r2 = (t + fMult(r2, C53)); + + /* imaginary part */ + x0 = (x[s * 0 + 1] >> SCALEFACTOR10); + x1 = (x[s * 4 + 1] >> SCALEFACTOR10); + x2 = (x[s * 8 + 1] >> SCALEFACTOR10); + x3 = (x[s * 12 + 1] >> SCALEFACTOR10); + x4 = (x[s * 16 + 1] >> SCALEFACTOR10); + + s1 = (x3 + x2); + s4 = (x3 - x2); + s3 = (x1 + x4); + s2 = (x1 - x4); + t = fMult((s1 - s3), C54); + s1 = (s1 + s3); + y01 = (x0 + s1); + s1 = (y01 + (fMult(s1, C55) << 1)); + s3 = (s1 - t); + s1 = (s1 + t); + t = fMult((s4 + s2), C51); + s4 = (t + (fMult(s4, C52) << 1)); + s2 = (t + fMult(s2, C53)); + + /* combination */ + y04 = (r1 + s2); + y16 = (r1 - s2); + y08 = (r3 - s4); + y12 = (r3 + s4); + + y05 = (s1 - r2); + y17 = (s1 + r2); + y09 = (s3 + r4); + y13 = (s3 - r4); + + /* real part */ + x0 = (x[s * 10] >> SCALEFACTOR10); + x1 = (x[s * 2] >> SCALEFACTOR10); + x2 = (x[s * 6] >> SCALEFACTOR10); + x3 = (x[s * 14] >> SCALEFACTOR10); + x4 = (x[s * 18] >> SCALEFACTOR10); + + r1 = (x1 + x4); + r4 = (x1 - x4); + r3 = (x3 + x2); + r2 = (x3 - x2); + t = fMult((r1 - r3), C54); + r1 = (r1 + r3); + y02 = (x0 + r1); + r1 = (y02 + ((fMult(r1, C55) << 1))); + r3 = (r1 - t); + r1 = (r1 + t); + t = fMult(((r4 + r2)), C51); + r4 = (t + (fMult(r4, C52) << 1)); + r2 = (t + fMult(r2, C53)); + + /* imaginary part */ + x0 = (x[s * 10 + 1] >> SCALEFACTOR10); + x1 = (x[s * 2 + 1] >> SCALEFACTOR10); + x2 = (x[s * 6 + 1] >> SCALEFACTOR10); + x3 = (x[s * 14 + 1] >> SCALEFACTOR10); + x4 = (x[s * 18 + 1] >> SCALEFACTOR10); + + s1 = (x1 + x4); + s4 = (x1 - x4); + s3 = (x3 + x2); + s2 = (x3 - x2); + t = fMult((s1 - s3), C54); + s1 = (s1 + s3); + y03 = (x0 + s1); + s1 = (y03 + (fMult(s1, C55) << 1)); + s3 = (s1 - t); + s1 = (s1 + t); + t = fMult((s4 + s2), C51); + s4 = (t + (fMult(s4, C52) << 1)); + s2 = (t + fMult(s2, C53)); + + /* combination */ + y06 = (r1 + s2); + y18 = (r1 - s2); + y10 = (r3 - s4); + y14 = (r3 + s4); + + y07 = (s1 - r2); + y19 = (s1 + r2); + y11 = (s3 + r4); + y15 = (s3 - r4); + + /* 5 fft2 stages */ + x[s * 0] = (y00 + y02); + x[s * 0 + 1] = (y01 + y03); + x[s * 10] = (y00 - y02); + x[s * 10 + 1] = (y01 - y03); + + x[s * 4] = (y04 + y06); + x[s * 4 + 1] = (y05 + y07); + x[s * 14] = (y04 - y06); + x[s * 14 + 1] = (y05 - y07); + + x[s * 8] = (y08 + y10); + x[s * 8 + 1] = (y09 + y11); + x[s * 18] = (y08 - y10); + x[s * 18 + 1] = (y09 - y11); + + x[s * 12] = (y12 + y14); + x[s * 12 + 1] = (y13 + y15); + x[s * 2] = (y12 - y14); + x[s * 2 + 1] = (y13 - y15); + + x[s * 16] = (y16 + y18); + x[s * 16 + 1] = (y17 + y19); + x[s * 6] = (y16 - y18); + x[s * 6 + 1] = (y17 - y19); +} + +#ifndef FUNCTION_fft12 +#define FUNCTION_fft12 + +#undef C31 +#define C31 (STC(0x91261468)) /* FL2FXCONST_DBL(-0.86602540) = -sqrt(3)/2 */ + +static inline void fft12(FIXP_DBL *pInput) { + FIXP_DBL aDst[24]; + FIXP_DBL *pSrc, *pDst; + int i; + + pSrc = pInput; + pDst = aDst; + FIXP_DBL r1, r2, s1, s2, pD; + + /* First 3*2 samples are shifted right by 2 before output */ + r1 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + pDst[2] = (r1 - s2) >> 1; + pDst[3] = (s1 + r2) >> 1; + pDst[4] = (r1 + s2) >> 1; + pDst[5] = (s1 - r2) >> 1; + pSrc += 2; + pDst += 6; + + const FIXP_STB *pVecRe = RotVectorReal12; + const FIXP_STB *pVecIm = RotVectorImag12; + FIXP_DBL re, im; + FIXP_STB vre, vim; + 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 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + re = (r1 - s2) >> 0; + im = (s1 + r2) >> 0; + vre = *pVecRe++; + vim = *pVecIm++; + cplxMultDiv2(&pDst[3], &pDst[2], im, re, vre, vim); + + re = (r1 + s2) >> 0; + im = (s1 - r2) >> 0; + vre = *pVecRe++; + vim = *pVecIm++; + cplxMultDiv2(&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 = pSrc[8] + pSrc[16]; + r2 = fMultDiv2((pSrc[8] - pSrc[16]), C31); + pD = pSrc[0] >> 1; + pDst[0] = (pD + (r1 >> 1)) >> 1; + r1 = pD - (r1 >> 2); + + /* imaginary part */ + s1 = pSrc[9] + pSrc[17]; + s2 = fMultDiv2((pSrc[9] - pSrc[17]), C31); + pD = pSrc[1] >> 1; + pDst[1] = (pD + (s1 >> 1)) >> 1; + s1 = pD - (s1 >> 2); + + /* combination */ + pDst[2] = (s1 + r2) >> 1; + pDst[3] = (s2 - r1) >> 1; + pDst[4] = -((r1 + s2) >> 1); + pDst[5] = (r2 - s1) >> 1; + + /* 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. + */ + pSrc = aDst; + pDst = pInput; + for (i = 0; i < 3; i++) { + /* inline FFT4 merged with incoming resorting loop */ + FIXP_DBL a00, a10, a20, a30, tmp0, tmp1; + + a00 = (pSrc[0] + pSrc[12]) >> 1; /* Re A + Re B */ + a10 = (pSrc[6] + pSrc[18]) >> 1; /* Re C + Re D */ + a20 = (pSrc[1] + pSrc[13]) >> 1; /* Im A + Im B */ + a30 = (pSrc[7] + pSrc[19]) >> 1; /* Im C + Im D */ + + pDst[0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + pDst[1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + + tmp0 = a00 - pSrc[12]; /* Re A - Re B */ + tmp1 = a20 - pSrc[13]; /* Im A - Im B */ + + pDst[12] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + pDst[13] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a10 = a10 - pSrc[18]; /* Re C - Re D */ + a30 = a30 - pSrc[19]; /* Im C - Im D */ + + pDst[6] = tmp0 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + pDst[18] = tmp0 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + pDst[7] = tmp1 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + pDst[19] = tmp1 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + + pSrc += 2; + pDst += 2; + } +} +#endif /* FUNCTION_fft12 */ + +#ifndef FUNCTION_fft15 + +#define N3 3 +#define N5 5 +#define N6 6 +#define N15 15 + +/* Performs the FFT of length 15. It is split into FFTs of length 3 and + * length 5. */ +static inline void fft15(FIXP_DBL *pInput) { + FIXP_DBL aDst[2 * N15]; + FIXP_DBL aDst1[2 * N15]; + int i, k, l; + + /* Sort input vector for fft's of length 3 + input3(0:2) = [input(0) input(5) input(10)]; + input3(3:5) = [input(3) input(8) input(13)]; + input3(6:8) = [input(6) input(11) input(1)]; + input3(9:11) = [input(9) input(14) input(4)]; + input3(12:14) = [input(12) input(2) input(7)]; */ + { + const FIXP_DBL *pSrc = pInput; + FIXP_DBL *RESTRICT pDst = aDst; + /* Merge 3 loops into one, skip call of fft3 */ + for (i = 0, l = 0, k = 0; i < N5; i++, k += 6) { + pDst[k + 0] = pSrc[l]; + pDst[k + 1] = pSrc[l + 1]; + l += 2 * N5; + if (l >= (2 * N15)) l -= (2 * N15); + + pDst[k + 2] = pSrc[l]; + pDst[k + 3] = pSrc[l + 1]; + l += 2 * N5; + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 4] = pSrc[l]; + pDst[k + 5] = pSrc[l + 1]; + l += (2 * N5) + (2 * N3); + if (l >= (2 * N15)) l -= (2 * N15); + + /* fft3 merged with shift right by 2 loop */ + FIXP_DBL r1, r2, r3; + FIXP_DBL s1, s2; + /* real part */ + r1 = pDst[k + 2] + pDst[k + 4]; + r2 = fMult((pDst[k + 2] - pDst[k + 4]), C31); + s1 = pDst[k + 0]; + pDst[k + 0] = (s1 + r1) >> 2; + r1 = s1 - (r1 >> 1); + + /* imaginary part */ + s1 = pDst[k + 3] + pDst[k + 5]; + s2 = fMult((pDst[k + 3] - pDst[k + 5]), C31); + r3 = pDst[k + 1]; + pDst[k + 1] = (r3 + s1) >> 2; + s1 = r3 - (s1 >> 1); + + /* combination */ + pDst[k + 2] = (r1 - s2) >> 2; + pDst[k + 4] = (r1 + s2) >> 2; + pDst[k + 3] = (s1 + r2) >> 2; + pDst[k + 5] = (s1 - r2) >> 2; + } + } + /* Sort input vector for fft's of length 5 + input5(0:4) = [output3(0) output3(3) output3(6) output3(9) output3(12)]; + input5(5:9) = [output3(1) output3(4) output3(7) output3(10) output3(13)]; + input5(10:14) = [output3(2) output3(5) output3(8) output3(11) output3(14)]; */ + /* Merge 2 loops into one, brings about 10% */ + { + const FIXP_DBL *pSrc = aDst; + FIXP_DBL *RESTRICT pDst = aDst1; + for (i = 0, l = 0, k = 0; i < N3; i++, k += 10) { + l = 2 * i; + pDst[k + 0] = pSrc[l + 0]; + pDst[k + 1] = pSrc[l + 1]; + pDst[k + 2] = pSrc[l + 0 + (2 * N3)]; + pDst[k + 3] = pSrc[l + 1 + (2 * N3)]; + pDst[k + 4] = pSrc[l + 0 + (4 * N3)]; + pDst[k + 5] = pSrc[l + 1 + (4 * N3)]; + pDst[k + 6] = pSrc[l + 0 + (6 * N3)]; + pDst[k + 7] = pSrc[l + 1 + (6 * N3)]; + pDst[k + 8] = pSrc[l + 0 + (8 * N3)]; + pDst[k + 9] = pSrc[l + 1 + (8 * N3)]; + fft5(&pDst[k]); + } + } + /* Sort output vector of length 15 + output = [out5(0) out5(6) out5(12) out5(3) out5(9) + out5(10) out5(1) out5(7) out5(13) out5(4) + out5(5) out5(11) out5(2) out5(8) out5(14)]; */ + /* optimize clumsy loop, brings about 5% */ + { + const FIXP_DBL *pSrc = aDst1; + FIXP_DBL *RESTRICT pDst = pInput; + for (i = 0, l = 0, k = 0; i < N3; i++, k += 10) { + pDst[k + 0] = pSrc[l]; + pDst[k + 1] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 2] = pSrc[l]; + pDst[k + 3] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 4] = pSrc[l]; + pDst[k + 5] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 6] = pSrc[l]; + pDst[k + 7] = pSrc[l + 1]; + l += (2 * N6); + if (l >= (2 * N15)) l -= (2 * N15); + pDst[k + 8] = pSrc[l]; + pDst[k + 9] = pSrc[l + 1]; + l += 2; /* no modulo check needed, it cannot occur */ + } + } +} +#endif /* FUNCTION_fft15 */ + +/* + Select shift placement. + Some processors like ARM may shift "for free" in combination with an addition + or substraction, but others don't so either combining shift with +/- or reduce + the total amount or shift operations is optimal + */ +#if !defined(__arm__) +#define SHIFT_A >> 1 +#define SHIFT_B +#else +#define SHIFT_A +#define SHIFT_B >> 1 +#endif + +#ifndef FUNCTION_fft_16 /* we check, if fft_16 (FIXP_DBL *) is not yet defined \ + */ + +/* This defines prevents this array to be declared twice, if 16-bit fft is + * enabled too */ +#define FUNCTION_DATA_fft_16_w16 +static const FIXP_STP fft16_w16[2] = {STCP(0x7641af3d, 0x30fbc54d), + STCP(0x30fbc54d, 0x7641af3d)}; + +LNK_SECTION_CODE_L1 +inline void fft_16(FIXP_DBL *RESTRICT x) { + FIXP_DBL vr, ur; + FIXP_DBL vr2, ur2; + FIXP_DBL vr3, ur3; + FIXP_DBL vr4, ur4; + FIXP_DBL vi, ui; + FIXP_DBL vi2, ui2; + FIXP_DBL vi3, ui3; + + vr = (x[0] >> 1) + (x[16] >> 1); /* Re A + Re B */ + ur = (x[1] >> 1) + (x[17] >> 1); /* Im A + Im B */ + vi = (x[8] SHIFT_A) + (x[24] SHIFT_A); /* Re C + Re D */ + ui = (x[9] SHIFT_A) + (x[25] SHIFT_A); /* Im C + Im D */ + x[0] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[1] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[4] >> 1) + (x[20] >> 1); /* Re A + Re B */ + ur2 = (x[5] >> 1) + (x[21] >> 1); /* Im A + Im B */ + + x[4] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[5] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr -= x[16]; /* Re A - Re B */ + vi = (vi SHIFT_B)-x[24]; /* Re C - Re D */ + ur -= x[17]; /* Im A - Im B */ + ui = (ui SHIFT_B)-x[25]; /* Im C - Im D */ + + vr3 = (x[2] >> 1) + (x[18] >> 1); /* Re A + Re B */ + ur3 = (x[3] >> 1) + (x[19] >> 1); /* Im A + Im B */ + + x[2] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[3] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[6] >> 1) + (x[22] >> 1); /* Re A + Re B */ + ur4 = (x[7] >> 1) + (x[23] >> 1); /* Im A + Im B */ + + x[6] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[7] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + vi2 = (x[12] SHIFT_A) + (x[28] SHIFT_A); /* Re C + Re D */ + ui2 = (x[13] SHIFT_A) + (x[29] SHIFT_A); /* Im C + Im D */ + x[8] = vr2 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[9] = ur2 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[12] = vr2 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[13] = ur2 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr2 -= x[20]; /* Re A - Re B */ + ur2 -= x[21]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[28]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[29]; /* Im C - Im D */ + + vi = (x[10] SHIFT_A) + (x[26] SHIFT_A); /* Re C + Re D */ + ui = (x[11] SHIFT_A) + (x[27] SHIFT_A); /* Im C + Im D */ + + x[10] = ui2 + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[11] = ur2 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[14] SHIFT_A) + (x[30] SHIFT_A); /* Re C + Re D */ + ui3 = (x[15] SHIFT_A) + (x[31] SHIFT_A); /* Im C + Im D */ + + x[14] = vr2 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[15] = vi2 + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + x[16] = vr3 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[17] = ur3 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[20] = vr3 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[21] = ur3 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr3 -= x[18]; /* Re A - Re B */ + ur3 -= x[19]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[26]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[27]; /* Im C - Im D */ + x[18] = ui + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[19] = ur3 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + x[24] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[28] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[25] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[29] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + vr4 -= x[22]; /* Re A - Re B */ + ur4 -= x[23]; /* Im A - Im B */ + + x[22] = vr3 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[23] = vi + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[30]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[31]; /* Im C - Im D */ + x[26] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[30] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[27] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[31] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + + // xt1 = 0 + // xt2 = 8 + vr = x[8]; + vi = x[9]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[8] = ur - (vr >> 1); + x[9] = ui - (vi >> 1); + + // xt1 = 4 + // xt2 = 12 + vr = x[13]; + vi = x[12]; + ur = x[4] >> 1; + ui = x[5] >> 1; + x[4] = ur + (vr >> 1); + x[5] = ui - (vi >> 1); + x[12] = ur - (vr >> 1); + x[13] = ui + (vi >> 1); + + // xt1 = 16 + // xt2 = 24 + vr = x[24]; + vi = x[25]; + ur = x[16] >> 1; + ui = x[17] >> 1; + x[16] = ur + (vr >> 1); + x[17] = ui + (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui - (vi >> 1); + + // xt1 = 20 + // xt2 = 28 + vr = x[29]; + vi = x[28]; + ur = x[20] >> 1; + ui = x[21] >> 1; + x[20] = ur + (vr >> 1); + x[21] = ui - (vi >> 1); + x[28] = ur - (vr >> 1); + x[29] = ui + (vi >> 1); + + // xt1 = 2 + // xt2 = 10 + SUMDIFF_PIFOURTH(vi, vr, x[10], x[11]) + // vr = fMultDiv2((x[11] + x[10]),W_PiFOURTH); + // vi = fMultDiv2((x[11] - x[10]),W_PiFOURTH); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[10] = (ur >> 1) - vr; + x[11] = (ui >> 1) - vi; + + // xt1 = 6 + // xt2 = 14 + SUMDIFF_PIFOURTH(vr, vi, x[14], x[15]) + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) - vi; + x[14] = (ur >> 1) - vr; + x[15] = (ui >> 1) + vi; + + // xt1 = 18 + // xt2 = 26 + SUMDIFF_PIFOURTH(vi, vr, x[26], x[27]) + ur = x[18]; + ui = x[19]; + x[18] = (ur >> 1) + vr; + x[19] = (ui >> 1) + vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) - vi; + + // xt1 = 22 + // xt2 = 30 + SUMDIFF_PIFOURTH(vr, vi, x[30], x[31]) + ur = x[22]; + ui = x[23]; + x[22] = (ur >> 1) + vr; + x[23] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; + + // xt1 = 0 + // xt2 = 16 + vr = x[16]; + vi = x[17]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[16] = ur - (vr >> 1); + x[17] = ui - (vi >> 1); + + // xt1 = 8 + // xt2 = 24 + vi = x[24]; + vr = x[25]; + ur = x[8] >> 1; + ui = x[9] >> 1; + x[8] = ur + (vr >> 1); + x[9] = ui - (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui + (vi >> 1); + + // xt1 = 2 + // xt2 = 18 + cplxMultDiv2(&vi, &vr, x[19], x[18], fft16_w16[0]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[18] = (ur >> 1) - vr; + x[19] = (ui >> 1) - vi; + + // xt1 = 10 + // xt2 = 26 + cplxMultDiv2(&vr, &vi, x[27], x[26], fft16_w16[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) - vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) + vi; + + // xt1 = 4 + // xt2 = 20 + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[20] = (ur >> 1) - vr; + x[21] = (ui >> 1) - vi; + + // xt1 = 12 + // xt2 = 28 + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) - vi; + x[28] = (ur >> 1) - vr; + x[29] = (ui >> 1) + vi; + + // xt1 = 6 + // xt2 = 22 + cplxMultDiv2(&vi, &vr, x[23], x[22], fft16_w16[1]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[22] = (ur >> 1) - vr; + x[23] = (ui >> 1) - vi; + + // xt1 = 14 + // xt2 = 30 + cplxMultDiv2(&vr, &vi, x[31], x[30], fft16_w16[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; +} +#endif /* FUNCTION_fft_16 */ + +#ifndef FUNCTION_fft_32 +static const FIXP_STP fft32_w32[6] = { + STCP(0x7641af3d, 0x30fbc54d), STCP(0x30fbc54d, 0x7641af3d), + STCP(0x7d8a5f40, 0x18f8b83c), STCP(0x6a6d98a4, 0x471cece7), + STCP(0x471cece7, 0x6a6d98a4), STCP(0x18f8b83c, 0x7d8a5f40)}; +#define W_PiFOURTH STC(0x5a82799a) + +LNK_SECTION_CODE_L1 +inline void fft_32(FIXP_DBL *const _x) { + /* + * 1+2 stage radix 4 + */ + + ///////////////////////////////////////////////////////////////////////////////////////// + { + FIXP_DBL *const x = _x; + FIXP_DBL vi, ui; + FIXP_DBL vi2, ui2; + FIXP_DBL vi3, ui3; + FIXP_DBL vr, ur; + FIXP_DBL vr2, ur2; + FIXP_DBL vr3, ur3; + FIXP_DBL vr4, ur4; + + // i = 0 + vr = (x[0] + x[32]) >> 1; /* Re A + Re B */ + ur = (x[1] + x[33]) >> 1; /* Im A + Im B */ + vi = (x[16] + x[48]) SHIFT_A; /* Re C + Re D */ + ui = (x[17] + x[49]) SHIFT_A; /* Im C + Im D */ + + x[0] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[1] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[4] + x[36]) >> 1; /* Re A + Re B */ + ur2 = (x[5] + x[37]) >> 1; /* Im A + Im B */ + + x[4] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[5] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[32]; /* Re A - Re B */ + ur -= x[33]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[48]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[49]; /* Im C - Im D */ + + vr3 = (x[2] + x[34]) >> 1; /* Re A + Re B */ + ur3 = (x[3] + x[35]) >> 1; /* Im A + Im B */ + + x[2] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[3] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[6] + x[38]) >> 1; /* Re A + Re B */ + ur4 = (x[7] + x[39]) >> 1; /* Im A + Im B */ + + x[6] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[7] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=16 + vi = (x[20] + x[52]) SHIFT_A; /* Re C + Re D */ + ui = (x[21] + x[53]) SHIFT_A; /* Im C + Im D */ + + x[16] = vr2 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[17] = ur2 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[20] = vr2 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[21] = ur2 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr2 -= x[36]; /* Re A - Re B */ + ur2 -= x[37]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[52]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[53]; /* Im C - Im D */ + + vi2 = (x[18] + x[50]) SHIFT_A; /* Re C + Re D */ + ui2 = (x[19] + x[51]) SHIFT_A; /* Im C + Im D */ + + x[18] = ui + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[19] = ur2 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[22] + x[54]) SHIFT_A; /* Re C + Re D */ + ui3 = (x[23] + x[55]) SHIFT_A; /* Im C + Im D */ + + x[22] = vr2 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[23] = vi + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + // i = 32 + + x[32] = vr3 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[33] = ur3 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[36] = vr3 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[37] = ur3 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr3 -= x[34]; /* Re A - Re B */ + ur3 -= x[35]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[50]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[51]; /* Im C - Im D */ + + x[34] = ui2 + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[35] = ur3 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + // i=48 + + x[48] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[52] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[49] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[53] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr4 -= x[38]; /* Re A - Re B */ + ur4 -= x[39]; /* Im A - Im B */ + + x[38] = vr3 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[39] = vi2 + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[54]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[55]; /* Im C - Im D */ + + x[50] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[54] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[51] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[55] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=8 + vr = (x[8] + x[40]) >> 1; /* Re A + Re B */ + ur = (x[9] + x[41]) >> 1; /* Im A + Im B */ + vi = (x[24] + x[56]) SHIFT_A; /* Re C + Re D */ + ui = (x[25] + x[57]) SHIFT_A; /* Im C + Im D */ + + x[8] = vr + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[9] = ur + (ui SHIFT_B); /* Im A' = sum of imag values */ + + vr2 = (x[12] + x[44]) >> 1; /* Re A + Re B */ + ur2 = (x[13] + x[45]) >> 1; /* Im A + Im B */ + + x[12] = vr - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[13] = ur - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr -= x[40]; /* Re A - Re B */ + ur -= x[41]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[56]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[57]; /* Im C - Im D */ + + vr3 = (x[10] + x[42]) >> 1; /* Re A + Re B */ + ur3 = (x[11] + x[43]) >> 1; /* Im A + Im B */ + + x[10] = ui + vr; /* Re B' = Im C - Im D + Re A - Re B */ + x[11] = ur - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vr4 = (x[14] + x[46]) >> 1; /* Re A + Re B */ + ur4 = (x[15] + x[47]) >> 1; /* Im A + Im B */ + + x[14] = vr - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[15] = vi + ur; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=24 + vi = (x[28] + x[60]) SHIFT_A; /* Re C + Re D */ + ui = (x[29] + x[61]) SHIFT_A; /* Im C + Im D */ + + x[24] = vr2 + (vi SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[28] = vr2 - (vi SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[25] = ur2 + (ui SHIFT_B); /* Im A' = sum of imag values */ + x[29] = ur2 - (ui SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr2 -= x[44]; /* Re A - Re B */ + ur2 -= x[45]; /* Im A - Im B */ + vi = (vi SHIFT_B)-x[60]; /* Re C - Re D */ + ui = (ui SHIFT_B)-x[61]; /* Im C - Im D */ + + vi2 = (x[26] + x[58]) SHIFT_A; /* Re C + Re D */ + ui2 = (x[27] + x[59]) SHIFT_A; /* Im C + Im D */ + + x[26] = ui + vr2; /* Re B' = Im C - Im D + Re A - Re B */ + x[27] = ur2 - vi; /* Im B'= -Re C + Re D + Im A - Im B */ + + vi3 = (x[30] + x[62]) SHIFT_A; /* Re C + Re D */ + ui3 = (x[31] + x[63]) SHIFT_A; /* Im C + Im D */ + + x[30] = vr2 - ui; /* Re D' = -Im C + Im D + Re A - Re B */ + x[31] = vi + ur2; /* Im D'= Re C - Re D + Im A - Im B */ + + // i=40 + + x[40] = vr3 + (vi2 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[44] = vr3 - (vi2 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[41] = ur3 + (ui2 SHIFT_B); /* Im A' = sum of imag values */ + x[45] = ur3 - (ui2 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr3 -= x[42]; /* Re A - Re B */ + ur3 -= x[43]; /* Im A - Im B */ + vi2 = (vi2 SHIFT_B)-x[58]; /* Re C - Re D */ + ui2 = (ui2 SHIFT_B)-x[59]; /* Im C - Im D */ + + x[42] = ui2 + vr3; /* Re B' = Im C - Im D + Re A - Re B */ + x[43] = ur3 - vi2; /* Im B'= -Re C + Re D + Im A - Im B */ + + // i=56 + + x[56] = vr4 + (vi3 SHIFT_B); /* Re A' = ReA + ReB +ReC + ReD */ + x[60] = vr4 - (vi3 SHIFT_B); /* Re C' = -(ReC+ReD) + (ReA+ReB) */ + x[57] = ur4 + (ui3 SHIFT_B); /* Im A' = sum of imag values */ + x[61] = ur4 - (ui3 SHIFT_B); /* Im C' = -Im C -Im D +Im A +Im B */ + + vr4 -= x[46]; /* Re A - Re B */ + ur4 -= x[47]; /* Im A - Im B */ + + x[46] = vr3 - ui2; /* Re D' = -Im C + Im D + Re A - Re B */ + x[47] = vi2 + ur3; /* Im D'= Re C - Re D + Im A - Im B */ + + vi3 = (vi3 SHIFT_B)-x[62]; /* Re C - Re D */ + ui3 = (ui3 SHIFT_B)-x[63]; /* Im C - Im D */ + + x[58] = ui3 + vr4; /* Re B' = Im C - Im D + Re A - Re B */ + x[62] = vr4 - ui3; /* Re D' = -Im C + Im D + Re A - Re B */ + x[59] = ur4 - vi3; /* Im B'= -Re C + Re D + Im A - Im B */ + x[63] = vi3 + ur4; /* Im D'= Re C - Re D + Im A - Im B */ + } + + { + FIXP_DBL *xt = _x; + + int j = 4; + do { + FIXP_DBL vi, ui, vr, ur; + + vr = xt[8]; + vi = xt[9]; + ur = xt[0] >> 1; + ui = xt[1] >> 1; + xt[0] = ur + (vr >> 1); + xt[1] = ui + (vi >> 1); + xt[8] = ur - (vr >> 1); + xt[9] = ui - (vi >> 1); + + vr = xt[13]; + vi = xt[12]; + ur = xt[4] >> 1; + ui = xt[5] >> 1; + xt[4] = ur + (vr >> 1); + xt[5] = ui - (vi >> 1); + xt[12] = ur - (vr >> 1); + xt[13] = ui + (vi >> 1); + + SUMDIFF_PIFOURTH(vi, vr, xt[10], xt[11]) + ur = xt[2]; + ui = xt[3]; + xt[2] = (ur >> 1) + vr; + xt[3] = (ui >> 1) + vi; + xt[10] = (ur >> 1) - vr; + xt[11] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, xt[14], xt[15]) + ur = xt[6]; + ui = xt[7]; + + xt[6] = (ur >> 1) + vr; + xt[7] = (ui >> 1) - vi; + xt[14] = (ur >> 1) - vr; + xt[15] = (ui >> 1) + vi; + xt += 16; + } while (--j != 0); + } + + { + FIXP_DBL *const x = _x; + FIXP_DBL vi, ui, vr, ur; + + vr = x[16]; + vi = x[17]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[16] = ur - (vr >> 1); + x[17] = ui - (vi >> 1); + + vi = x[24]; + vr = x[25]; + ur = x[8] >> 1; + ui = x[9] >> 1; + x[8] = ur + (vr >> 1); + x[9] = ui - (vi >> 1); + x[24] = ur - (vr >> 1); + x[25] = ui + (vi >> 1); + + vr = x[48]; + vi = x[49]; + ur = x[32] >> 1; + ui = x[33] >> 1; + x[32] = ur + (vr >> 1); + x[33] = ui + (vi >> 1); + x[48] = ur - (vr >> 1); + x[49] = ui - (vi >> 1); + + vi = x[56]; + vr = x[57]; + ur = x[40] >> 1; + ui = x[41] >> 1; + x[40] = ur + (vr >> 1); + x[41] = ui - (vi >> 1); + x[56] = ur - (vr >> 1); + x[57] = ui + (vi >> 1); + + cplxMultDiv2(&vi, &vr, x[19], x[18], fft32_w32[0]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[18] = (ur >> 1) - vr; + x[19] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[27], x[26], fft32_w32[0]); + ur = x[10]; + ui = x[11]; + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) - vi; + x[26] = (ur >> 1) - vr; + x[27] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[51], x[50], fft32_w32[0]); + ur = x[34]; + ui = x[35]; + x[34] = (ur >> 1) + vr; + x[35] = (ui >> 1) + vi; + x[50] = (ur >> 1) - vr; + x[51] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[0]); + ur = x[42]; + ui = x[43]; + x[42] = (ur >> 1) + vr; + x[43] = (ui >> 1) - vi; + x[58] = (ur >> 1) - vr; + x[59] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[20], x[21]) + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[20] = (ur >> 1) - vr; + x[21] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[28], x[29]) + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) - vi; + x[28] = (ur >> 1) - vr; + x[29] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[52], x[53]) + ur = x[36]; + ui = x[37]; + x[36] = (ur >> 1) + vr; + x[37] = (ui >> 1) + vi; + x[52] = (ur >> 1) - vr; + x[53] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[60], x[61]) + ur = x[44]; + ui = x[45]; + x[44] = (ur >> 1) + vr; + x[45] = (ui >> 1) - vi; + x[60] = (ur >> 1) - vr; + x[61] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[23], x[22], fft32_w32[1]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[22] = (ur >> 1) - vr; + x[23] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[31], x[30], fft32_w32[1]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) - vi; + x[30] = (ur >> 1) - vr; + x[31] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[55], x[54], fft32_w32[1]); + ur = x[38]; + ui = x[39]; + x[38] = (ur >> 1) + vr; + x[39] = (ui >> 1) + vi; + x[54] = (ur >> 1) - vr; + x[55] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[1]); + ur = x[46]; + ui = x[47]; + + x[46] = (ur >> 1) + vr; + x[47] = (ui >> 1) - vi; + x[62] = (ur >> 1) - vr; + x[63] = (ui >> 1) + vi; + + vr = x[32]; + vi = x[33]; + ur = x[0] >> 1; + ui = x[1] >> 1; + x[0] = ur + (vr >> 1); + x[1] = ui + (vi >> 1); + x[32] = ur - (vr >> 1); + x[33] = ui - (vi >> 1); + + vi = x[48]; + vr = x[49]; + ur = x[16] >> 1; + ui = x[17] >> 1; + x[16] = ur + (vr >> 1); + x[17] = ui - (vi >> 1); + x[48] = ur - (vr >> 1); + x[49] = ui + (vi >> 1); + + cplxMultDiv2(&vi, &vr, x[35], x[34], fft32_w32[2]); + ur = x[2]; + ui = x[3]; + x[2] = (ur >> 1) + vr; + x[3] = (ui >> 1) + vi; + x[34] = (ur >> 1) - vr; + x[35] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[51], x[50], fft32_w32[2]); + ur = x[18]; + ui = x[19]; + x[18] = (ur >> 1) + vr; + x[19] = (ui >> 1) - vi; + x[50] = (ur >> 1) - vr; + x[51] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[37], x[36], fft32_w32[0]); + ur = x[4]; + ui = x[5]; + x[4] = (ur >> 1) + vr; + x[5] = (ui >> 1) + vi; + x[36] = (ur >> 1) - vr; + x[37] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[53], x[52], fft32_w32[0]); + ur = x[20]; + ui = x[21]; + x[20] = (ur >> 1) + vr; + x[21] = (ui >> 1) - vi; + x[52] = (ur >> 1) - vr; + x[53] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[39], x[38], fft32_w32[3]); + ur = x[6]; + ui = x[7]; + x[6] = (ur >> 1) + vr; + x[7] = (ui >> 1) + vi; + x[38] = (ur >> 1) - vr; + x[39] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[55], x[54], fft32_w32[3]); + ur = x[22]; + ui = x[23]; + x[22] = (ur >> 1) + vr; + x[23] = (ui >> 1) - vi; + x[54] = (ur >> 1) - vr; + x[55] = (ui >> 1) + vi; + + SUMDIFF_PIFOURTH(vi, vr, x[40], x[41]) + ur = x[8]; + ui = x[9]; + x[8] = (ur >> 1) + vr; + x[9] = (ui >> 1) + vi; + x[40] = (ur >> 1) - vr; + x[41] = (ui >> 1) - vi; + + SUMDIFF_PIFOURTH(vr, vi, x[56], x[57]) + ur = x[24]; + ui = x[25]; + x[24] = (ur >> 1) + vr; + x[25] = (ui >> 1) - vi; + x[56] = (ur >> 1) - vr; + x[57] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[43], x[42], fft32_w32[4]); + ur = x[10]; + ui = x[11]; + + x[10] = (ur >> 1) + vr; + x[11] = (ui >> 1) + vi; + x[42] = (ur >> 1) - vr; + x[43] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[59], x[58], fft32_w32[4]); + ur = x[26]; + ui = x[27]; + x[26] = (ur >> 1) + vr; + x[27] = (ui >> 1) - vi; + x[58] = (ur >> 1) - vr; + x[59] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[45], x[44], fft32_w32[1]); + ur = x[12]; + ui = x[13]; + x[12] = (ur >> 1) + vr; + x[13] = (ui >> 1) + vi; + x[44] = (ur >> 1) - vr; + x[45] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[61], x[60], fft32_w32[1]); + ur = x[28]; + ui = x[29]; + x[28] = (ur >> 1) + vr; + x[29] = (ui >> 1) - vi; + x[60] = (ur >> 1) - vr; + x[61] = (ui >> 1) + vi; + + cplxMultDiv2(&vi, &vr, x[47], x[46], fft32_w32[5]); + ur = x[14]; + ui = x[15]; + x[14] = (ur >> 1) + vr; + x[15] = (ui >> 1) + vi; + x[46] = (ur >> 1) - vr; + x[47] = (ui >> 1) - vi; + + cplxMultDiv2(&vr, &vi, x[63], x[62], fft32_w32[5]); + ur = x[30]; + ui = x[31]; + x[30] = (ur >> 1) + vr; + x[31] = (ui >> 1) - vi; + x[62] = (ur >> 1) - vr; + x[63] = (ui >> 1) + vi; + } +} +#endif /* #ifndef FUNCTION_fft_32 */ + +/** + * \brief Apply rotation vectors to a data buffer. + * \param cl length of each row of input data. + * \param l total length of input data. + * \param pVecRe real part of rotation coefficient vector. + * \param pVecIm imaginary part of rotation coefficient vector. + */ + +/* + This defines patches each inaccurate 0x7FFF i.e. 0.9999 and uses 0x8000 + (-1.0) instead. At the end, the sign of the result is inverted +*/ +#define noFFT_APPLY_ROT_VECTOR_HQ + +#ifndef FUNCTION_fft_apply_rot_vector__FIXP_DBL +static inline void fft_apply_rot_vector(FIXP_DBL *RESTRICT pData, const int cl, + const int l, const FIXP_STB *pVecRe, + const FIXP_STB *pVecIm) { + FIXP_DBL re, im; + FIXP_STB vre, vim; + + int i, c; + + for (i = 0; i < cl; i++) { + re = pData[2 * i]; + im = pData[2 * i + 1]; + + pData[2 * i] = re >> 2; /* * 0.25 */ + pData[2 * i + 1] = im >> 2; /* * 0.25 */ + } + for (; i < l; i += cl) { + re = pData[2 * i]; + im = pData[2 * i + 1]; + + pData[2 * i] = re >> 2; /* * 0.25 */ + pData[2 * i + 1] = im >> 2; /* * 0.25 */ + + for (c = i + 1; c < i + cl; c++) { + re = pData[2 * c] >> 1; + im = pData[2 * c + 1] >> 1; + vre = *pVecRe++; + vim = *pVecIm++; + + cplxMultDiv2(&pData[2 * c + 1], &pData[2 * c], im, re, vre, vim); + } + } +} +#endif /* FUNCTION_fft_apply_rot_vector__FIXP_DBL */ + +/* select either switch case of function pointer. */ +//#define FFT_TWO_STAGE_SWITCH_CASE +#ifndef FUNCTION_fftN2_func +static inline void fftN2_func(FIXP_DBL *pInput, const int length, + const int dim1, const int dim2, + void (*const fft1)(FIXP_DBL *), + void (*const fft2)(FIXP_DBL *), + const FIXP_STB *RotVectorReal, + const FIXP_STB *RotVectorImag, FIXP_DBL *aDst, + FIXP_DBL *aDst2) { + /* The real part of the input samples are at the addresses with even indices + and the imaginary part of the input samples are at the addresses with odd + indices. The output samples are stored at the address of pInput + */ + FIXP_DBL *pSrc, *pDst, *pDstOut; + int i; + + FDK_ASSERT(length == dim1 * dim2); + + /* Perform dim2 times the fft of length dim1. The input samples are at the + address of pSrc and the output samples are at the address of pDst. The input + vector for the fft of length dim1 is built of the interleaved samples in pSrc, + the output samples are stored consecutively. + */ + pSrc = pInput; + pDst = aDst; + for (i = 0; i < dim2; i++) { + for (int j = 0; j < dim1; j++) { + pDst[2 * j] = pSrc[2 * j * dim2]; + pDst[2 * j + 1] = pSrc[2 * j * dim2 + 1]; + } + + /* fft of size dim1 */ +#ifndef FFT_TWO_STAGE_SWITCH_CASE + fft1(pDst); +#else + switch (dim1) { + case 2: + fft2(pDst); + break; + case 3: + fft3(pDst); + break; + case 4: + fft_4(pDst); + break; + /* case 5: fft5(pDst); break; */ + /* case 8: fft_8(pDst); break; */ + case 12: + fft12(pDst); + break; + /* case 15: fft15(pDst); break; */ + case 16: + fft_16(pDst); + break; + case 32: + fft_32(pDst); + break; + /*case 64: fft_64(pDst); break;*/ + /* case 128: fft_128(pDst); break; */ + } +#endif + pSrc += 2; + pDst = pDst + 2 * dim1; + } + + /* Perform the modulation of the output of the fft of length dim1 */ + pSrc = aDst; + fft_apply_rot_vector(pSrc, dim1, length, RotVectorReal, RotVectorImag); + + /* Perform dim1 times the fft of length dim2. 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 dim2 is built of the interleaved samples in aDst, + the output samples are stored consecutively at the address of pInput. + */ + pSrc = aDst; + pDst = aDst2; + pDstOut = pInput; + for (i = 0; i < dim1; i++) { + for (int j = 0; j < dim2; j++) { + pDst[2 * j] = pSrc[2 * j * dim1]; + pDst[2 * j + 1] = pSrc[2 * j * dim1 + 1]; + } + +#ifndef FFT_TWO_STAGE_SWITCH_CASE + fft2(pDst); +#else + switch (dim2) { + case 4: + fft_4(pDst); + break; + case 9: + fft9(pDst); + break; + case 12: + fft12(pDst); + break; + case 15: + fft15(pDst); + break; + case 16: + fft_16(pDst); + break; + case 32: + fft_32(pDst); + break; + } +#endif + + for (int j = 0; j < dim2; j++) { + pDstOut[2 * j * dim1] = pDst[2 * j]; + pDstOut[2 * j * dim1 + 1] = pDst[2 * j + 1]; + } + pSrc += 2; + pDstOut += 2; + } +} +#endif /* FUNCTION_fftN2_function */ + +#define fftN2(DATA_TYPE, pInput, length, dim1, dim2, fft_func1, fft_func2, \ + RotVectorReal, RotVectorImag) \ + { \ + C_AALLOC_SCRATCH_START(aDst, DATA_TYPE, 2 * length) \ + C_AALLOC_SCRATCH_START(aDst2, DATA_TYPE, 2 * dim2) \ + fftN2_func(pInput, length, dim1, dim2, fft_func1, fft_func2, \ + RotVectorReal, RotVectorImag, aDst, aDst2); \ + C_AALLOC_SCRATCH_END(aDst2, DATA_TYPE, 2 * dim2) \ + C_AALLOC_SCRATCH_END(aDst, DATA_TYPE, 2 * length) \ + } + + /*! + * + * \brief complex FFT of length 12,18,24,30,48,60,96, 192, 240, 384, 480 + * \param pInput contains the input signal prescaled right by 2 + * pInput contains the output signal scaled by SCALEFACTOR<#length> + * The output signal does not have any fixed headroom + * \return void + * + */ + +#ifndef FUNCTION_fft6 +static inline void fft6(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 6, 2, 3, fft2, fft3, RotVectorReal6, RotVectorImag6); +} +#endif /* #ifndef FUNCTION_fft6 */ + +#ifndef FUNCTION_fft12 +static inline void fft12(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 12, 3, 4, fft3, fft_4, RotVectorReal12, + RotVectorImag12); /* 16,58 */ +} +#endif /* #ifndef FUNCTION_fft12 */ + +#ifndef FUNCTION_fft20 +static inline void fft20(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 20, 4, 5, fft_4, fft5, RotVectorReal20, + RotVectorImag20); +} +#endif /* FUNCTION_fft20 */ + +static inline void fft24(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 24, 2, 12, fft2, fft12, RotVectorReal24, + RotVectorImag24); /* 16,73 */ +} + +static inline void fft48(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 48, 4, 12, fft_4, fft12, RotVectorReal48, + RotVectorImag48); /* 16,32 */ +} + +#ifndef FUNCTION_fft60 +static inline void fft60(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 60, 4, 15, fft_4, fft15, RotVectorReal60, + RotVectorImag60); /* 15,51 */ +} +#endif /* FUNCTION_fft60 */ + +#ifndef FUNCTION_fft80 +static inline void fft80(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 80, 5, 16, fft5, fft_16, RotVectorReal80, + RotVectorImag80); /* */ +} +#endif + +#ifndef FUNCTION_fft96 +static inline void fft96(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 96, 3, 32, fft3, fft_32, RotVectorReal96, + RotVectorImag96); /* 15,47 */ +} +#endif /* FUNCTION_fft96*/ + +#ifndef FUNCTION_fft120 +static inline void fft120(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 120, 8, 15, fft_8, fft15, RotVectorReal120, + RotVectorImag120); +} +#endif /* FUNCTION_fft120 */ + +#ifndef FUNCTION_fft192 +static inline void fft192(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 192, 16, 12, fft_16, fft12, RotVectorReal192, + RotVectorImag192); /* 15,50 */ +} +#endif + +#ifndef FUNCTION_fft240 +static inline void fft240(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 240, 16, 15, fft_16, fft15, RotVectorReal240, + RotVectorImag240); /* 15.44 */ +} +#endif + +#ifndef FUNCTION_fft384 +static inline void fft384(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 384, 12, 32, fft12, fft_32, RotVectorReal384, + RotVectorImag384); /* 16.02 */ +} +#endif /* FUNCTION_fft384 */ + +#ifndef FUNCTION_fft480 +static inline void fft480(FIXP_DBL *pInput) { + fftN2(FIXP_DBL, pInput, 480, 32, 15, fft_32, fft15, RotVectorReal480, + RotVectorImag480); /* 15.84 */ +} +#endif /* FUNCTION_fft480 */ + +void fft(int length, FIXP_DBL *pInput, INT *pScalefactor) { + /* Ensure, that the io-ptr is always (at least 8-byte) aligned */ + C_ALLOC_ALIGNED_CHECK(pInput); + + if (length == 32) { + fft_32(pInput); + *pScalefactor += SCALEFACTOR32; + } else { + switch (length) { + case 16: + fft_16(pInput); + *pScalefactor += SCALEFACTOR16; + break; + case 8: + fft_8(pInput); + *pScalefactor += SCALEFACTOR8; + break; + case 2: + fft2(pInput); + *pScalefactor += SCALEFACTOR2; + break; + case 3: + fft3(pInput); + *pScalefactor += SCALEFACTOR3; + break; + case 4: + fft_4(pInput); + *pScalefactor += SCALEFACTOR4; + break; + case 5: + fft5(pInput); + *pScalefactor += SCALEFACTOR5; + break; + case 6: + fft6(pInput); + *pScalefactor += SCALEFACTOR6; + break; + case 10: + fft10(pInput); + *pScalefactor += SCALEFACTOR10; + break; + case 12: + fft12(pInput); + *pScalefactor += SCALEFACTOR12; + break; + case 15: + fft15(pInput); + *pScalefactor += SCALEFACTOR15; + break; + case 20: + fft20(pInput); + *pScalefactor += SCALEFACTOR20; + break; + case 24: + fft24(pInput); + *pScalefactor += SCALEFACTOR24; + break; + case 48: + fft48(pInput); + *pScalefactor += SCALEFACTOR48; + break; + case 60: + fft60(pInput); + *pScalefactor += SCALEFACTOR60; + break; + case 64: + dit_fft(pInput, 6, SineTable512, 512); + *pScalefactor += SCALEFACTOR64; + break; + case 80: + fft80(pInput); + *pScalefactor += SCALEFACTOR80; + break; + case 96: + fft96(pInput); + *pScalefactor += SCALEFACTOR96; + break; + case 120: + fft120(pInput); + *pScalefactor += SCALEFACTOR120; + break; + case 128: + dit_fft(pInput, 7, SineTable512, 512); + *pScalefactor += SCALEFACTOR128; + break; + case 192: + fft192(pInput); + *pScalefactor += SCALEFACTOR192; + break; + case 240: + fft240(pInput); + *pScalefactor += SCALEFACTOR240; + break; + case 256: + dit_fft(pInput, 8, SineTable512, 512); + *pScalefactor += SCALEFACTOR256; + break; + case 384: + fft384(pInput); + *pScalefactor += SCALEFACTOR384; + break; + case 480: + fft480(pInput); + *pScalefactor += SCALEFACTOR480; + break; + case 512: + dit_fft(pInput, 9, SineTable512, 512); + *pScalefactor += SCALEFACTOR512; + break; + default: + FDK_ASSERT(0); /* FFT length not supported! */ + break; + } + } +} + +void ifft(int length, FIXP_DBL *pInput, INT *scalefactor) { + switch (length) { + default: + FDK_ASSERT(0); /* IFFT length not supported! */ + break; + } +} diff --git a/fdk-aac/libFDK/src/fft_rad2.cpp b/fdk-aac/libFDK/src/fft_rad2.cpp new file mode 100644 index 0000000..27f3aa0 --- /dev/null +++ b/fdk-aac/libFDK/src/fft_rad2.cpp @@ -0,0 +1,324 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Lohwasser, M. Gayer + + Description: + +*******************************************************************************/ + +#include "fft_rad2.h" + +#include "scramble.h" + +#define __FFT_RAD2_CPP__ + +#if defined(__arm__) +#include "arm/fft_rad2_arm.cpp" + +#elif defined(__GNUC__) && defined(__mips__) && defined(__mips_dsp) +#include "mips/fft_rad2_mips.cpp" + +#endif + +/***************************************************************************** + + functionname: dit_fft (analysis) + description: dit-tukey-algorithm + scrambles data at entry + i.e. loop is made with scrambled data + returns: + input: + output: + +*****************************************************************************/ + +#ifndef FUNCTION_dit_fft + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + const INT n = 1 << ldn; + INT trigstep, i, ldm; + + C_ALLOC_ALIGNED_CHECK(x); + + scramble(x, n); + /* + * 1+2 stage radix 4 + */ + + for (i = 0; i < n * 2; i += 8) { + FIXP_DBL a00, a10, a20, a30; + a00 = (x[i + 0] + x[i + 2]) >> 1; /* Re A + Re B */ + a10 = (x[i + 4] + x[i + 6]) >> 1; /* Re C + Re D */ + a20 = (x[i + 1] + x[i + 3]) >> 1; /* Im A + Im B */ + a30 = (x[i + 5] + x[i + 7]) >> 1; /* Im C + Im D */ + + x[i + 0] = a00 + a10; /* Re A' = Re A + Re B + Re C + Re D */ + x[i + 4] = a00 - a10; /* Re C' = Re A + Re B - Re C - Re D */ + x[i + 1] = a20 + a30; /* Im A' = Im A + Im B + Im C + Im D */ + x[i + 5] = a20 - a30; /* Im C' = Im A + Im B - Im C - Im D */ + + a00 = a00 - x[i + 2]; /* Re A - Re B */ + a10 = a10 - x[i + 6]; /* Re C - Re D */ + a20 = a20 - x[i + 3]; /* Im A - Im B */ + a30 = a30 - x[i + 7]; /* Im C - Im D */ + + x[i + 2] = a00 + a30; /* Re B' = Re A - Re B + Im C - Im D */ + x[i + 6] = a00 - a30; /* Re D' = Re A - Re B - Im C + Im D */ + x[i + 3] = a20 - a10; /* Im B' = Im A - Im B - Re C + Re D */ + x[i + 7] = a20 + a10; /* Im D' = Im A - Im B + Re C - Re D */ + } + + for (ldm = 3; ldm <= ldn; ++ldm) { + INT m = (1 << ldm); + INT mh = (m >> 1); + INT j, r; + + trigstep = ((trigDataSize << 2) >> ldm); + + FDK_ASSERT(trigstep > 0); + + /* Do first iteration with c=1.0 and s=0.0 separately to avoid loosing to + much precision. Beware: The impact on the overal FFT precision is rather + large. */ + { /* block 1 */ + + j = 0; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + // cplxMultDiv2(&vi, &vr, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vi = x[t2 + 1] >> 1; + vr = x[t2] >> 1; + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + // cplxMultDiv2(&vr, &vi, x[t2+1], x[t2], (FIXP_SGL)1.0, (FIXP_SGL)0.0); + vr = x[t2 + 1] >> 1; + vi = x[t2] >> 1; + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + } + + } /* end of block 1 */ + + for (j = 1; j < mh / 4; ++j) { + FIXP_STP cs; + + cs = trigdata[j * trigstep]; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, x[t2 + 1], x[t2], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2 + 1], x[t2], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + + /* Same as above but for t1,t2 with j>mh/4 and thus cs swapped */ + t1 = (r + mh / 2 - j) << 1; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vi, &vr, x[t2], x[t2 + 1], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2], x[t2 + 1], cs); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur - vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur + vr; + x[t2 + 1] = ui + vi; + } + } + + { /* block 2 */ + j = mh / 4; + + for (r = 0; r < n; r += m) { + INT t1 = (r + j) << 1; + INT t2 = t1 + (mh << 1); + FIXP_DBL vr, vi, ur, ui; + + cplxMultDiv2(&vi, &vr, x[t2 + 1], x[t2], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui + vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui - vi; + + t1 += mh; + t2 = t1 + (mh << 1); + + cplxMultDiv2(&vr, &vi, x[t2 + 1], x[t2], STC(0x5a82799a), + STC(0x5a82799a)); + + ur = x[t1] >> 1; + ui = x[t1 + 1] >> 1; + + x[t1] = ur + vr; + x[t1 + 1] = ui - vi; + + x[t2] = ur - vr; + x[t2 + 1] = ui + vi; + } + } /* end of block 2 */ + } +} + +#endif diff --git a/fdk-aac/libFDK/src/fixpoint_math.cpp b/fdk-aac/libFDK/src/fixpoint_math.cpp new file mode 100644 index 0000000..6c656fa --- /dev/null +++ b/fdk-aac/libFDK/src/fixpoint_math.cpp @@ -0,0 +1,900 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): M. Gayer + + Description: Fixed point specific mathematical functions + +*******************************************************************************/ + +#include "fixpoint_math.h" + +/* + * Hardware specific implementations + */ + +/* + * Fallback implementations + */ + +/***************************************************************************** + functionname: LdDataVector +*****************************************************************************/ +LNK_SECTION_CODE_L1 +void LdDataVector(FIXP_DBL *srcVector, FIXP_DBL *destVector, INT n) { + INT i; + for (i = 0; i < n; i++) { + destVector[i] = fLog2(srcVector[i], 0); + } +} + +#define MAX_POW2_PRECISION 8 +#ifndef SINETABLE_16BIT +#define POW2_PRECISION MAX_POW2_PRECISION +#else +#define POW2_PRECISION 5 +#endif + +/* + Taylor series coefficients of the function x^2. The first coefficient is + ommited (equal to 1.0). + + pow2Coeff[i-1] = (1/i!) d^i(2^x)/dx^i, i=1..MAX_POW2_PRECISION + To evaluate the taylor series around x = 0, the coefficients are: 1/!i * + ln(2)^i + */ +#ifndef POW2COEFF_16BIT +RAM_ALIGN +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL pow2Coeff[MAX_POW2_PRECISION] = { + FL2FXCONST_DBL(0.693147180559945309417232121458177), /* ln(2)^1 /1! */ + FL2FXCONST_DBL(0.240226506959100712333551263163332), /* ln(2)^2 /2! */ + FL2FXCONST_DBL(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */ + FL2FXCONST_DBL(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */ + FL2FXCONST_DBL(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */ + FL2FXCONST_DBL(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */ + FL2FXCONST_DBL(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */ + FL2FXCONST_DBL(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */ +}; +#else +RAM_ALIGN +LNK_SECTION_CONSTDATA_L1 +static const FIXP_SGL pow2Coeff[MAX_POW2_PRECISION] = { + FL2FXCONST_SGL(0.693147180559945309417232121458177), /* ln(2)^1 /1! */ + FL2FXCONST_SGL(0.240226506959100712333551263163332), /* ln(2)^2 /2! */ + FL2FXCONST_SGL(0.0555041086648215799531422637686218), /* ln(2)^3 /3! */ + FL2FXCONST_SGL(0.00961812910762847716197907157365887), /* ln(2)^4 /4! */ + FL2FXCONST_SGL(0.00133335581464284434234122219879962), /* ln(2)^5 /5! */ + FL2FXCONST_SGL(1.54035303933816099544370973327423e-4), /* ln(2)^6 /6! */ + FL2FXCONST_SGL(1.52527338040598402800254390120096e-5), /* ln(2)^7 /7! */ + FL2FXCONST_SGL(1.32154867901443094884037582282884e-6) /* ln(2)^8 /8! */ +}; +#endif + +/***************************************************************************** + + functionname: CalcInvLdData + description: Delivers the inverse of function CalcLdData(). + Delivers 2^(op*LD_DATA_SCALING) + input: Input op is assumed to be fractional -1.0 < op < 1.0 + output: For op == 0, the result is MAXVAL_DBL (almost 1.0). + For negative input values the output should be treated as a +positive fractional value. For positive input values the output should be +treated as a positive integer value. This function does not output negative +values. + +*****************************************************************************/ +/* Date: 06-JULY-2012 Arthur Tritthart, IIS Fraunhofer Erlangen */ +/* Version with 3 table lookup and 1 linear interpolations */ +/* Algorithm: compute power of 2, argument x is in Q7.25 format */ +/* result = 2^(x/64) */ +/* We split exponent (x/64) into 5 components: */ +/* integer part: represented by b31..b25 (exp) */ +/* fractional part 1: represented by b24..b20 (lookup1) */ +/* fractional part 2: represented by b19..b15 (lookup2) */ +/* fractional part 3: represented by b14..b10 (lookup3) */ +/* fractional part 4: represented by b09..b00 (frac) */ +/* => result = (lookup1*lookup2*(lookup3+C1*frac)<<3)>>exp */ +/* Due to the fact, that all lookup values contain a factor 0.5 */ +/* the result has to be shifted by 3 to the right also. */ +/* Table exp2_tab_long contains the log2 for 0 to 1.0 in steps */ +/* of 1/32, table exp2w_tab_long the log2 for 0 to 1/32 in steps*/ +/* of 1/1024, table exp2x_tab_long the log2 for 0 to 1/1024 in */ +/* steps of 1/32768. Since the 2-logarithm of very very small */ +/* negative value is rather linear, we can use interpolation. */ +/* Limitations: */ +/* For x <= 0, the result is fractional positive */ +/* For x > 0, the result is integer in range 1...7FFF.FFFF */ +/* For x < -31/64, we have to clear the result */ +/* For x = 0, the result is ~1.0 (0x7FFF.FFFF) */ +/* For x >= 31/64, the result is 0x7FFF.FFFF */ + +/* This table is used for lookup 2^x with */ +/* x in range [0...1.0[ in steps of 1/32 */ +LNK_SECTION_DATA_L1 +const UINT exp2_tab_long[32] = { + 0x40000000, 0x4166C34C, 0x42D561B4, 0x444C0740, 0x45CAE0F2, 0x47521CC6, + 0x48E1E9BA, 0x4A7A77D4, 0x4C1BF829, 0x4DC69CDD, 0x4F7A9930, 0x51382182, + 0x52FF6B55, 0x54D0AD5A, 0x56AC1F75, 0x5891FAC1, 0x5A82799A, 0x5C7DD7A4, + 0x5E8451D0, 0x60962665, 0x62B39509, 0x64DCDEC3, 0x6712460B, 0x69540EC9, + 0x6BA27E65, 0x6DFDDBCC, 0x70666F76, 0x72DC8374, 0x75606374, 0x77F25CCE, + 0x7A92BE8B, 0x7D41D96E + // 0x80000000 +}; + +/* This table is used for lookup 2^x with */ +/* x in range [0...1/32[ in steps of 1/1024 */ +LNK_SECTION_DATA_L1 +const UINT exp2w_tab_long[32] = { + 0x40000000, 0x400B1818, 0x4016321B, 0x40214E0C, 0x402C6BE9, 0x40378BB4, + 0x4042AD6D, 0x404DD113, 0x4058F6A8, 0x40641E2B, 0x406F479E, 0x407A7300, + 0x4085A051, 0x4090CF92, 0x409C00C4, 0x40A733E6, 0x40B268FA, 0x40BD9FFF, + 0x40C8D8F5, 0x40D413DD, 0x40DF50B8, 0x40EA8F86, 0x40F5D046, 0x410112FA, + 0x410C57A2, 0x41179E3D, 0x4122E6CD, 0x412E3152, 0x41397DCC, 0x4144CC3B, + 0x41501CA0, 0x415B6EFB, + // 0x4166C34C, +}; +/* This table is used for lookup 2^x with */ +/* x in range [0...1/1024[ in steps of 1/32768 */ +LNK_SECTION_DATA_L1 +const UINT exp2x_tab_long[32] = { + 0x40000000, 0x400058B9, 0x4000B173, 0x40010A2D, 0x400162E8, 0x4001BBA3, + 0x4002145F, 0x40026D1B, 0x4002C5D8, 0x40031E95, 0x40037752, 0x4003D011, + 0x400428CF, 0x4004818E, 0x4004DA4E, 0x4005330E, 0x40058BCE, 0x4005E48F, + 0x40063D51, 0x40069613, 0x4006EED5, 0x40074798, 0x4007A05B, 0x4007F91F, + 0x400851E4, 0x4008AAA8, 0x4009036E, 0x40095C33, 0x4009B4FA, 0x400A0DC0, + 0x400A6688, 0x400ABF4F, + // 0x400B1818 +}; + +/***************************************************************************** + functionname: InitLdInt and CalcLdInt + description: Create and access table with integer LdData (0 to +LD_INT_TAB_LEN) +*****************************************************************************/ +#ifndef LD_INT_TAB_LEN +#define LD_INT_TAB_LEN \ + 193 /* Default tab length. Lower value should be set in fix.h */ +#endif + +#if (LD_INT_TAB_LEN <= 120) +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldIntCoeff[] = { + (FIXP_DBL)0x80000001, (FIXP_DBL)0x00000000, (FIXP_DBL)0x02000000, + (FIXP_DBL)0x032b8034, (FIXP_DBL)0x04000000, (FIXP_DBL)0x04a4d3c2, + (FIXP_DBL)0x052b8034, (FIXP_DBL)0x059d5da0, (FIXP_DBL)0x06000000, + (FIXP_DBL)0x06570069, (FIXP_DBL)0x06a4d3c2, (FIXP_DBL)0x06eb3a9f, + (FIXP_DBL)0x072b8034, (FIXP_DBL)0x0766a009, (FIXP_DBL)0x079d5da0, + (FIXP_DBL)0x07d053f7, (FIXP_DBL)0x08000000, (FIXP_DBL)0x082cc7ee, + (FIXP_DBL)0x08570069, (FIXP_DBL)0x087ef05b, (FIXP_DBL)0x08a4d3c2, + (FIXP_DBL)0x08c8ddd4, (FIXP_DBL)0x08eb3a9f, (FIXP_DBL)0x090c1050, + (FIXP_DBL)0x092b8034, (FIXP_DBL)0x0949a785, (FIXP_DBL)0x0966a009, + (FIXP_DBL)0x0982809d, (FIXP_DBL)0x099d5da0, (FIXP_DBL)0x09b74949, + (FIXP_DBL)0x09d053f7, (FIXP_DBL)0x09e88c6b, (FIXP_DBL)0x0a000000, + (FIXP_DBL)0x0a16bad3, (FIXP_DBL)0x0a2cc7ee, (FIXP_DBL)0x0a423162, + (FIXP_DBL)0x0a570069, (FIXP_DBL)0x0a6b3d79, (FIXP_DBL)0x0a7ef05b, + (FIXP_DBL)0x0a92203d, (FIXP_DBL)0x0aa4d3c2, (FIXP_DBL)0x0ab7110e, + (FIXP_DBL)0x0ac8ddd4, (FIXP_DBL)0x0ada3f60, (FIXP_DBL)0x0aeb3a9f, + (FIXP_DBL)0x0afbd42b, (FIXP_DBL)0x0b0c1050, (FIXP_DBL)0x0b1bf312, + (FIXP_DBL)0x0b2b8034, (FIXP_DBL)0x0b3abb40, (FIXP_DBL)0x0b49a785, + (FIXP_DBL)0x0b584822, (FIXP_DBL)0x0b66a009, (FIXP_DBL)0x0b74b1fd, + (FIXP_DBL)0x0b82809d, (FIXP_DBL)0x0b900e61, (FIXP_DBL)0x0b9d5da0, + (FIXP_DBL)0x0baa708f, (FIXP_DBL)0x0bb74949, (FIXP_DBL)0x0bc3e9ca, + (FIXP_DBL)0x0bd053f7, (FIXP_DBL)0x0bdc899b, (FIXP_DBL)0x0be88c6b, + (FIXP_DBL)0x0bf45e09, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x0c0b73cb, + (FIXP_DBL)0x0c16bad3, (FIXP_DBL)0x0c21d671, (FIXP_DBL)0x0c2cc7ee, + (FIXP_DBL)0x0c379085, (FIXP_DBL)0x0c423162, (FIXP_DBL)0x0c4caba8, + (FIXP_DBL)0x0c570069, (FIXP_DBL)0x0c6130af, (FIXP_DBL)0x0c6b3d79, + (FIXP_DBL)0x0c7527b9, (FIXP_DBL)0x0c7ef05b, (FIXP_DBL)0x0c88983f, + (FIXP_DBL)0x0c92203d, (FIXP_DBL)0x0c9b8926, (FIXP_DBL)0x0ca4d3c2, + (FIXP_DBL)0x0cae00d2, (FIXP_DBL)0x0cb7110e, (FIXP_DBL)0x0cc0052b, + (FIXP_DBL)0x0cc8ddd4, (FIXP_DBL)0x0cd19bb0, (FIXP_DBL)0x0cda3f60, + (FIXP_DBL)0x0ce2c97d, (FIXP_DBL)0x0ceb3a9f, (FIXP_DBL)0x0cf39355, + (FIXP_DBL)0x0cfbd42b, (FIXP_DBL)0x0d03fda9, (FIXP_DBL)0x0d0c1050, + (FIXP_DBL)0x0d140ca0, (FIXP_DBL)0x0d1bf312, (FIXP_DBL)0x0d23c41d, + (FIXP_DBL)0x0d2b8034, (FIXP_DBL)0x0d3327c7, (FIXP_DBL)0x0d3abb40, + (FIXP_DBL)0x0d423b08, (FIXP_DBL)0x0d49a785, (FIXP_DBL)0x0d510118, + (FIXP_DBL)0x0d584822, (FIXP_DBL)0x0d5f7cff, (FIXP_DBL)0x0d66a009, + (FIXP_DBL)0x0d6db197, (FIXP_DBL)0x0d74b1fd, (FIXP_DBL)0x0d7ba190, + (FIXP_DBL)0x0d82809d, (FIXP_DBL)0x0d894f75, (FIXP_DBL)0x0d900e61, + (FIXP_DBL)0x0d96bdad, (FIXP_DBL)0x0d9d5da0, (FIXP_DBL)0x0da3ee7f, + (FIXP_DBL)0x0daa708f, (FIXP_DBL)0x0db0e412, (FIXP_DBL)0x0db74949, + (FIXP_DBL)0x0dbda072, (FIXP_DBL)0x0dc3e9ca, (FIXP_DBL)0x0dca258e}; + +#elif (LD_INT_TAB_LEN <= 193) +LNK_SECTION_CONSTDATA_L1 +static const FIXP_DBL ldIntCoeff[] = { + (FIXP_DBL)0x80000001, (FIXP_DBL)0x00000000, (FIXP_DBL)0x02000000, + (FIXP_DBL)0x032b8034, (FIXP_DBL)0x04000000, (FIXP_DBL)0x04a4d3c2, + (FIXP_DBL)0x052b8034, (FIXP_DBL)0x059d5da0, (FIXP_DBL)0x06000000, + (FIXP_DBL)0x06570069, (FIXP_DBL)0x06a4d3c2, (FIXP_DBL)0x06eb3a9f, + (FIXP_DBL)0x072b8034, (FIXP_DBL)0x0766a009, (FIXP_DBL)0x079d5da0, + (FIXP_DBL)0x07d053f7, (FIXP_DBL)0x08000000, (FIXP_DBL)0x082cc7ee, + (FIXP_DBL)0x08570069, (FIXP_DBL)0x087ef05b, (FIXP_DBL)0x08a4d3c2, + (FIXP_DBL)0x08c8ddd4, (FIXP_DBL)0x08eb3a9f, (FIXP_DBL)0x090c1050, + (FIXP_DBL)0x092b8034, (FIXP_DBL)0x0949a785, (FIXP_DBL)0x0966a009, + (FIXP_DBL)0x0982809d, (FIXP_DBL)0x099d5da0, (FIXP_DBL)0x09b74949, + (FIXP_DBL)0x09d053f7, (FIXP_DBL)0x09e88c6b, (FIXP_DBL)0x0a000000, + (FIXP_DBL)0x0a16bad3, (FIXP_DBL)0x0a2cc7ee, (FIXP_DBL)0x0a423162, + (FIXP_DBL)0x0a570069, (FIXP_DBL)0x0a6b3d79, (FIXP_DBL)0x0a7ef05b, + (FIXP_DBL)0x0a92203d, (FIXP_DBL)0x0aa4d3c2, (FIXP_DBL)0x0ab7110e, + (FIXP_DBL)0x0ac8ddd4, (FIXP_DBL)0x0ada3f60, (FIXP_DBL)0x0aeb3a9f, + (FIXP_DBL)0x0afbd42b, (FIXP_DBL)0x0b0c1050, (FIXP_DBL)0x0b1bf312, + (FIXP_DBL)0x0b2b8034, (FIXP_DBL)0x0b3abb40, (FIXP_DBL)0x0b49a785, + (FIXP_DBL)0x0b584822, (FIXP_DBL)0x0b66a009, (FIXP_DBL)0x0b74b1fd, + (FIXP_DBL)0x0b82809d, (FIXP_DBL)0x0b900e61, (FIXP_DBL)0x0b9d5da0, + (FIXP_DBL)0x0baa708f, (FIXP_DBL)0x0bb74949, (FIXP_DBL)0x0bc3e9ca, + (FIXP_DBL)0x0bd053f7, (FIXP_DBL)0x0bdc899b, (FIXP_DBL)0x0be88c6b, + (FIXP_DBL)0x0bf45e09, (FIXP_DBL)0x0c000000, (FIXP_DBL)0x0c0b73cb, + (FIXP_DBL)0x0c16bad3, (FIXP_DBL)0x0c21d671, (FIXP_DBL)0x0c2cc7ee, + (FIXP_DBL)0x0c379085, (FIXP_DBL)0x0c423162, (FIXP_DBL)0x0c4caba8, + (FIXP_DBL)0x0c570069, (FIXP_DBL)0x0c6130af, (FIXP_DBL)0x0c6b3d79, + (FIXP_DBL)0x0c7527b9, (FIXP_DBL)0x0c7ef05b, (FIXP_DBL)0x0c88983f, + (FIXP_DBL)0x0c92203d, (FIXP_DBL)0x0c9b8926, (FIXP_DBL)0x0ca4d3c2, + (FIXP_DBL)0x0cae00d2, (FIXP_DBL)0x0cb7110e, (FIXP_DBL)0x0cc0052b, + (FIXP_DBL)0x0cc8ddd4, (FIXP_DBL)0x0cd19bb0, (FIXP_DBL)0x0cda3f60, + (FIXP_DBL)0x0ce2c97d, (FIXP_DBL)0x0ceb3a9f, (FIXP_DBL)0x0cf39355, + (FIXP_DBL)0x0cfbd42b, (FIXP_DBL)0x0d03fda9, (FIXP_DBL)0x0d0c1050, + (FIXP_DBL)0x0d140ca0, (FIXP_DBL)0x0d1bf312, (FIXP_DBL)0x0d23c41d, + (FIXP_DBL)0x0d2b8034, (FIXP_DBL)0x0d3327c7, (FIXP_DBL)0x0d3abb40, + (FIXP_DBL)0x0d423b08, (FIXP_DBL)0x0d49a785, (FIXP_DBL)0x0d510118, + (FIXP_DBL)0x0d584822, (FIXP_DBL)0x0d5f7cff, (FIXP_DBL)0x0d66a009, + (FIXP_DBL)0x0d6db197, (FIXP_DBL)0x0d74b1fd, (FIXP_DBL)0x0d7ba190, + (FIXP_DBL)0x0d82809d, (FIXP_DBL)0x0d894f75, (FIXP_DBL)0x0d900e61, + (FIXP_DBL)0x0d96bdad, (FIXP_DBL)0x0d9d5da0, (FIXP_DBL)0x0da3ee7f, + (FIXP_DBL)0x0daa708f, (FIXP_DBL)0x0db0e412, (FIXP_DBL)0x0db74949, + (FIXP_DBL)0x0dbda072, (FIXP_DBL)0x0dc3e9ca, (FIXP_DBL)0x0dca258e, + (FIXP_DBL)0x0dd053f7, (FIXP_DBL)0x0dd6753e, (FIXP_DBL)0x0ddc899b, + (FIXP_DBL)0x0de29143, (FIXP_DBL)0x0de88c6b, (FIXP_DBL)0x0dee7b47, + (FIXP_DBL)0x0df45e09, (FIXP_DBL)0x0dfa34e1, (FIXP_DBL)0x0e000000, + (FIXP_DBL)0x0e05bf94, (FIXP_DBL)0x0e0b73cb, (FIXP_DBL)0x0e111cd2, + (FIXP_DBL)0x0e16bad3, (FIXP_DBL)0x0e1c4dfb, (FIXP_DBL)0x0e21d671, + (FIXP_DBL)0x0e275460, (FIXP_DBL)0x0e2cc7ee, (FIXP_DBL)0x0e323143, + (FIXP_DBL)0x0e379085, (FIXP_DBL)0x0e3ce5d8, (FIXP_DBL)0x0e423162, + (FIXP_DBL)0x0e477346, (FIXP_DBL)0x0e4caba8, (FIXP_DBL)0x0e51daa8, + (FIXP_DBL)0x0e570069, (FIXP_DBL)0x0e5c1d0b, (FIXP_DBL)0x0e6130af, + (FIXP_DBL)0x0e663b74, (FIXP_DBL)0x0e6b3d79, (FIXP_DBL)0x0e7036db, + (FIXP_DBL)0x0e7527b9, (FIXP_DBL)0x0e7a1030, (FIXP_DBL)0x0e7ef05b, + (FIXP_DBL)0x0e83c857, (FIXP_DBL)0x0e88983f, (FIXP_DBL)0x0e8d602e, + (FIXP_DBL)0x0e92203d, (FIXP_DBL)0x0e96d888, (FIXP_DBL)0x0e9b8926, + (FIXP_DBL)0x0ea03232, (FIXP_DBL)0x0ea4d3c2, (FIXP_DBL)0x0ea96df0, + (FIXP_DBL)0x0eae00d2, (FIXP_DBL)0x0eb28c7f, (FIXP_DBL)0x0eb7110e, + (FIXP_DBL)0x0ebb8e96, (FIXP_DBL)0x0ec0052b, (FIXP_DBL)0x0ec474e4, + (FIXP_DBL)0x0ec8ddd4, (FIXP_DBL)0x0ecd4012, (FIXP_DBL)0x0ed19bb0, + (FIXP_DBL)0x0ed5f0c4, (FIXP_DBL)0x0eda3f60, (FIXP_DBL)0x0ede8797, + (FIXP_DBL)0x0ee2c97d, (FIXP_DBL)0x0ee70525, (FIXP_DBL)0x0eeb3a9f, + (FIXP_DBL)0x0eef69ff, (FIXP_DBL)0x0ef39355, (FIXP_DBL)0x0ef7b6b4, + (FIXP_DBL)0x0efbd42b, (FIXP_DBL)0x0effebcd, (FIXP_DBL)0x0f03fda9, + (FIXP_DBL)0x0f0809cf, (FIXP_DBL)0x0f0c1050, (FIXP_DBL)0x0f10113b, + (FIXP_DBL)0x0f140ca0, (FIXP_DBL)0x0f18028d, (FIXP_DBL)0x0f1bf312, + (FIXP_DBL)0x0f1fde3d, (FIXP_DBL)0x0f23c41d, (FIXP_DBL)0x0f27a4c0, + (FIXP_DBL)0x0f2b8034}; + +#else +#error "ldInt table size too small" + +#endif + +LNK_SECTION_INITCODE +void InitLdInt() { /* nothing to do! Use preinitialized logarithm table */ +} + +#if (LD_INT_TAB_LEN != 0) + +LNK_SECTION_CODE_L1 +FIXP_DBL CalcLdInt(INT i) { + /* calculates ld(op)/LD_DATA_SCALING */ + /* op is assumed to be an integer value between 1 and LD_INT_TAB_LEN */ + + FDK_ASSERT((LD_INT_TAB_LEN > 0) && + ((FIXP_DBL)ldIntCoeff[0] == + (FIXP_DBL)0x80000001)); /* tab has to be initialized */ + + if ((i > 0) && (i < LD_INT_TAB_LEN)) + return ldIntCoeff[i]; + else { + return (0); + } +} +#endif /* (LD_INT_TAB_LEN!=0) */ + +#if !defined(FUNCTION_schur_div) +/***************************************************************************** + + functionname: schur_div + description: delivers op1/op2 with op3-bit accuracy + +*****************************************************************************/ + +FIXP_DBL schur_div(FIXP_DBL num, FIXP_DBL denum, INT count) { + INT L_num = (LONG)num >> 1; + INT L_denum = (LONG)denum >> 1; + INT div = 0; + INT k = count; + + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denum > (FIXP_DBL)0); + FDK_ASSERT(num <= denum); + + if (L_num != 0) + while (--k) { + div <<= 1; + L_num <<= 1; + if (L_num >= L_denum) { + L_num -= L_denum; + div++; + } + } + return (FIXP_DBL)(div << (DFRACT_BITS - count)); +} + +#endif /* !defined(FUNCTION_schur_div) */ + +#ifndef FUNCTION_fMultNorm +FIXP_DBL fMultNorm(FIXP_DBL f1, FIXP_DBL f2, INT *result_e) { + INT product = 0; + INT norm_f1, norm_f2; + + if ((f1 == (FIXP_DBL)0) || (f2 == (FIXP_DBL)0)) { + *result_e = 0; + return (FIXP_DBL)0; + } + norm_f1 = CountLeadingBits(f1); + f1 = f1 << norm_f1; + norm_f2 = CountLeadingBits(f2); + f2 = f2 << norm_f2; + + if ((f1 == (FIXP_DBL)MINVAL_DBL) && (f2 == (FIXP_DBL)MINVAL_DBL)) { + product = -((FIXP_DBL)MINVAL_DBL >> 1); + *result_e = -(norm_f1 + norm_f2 - 1); + } else { + product = fMult(f1, f2); + *result_e = -(norm_f1 + norm_f2); + } + + return (FIXP_DBL)product; +} +#endif + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT(L_num >= (FIXP_DBL)0); + FDK_ASSERT(L_denum > (FIXP_DBL)0); + + if (L_num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(L_num); + L_num = L_num << norm_num; + L_num = L_num >> 1; + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(L_denum); + L_denum = L_denum << norm_den; + *result_e -= -norm_den; + + div = schur_div(L_num, L_denum, FRACT_BITS); + + return div; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNorm +FIXP_DBL fDivNorm(FIXP_DBL num, FIXP_DBL denom) { + INT e; + FIXP_DBL res; + + FDK_ASSERT(denom >= num); + + res = fDivNorm(num, denom, &e); + + /* Avoid overflow since we must output a value with exponent 0 + there is no other choice than saturating to almost 1.0f */ + if (res == (FIXP_DBL)(1 << (DFRACT_BITS - 2)) && e == 1) { + res = (FIXP_DBL)MAXVAL_DBL; + } else { + res = scaleValue(res, e); + } + + return res; +} +#endif /* !FUNCTION_fDivNorm */ + +#ifndef FUNCTION_fDivNormSigned +FIXP_DBL fDivNormSigned(FIXP_DBL num, FIXP_DBL denom) { + INT e; + FIXP_DBL res; + int sign; + + if (denom == (FIXP_DBL)0) { + return (FIXP_DBL)MAXVAL_DBL; + } + + sign = ((num >= (FIXP_DBL)0) != (denom >= (FIXP_DBL)0)); + res = fDivNormSigned(num, denom, &e); + + /* Saturate since we must output a value with exponent 0 */ + if ((e > 0) && (fAbs(res) >= FL2FXCONST_DBL(0.5))) { + if (sign) { + res = (FIXP_DBL)MINVAL_DBL; + } else { + res = (FIXP_DBL)MAXVAL_DBL; + } + } else { + res = scaleValue(res, e); + } + + return res; +} +FIXP_DBL fDivNormSigned(FIXP_DBL L_num, FIXP_DBL L_denum, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + int sign; + + sign = ((L_num >= (FIXP_DBL)0) != (L_denum >= (FIXP_DBL)0)); + + if (L_num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + if (L_denum == (FIXP_DBL)0) { + *result_e = 14; + return ((FIXP_DBL)MAXVAL_DBL); + } + + norm_num = CountLeadingBits(L_num); + L_num = L_num << norm_num; + L_num = L_num >> 2; + L_num = fAbs(L_num); + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(L_denum); + L_denum = L_denum << norm_den; + L_denum = L_denum >> 1; + L_denum = fAbs(L_denum); + *result_e -= -norm_den; + + div = schur_div(L_num, L_denum, FRACT_BITS); + + if (sign) { + div = -div; + } + + return div; +} +#endif /* FUNCTION_fDivNormSigned */ + +#ifndef FUNCTION_fDivNormHighPrec +FIXP_DBL fDivNormHighPrec(FIXP_DBL num, FIXP_DBL denom, INT *result_e) { + FIXP_DBL div; + INT norm_num, norm_den; + + FDK_ASSERT(num >= (FIXP_DBL)0); + FDK_ASSERT(denom > (FIXP_DBL)0); + + if (num == (FIXP_DBL)0) { + *result_e = 0; + return ((FIXP_DBL)0); + } + + norm_num = CountLeadingBits(num); + num = num << norm_num; + num = num >> 1; + *result_e = -norm_num + 1; + + norm_den = CountLeadingBits(denom); + denom = denom << norm_den; + *result_e -= -norm_den; + + div = schur_div(num, denom, 31); + return div; +} +#endif /* !FUNCTION_fDivNormHighPrec */ + +#ifndef FUNCTION_fPow +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e, INT *result_e) { + FIXP_DBL frac_part, result_m; + INT int_part; + + if (exp_e > 0) { + INT exp_bits = DFRACT_BITS - 1 - exp_e; + int_part = exp_m >> exp_bits; + frac_part = exp_m - (FIXP_DBL)(int_part << exp_bits); + frac_part = frac_part << exp_e; + } else { + int_part = 0; + frac_part = exp_m >> -exp_e; + } + + /* Best accuracy is around 0, so try to get there with the fractional part. */ + if (frac_part > FL2FXCONST_DBL(0.5f)) { + int_part = int_part + 1; + frac_part = frac_part + FL2FXCONST_DBL(-1.0f); + } + if (frac_part < FL2FXCONST_DBL(-0.5f)) { + int_part = int_part - 1; + frac_part = -(FL2FXCONST_DBL(-1.0f) - frac_part); + } + + /* "+ 1" compensates fMultAddDiv2() of the polynomial evaluation below. */ + *result_e = int_part + 1; + + /* Evaluate taylor polynomial which approximates 2^x */ + { + FIXP_DBL p; + + /* result_m ~= 2^frac_part */ + p = frac_part; + /* First taylor series coefficient a_0 = 1.0, scaled by 0.5 due to + * fMultDiv2(). */ + result_m = FL2FXCONST_DBL(1.0f / 2.0f); + for (INT i = 0; i < POW2_PRECISION; i++) { + /* next taylor series term: a_i * x^i, x=0 */ + result_m = fMultAddDiv2(result_m, pow2Coeff[i], p); + p = fMult(p, frac_part); + } + } + return result_m; +} + +FIXP_DBL f2Pow(const FIXP_DBL exp_m, const INT exp_e) { + FIXP_DBL result_m; + INT result_e; + + result_m = f2Pow(exp_m, exp_e, &result_e); + result_e = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), result_e)); + + return scaleValue(result_m, result_e); +} + +FIXP_DBL fPow(FIXP_DBL base_m, INT base_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e) { + INT ans_lg2_e, baselg2_e; + FIXP_DBL base_lg2, ans_lg2, result; + + /* Calc log2 of base */ + base_lg2 = fLog2(base_m, base_e, &baselg2_e); + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(base_lg2, exp_m); + ans_lg2_e = exp_e + baselg2_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e, + INT *result_e) { + INT ans_lg2_e; + FIXP_DBL ans_lg2, result; + + /* Prepare exp */ + { + INT leadingBits; + + leadingBits = CountLeadingBits(fAbs(exp_m)); + exp_m = exp_m << leadingBits; + exp_e -= leadingBits; + } + + /* Calc base pow exp */ + ans_lg2 = fMult(baseLd_m, exp_m); + ans_lg2_e = exp_e + baseLd_e; + + /* Calc antilog */ + result = f2Pow(ans_lg2, ans_lg2_e, result_e); + + return result; +} + +FIXP_DBL fLdPow(FIXP_DBL baseLd_m, INT baseLd_e, FIXP_DBL exp_m, INT exp_e) { + FIXP_DBL result_m; + int result_e; + + result_m = fLdPow(baseLd_m, baseLd_e, exp_m, exp_e, &result_e); + + return SATURATE_SHIFT(result_m, -result_e, DFRACT_BITS); +} + +FIXP_DBL fPowInt(FIXP_DBL base_m, INT base_e, INT exp, INT *pResult_e) { + FIXP_DBL result; + + if (exp != 0) { + INT result_e = 0; + + if (base_m != (FIXP_DBL)0) { + { + INT leadingBits; + leadingBits = CountLeadingBits(base_m); + base_m <<= leadingBits; + base_e -= leadingBits; + } + + result = base_m; + + { + int i; + for (i = 1; i < fAbs(exp); i++) { + result = fMult(result, base_m); + } + } + + if (exp < 0) { + /* 1.0 / ans */ + result = fDivNorm(FL2FXCONST_DBL(0.5f), result, &result_e); + result_e++; + } else { + int ansScale = CountLeadingBits(result); + result <<= ansScale; + result_e -= ansScale; + } + + result_e += exp * base_e; + + } else { + result = (FIXP_DBL)0; + } + *pResult_e = result_e; + } else { + result = FL2FXCONST_DBL(0.5f); + *pResult_e = 1; + } + + return result; +} +#endif /* FUNCTION_fPow */ + +#ifndef FUNCTION_fLog2 +FIXP_DBL CalcLog2(FIXP_DBL base_m, INT base_e, INT *result_e) { + return fLog2(base_m, base_e, result_e); +} +#endif /* FUNCTION_fLog2 */ + +INT fixp_floorToInt(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT floorInt = (INT)(f_inp >> ((DFRACT_BITS - 1) - sf)); + return floorInt; +} + +FIXP_DBL fixp_floor(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT floorInt = fixp_floorToInt(f_inp, sf); + FIXP_DBL f_floor = (FIXP_DBL)(floorInt << ((DFRACT_BITS - 1) - sf)); + return f_floor; +} + +INT fixp_ceilToInt(FIXP_DBL f_inp, INT sf) // sf mantissaBits left of dot +{ + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; // sx mantissaBits right of dot + INT inpINT = (INT)f_inp; + + INT mask = (0x1 << sx) - 1; + INT ceilInt = (INT)(f_inp >> sx); + + if (inpINT & mask) { + ceilInt++; // increment only, if there is at least one set mantissaBit + // right of dot [in inpINT] + } + + return ceilInt; +} + +FIXP_DBL fixp_ceil(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; + INT ceilInt = fixp_ceilToInt(f_inp, sf); + ULONG mask = (ULONG)0x1 << (DFRACT_BITS - 1); // 0x80000000 + ceilInt = ceilInt + << sx; // no fract warn bec. shift into saturation done on int side + + if ((f_inp > FL2FXCONST_DBL(0.0f)) && (ceilInt & mask)) { + --ceilInt; + } + FIXP_DBL f_ceil = (FIXP_DBL)ceilInt; + + return f_ceil; +} + +/***************************************************************************** + fixp_truncateToInt() + Just remove the fractional part which is located right of decimal point + Same as which is done when a float is casted to (INT) : + result_INTtype = (INT)b_floatTypeInput; + + returns INT +*****************************************************************************/ +INT fixp_truncateToInt(FIXP_DBL f_inp, INT sf) // sf mantissaBits left of dot + // (without sign) e.g. at width + // 32 this would be [sign]7. + // supposed sf equals 8. +{ + FDK_ASSERT(sf >= 0); + INT sx = (DFRACT_BITS - 1) - sf; // sx mantissaBits right of dot + // at width 32 this would be .24 + // supposed sf equals 8. + INT fbaccu = (INT)f_inp; + INT mask = (0x1 << sx); + + if ((fbaccu < 0) && (fbaccu & (mask - 1))) { + fbaccu = fbaccu + mask; + } + + fbaccu = fbaccu >> sx; + return fbaccu; +} + +/***************************************************************************** + fixp_truncate() + Just remove the fractional part which is located right of decimal point + + returns FIXP_DBL +*****************************************************************************/ +FIXP_DBL fixp_truncate(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT truncateInt = fixp_truncateToInt(f_inp, sf); + FIXP_DBL f_truncate = (FIXP_DBL)(truncateInt << ((DFRACT_BITS - 1) - sf)); + return f_truncate; +} + +/***************************************************************************** + fixp_roundToInt() + round [typical rounding] + + See fct roundRef() [which is the reference] + returns INT +*****************************************************************************/ +INT fixp_roundToInt(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = DFRACT_BITS - 1 - sf; + INT inp = (INT)f_inp; + INT mask1 = (0x1 << (sx - 1)); + INT mask2 = (0x1 << (sx)) - 1; + INT mask3 = 0x7FFFFFFF; + INT iam = inp & mask2; + INT rnd; + + if ((inp < 0) && !(iam == mask1)) + rnd = inp + mask1; + else if ((inp > 0) && !(inp == mask3)) + rnd = inp + mask1; + else + rnd = inp; + + rnd = rnd >> sx; + + if (inp == mask3) rnd++; + + return rnd; +} + +/***************************************************************************** + fixp_round() + round [typical rounding] + + See fct roundRef() [which is the reference] + returns FIXP_DBL +*****************************************************************************/ +FIXP_DBL fixp_round(FIXP_DBL f_inp, INT sf) { + FDK_ASSERT(sf >= 0); + INT sx = DFRACT_BITS - 1 - sf; + INT r = fixp_roundToInt(f_inp, sf); + ULONG mask = (ULONG)0x1 << (DFRACT_BITS - 1); // 0x80000000 + r = r << sx; + + if ((f_inp > FL2FXCONST_DBL(0.0f)) && (r & mask)) { + --r; + } + + FIXP_DBL f_round = (FIXP_DBL)r; + return f_round; +} diff --git a/fdk-aac/libFDK/src/huff_nodes.cpp b/fdk-aac/libFDK/src/huff_nodes.cpp new file mode 100644 index 0000000..66dc908 --- /dev/null +++ b/fdk-aac/libFDK/src/huff_nodes.cpp @@ -0,0 +1,1084 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: MPEG-D SAC/USAC/SAOC Huffman Part0 Tables + +*******************************************************************************/ + +#include "huff_nodes.h" + +const HUFF_PT0_NODES FDK_huffPart0Nodes = { + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, {12, 11}, + {14, 13}, {-8, 15}, {-9, 16}, {-10, 17}, {-18, 18}, {-17, -19}, + {-16, 19}, {-11, -20}, {-15, -21}, {-7, 20}, {-22, 21}, {-12, -14}, + {-13, -23}, {23, 22}, {-24, -31}, {-6, 24}, {-25, -26}, {26, 25}, + {-5, -27}, {-28, 27}, {-4, 28}, {-29, 29}, {-1, -30}, {-2, -3}}, + {{2, 1}, {-5, 3}, {-4, -6}, {-3, 4}, {-2, 5}, {-1, 6}, {-7, -8}}, + {{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-7, 6}, {-3, -5}, {-4, -6}}, + {{-1, 1}, + {3, 2}, + {-8, 4}, + {6, 5}, + {-16, 7}, + {9, 8}, + {11, 10}, + {-2, -7}, + {-6, 12}, + {-4, -5}, + {-3, 13}, + {-10, 14}, + {-11, -12}, + {-14, -15}, + {-9, -13}}, + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, {12, 11}, + {14, 13}, {16, 15}, {18, 17}, {20, 19}, {22, 21}, {24, 23}, + {26, 25}, {28, 27}, {30, 29}, {32, 31}, {-47, 33}, {-54, 34}, + {-46, 35}, {-48, 36}, {-23, -27}, {-45, 37}, {-55, 38}, {-22, -49}, + {-24, -53}, {-44, 39}, {-57, 40}, {-28, 41}, {-52, -56}, {-43, 42}, + {-50, 43}, {-25, -26}, {-29, -64}, {-62, 44}, {-21, -51}, {-58, 45}, + {-32, 46}, {-31, -42}, {-60, 47}, {-30, 48}, {-20, -61}, {-41, -63}, + {-19, -59}, {-40, 49}, {-18, -38}, {-39, 50}, {-36, -37}, {-35, 51}, + {-17, 52}, {-16, -34}, {-33, 53}, {-15, 54}, {-14, 55}, {-13, 56}, + {-12, 57}, {-11, 58}, {-10, 59}, {-9, 60}, {-7, 61}, {-1, -4}, + {-6, 62}, {-5, -8}, {-2, -3}}}; + +const HUFF_LAV_NODES FDK_huffLavIdxNodes = {{{-1, 1}, {-2, 2}, {-3, -4}}}; + +static const HUFF_ICC_NOD_1D FDK_huffICCNodes_h1D_0 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, {-7, -8}}}; + +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_0_0 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{2, 1}, + {-1, -52}, + {-2, 3}, + {5, 4}, + {-51, 6}, + {-18, 7}, + {-17, 8}, + {-3, 9}, + {-36, 10}, + {-19, -50}, + {-35, 11}, + {-4, 12}, + {-34, 13}, + {-33, 14}, + {-20, -49}}, + {{2, 1}, {-86, 3}, {-1, 4}, {6, 5}, {-2, 7}, {-85, 8}, + {-18, 9}, {11, 10}, {-17, 12}, {14, 13}, {-70, 15}, {-3, -19}, + {-69, 16}, {-84, 17}, {-68, 18}, {-20, -35}, {-34, -83}, {20, 19}, + {-4, 21}, {-33, 22}, {-5, 23}, {-53, 24}, {-36, -52}, {-67, 25}, + {-21, -82}, {-54, 26}, {-6, 27}, {-51, 28}, {-50, 29}, {-49, 30}, + {-37, 31}, {-38, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, -120}, {6, 5}, {8, 7}, {-18, 9}, + {-2, 10}, {12, 11}, {14, 13}, {-17, -119}, {16, 15}, {-103, 17}, + {-104, 18}, {-52, 19}, {21, 20}, {-69, 22}, {24, 23}, {-3, -35}, + {-19, 25}, {-34, -85}, {27, 26}, {-86, 28}, {-118, 29}, {-37, 30}, + {32, 31}, {-102, 33}, {-20, -22}, {-4, -117}, {-87, 34}, {-100, 35}, + {-33, -36}, {37, 36}, {-70, -88}, {-101, 38}, {-5, 39}, {-51, -53}, + {-50, 40}, {-115, 41}, {-21, 42}, {-116, 43}, {-38, 44}, {-23, -84}, + {-49, -99}, {46, 45}, {-6, -114}, {-7, -72}, {-71, 47}, {-8, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_0_1 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{2, 1}, + {-1, -52}, + {-17, 3}, + {5, 4}, + {-36, 6}, + {-2, 7}, + {-18, -33}, + {9, 8}, + {-20, 10}, + {-34, -51}, + {-49, 11}, + {-35, 12}, + {-19, 13}, + {-3, 14}, + {-4, -50}}, + {{2, 1}, {-86, 3}, {-1, 4}, {-17, 5}, {7, 6}, {-70, 8}, + {-33, 9}, {-18, 10}, {-2, 11}, {-54, 12}, {-49, 13}, {-38, 14}, + {-34, -65}, {-85, 15}, {-50, 16}, {-69, 17}, {-22, 18}, {-53, 19}, + {21, 20}, {-19, -81}, {-66, 22}, {-3, -35}, {24, 23}, {-37, 25}, + {-68, -84}, {-51, 26}, {28, 27}, {-20, -52}, {30, 29}, {-4, -36}, + {-83, 31}, {-67, 32}, {-82, 33}, {-21, 34}, {-5, -6}}, + {{2, 1}, {-1, 3}, {-120, 4}, {-17, 5}, {7, 6}, {-104, 8}, + {-33, 9}, {11, 10}, {13, 12}, {-49, 14}, {-88, 15}, {-18, -97}, + {-65, 16}, {-40, 17}, {-2, -72}, {19, 18}, {-113, 20}, {-34, 21}, + {-56, -81}, {23, 22}, {-50, 24}, {-82, -119}, {-24, -103}, {26, 25}, + {28, 27}, {30, 29}, {-55, -87}, {-66, 31}, {33, 32}, {-98, 34}, + {-35, -67}, {-19, 35}, {-70, 36}, {-71, 37}, {-51, -52}, {-3, 38}, + {40, 39}, {-86, -118}, {42, 41}, {-39, -69}, {-54, -83}, {44, 43}, + {-102, 45}, {-101, 46}, {-68, -85}, {-36, -53}, {-5, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_1_0 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{-52, 1}, + {-1, 2}, + {4, 3}, + {-2, -17}, + {-18, 5}, + {-36, 6}, + {-51, 7}, + {9, 8}, + {-33, 10}, + {-34, 11}, + {-35, 12}, + {-19, -20}, + {-3, 13}, + {-49, 14}, + {-4, -50}}, + {{-1, 1}, {-86, 2}, {4, 3}, {-17, 5}, {-2, 6}, {-18, 7}, + {-70, 8}, {-85, 9}, {11, 10}, {13, 12}, {-33, 14}, {16, 15}, + {-34, -54}, {-69, 17}, {-38, 18}, {-50, 19}, {-35, -53}, {-49, 20}, + {-19, 21}, {-3, 22}, {-65, 23}, {-68, 24}, {-22, 25}, {-81, -84}, + {-66, 26}, {-37, 27}, {-20, -51}, {29, 28}, {-52, 30}, {-4, -83}, + {-36, 31}, {-67, 32}, {-5, 33}, {-82, 34}, {-21, 0}}, + {{-1, 1}, {-120, 2}, {4, 3}, {-17, 5}, {-2, 6}, {8, 7}, + {-18, 9}, {-104, 10}, {12, 11}, {14, 13}, {16, 15}, {-119, 17}, + {-81, 18}, {20, 19}, {-33, 21}, {-88, 22}, {-103, 23}, {-34, 24}, + {-56, 25}, {-72, 26}, {-49, 27}, {-82, 28}, {-50, 29}, {-65, 30}, + {-55, -87}, {-19, 31}, {-67, 32}, {-35, -40}, {34, 33}, {-52, -71}, + {-66, 35}, {-70, 36}, {38, 37}, {-51, -97}, {-86, -102}, {-3, 39}, + {-118, 40}, {42, 41}, {-24, -85}, {-54, 43}, {-39, 44}, {-98, -113}, + {-36, -37}, {-20, -69}, {-4, 45}, {-5, 46}, {-21, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_ICC_NOD_2D FDK_huffICCNodes_h2D_1_1 = { + {{-1, 1}, {-18, 2}, {-2, -17}}, + {{-52, 1}, + {-1, 2}, + {4, 3}, + {-2, 5}, + {-17, -18}, + {-51, 6}, + {-36, 7}, + {9, 8}, + {-35, 10}, + {-3, 11}, + {-19, -34}, + {-33, 12}, + {-50, 13}, + {-20, 14}, + {-4, -49}}, + {{2, 1}, {-86, 3}, {-1, 4}, {6, 5}, {-18, 7}, {-2, -17}, + {9, 8}, {-70, 10}, {-69, -85}, {-35, 11}, {13, 12}, {-34, 14}, + {-19, 15}, {-53, 16}, {-68, 17}, {-33, 18}, {-3, -52}, {20, 19}, + {-54, 21}, {-84, 22}, {-50, 23}, {-20, -51}, {-36, 24}, {26, 25}, + {-83, 27}, {-4, -38}, {-49, 28}, {-37, 29}, {-67, 30}, {-5, 31}, + {-21, 32}, {-65, -66}, {-82, 33}, {-22, 34}, {-6, -81}}, + {{2, 1}, {-1, -120}, {4, 3}, {6, 5}, {-18, 7}, {9, 8}, + {-17, 10}, {-2, 11}, {-103, 12}, {-52, 13}, {-35, -104}, {-119, 14}, + {16, 15}, {-69, -86}, {18, 17}, {-34, 19}, {-19, 20}, {22, 21}, + {-70, 23}, {-87, 24}, {-102, 25}, {-85, 26}, {-33, 27}, {-36, 28}, + {-3, 29}, {-88, 30}, {-51, 31}, {-118, 32}, {34, 33}, {-68, 35}, + {-53, 36}, {-67, 37}, {-20, 38}, {-101, 39}, {-50, 40}, {42, 41}, + {-37, 43}, {-116, 44}, {-117, 45}, {-49, 46}, {-21, -100}, {48, 47}, + {-55, -71}, {-4, 49}, {-22, -84}, {-115, 50}, {-66, -82}, {-72, 51}, + {-5, -6}, {-54, 52}, {-38, 53}, {-83, 54}, {-40, 55}, {-39, 56}, + {-99, 57}, {-23, -56}, {-7, 58}, {-65, -97}, {-8, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}; + +const HUFF_ICC_NODES FDK_huffICCNodes = { + {&FDK_huffICCNodes_h1D_0, &FDK_huffICCNodes_h1D_0, &FDK_huffICCNodes_h1D_0}, + {{&FDK_huffICCNodes_h2D_0_0, &FDK_huffICCNodes_h2D_0_1}, + {&FDK_huffICCNodes_h2D_1_0, &FDK_huffICCNodes_h2D_1_1}, + {&FDK_huffICCNodes_h2D_0_1, &FDK_huffICCNodes_h2D_0_1}}}; + +static const HUFF_CLD_NOD_1D FDK_huffCLDNodes_h1D_0 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, + {-7, 7}, {-8, 8}, {-9, 9}, {-10, 10}, {-11, 11}, {-12, 12}, + {-13, 13}, {15, 14}, {-14, 16}, {-15, 17}, {-16, 18}, {-17, 19}, + {-18, 20}, {-19, 21}, {-20, -21}, {-23, 22}, {-22, 23}, {-24, 24}, + {-25, 25}, {27, 26}, {29, 28}, {-30, -31}, {-28, -29}, {-26, -27}}}; +static const HUFF_CLD_NOD_1D FDK_huffCLDNodes_h1D_1 = { + {{-1, 1}, {-2, 2}, {-3, 3}, {-4, 4}, {-5, 5}, {-6, 6}, + {-7, 7}, {9, 8}, {-8, 10}, {-9, 11}, {-10, 12}, {-11, 13}, + {-12, 14}, {-13, 15}, {-14, 16}, {-15, 17}, {-16, 18}, {-17, 19}, + {-18, 20}, {-19, -20}, {-21, 21}, {-22, 22}, {-23, 23}, {25, 24}, + {-24, 26}, {-25, 27}, {29, 28}, {-26, -31}, {-29, -30}, {-27, -28}}}; + +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_0_0 = { + {{2, 1}, + {-1, -52}, + {4, 3}, + {-2, 5}, + {-51, 6}, + {-17, -18}, + {8, 7}, + {10, 9}, + {-3, -36}, + {-19, 11}, + {-35, -50}, + {-34, 12}, + {-4, 13}, + {-33, 14}, + {-20, -49}}, + {{2, 1}, {4, 3}, {-86, 5}, {7, 6}, {9, 8}, {-1, -2}, + {-85, 10}, {-18, 11}, {-17, 12}, {14, 13}, {-70, 15}, {17, 16}, + {-19, -69}, {-84, 18}, {-3, 19}, {21, 20}, {-34, -68}, {-20, 22}, + {-35, 23}, {-83, 24}, {-33, 25}, {-4, 26}, {-53, 27}, {-54, -67}, + {-36, 28}, {-21, -52}, {-82, 29}, {-5, -50}, {-51, 30}, {-38, 31}, + {-37, -49}, {-6, 32}, {-66, 33}, {-65, 34}, {-22, -81}}, + {{2, 1}, {4, 3}, {-120, 5}, {7, 6}, {9, 8}, {11, 10}, + {-1, 12}, {-18, -119}, {-2, 13}, {15, 14}, {-17, 16}, {-104, 17}, + {19, 18}, {-19, 20}, {-103, 21}, {-118, 22}, {24, 23}, {-3, 25}, + {27, 26}, {-34, 28}, {-102, 29}, {-20, 30}, {-35, 31}, {33, 32}, + {-117, 34}, {-33, 35}, {-88, 36}, {-4, 37}, {-87, 38}, {40, 39}, + {-36, -101}, {-86, 41}, {-21, -37}, {-85, -100}, {-52, 42}, {-22, 43}, + {-116, 44}, {-50, 45}, {47, 46}, {-5, -51}, {-115, 48}, {-70, 49}, + {-84, 50}, {-38, -49}, {-72, -99}, {-53, 51}, {-69, -71}, {-23, 52}, + {-6, -67}, {-114, 53}, {-7, 54}, {-66, -68}, {-55, 55}, {57, 56}, + {-54, -65}, {-8, -56}, {-82, -83}, {59, 58}, {-39, -40}, {-81, 60}, + {-98, 61}, {-97, 62}, {-24, -113}}, + {{2, 1}, {4, 3}, {6, 5}, {-154, 7}, {9, 8}, + {11, 10}, {13, 12}, {15, 14}, {-18, 16}, {-153, 17}, + {-1, -2}, {19, 18}, {-138, 20}, {-17, 21}, {23, 22}, + {25, 24}, {-19, -137}, {27, 26}, {-152, 28}, {30, 29}, + {-3, -34}, {32, 31}, {34, 33}, {36, 35}, {-136, 37}, + {-35, 38}, {-20, 39}, {-122, 40}, {-151, 41}, {-33, 42}, + {-121, 43}, {45, 44}, {47, 46}, {-4, 48}, {-36, -120}, + {-135, 49}, {51, 50}, {-21, 52}, {54, 53}, {56, 55}, + {-50, -150}, {58, 57}, {-51, 59}, {61, 60}, {-119, 62}, + {-52, 63}, {-5, 64}, {-37, 65}, {-117, -134}, {-39, -54}, + {-22, 66}, {-106, 67}, {-69, -102}, {-132, 68}, {-105, 69}, + {-49, 70}, {-149, 71}, {-24, -104}, {73, 72}, {-53, 74}, + {-38, -118}, {-103, 75}, {-6, 76}, {-66, -87}, {-133, -147}, + {-23, 77}, {-67, 78}, {-68, -86}, {-70, -101}, {-40, -148}, + {-116, 79}, {-55, 80}, {-84, -131}, {82, 81}, {-89, -90}, + {-7, -25}, {-85, -88}, {-65, 83}, {-72, -146}, {85, 84}, + {-9, -71}, {-83, 86}, {-82, 87}, {-8, 88}, {-100, 89}, + {-74, -99}, {-73, 90}, {-10, -81}, {-56, 91}, {-57, -98}, + {93, 92}, {-58, -114}, {-97, -115}, {95, 94}, {-41, 96}, + {-42, 97}, {-26, -129}, {-113, 98}, {-130, -145}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_0_1 = { + {{-1, 1}, + {-52, 2}, + {-17, 3}, + {5, 4}, + {-36, 6}, + {-33, 7}, + {-2, -18}, + {-20, 8}, + {10, 9}, + {-34, -49}, + {-51, 11}, + {-35, 12}, + {-19, 13}, + {-3, 14}, + {-4, -50}}, + {{2, 1}, {4, 3}, {-86, 5}, {-1, 6}, {-17, 7}, {-70, 8}, + {10, 9}, {-18, 11}, {-33, 12}, {-54, 13}, {-2, 14}, {-34, 15}, + {-38, 16}, {-49, 17}, {-85, 18}, {-50, 19}, {-69, 20}, {-53, -65}, + {-22, 21}, {-66, 22}, {-19, 23}, {-37, 24}, {-35, -81}, {-3, 25}, + {-51, 26}, {-68, -84}, {-52, 27}, {29, 28}, {-20, 30}, {-4, -36}, + {-83, 31}, {-67, 32}, {-21, 33}, {-5, 34}, {-6, -82}}, + {{2, 1}, {4, 3}, {6, 5}, {-120, 7}, {-17, 8}, {-1, -104}, + {10, 9}, {12, 11}, {-18, 13}, {-33, -88}, {15, 14}, {17, 16}, + {-2, 18}, {-34, 19}, {-72, 20}, {-49, 21}, {-119, 22}, {-50, 23}, + {-103, 24}, {-56, 25}, {-65, 26}, {28, 27}, {-40, -87}, {-66, 29}, + {-82, 30}, {32, 31}, {-19, -81}, {-71, 33}, {-97, 34}, {-35, -55}, + {-24, 35}, {37, 36}, {-3, -98}, {-51, 38}, {-67, 39}, {-39, -118}, + {-113, 40}, {-102, 41}, {-86, 42}, {-70, -83}, {44, 43}, {-20, -54}, + {-52, 45}, {-36, 46}, {-4, 47}, {-68, 48}, {-85, 49}, {-101, -117}, + {-69, 50}, {52, 51}, {-21, -37}, {-53, 53}, {55, 54}, {-5, -100}, + {-116, 56}, {-84, 57}, {-38, 58}, {-22, -99}, {-115, 59}, {-6, 60}, + {-23, 61}, {-7, 62}, {-114, 0}}, + {{2, 1}, {4, 3}, {6, 5}, {-154, 7}, {9, 8}, + {-17, 10}, {-138, 11}, {-1, 12}, {14, 13}, {16, 15}, + {-33, -122}, {-18, 17}, {19, 18}, {-34, 20}, {-2, 21}, + {-106, 22}, {-49, 23}, {25, 24}, {-50, 26}, {-153, 27}, + {-90, 28}, {-137, 29}, {-65, 30}, {32, 31}, {-66, 33}, + {-121, 34}, {-74, 35}, {-81, 36}, {38, 37}, {-42, 39}, + {-82, 40}, {-105, 41}, {-19, -114}, {-58, 42}, {-35, 43}, + {-97, 44}, {46, 45}, {-129, 47}, {-26, -89}, {-57, -98}, + {-51, 48}, {-3, 49}, {-113, 50}, {-130, 51}, {-152, 52}, + {-67, -73}, {-99, -136}, {-145, 53}, {-120, 54}, {-41, 55}, + {-83, 56}, {-72, 57}, {-104, 58}, {-115, 59}, {-20, 60}, + {62, 61}, {-36, -88}, {-84, 63}, {-52, -56}, {65, 64}, + {-4, -87}, {-68, 66}, {-151, 67}, {-100, -135}, {69, 68}, + {-69, -119}, {-103, 70}, {-71, 71}, {73, 72}, {-21, 74}, + {-85, 75}, {-37, -53}, {-86, 76}, {78, 77}, {-102, -150}, + {-5, 79}, {-134, 80}, {-118, 81}, {-54, -117}, {83, 82}, + {-38, -70}, {-22, 84}, {-6, 85}, {87, 86}, {-55, 88}, + {-101, 89}, {-133, -149}, {-24, -39}, {91, 90}, {-132, 92}, + {-23, 93}, {-7, 94}, {-147, -148}, {-116, -131}, {-25, 95}, + {-40, 0}, {0, 0}, {0, 0}, {0, 0}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_1_0 = { + {{-1, 1}, + {-52, 2}, + {-17, 3}, + {5, 4}, + {-2, -36}, + {-18, 6}, + {8, 7}, + {-51, 9}, + {-33, 10}, + {-34, 11}, + {-20, -35}, + {-19, 12}, + {-3, 13}, + {-49, 14}, + {-4, -50}}, + {{2, 1}, {-86, 3}, {-1, 4}, {-17, 5}, {7, 6}, {-70, 8}, + {-2, -18}, {10, 9}, {12, 11}, {-85, 13}, {-33, 14}, {-34, -54}, + {16, 15}, {-69, 17}, {19, 18}, {-50, -53}, {-19, 20}, {-38, 21}, + {-35, -49}, {-3, 22}, {24, 23}, {-68, 25}, {-84, 26}, {-65, 27}, + {-51, -66}, {-22, -37}, {-52, 28}, {-20, 29}, {-36, 30}, {-81, 31}, + {-4, -83}, {-67, 32}, {-21, 33}, {-5, 34}, {-6, -82}}, + {{2, 1}, {-120, 3}, {-1, 4}, {6, 5}, {-17, 7}, {-104, 8}, + {-18, 9}, {-2, 10}, {12, 11}, {14, 13}, {-119, 15}, {-33, 16}, + {-34, -88}, {-103, 17}, {19, 18}, {21, 20}, {23, 22}, {25, 24}, + {-19, -72}, {-50, 26}, {-49, 27}, {-87, 28}, {30, 29}, {32, 31}, + {-3, -35}, {34, 33}, {-56, 35}, {-65, -66}, {-40, 36}, {-82, -118}, + {-71, 37}, {-55, 38}, {-67, -102}, {-51, 39}, {-70, 40}, {42, 41}, + {-81, 43}, {-86, 44}, {-52, -97}, {-98, 45}, {-24, -39}, {-20, 46}, + {-54, -83}, {-36, 47}, {-85, 48}, {-68, 49}, {-4, 50}, {-69, -113}, + {-117, 51}, {-37, -101}, {-53, 52}, {-21, 53}, {55, 54}, {-84, -100}, + {-5, 56}, {-116, 57}, {-22, 58}, {-38, -115}, {60, 59}, {-6, -99}, + {-23, 61}, {-114, 62}, {-7, -8}}, + {{2, 1}, {-154, 3}, {5, 4}, {-1, 6}, {8, 7}, + {-17, 9}, {-138, 10}, {-18, 11}, {-2, 12}, {14, 13}, + {16, 15}, {-153, 17}, {-34, 18}, {-33, -122}, {20, 19}, + {22, 21}, {-137, 23}, {25, 24}, {27, 26}, {-106, 28}, + {30, 29}, {-50, 31}, {-19, 32}, {-49, -121}, {34, 33}, + {36, 35}, {-35, 37}, {-90, 38}, {-66, 39}, {-3, 40}, + {42, 41}, {-65, 43}, {-105, 44}, {46, 45}, {-74, 47}, + {-51, 48}, {-82, -152}, {-136, 49}, {-81, 50}, {-42, -89}, + {-114, 51}, {53, 52}, {-57, -58}, {-120, 54}, {-98, 55}, + {-67, 56}, {-97, 57}, {59, 58}, {-99, 60}, {-73, -104}, + {-72, 61}, {-113, 62}, {-20, -83}, {-84, -130}, {-36, 63}, + {-26, 64}, {-41, 65}, {-52, -129}, {-87, -88}, {67, 66}, + {-115, 68}, {-68, 69}, {-56, -69}, {-4, -100}, {-151, 70}, + {-135, 71}, {-103, -119}, {73, 72}, {-71, -145}, {-102, 74}, + {76, 75}, {-53, -85}, {-37, 77}, {-21, -86}, {79, 78}, + {-5, 80}, {-54, -134}, {-150, 81}, {-118, 82}, {-70, 83}, + {-117, 84}, {-22, -38}, {-101, 85}, {-55, 86}, {-149, 87}, + {-39, 88}, {-133, 89}, {-6, 90}, {-116, 91}, {-24, 92}, + {-7, -132}, {-23, 93}, {-40, 94}, {-131, -148}, {-25, 95}, + {-147, 96}, {-146, 97}, {-8, 0}, {0, 0}}}; +static const HUFF_CLD_NOD_2D FDK_huffCLDNodes_h2_1_1 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {-2, 5}, + {-17, 6}, + {-18, 7}, + {-36, -51}, + {9, 8}, + {-35, 10}, + {-34, 11}, + {-19, -33}, + {-3, 12}, + {-20, 13}, + {-50, 14}, + {-4, -49}}, + {{2, 1}, {-86, 3}, {5, 4}, {-1, 6}, {8, 7}, {-17, -18}, + {-2, 9}, {-70, 10}, {-85, 11}, {13, 12}, {-69, 14}, {-34, 15}, + {17, 16}, {-19, 18}, {-33, -35}, {-54, 19}, {-53, 20}, {-3, 21}, + {-68, 22}, {-84, 23}, {-50, 24}, {-52, 25}, {-51, 26}, {-20, -36}, + {-49, 27}, {-38, 28}, {-37, 29}, {-4, -83}, {-67, 30}, {-66, 31}, + {-21, 32}, {-22, -65}, {-5, 33}, {-82, 34}, {-6, -81}}, + {{2, 1}, {4, 3}, {-120, 5}, {7, 6}, {9, 8}, {-1, 10}, + {-18, 11}, {-17, 12}, {-2, -104}, {-119, 13}, {15, 14}, {-103, 16}, + {18, 17}, {-34, 19}, {-19, 20}, {22, 21}, {-35, 23}, {-33, 24}, + {-88, 25}, {-87, 26}, {28, 27}, {-3, -102}, {-86, 29}, {-52, -118}, + {31, 30}, {-50, 32}, {-51, 33}, {-70, 34}, {-36, 35}, {-85, 36}, + {-20, 37}, {39, 38}, {-69, -71}, {-72, 40}, {-49, -67}, {42, 41}, + {-68, 43}, {-4, -101}, {-53, -117}, {-37, 44}, {-66, 45}, {-55, 46}, + {48, 47}, {-54, 49}, {-21, 50}, {-84, -100}, {-56, -65}, {52, 51}, + {-82, -83}, {54, 53}, {-5, -116}, {-22, 55}, {-38, 56}, {-39, -40}, + {58, 57}, {-81, -115}, {-98, -99}, {-6, 59}, {-23, 60}, {-24, 61}, + {-7, -97}, {-114, 62}, {-8, -113}}, + {{2, 1}, {4, 3}, {-154, 5}, {7, 6}, {9, 8}, + {11, 10}, {-1, 12}, {-18, 13}, {-17, 14}, {-2, -138}, + {16, 15}, {-153, 17}, {-137, 18}, {20, 19}, {22, 21}, + {-34, 23}, {-19, 24}, {-35, 25}, {27, 26}, {29, 28}, + {-121, 30}, {-120, 31}, {-136, 32}, {-33, -122}, {34, 33}, + {-152, 35}, {-3, 36}, {-51, 37}, {-52, 38}, {-69, 39}, + {-36, 40}, {-50, 41}, {43, 42}, {-20, 44}, {-104, 45}, + {-103, 46}, {-87, 47}, {-119, 48}, {-105, 49}, {-86, 50}, + {-102, 51}, {-106, 52}, {-49, -135}, {-68, 53}, {55, 54}, + {-53, 56}, {-67, -151}, {-4, 57}, {-84, 58}, {-85, 59}, + {-66, 60}, {-37, 61}, {-70, 62}, {-54, -88}, {-21, 63}, + {65, 64}, {-89, 66}, {-118, 67}, {-72, 68}, {-90, 69}, + {-71, 70}, {-65, -134}, {-150, 71}, {-83, 72}, {-5, 73}, + {-101, -117}, {-82, 74}, {76, 75}, {-99, 77}, {-38, 78}, + {-100, 79}, {-22, 80}, {-73, 81}, {-39, -74}, {83, 82}, + {-55, -81}, {-57, 84}, {-133, -149}, {-56, 85}, {-6, 86}, + {-98, 87}, {-132, 88}, {-23, 89}, {-114, 90}, {-116, 91}, + {-58, -115}, {-24, 92}, {-97, -148}, {-40, -41}, {-7, -42}, + {-147, 93}, {95, 94}, {-131, 96}, {-8, -130}, {-25, -113}, + {-9, 97}, {-26, -129}, {-146, 98}, {-10, -145}}}; + +const HUFF_CLD_NODES FDK_huffCLDNodes = { + {&FDK_huffCLDNodes_h1D_0, &FDK_huffCLDNodes_h1D_1, &FDK_huffCLDNodes_h1D_1}, + {{&FDK_huffCLDNodes_h2_0_0, &FDK_huffCLDNodes_h2_0_1}, + {&FDK_huffCLDNodes_h2_1_0, &FDK_huffCLDNodes_h2_1_1}, + {&FDK_huffCLDNodes_h2_0_1, &FDK_huffCLDNodes_h2_0_1}}}; + +const HUFF_RES_NODES FDK_huffReshapeNodes = { + {{2, 1}, {4, 3}, {6, 5}, {-33, 7}, {-17, 8}, {-49, 9}, + {-34, 10}, {12, 11}, {-18, -35}, {-50, 13}, {15, 14}, {-40, 16}, + {-36, 17}, {-19, 18}, {-1, -37}, {-51, 19}, {21, 20}, {-38, -65}, + {-2, -39}, {-20, 22}, {-52, 23}, {25, 24}, {-21, 26}, {-66, 27}, + {-53, 28}, {-3, 29}, {31, 30}, {-22, 32}, {-54, 33}, {-4, 34}, + {-56, 35}, {-24, -67}, {-23, -55}, {-8, -72}, {-5, 36}, {-68, 37}, + {-6, 38}, {-7, -69}, {-70, -71}}}; + +const HUFF_IPD_NODES FDK_huffIPDNodes = { + {{{{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-3, -7}, {-6, 6}, {-4, -5}}}, + {{{-1, 1}, {-2, 2}, {-8, 3}, {-3, 4}, {-7, 5}, {-4, 6}, {-5, -6}}}, + {{{-1, 1}, {-8, 2}, {-2, 3}, {5, 4}, {-3, -7}, {-6, 6}, {-4, -5}}}}, + {{{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}, + {{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {3, 2}, + {-18, 4}, + {-52, 5}, + {-34, -36}, + {-35, 6}, + {-17, 7}, + {-33, 8}, + {-20, 9}, + {-49, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {-52, 4}, {-86, 5}, {-35, 6}, {-53, 7}, + {-70, 8}, {-17, 9}, {-37, 10}, {12, 11}, {-38, -66}, {-18, 13}, + {-51, 14}, {16, 15}, {-34, -69}, {18, 17}, {-54, -65}, {-50, 19}, + {-33, -49}, {-22, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{-1, 1}, {-69, 2}, {4, 3}, {-120, 5}, {7, 6}, {-113, 8}, + {-68, 9}, {11, 10}, {-17, 12}, {-52, 13}, {-24, 14}, {-18, 15}, + {17, 16}, {-104, 18}, {20, 19}, {-54, -70}, {22, 21}, {24, 23}, + {-86, -97}, {-103, 25}, {-83, 26}, {-35, 27}, {-34, -98}, {-40, 28}, + {-39, -67}, {30, 29}, {-33, -51}, {-87, 31}, {-88, 32}, {-82, 33}, + {-55, -81}, {-56, -71}, {-72, 34}, {-50, -66}, {-65, 35}, {-49, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {3, 2}, + {-18, 4}, + {-52, 5}, + {-34, -36}, + {-35, 6}, + {-17, 7}, + {-33, 8}, + {-20, 9}, + {-49, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {-52, 4}, {-86, 5}, {-35, 6}, {-53, 7}, + {-70, 8}, {-17, 9}, {-37, 10}, {12, 11}, {-38, -66}, {-18, 13}, + {-51, 14}, {16, 15}, {-34, -69}, {18, 17}, {-54, -65}, {-50, 19}, + {-33, -49}, {-22, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{-1, 1}, {-69, 2}, {4, 3}, {-120, 5}, {7, 6}, {-113, 8}, + {-68, 9}, {11, 10}, {-17, 12}, {-52, 13}, {-24, 14}, {-18, 15}, + {17, 16}, {-104, 18}, {20, 19}, {-54, -70}, {22, 21}, {24, 23}, + {-86, -97}, {-103, 25}, {-83, 26}, {-35, 27}, {-34, -98}, {-40, 28}, + {-39, -67}, {30, 29}, {-33, -51}, {-87, 31}, {-88, 32}, {-82, 33}, + {-55, -81}, {-56, -71}, {-72, 34}, {-50, -66}, {-65, 35}, {-49, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}, + {{{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}, + {{{-1, 1}, {-18, 2}, {-17, 0}}, + {{-1, 1}, + {-36, 2}, + {-18, 3}, + {-35, 4}, + {-52, 5}, + {7, 6}, + {-34, 8}, + {-33, -49}, + {-20, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}, + {0, 0}}, + {{-1, 1}, {3, 2}, {5, 4}, {-86, 6}, {-66, 7}, {9, 8}, + {11, 10}, {-18, 12}, {-51, 13}, {-37, -52}, {-69, 14}, {-38, 15}, + {-53, 16}, {-35, 17}, {-50, -70}, {-22, -49}, {-33, 18}, {-17, 19}, + {-34, -65}, {-81, 20}, {-54, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, + {{2, 1}, {4, 3}, {-1, 5}, {-69, 6}, {-120, 7}, {-68, 8}, + {10, 9}, {12, 11}, {14, 13}, {-52, -54}, {-18, 15}, {-70, 16}, + {-67, 17}, {19, 18}, {-17, 20}, {-113, 21}, {23, 22}, {-83, 24}, + {-24, 25}, {-103, -104}, {-51, -55}, {27, 26}, {-71, 28}, {-86, 29}, + {-35, 30}, {-66, 31}, {-39, -50}, {-82, -98}, {-72, 32}, {-56, -87}, + {-34, 33}, {-33, -88}, {-40, -97}, {-65, 34}, {-49, 35}, {-81, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, + {0, 0}, {0, 0}, {0, 0}}}}}}; + +static const HUFF_OLD_NOD_1D huffOLDNodes_h1D_0 = {{{-1, 1}, + {3, 2}, + {-2, 4}, + {-3, 5}, + {-4, 6}, + {-5, 7}, + {-6, -8}, + {-7, 8}, + {10, 9}, + {12, 11}, + {-9, -11}, + {-10, 13}, + {-12, 14}, + {-13, -16}, + {-14, -15}}}; + +static const HUFF_OLD_NOD_1D huffOLDNodes_h1D_1 = {{{-1, 1}, + {-2, 2}, + {4, 3}, + {-3, 5}, + {-4, 6}, + {-5, 7}, + {-6, -8}, + {-7, 8}, + {10, 9}, + {12, 11}, + {-9, 13}, + {-16, 14}, + {-10, -15}, + {-11, -12}, + {-13, -14}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_0_0 = { + {{2, 1}, + {-1, 3}, + {5, 4}, + {-2, 6}, + {-3, -4}, + {-17, 7}, + {-18, 8}, + {-19, 9}, + {-20, 10}, + {-52, 11}, + {-33, 12}, + {-34, -35}, + {-36, 13}, + {-51, 14}, + {-49, -50}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {-103, 8}, {10, 9}, + {12, 11}, {-18, 13}, {15, 14}, {-2, 16}, {-86, 17}, {-35, 18}, + {20, 19}, {-102, 21}, {23, 22}, {-69, 24}, {-87, 25}, {-3, 26}, + {-17, 27}, {-19, 28}, {-52, 29}, {-34, -101}, {31, 30}, {-85, 32}, + {34, 33}, {-20, -70}, {-4, 35}, {-71, -100}, {-5, -33}, {-50, 36}, + {-36, -55}, {-54, -84}, {38, 37}, {-51, -53}, {-21, 39}, {-6, -99}, + {-37, -68}, {-83, 40}, {-7, -49}, {-22, -98}, {42, 41}, {44, 43}, + {-66, 45}, {-67, 46}, {-38, -39}, {-65, -82}, {-23, 47}, {-81, -97}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {15, 14}, {-154, 16}, {-103, 17}, + {19, 18}, {21, 20}, {-18, 22}, {24, 23}, {26, 25}, + {28, 27}, {-137, 29}, {31, 30}, {-2, -51}, {33, 32}, + {-35, 34}, {-26, 35}, {37, 36}, {-8, 38}, {-70, -153}, + {40, 39}, {-120, 41}, {-52, 42}, {44, 43}, {-3, -138}, + {46, 45}, {48, 47}, {-34, 49}, {-7, 50}, {-19, 51}, + {-17, 52}, {-152, 53}, {-4, -151}, {-33, 54}, {-106, 55}, + {-53, -122}, {-105, -136}, {-121, 56}, {-104, 57}, {-50, -118}, + {-20, 58}, {-5, 59}, {-38, 60}, {-133, 61}, {-148, 62}, + {-23, -135}, {-36, 63}, {-6, 64}, {66, 65}, {-21, -150}, + {68, 67}, {-49, 69}, {-134, 70}, {-119, 71}, {-37, 72}, + {-149, 73}, {-9, 74}, {-69, 75}, {-86, 76}, {-22, 77}, + {-68, 78}, {80, 79}, {82, 81}, {84, 83}, {-88, 85}, + {-132, 86}, {-90, 87}, {-10, -117}, {-67, 88}, {-71, 89}, + {-87, 90}, {-54, -66}, {-25, 91}, {-89, 92}, {-72, 93}, + {-131, 94}, {-113, -115}, {-99, 95}, {-73, -116}, {-24, -85}, + {-84, -102}, {-39, 96}, {-55, -98}, {-81, -97}, {-82, -83}, + {-114, 97}, {-146, -147}, {-42, -101}, {-57, -100}, {-65, -130}, + {-74, 98}, {-56, -58}, {-40, -129}, {-41, -145}}, + {{2, 1}, {4, 3}, {6, 5}, {8, 7}, {10, 9}, + {12, 11}, {-4, 13}, {-11, -28}, {-21, 14}, {-1, 15}, + {17, 16}, {19, 18}, {-38, 20}, {22, 21}, {24, 23}, + {26, 25}, {28, 27}, {-54, 29}, {31, 30}, {-44, 32}, + {-45, 33}, {-37, 34}, {-5, 35}, {-27, 36}, {38, 37}, + {40, 39}, {-53, 41}, {-12, 42}, {-22, 43}, {-20, 44}, + {-36, 45}, {-43, 46}, {-6, 47}, {-205, 48}, {-51, -52}, + {-35, 49}, {-34, 50}, {-13, 51}, {-42, 52}, {-29, 53}, + {-18, -41}, {55, 54}, {-17, -26}, {-19, 56}, {-7, 57}, + {-23, -188}, {59, 58}, {-10, 60}, {62, 61}, {-39, 63}, + {-33, 64}, {-2, 65}, {-204, 66}, {68, 67}, {-189, 69}, + {-171, 70}, {72, 71}, {74, 73}, {-203, 75}, {-3, -25}, + {-24, 76}, {78, 77}, {80, 79}, {82, 81}, {-173, 83}, + {-172, -187}, {85, 84}, {-86, 86}, {-50, 87}, {-202, 88}, + {90, 89}, {-154, 91}, {93, 92}, {-120, 94}, {96, 95}, + {-186, 97}, {99, 98}, {-69, 100}, {-156, -157}, {102, 101}, + {104, 103}, {-170, -201}, {-103, 105}, {107, 106}, {-155, 108}, + {-137, 109}, {-185, 110}, {-49, 111}, {-8, 112}, {-66, 113}, + {-67, 114}, {116, 115}, {-169, 117}, {-141, 118}, {120, 119}, + {122, 121}, {-200, 123}, {-68, -121}, {125, 124}, {-136, 126}, + {-140, 127}, {-71, 128}, {-139, 129}, {-151, -184}, {-82, 130}, + {-56, -101}, {132, 131}, {-9, -153}, {-40, 133}, {-138, 134}, + {-83, -199}, {-84, 135}, {-90, -168}, {-65, -91}, {-102, 136}, + {-135, -166}, {-72, -183}, {-87, -150}, {-181, 137}, {-125, 138}, + {-55, -70}, {-85, -152}, {-106, -124}, {-89, -123}, {-198, 139}, + {-57, 140}, {-105, 141}, {-167, -196}, {-81, -122}, {-182, 142}, + {-99, -180}, {-100, -104}, {-116, -165}, {-98, 143}, {-117, -119}, + {-88, -134}, {-197, 144}, {-73, -195}, {-92, -149}, {-118, -164}, + {-58, -108}, {-107, -179}, {-109, 145}, {-93, -97}, {-115, -194}, + {-114, 146}, {-113, 147}, {149, 148}, {151, 150}, {153, 152}, + {155, 154}, {157, 156}, {159, 158}, {161, 160}, {163, 162}, + {165, 164}, {167, 166}, {-178, -193}, {-163, -177}, {-161, -162}, + {-147, -148}, {-145, -146}, {-132, -133}, {-130, -131}, {-77, -129}, + {-75, -76}, {-61, -74}, {-59, -60}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_0_1 = { + {{-1, 1}, + {3, 2}, + {5, 4}, + {-52, 6}, + {-49, 7}, + {9, 8}, + {-17, 10}, + {-36, 11}, + {-18, 12}, + {-2, -3}, + {-35, 13}, + {-34, -50}, + {-4, -33}, + {-20, 14}, + {-19, -51}}, + {{-1, 1}, {3, 2}, {-103, 4}, {6, 5}, {8, 7}, {-18, 9}, + {11, 10}, {-87, 12}, {-17, 13}, {15, 14}, {-86, 16}, {18, 17}, + {-71, 19}, {21, 20}, {-33, -35}, {-34, 22}, {-55, 23}, {-2, 24}, + {-50, -102}, {26, 25}, {-49, 27}, {-69, -70}, {-39, 28}, {-65, 29}, + {-66, 30}, {-54, 31}, {-19, 32}, {-23, -52}, {-51, 33}, {-81, 34}, + {-82, 35}, {-3, -38}, {-85, -101}, {-67, -97}, {37, 36}, {-20, -53}, + {-36, 38}, {40, 39}, {-100, 41}, {-4, -84}, {-68, 42}, {-21, 43}, + {-37, 44}, {-99, 45}, {-5, -83}, {-22, 46}, {-98, 47}, {-6, -7}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {12, 11}, {14, 13}, {-18, 15}, {17, 16}, + {19, 18}, {21, 20}, {-17, 22}, {-137, 23}, {-35, 24}, + {-138, 25}, {27, 26}, {-113, 28}, {-34, 29}, {31, 30}, + {33, 32}, {-122, 34}, {-33, 35}, {-73, 36}, {38, 37}, + {40, 39}, {-106, 41}, {-52, 42}, {-58, -120}, {-50, 43}, + {45, 44}, {-49, 46}, {-10, -103}, {-36, 47}, {-54, -90}, + {-53, 48}, {-2, 49}, {-98, -153}, {-121, 50}, {-66, 51}, + {-65, -72}, {-51, 52}, {-74, 53}, {-9, 54}, {-105, 55}, + {-71, -82}, {-19, -55}, {-81, 56}, {58, 57}, {-83, 59}, + {-68, -88}, {-89, -97}, {-70, 60}, {-3, 61}, {-67, 62}, + {64, 63}, {-69, 65}, {-104, 66}, {-136, -152}, {68, 67}, + {-8, -26}, {-37, 69}, {-4, 70}, {72, 71}, {-22, 73}, + {-42, 74}, {-7, -20}, {76, 75}, {78, 77}, {-6, 79}, + {-114, 80}, {-25, -135}, {-119, -151}, {-24, 81}, {-57, 82}, + {-5, 83}, {-99, 84}, {-23, -130}, {-129, 85}, {-118, 86}, + {-21, -41}, {-86, 87}, {-115, -145}, {-84, 88}, {-87, -150}, + {-38, -56}, {-134, 89}, {-100, 90}, {-85, -133}, {-149, 91}, + {-102, 92}, {-117, -148}, {94, 93}, {-39, 95}, {-101, 96}, + {-116, 97}, {-131, -132}, {-40, 98}, {-146, -147}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {-205, 10}, {12, 11}, {14, 13}, {16, 15}, {-18, 17}, + {19, 18}, {21, 20}, {23, 22}, {-189, 24}, {-188, 25}, + {27, 26}, {-17, 28}, {-173, 29}, {31, 30}, {33, 32}, + {-34, -157}, {-35, 34}, {-33, 35}, {37, 36}, {39, 38}, + {41, 40}, {-50, 42}, {-49, 43}, {-141, 44}, {-204, 45}, + {-2, -171}, {-172, 46}, {-66, 47}, {49, 48}, {51, 50}, + {-65, 52}, {-125, 53}, {-156, 54}, {-82, 55}, {57, 56}, + {59, 58}, {-19, -52}, {61, 60}, {-81, 62}, {64, 63}, + {-109, -140}, {-51, 65}, {67, 66}, {-98, 68}, {70, 69}, + {72, 71}, {-67, -93}, {74, 73}, {-203, 75}, {-154, 76}, + {-124, 77}, {-97, -187}, {-114, 78}, {-61, 79}, {-155, 80}, + {82, 81}, {-113, 83}, {-3, -146}, {-83, 84}, {-108, 85}, + {-20, 86}, {-76, 87}, {-45, -77}, {-139, 88}, {90, 89}, + {-69, -130}, {-129, 91}, {-36, 92}, {-99, -161}, {94, 93}, + {-92, -162}, {-68, 95}, {-29, 96}, {-86, 97}, {-60, 98}, + {-123, -177}, {-145, 99}, {-91, -131}, {101, 100}, {-137, -178}, + {-115, 102}, {-84, -116}, {-147, 103}, {-4, 104}, {-106, -202}, + {106, 105}, {-132, -186}, {-107, 107}, {-193, 108}, {-100, -120}, + {-75, -170}, {-44, 109}, {-122, -163}, {-138, 110}, {-90, 111}, + {-37, 112}, {-101, 113}, {-121, 114}, {116, 115}, {-103, 117}, + {-74, -201}, {-21, -85}, {-53, -59}, {-117, 118}, {-148, 119}, + {-5, 120}, {-169, 121}, {-105, -185}, {123, 122}, {-102, -133}, + {-136, 124}, {-153, 125}, {127, 126}, {-54, 128}, {130, 129}, + {-22, -104}, {-38, 131}, {-89, -118}, {-184, 132}, {-71, 133}, + {-87, 134}, {-70, 135}, {-200, 136}, {-168, 137}, {-152, 138}, + {-6, -23}, {-39, 139}, {-119, -199}, {141, 140}, {-55, 142}, + {-7, -151}, {-183, 143}, {145, 144}, {-135, 146}, {-56, 147}, + {-150, 148}, {-40, 149}, {-72, -198}, {-88, 150}, {-57, -134}, + {-41, 151}, {-166, -167}, {-25, -165}, {-9, 152}, {-8, -24}, + {-73, -181}, {-182, 153}, {155, 154}, {-197, 156}, {-42, -180}, + {158, 157}, {-43, -149}, {-196, 159}, {-58, -164}, {-26, 160}, + {162, 161}, {164, 163}, {166, 165}, {-195, 167}, {-179, -194}, + {-27, -28}, {-12, -13}, {-10, -11}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_1_0 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {-18, 5}, + {7, 6}, + {-17, 8}, + {-36, 9}, + {-35, 10}, + {-2, 11}, + {-19, 12}, + {-33, -51}, + {-20, -34}, + {14, 13}, + {-3, -49}, + {-4, -50}}, + {{-1, 1}, {3, 2}, {5, 4}, {-103, 6}, {8, 7}, {-18, 9}, + {11, 10}, {13, 12}, {-86, 14}, {-87, 15}, {17, 16}, {-35, 18}, + {-17, 19}, {21, 20}, {-34, -71}, {23, 22}, {-50, -55}, {-33, 24}, + {-69, 25}, {-2, -70}, {27, 26}, {-102, 28}, {-49, 29}, {-66, 30}, + {-39, -54}, {-52, 31}, {-51, 32}, {-65, 33}, {-19, 34}, {-38, -82}, + {-23, -85}, {-67, 35}, {-81, 36}, {-3, 37}, {-53, -101}, {-20, -97}, + {39, 38}, {-36, 40}, {-84, 41}, {-100, 42}, {-4, -68}, {-21, 43}, + {-37, 44}, {-83, 45}, {-5, -99}, {-22, 46}, {-98, 47}, {-6, -7}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {12, 11}, {14, 13}, {-18, 15}, {17, 16}, + {-113, 18}, {20, 19}, {-137, 21}, {23, 22}, {25, 24}, + {27, 26}, {-35, 28}, {-138, 29}, {-58, 30}, {-103, 31}, + {-98, 32}, {34, 33}, {-122, 35}, {-120, 36}, {-17, -73}, + {-34, 37}, {-106, 38}, {-50, 39}, {-83, -90}, {-74, 40}, + {-52, 41}, {-66, -121}, {-33, -88}, {43, 42}, {-82, -105}, + {-49, 44}, {-68, -153}, {-2, -89}, {-51, -65}, {-67, 45}, + {-81, -97}, {47, 46}, {-104, 48}, {-19, 49}, {51, 50}, + {53, 52}, {55, 54}, {-136, 56}, {-152, 57}, {-3, 58}, + {60, 59}, {62, 61}, {64, 63}, {-36, 65}, {-20, 66}, + {-53, 67}, {-114, 68}, {-57, -99}, {-72, 69}, {-69, 70}, + {-42, 71}, {-151, 72}, {-119, 73}, {-84, -118}, {-135, 74}, + {-4, -130}, {-115, 75}, {-26, -41}, {-87, 76}, {-56, -86}, + {-100, 77}, {-37, -129}, {-21, 78}, {-38, 79}, {-71, -145}, + {-134, 80}, {-85, 81}, {-150, 82}, {-5, 83}, {-133, 84}, + {-102, 85}, {-22, 86}, {-23, 87}, {-54, 88}, {-149, 89}, + {-117, -148}, {-70, 90}, {-6, -101}, {92, 91}, {-8, -55}, + {-7, 93}, {-132, 94}, {-39, -116}, {-24, 95}, {-147, 96}, + {-40, 97}, {-10, -131}, {-146, 98}, {-9, -25}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {-205, 14}, {16, 15}, {18, 17}, + {20, 19}, {-18, 21}, {23, 22}, {25, 24}, {27, 26}, + {29, 28}, {-188, 30}, {32, 31}, {34, 33}, {36, 35}, + {-189, 37}, {39, 38}, {-35, 40}, {42, 41}, {44, 43}, + {46, 45}, {-173, 47}, {49, 48}, {-34, 50}, {-17, 51}, + {53, 52}, {-157, 54}, {56, 55}, {58, 57}, {-171, 59}, + {-50, 60}, {62, 61}, {-66, -141}, {-172, 63}, {-125, 64}, + {66, 65}, {-33, 67}, {-52, 68}, {-204, 69}, {-82, 70}, + {-156, 71}, {-2, 72}, {74, 73}, {-109, 75}, {-51, -98}, + {77, 76}, {-49, -140}, {79, 78}, {-146, 80}, {-124, 81}, + {-61, -93}, {-19, -76}, {-81, -154}, {-65, -114}, {83, 82}, + {-83, -108}, {-67, 84}, {-77, 85}, {-130, 86}, {-99, -155}, + {88, 87}, {-97, 89}, {-69, -91}, {-92, 90}, {-131, 91}, + {93, 92}, {-116, -187}, {-123, 94}, {-60, 95}, {-86, -139}, + {97, 96}, {-68, -162}, {99, 98}, {-45, -113}, {-147, -203}, + {-115, 100}, {-75, 101}, {-84, -106}, {-129, 102}, {-3, 103}, + {-137, 104}, {-132, 105}, {-44, -120}, {-107, 106}, {-20, -100}, + {-36, 107}, {-90, -163}, {-161, 108}, {-59, -145}, {-101, 109}, + {-29, -138}, {-121, 110}, {-177, -178}, {-186, 111}, {-122, -148}, + {-117, 112}, {-85, -170}, {-202, 113}, {-4, 114}, {-37, -105}, + {-74, 115}, {-133, 116}, {-102, 117}, {119, 118}, {-89, -193}, + {-103, 120}, {-21, -53}, {-153, 121}, {123, 122}, {125, 124}, + {-185, 126}, {-104, -169}, {-201, 127}, {-136, 128}, {-118, 129}, + {-87, 130}, {-5, 131}, {-38, 132}, {-54, 133}, {-70, -184}, + {-71, -168}, {-22, 134}, {136, 135}, {-151, -152}, {-55, 137}, + {-6, 138}, {-39, -72}, {-200, 139}, {-167, 140}, {142, 141}, + {-119, -166}, {-88, 143}, {-23, -135}, {-199, 144}, {-165, 145}, + {-56, -150}, {-57, -183}, {-7, 146}, {-41, 147}, {-181, 148}, + {-134, 149}, {-24, -25}, {-40, 150}, {-73, 151}, {-9, 152}, + {-43, 153}, {-182, -197}, {-8, -195}, {-198, 154}, {-149, 155}, + {157, 156}, {159, 158}, {161, 160}, {163, 162}, {165, 164}, + {167, 166}, {-194, -196}, {-179, -180}, {-58, -164}, {-28, -42}, + {-26, -27}, {-12, -13}, {-10, -11}}}; + +static const HUFF_OLD_NOD_2D huffOLDNodes_h2D_1_1 = { + {{-1, 1}, + {-52, 2}, + {4, 3}, + {6, 5}, + {-18, 7}, + {-2, 8}, + {-17, 9}, + {-35, 10}, + {-36, -51}, + {-34, 11}, + {-33, 12}, + {-19, 13}, + {-3, -20}, + {-50, 14}, + {-4, -49}}, + {{-1, 1}, {3, 2}, {5, 4}, {-103, 6}, {8, 7}, {-18, 9}, + {11, 10}, {13, 12}, {-86, 14}, {16, 15}, {-2, -35}, {-17, 17}, + {-87, 18}, {-102, 19}, {21, 20}, {-69, 22}, {-34, 23}, {-19, 24}, + {26, 25}, {-3, 27}, {-52, -70}, {-33, -71}, {-85, 28}, {-101, 29}, + {31, 30}, {-50, 32}, {-51, 33}, {-20, 34}, {-36, 35}, {-4, -55}, + {-54, 36}, {-49, -100}, {-53, 37}, {-84, 38}, {-68, 39}, {41, 40}, + {-5, 42}, {-21, 43}, {-65, -66}, {-67, 44}, {-37, -99}, {-39, 45}, + {-6, 46}, {-38, -83}, {-22, 47}, {-81, -82}, {-7, -98}, {-23, -97}}, + {{-1, 1}, {3, 2}, {5, 4}, {7, 6}, {9, 8}, + {-154, 10}, {-103, 11}, {13, 12}, {-18, 14}, {16, 15}, + {-137, 17}, {19, 18}, {-35, 20}, {22, 21}, {-120, 23}, + {25, 24}, {-52, 26}, {-2, 27}, {-138, 28}, {-153, 29}, + {-17, 30}, {32, 31}, {34, 33}, {-34, 35}, {-19, 36}, + {38, 37}, {40, 39}, {-3, 41}, {-121, 42}, {-122, 43}, + {-136, -152}, {-33, 44}, {-104, 45}, {-105, 46}, {-51, -106}, + {-50, 47}, {-36, 48}, {-20, 49}, {-53, -119}, {-4, 50}, + {-135, -151}, {-68, 51}, {53, 52}, {-49, 54}, {56, 55}, + {-118, 57}, {-88, 58}, {60, 59}, {-5, -8}, {-38, 61}, + {63, 62}, {-21, 64}, {-37, -83}, {-67, 65}, {-66, -133}, + {-6, 66}, {-150, 67}, {-134, 68}, {-23, -65}, {-73, -90}, + {-69, -89}, {-148, 69}, {-7, -22}, {-98, -113}, {71, 70}, + {-82, 72}, {-86, -149}, {-58, -81}, {-74, 73}, {75, 74}, + {77, 76}, {-87, -97}, {-102, 78}, {80, 79}, {-84, 81}, + {-85, 82}, {-54, 83}, {-70, 84}, {-72, 85}, {-117, 86}, + {-71, 87}, {-99, 88}, {-101, 89}, {-39, -100}, {-55, 90}, + {-57, 91}, {-132, 92}, {-56, 93}, {-24, -114}, {-115, 94}, + {-40, -116}, {-42, -147}, {-9, -41}, {-131, 95}, {97, 96}, + {-129, 98}, {-25, -130}, {-26, -146}, {-10, -145}}, + {{2, 1}, {-1, 3}, {5, 4}, {7, 6}, {9, 8}, + {11, 10}, {13, 12}, {-205, 14}, {16, 15}, {18, 17}, + {-18, 19}, {21, 20}, {23, 22}, {-188, 24}, {26, 25}, + {28, 27}, {30, 29}, {-35, 31}, {33, 32}, {35, 34}, + {-171, 36}, {-189, 37}, {-204, 38}, {40, 39}, {-2, 41}, + {43, 42}, {-17, 44}, {-52, 45}, {-34, 46}, {-19, 47}, + {49, 48}, {-154, 50}, {52, 51}, {54, 53}, {-172, 55}, + {-173, 56}, {-69, -187}, {-203, 57}, {59, 58}, {-86, 60}, + {-3, 61}, {63, 62}, {-33, -50}, {-51, 64}, {-36, 65}, + {-137, 66}, {-20, 67}, {69, 68}, {-120, 70}, {72, 71}, + {-156, -157}, {-155, 73}, {-170, 74}, {76, 75}, {-186, -202}, + {78, 77}, {80, 79}, {82, 81}, {-4, -67}, {-49, -103}, + {-66, 83}, {-68, 84}, {-53, 85}, {-21, 86}, {-37, 87}, + {89, 88}, {91, 90}, {93, 92}, {-138, 94}, {-140, 95}, + {-141, -153}, {-139, 96}, {-201, 97}, {-185, 98}, {-121, 99}, + {-169, 100}, {-5, 101}, {-136, 102}, {-65, -84}, {-83, -85}, + {-82, 103}, {-70, 104}, {-54, 105}, {-38, 106}, {108, 107}, + {-101, 109}, {-22, -102}, {-122, -123}, {111, 110}, {113, 112}, + {-125, 114}, {-87, -124}, {-71, 115}, {-168, 116}, {-6, -200}, + {-184, 117}, {-152, 118}, {-81, 119}, {121, 120}, {-105, 122}, + {-106, 123}, {-99, 124}, {-98, -100}, {-23, 125}, {-104, 126}, + {-39, 127}, {-135, 128}, {-55, -151}, {130, 129}, {-91, -119}, + {-7, -199}, {-183, 131}, {-107, -108}, {-116, 132}, {-109, -117}, + {-56, -167}, {-97, 133}, {-90, 134}, {-72, 135}, {-115, -118}, + {-92, 136}, {-93, -166}, {-24, -114}, {-89, 137}, {-88, -150}, + {139, 138}, {-8, 140}, {-40, 141}, {-198, 142}, {-134, 143}, + {-113, 144}, {-182, 145}, {147, 146}, {-41, 148}, {-57, -181}, + {-131, 149}, {151, 150}, {-25, 152}, {-132, 153}, {155, 154}, + {-9, -76}, {-42, -165}, {-73, -133}, {-77, 156}, {-130, 157}, + {-75, -149}, {-10, -146}, {-26, 158}, {-197, 159}, {-180, 160}, + {-147, -196}, {-58, -74}, {-27, 161}, {-129, -148}, {-11, -61}, + {-60, 162}, {-59, 163}, {-43, -145}, {-12, -164}, {-161, 164}, + {-163, 165}, {-162, -195}, {-179, 166}, {-177, 167}, {-28, -178}, + {-45, -194}, {-29, -44}, {-13, -193}}}; + +const HUFF_OLD_NODES huffOLDNodes = { + {&huffOLDNodes_h1D_0, &huffOLDNodes_h1D_1, &huffOLDNodes_h1D_1}, + {{&huffOLDNodes_h2D_0_0, &huffOLDNodes_h2D_0_1}, + {&huffOLDNodes_h2D_1_0, &huffOLDNodes_h2D_1_1}, + {&huffOLDNodes_h2D_0_1, &huffOLDNodes_h2D_0_1}}}; diff --git a/fdk-aac/libFDK/src/mdct.cpp b/fdk-aac/libFDK/src/mdct.cpp new file mode 100644 index 0000000..f5aa284 --- /dev/null +++ b/fdk-aac/libFDK/src/mdct.cpp @@ -0,0 +1,730 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Josef Hoepfl, Manuel Jander, Youliy Ninov, Daniel Hagel + + Description: MDCT/MDST routines + +*******************************************************************************/ + +#include "mdct.h" + +#include "FDK_tools_rom.h" +#include "dct.h" +#include "fixpoint_math.h" + +void mdct_init(H_MDCT hMdct, FIXP_DBL *overlap, INT overlapBufferSize) { + hMdct->overlap.freq = overlap; + // FDKmemclear(overlap, overlapBufferSize*sizeof(FIXP_DBL)); + hMdct->prev_fr = 0; + hMdct->prev_nr = 0; + hMdct->prev_tl = 0; + hMdct->ov_size = overlapBufferSize; + hMdct->prevAliasSymmetry = 0; + hMdct->prevPrevAliasSymmetry = 0; + hMdct->pFacZir = NULL; + hMdct->pAsymOvlp = NULL; +} + +/* +This program implements the forward MDCT transform on an input block of data. +The input block is in a form (A,B,C,D) where A,B,C and D are the respective +1/4th segments of the block. The program takes the input block and folds it in +the form: +(-D-Cr,A-Br). This block is twice shorter and here the 'r' suffix denotes +flipping of the sequence (reversing the order of the samples). While folding the +input block in the above mentioned shorter block the program windows the data. +Because the two operations (windowing and folding) are not implemented +sequentially, but together the program's structure is not easy to understand. +Once the output (already windowed) block (-D-Cr,A-Br) is ready it is passed to +the DCT IV for processing. +*/ +INT mdct_block(H_MDCT hMdct, const INT_PCM *RESTRICT timeData, + const INT noInSamples, FIXP_DBL *RESTRICT mdctData, + const INT nSpec, const INT tl, const FIXP_WTP *pRightWindowPart, + const INT fr, SHORT *pMdctData_e) { + int i, n; + /* tl: transform length + fl: left window slope length + nl: left window slope offset + fr: right window slope length + nr: right window slope offset + See FDK_tools/doc/intern/mdct.tex for more detail. */ + int fl, nl, nr; + const FIXP_WTP *wls, *wrs; + + wrs = pRightWindowPart; + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr == + 0) { /* At start just initialize and pass parameters as they are */ + hMdct->prev_fr = fr; + hMdct->prev_wrs = wrs; + hMdct->prev_tl = tl; + } + + /* Derive NR */ + nr = (tl - fr) >> 1; + + /* Skip input samples if tl is smaller than block size */ + timeData += (noInSamples - tl) >> 1; + + /* windowing */ + for (n = 0; n < nSpec; n++) { + /* + * MDCT scale: + * + 1: fMultDiv2() in windowing. + * + 1: Because of factor 1/2 in Princen-Bradley compliant windowed TDAC. + */ + INT mdctData_e = 1 + 1; + + /* Derive left parameters */ + wls = hMdct->prev_wrs; + fl = hMdct->prev_fr; + nl = (tl - fl) >> 1; + + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of A and B + segments to (A-Br) but A is zero, because in this part of the MDCT sequence + the window coefficients with which A must be multiplied are zero. */ + for (i = 0; i < nl; i++) { +#if SAMPLE_BITS == DFRACT_BITS /* SPC_BITS and DFRACT_BITS should be equal. */ + mdctData[(tl / 2) + i] = -((FIXP_DBL)timeData[tl - i - 1] >> (1)); +#else + mdctData[(tl / 2) + i] = -(FIXP_DBL)timeData[tl - i - 1] + << (DFRACT_BITS - SAMPLE_BITS - 1); /* 0(A)-Br */ +#endif + } + + /* Implements the folding and windowing of the left part of the sequence, + that is segments A and B. The A segment is multiplied by the respective left + window coefficient and placed in a temporary variable. + + tmp0 = fMultDiv2((FIXP_PCM)timeData[i+nl], pLeftWindowPart[i].v.im); + + After this the B segment taken in reverse order is multiplied by the left + window and subtracted from the previously derived temporary variable, so + that finally we implement the A-Br operation. This output is written to the + right part of the MDCT output : (-D-Cr,A-Br). + + mdctData[(tl/2)+i+nl] = fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl-nl-i-1], + pLeftWindowPart[i].v.re);//A*window-Br*window + + The (A-Br) data is written to the output buffer (mdctData) without being + flipped. */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL tmp0; + tmp0 = fMultDiv2((FIXP_PCM)timeData[i + nl], wls[i].v.im); /* a*window */ + mdctData[(tl / 2) + i + nl] = + fMultSubDiv2(tmp0, (FIXP_PCM)timeData[tl - nl - i - 1], + wls[i].v.re); /* A*window-Br*window */ + } + + /* Right window slope offset */ + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of C and D + segments to (-D-Cr) but D is zero, because in this part of the MDCT sequence + the window coefficients with which D must be multiplied are zero. */ + for (i = 0; i < nr; i++) { +#if SAMPLE_BITS == \ + DFRACT_BITS /* This should be SPC_BITS instead of DFRACT_BITS. */ + mdctData[(tl / 2) - 1 - i] = -((FIXP_DBL)timeData[tl + i] >> (1)); +#else + mdctData[(tl / 2) - 1 - i] = + -(FIXP_DBL)timeData[tl + i] + << (DFRACT_BITS - SAMPLE_BITS - 1); /* -C flipped at placing */ +#endif + } + + /* Implements the folding and windowing of the right part of the sequence, + that is, segments C and D. The C segment is multiplied by the respective + right window coefficient and placed in a temporary variable. + + tmp1 = fMultDiv2((FIXP_PCM)timeData[tl+nr+i], pRightWindowPart[i].v.re); + + After this the D segment taken in reverse order is multiplied by the right + window and added from the previously derived temporary variable, so that we + get (C+Dr) operation. This output is negated to get (-C-Dr) and written to + the left part of the MDCT output while being reversed (flipped) at the same + time, so that from (-C-Dr) we get (-D-Cr)=> (-D-Cr,A-Br). + + mdctData[(tl/2)-nr-i-1] = -fMultAddDiv2(tmp1, + (FIXP_PCM)timeData[(tl*2)-nr-i-1], pRightWindowPart[i].v.im);*/ + for (i = 0; i < fr / 2; i++) { + FIXP_DBL tmp1; + tmp1 = fMultDiv2((FIXP_PCM)timeData[tl + nr + i], + wrs[i].v.re); /* C*window */ + mdctData[(tl / 2) - nr - i - 1] = + -fMultAddDiv2(tmp1, (FIXP_PCM)timeData[(tl * 2) - nr - i - 1], + wrs[i].v.im); /* -(C*window+Dr*window) and flip before + placing -> -Cr - D */ + } + + /* We pass the shortened folded data (-D-Cr,A-Br) to the MDCT function */ + dct_IV(mdctData, tl, &mdctData_e); + + pMdctData_e[n] = (SHORT)mdctData_e; + + timeData += tl; + mdctData += tl; + + hMdct->prev_wrs = wrs; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + } + + return nSpec * tl; +} + +void imdct_gain(FIXP_DBL *pGain_m, int *pGain_e, int tl) { + FIXP_DBL gain_m = *pGain_m; + int gain_e = *pGain_e; + int log2_tl; + + gain_e += -MDCT_OUTPUT_GAIN - MDCT_OUT_HEADROOM + 1; + if (tl == 0) { + /* Dont regard the 2/N factor from the IDCT. It is compensated for somewhere + * else. */ + *pGain_e = gain_e; + return; + } + + log2_tl = DFRACT_BITS - 1 - fNormz((FIXP_DBL)tl); + gain_e += -log2_tl; + + FDK_ASSERT(log2_tl - 2 >= 0); + FDK_ASSERT(log2_tl - 2 < 8*sizeof(int)); + + /* Detect non-radix 2 transform length and add amplitude compensation factor + which cannot be included into the exponent above */ + switch ((tl) >> (log2_tl - 2)) { + case 0x7: /* 10 ms, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * + 0.53333333333333333333) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(0.53333333333333333333f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); + } + break; + case 0x6: /* 3/4 of radix 2, 1/tl = 1.0/(FDKpow(2.0, -log2_tl) * 2.0/3.0) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(2.0 / 3.0f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(2.0 / 3.0f)); + } + break; + case 0x5: /* 0.8 of radix 2 (e.g. tl 160), 1/tl = 1.0/(FDKpow(2.0, -log2_tl) + * 0.8/1.5) */ + if (gain_m == (FIXP_DBL)0) { + gain_m = FL2FXCONST_DBL(0.53333333333333333333f); + } else { + gain_m = fMult(gain_m, FL2FXCONST_DBL(0.53333333333333333333f)); + } + break; + case 0x4: + /* radix 2, nothing to do. */ + break; + default: + /* unsupported */ + FDK_ASSERT(0); + break; + } + + *pGain_m = gain_m; + *pGain_e = gain_e; +} + +INT imdct_drain(H_MDCT hMdct, FIXP_DBL *output, INT nrSamplesRoom) { + int buffered_samples = 0; + + if (nrSamplesRoom > 0) { + buffered_samples = hMdct->ov_offset; + + FDK_ASSERT(buffered_samples <= nrSamplesRoom); + + if (buffered_samples > 0) { + FDKmemcpy(output, hMdct->overlap.time, + buffered_samples * sizeof(FIXP_DBL)); + hMdct->ov_offset = 0; + } + } + return buffered_samples; +} + +INT imdct_copy_ov_and_nr(H_MDCT hMdct, FIXP_DBL *pTimeData, INT nrSamples) { + FIXP_DBL *pOvl; + int nt, nf, i; + + nt = fMin(hMdct->ov_offset, nrSamples); + nrSamples -= nt; + nf = fMin(hMdct->prev_nr, nrSamples); + FDKmemcpy(pTimeData, hMdct->overlap.time, nt * sizeof(FIXP_DBL)); + pTimeData += nt; + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < nf; i++) { + FIXP_DBL x = -(*pOvl--); + *pTimeData = IMDCT_SCALE_DBL(x); + pTimeData++; + } + } else { + for (i = 0; i < nf; i++) { + FIXP_DBL x = (*pOvl--); + *pTimeData = IMDCT_SCALE_DBL(x); + pTimeData++; + } + } + + return (nt + nf); +} + +void imdct_adapt_parameters(H_MDCT hMdct, int *pfl, int *pnl, int tl, + const FIXP_WTP *wls, int noOutSamples) { + int fl = *pfl, nl = *pnl; + int window_diff, use_current = 0, use_previous = 0; + if (hMdct->prev_tl == 0) { + hMdct->prev_wrs = wls; + hMdct->prev_fr = fl; + hMdct->prev_nr = (noOutSamples - fl) >> 1; + hMdct->prev_tl = noOutSamples; + hMdct->ov_offset = 0; + use_current = 1; + } + + window_diff = (hMdct->prev_fr - fl) >> 1; + + /* check if the previous window slope can be adjusted to match the current + * window slope */ + if (hMdct->prev_nr + window_diff > 0) { + use_current = 1; + } + /* check if the current window slope can be adjusted to match the previous + * window slope */ + if (nl - window_diff > 0) { + use_previous = 1; + } + + /* if both is possible choose the larger of both window slope lengths */ + if (use_current && use_previous) { + if (fl < hMdct->prev_fr) { + use_current = 0; + } + } + /* + * If the previous transform block is big enough, enlarge previous window + * overlap, if not, then shrink current window overlap. + */ + if (use_current) { + hMdct->prev_nr += window_diff; + hMdct->prev_fr = fl; + hMdct->prev_wrs = wls; + } else { + nl -= window_diff; + fl = hMdct->prev_fr; + } + + *pfl = fl; + *pnl = nl; +} + +/* +This program implements the inverse modulated lapped transform, a generalized +version of the inverse MDCT transform. Setting none of the MLT_*_ALIAS_FLAG +flags computes the IMDCT, setting all of them computes the IMDST. Other +combinations of these flags compute type III transforms used by the RSVD60 +multichannel tool for transitions between MDCT/MDST. The following description +relates to the IMDCT only. + +If we pass the data block (A,B,C,D,E,F) to the FORWARD MDCT it will produce two +outputs. The first one will be over the (A,B,C,D) part =>(-D-Cr,A-Br) and the +second one will be over the (C,D,E,F) part => (-F-Er,C-Dr), since there is a +overlap between consequtive passes of the algorithm. This overlap is over the +(C,D) segments. The two outputs will be given sequentially to the DCT IV +algorithm. At the INVERSE MDCT side we get two consecutive outputs from the IDCT +IV algorithm, namely the same blocks: (-D-Cr,A-Br) and (-F-Er,C-Dr). The first +of them lands in the Overlap buffer and the second is in the working one, which, +one algorithm pass later will substitute the one residing in the overlap +register. The IMDCT algorithm has to produce the C and D segments from the two +buffers. In order to do this we take the left part of the overlap +buffer(-D-Cr,A-Br), namely (-D-Cr) and add it appropriately to the right part of +the working buffer (-F-Er,C-Dr), namely (C-Dr), so that we get first the C +segment and later the D segment. We do this in the following way: From the right +part of the working buffer(C-Dr) we subtract the flipped left part of the +overlap buffer(-D-Cr): + +Result = (C-Dr) - flipped(-D-Cr) = C -Dr + Dr + C = 2C +We divide by two and get the C segment. What we did is adding the right part of +the first frame to the left part of the second one. While applying these +operation we multiply the respective segments with the appropriate window +functions. + +In order to get the D segment we do the following: +From the negated second part of the working buffer(C-Dr) we subtract the flipped +first part of the overlap buffer (-D-Cr): + +Result= - (C -Dr) - flipped(-D-Cr)= -C +Dr +Dr +C = 2Dr. +After dividing by two and flipping we get the D segment.What we did is adding +the right part of the first frame to the left part of the second one. While +applying these operation we multiply the respective segments with the +appropriate window functions. + +Once we have obtained the C and D segments the overlap buffer is emptied and the +current buffer is sent in it, so that the E and F segments are available for +decoding in the next algorithm pass.*/ +INT imlt_block(H_MDCT hMdct, FIXP_DBL *output, FIXP_DBL *spectrum, + const SHORT scalefactor[], const INT nSpec, + const INT noOutSamples, const INT tl, const FIXP_WTP *wls, + INT fl, const FIXP_WTP *wrs, const INT fr, FIXP_DBL gain, + int flags) { + FIXP_DBL *pOvl; + FIXP_DBL *pOut0 = output, *pOut1; + INT nl, nr; + int w, i, nrSamples = 0, specShiftScale, transform_gain_e = 0; + int currAliasSymmetry = (flags & MLT_FLAG_CURR_ALIAS_SYMMETRY); + + /* Derive NR and NL */ + nr = (tl - fr) >> 1; + nl = (tl - fl) >> 1; + + /* Include 2/N IMDCT gain into gain factor and exponent. */ + imdct_gain(&gain, &transform_gain_e, tl); + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr != fl) { + imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples); + } + + pOvl = hMdct->overlap.freq + hMdct->ov_size - 1; + + if (noOutSamples > nrSamples) { + /* Purge buffered output. */ + for (i = 0; i < hMdct->ov_offset; i++) { + *pOut0 = hMdct->overlap.time[i]; + pOut0++; + } + nrSamples = hMdct->ov_offset; + hMdct->ov_offset = 0; + } + + for (w = 0; w < nSpec; w++) { + FIXP_DBL *pSpec, *pCurr; + const FIXP_WTP *pWindow; + + /* Detect FRprevious / FL mismatches and override parameters accordingly */ + if (hMdct->prev_fr != fl) { + imdct_adapt_parameters(hMdct, &fl, &nl, tl, wls, noOutSamples); + } + + specShiftScale = transform_gain_e; + + /* Setup window pointers */ + pWindow = hMdct->prev_wrs; + + /* Current spectrum */ + pSpec = spectrum + w * tl; + + /* DCT IV of current spectrum. */ + if (currAliasSymmetry == 0) { + if (hMdct->prevAliasSymmetry == 0) { + dct_IV(pSpec, tl, &specShiftScale); + } else { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dct_III(pSpec, tmp, tl, &specShiftScale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } + } else { + if (hMdct->prevAliasSymmetry == 0) { + FIXP_DBL _tmp[1024 + ALIGNMENT_DEFAULT / sizeof(FIXP_DBL)]; + FIXP_DBL *tmp = (FIXP_DBL *)ALIGN_PTR(_tmp); + C_ALLOC_ALIGNED_REGISTER(tmp, sizeof(_tmp)); + dst_III(pSpec, tmp, tl, &specShiftScale); + C_ALLOC_ALIGNED_UNREGISTER(tmp); + } else { + dst_IV(pSpec, tl, &specShiftScale); + } + } + + /* Optional scaling of time domain - no yet windowed - of current spectrum + */ + /* and de-scale current spectrum signal (time domain, no yet windowed) */ + if (gain != (FIXP_DBL)0) { + for (i = 0; i < tl; i++) { + pSpec[i] = fMult(pSpec[i], gain); + } + } + + { + int loc_scale = + fixmin_I(scalefactor[w] + specShiftScale, (INT)DFRACT_BITS - 1); + DWORD_ALIGNED(pSpec); + scaleValuesSaturate(pSpec, tl, loc_scale); + } + + if (noOutSamples <= nrSamples) { + /* Divert output first half to overlap buffer if we already got enough + * output samples. */ + pOut0 = hMdct->overlap.time + hMdct->ov_offset; + hMdct->ov_offset += hMdct->prev_nr + fl / 2; + } else { + /* Account output samples */ + nrSamples += hMdct->prev_nr + fl / 2; + } + + /* NR output samples 0 .. NR. -overlap[TL/2..TL/2-NR] */ + if ((hMdct->pFacZir != 0) && (hMdct->prev_nr == fl / 2)) { + /* In the case of ACELP -> TCX20 -> FD short add FAC ZIR on nr signal part + */ + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x + hMdct->pFacZir[i]); + pOut0++; + } + hMdct->pFacZir = NULL; + } else { + /* Here we implement a simplified version of what happens after the this + piece of code (see the comments below). We implement the folding of C and + D segments from (-D-Cr) but D is zero, because in this part of the MDCT + sequence the window coefficients with which D must be multiplied are zero. + "pOut0" writes sequentially the C block from left to right. */ + if (hMdct->prevPrevAliasSymmetry == 0) { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = -(*pOvl--); + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } else { + for (i = 0; i < hMdct->prev_nr; i++) { + FIXP_DBL x = *pOvl--; + *pOut0 = IMDCT_SCALE_DBL(x); + pOut0++; + } + } + } + + if (noOutSamples <= nrSamples) { + /* Divert output second half to overlap buffer if we already got enough + * output samples. */ + pOut1 = hMdct->overlap.time + hMdct->ov_offset + fl / 2 - 1; + hMdct->ov_offset += fl / 2 + nl; + } else { + pOut1 = pOut0 + (fl - 1); + nrSamples += fl / 2 + nl; + } + + /* output samples before window crossing point NR .. TL/2. + * -overlap[TL/2-NR..TL/2-NR-FL/2] + current[NR..TL/2] */ + /* output samples after window crossing point TL/2 .. TL/2+FL/2. + * -overlap[0..FL/2] - current[TL/2..FL/2] */ + pCurr = pSpec + tl - fl / 2; + DWORD_ALIGNED(pCurr); + C_ALLOC_ALIGNED_REGISTER(pWindow, fl); + DWORD_ALIGNED(pWindow); + C_ALLOC_ALIGNED_UNREGISTER(pWindow); + + if (hMdct->prevPrevAliasSymmetry == 0) { + if (hMdct->prevAliasSymmetry == 0) { + if (!hMdct->pAsymOvlp) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1); + pOut0++; + pOut1--; + } + } else { + FIXP_DBL *pAsymOvl = hMdct->pAsymOvlp + fl / 2 - 1; + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + x1 = -fMultDiv2(*pCurr, pWindow[i].v.re) + + fMultDiv2(*pAsymOvl, pWindow[i].v.im); + x0 = fMultDiv2(*pCurr, pWindow[i].v.im) - + fMultDiv2(*pOvl, pWindow[i].v.re); + pCurr++; + pOvl--; + pAsymOvl--; + *pOut0++ = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1-- = IMDCT_SCALE_DBL_LSH1(x1); + } + hMdct->pAsymOvlp = NULL; + } + } else { /* prevAliasingSymmetry == 1 */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, -*pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } + } else { /* prevPrevAliasingSymmetry == 1 */ + if (hMdct->prevAliasSymmetry == 0) { + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(-x1); + pOut0++; + pOut1--; + } + } else { /* prevAliasingSymmetry == 1 */ + for (i = 0; i < fl / 2; i++) { + FIXP_DBL x0, x1; + cplxMultDiv2(&x1, &x0, *pCurr++, *pOvl--, pWindow[i]); + *pOut0 = IMDCT_SCALE_DBL_LSH1(x0); + *pOut1 = IMDCT_SCALE_DBL_LSH1(x1); + pOut0++; + pOut1--; + } + } + } + + if (hMdct->pFacZir != 0) { + /* add FAC ZIR of previous ACELP -> mdct transition */ + FIXP_DBL *pOut = pOut0 - fl / 2; + FDK_ASSERT(fl / 2 <= 128); + for (i = 0; i < fl / 2; i++) { + pOut[i] += IMDCT_SCALE_DBL(hMdct->pFacZir[i]); + } + hMdct->pFacZir = NULL; + } + pOut0 += (fl / 2) + nl; + + /* NL output samples TL/2+FL/2..TL. - current[FL/2..0] */ + pOut1 += (fl / 2) + 1; + pCurr = pSpec + tl - fl / 2 - 1; + /* Here we implement a simplified version of what happens above the this + piece of code (see the comments above). We implement the folding of C and D + segments from (C-Dr) but C is zero, because in this part of the MDCT + sequence the window coefficients with which C must be multiplied are zero. + "pOut1" writes sequentially the D block from left to right. */ + if (hMdct->prevAliasSymmetry == 0) { + for (i = 0; i < nl; i++) { + FIXP_DBL x = -(*pCurr--); + *pOut1++ = IMDCT_SCALE_DBL(x); + } + } else { + for (i = 0; i < nl; i++) { + FIXP_DBL x = *pCurr--; + *pOut1++ = IMDCT_SCALE_DBL(x); + } + } + + /* Set overlap source pointer for next window pOvl = pSpec + tl/2 - 1; */ + pOvl = pSpec + tl / 2 - 1; + + /* Previous window values. */ + hMdct->prev_nr = nr; + hMdct->prev_fr = fr; + hMdct->prev_tl = tl; + hMdct->prev_wrs = wrs; + + /* Previous aliasing symmetry */ + hMdct->prevPrevAliasSymmetry = hMdct->prevAliasSymmetry; + hMdct->prevAliasSymmetry = currAliasSymmetry; + } + + /* Save overlap */ + + pOvl = hMdct->overlap.freq + hMdct->ov_size - tl / 2; + FDKmemcpy(pOvl, &spectrum[(nSpec - 1) * tl], (tl / 2) * sizeof(FIXP_DBL)); + + return nrSamples; +} diff --git a/fdk-aac/libFDK/src/mips/fft_rad2_mips.cpp b/fdk-aac/libFDK/src/mips/fft_rad2_mips.cpp new file mode 100644 index 0000000..7db8b4e --- /dev/null +++ b/fdk-aac/libFDK/src/mips/fft_rad2_mips.cpp @@ -0,0 +1,165 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: dit_fft MIPS assembler replacements. + +*******************************************************************************/ + +#ifndef __FFT_RAD2_CPP__ +#error \ + "Do not compile this file separately. It is included on demand from fft_rad2.cpp" +#endif + +#if defined(MIPS_DSP_LIB) + +#include "dsplib_util.h" +#include "dsplib_dsp.h" + +#define FUNCTION_dit_fft + +#ifdef FUNCTION_dit_fft + +#include "mips_fft_twiddles.cpp" + +void dit_fft(FIXP_DBL *x, const INT ldn, const FIXP_STP *trigdata, + const INT trigDataSize) { + int i; + + int32c *din = (int32c *)x; + int32c *dout = (int32c *)x; + + int32c scratch[1024]; + int32c *twiddles; + + switch (ldn) { + case 4: + twiddles = (int32c *)__twiddles_mips_fft32_16; + break; + case 5: + twiddles = (int32c *)__twiddles_mips_fft32_32; + break; + case 6: + twiddles = (int32c *)__twiddles_mips_fft32_64; + break; + case 7: + twiddles = (int32c *)__twiddles_mips_fft32_128; + break; + case 8: + twiddles = (int32c *)__twiddles_mips_fft32_256; + break; + case 9: + twiddles = (int32c *)__twiddles_mips_fft32_512; + break; + case 10: + twiddles = (int32c *)__twiddles_mips_fft32_1024; + break; + default: + FDK_ASSERT(0); + break; + } + + mips_fft32(dout, din, twiddles, scratch, ldn); + + for (i = 0; i < (1 << ldn); i++) { + x[2 * i] = dout[i].re << 1; + x[2 * i + 1] = dout[i].im << 1; + } +} +#endif + +#endif /* defined(MIPS_DSP_LIB) */ diff --git a/fdk-aac/libFDK/src/mips/mips_fft_twiddles.cpp b/fdk-aac/libFDK/src/mips/mips_fft_twiddles.cpp new file mode 100644 index 0000000..f905f86 --- /dev/null +++ b/fdk-aac/libFDK/src/mips/mips_fft_twiddles.cpp @@ -0,0 +1,931 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +static const INT __twiddles_mips_fft32_16[] = { + (0x7FFFFFFF), (0x00000000), (0x7641AF32), (0xCF043A9E), (0x5A827978), + (0xA57D8646), (0x30FBC547), (0x89BE50C2), (0xFFFFFFA3), (0x80000002), + (0xCF043AF8), (0x89BE50A8), (0xA57D865E), (0xA57D8670), (0x89BE5100), + (0xCF043A24), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_32[] = { + (0x7FFFFFFF), (0x00000000), (0x7D8A5F3C), (0xE70747B9), (0x7641AF32), + (0xCF043A9E), (0x6A6D98A1), (0xB8E31318), (0x5A827978), (0xA57D8646), + (0x471CED05), (0x95926772), (0x30FBC547), (0x89BE50C2), (0x18F8B888), + (0x8275A0D1), (0xFFFFFFA3), (0x80000002), (0xE70747BB), (0x8275A0C3), + (0xCF043AF8), (0x89BE50A8), (0xB8E3139E), (0x95926705), (0xA57D865E), + (0xA57D8670), (0x959266F7), (0xB8E313B4), (0x89BE5100), (0xCF043A24), + (0x8275A0BE), (0xE70747D4), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x37000000), (0x000080A3), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_64[] = { + (0x7FFFFFFF), (0x00000000), (0x7F62368D), (0xF3742C9D), (0x7D8A5F3C), + (0xE70747B9), (0x7A7D0559), (0xDAD7F3A2), (0x7641AF32), (0xCF043A9E), + (0x70E2CBCD), (0xC3A945A1), (0x6A6D98A1), (0xB8E31318), (0x62F201C4), + (0xAECC338B), (0x5A827978), (0xA57D8646), (0x5133CC8F), (0x9D0DFE52), + (0x471CED05), (0x95926772), (0x3C56BAB5), (0x8F1D3461), (0x30FBC547), + (0x89BE50C2), (0x25280C05), (0x8582FA8C), (0x18F8B888), (0x8275A0D1), + (0x0C8BD356), (0x809DC971), (0xFFFFFFA3), (0x80000002), (0xF3742CEE), + (0x809DC96B), (0xE70747BB), (0x8275A0C3), (0xDAD7F348), (0x8582FAC2), + (0xCF043AF8), (0x89BE50A8), (0xC3A94669), (0x8F1D33C8), (0xB8E3139E), + (0x95926705), (0xAECC33A5), (0x9D0DFE27), (0xA57D865E), (0xA57D8670), + (0x9D0DFE16), (0xAECC33B9), (0x959266F7), (0xB8E313B4), (0x8F1D34AD), + (0xC3A944BC), (0x89BE5100), (0xCF043A24), (0x8582FABB), (0xDAD7F360), + (0x8275A0BE), (0xE70747D4), (0x809DC968), (0xF3742D08), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0xFF7B0000), + (0x2E8050F1), (0x10214482), (0x1BA00005), (0x0000C0FF), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000)}; + +static const INT __twiddles_mips_fft32_128[] = { + (0x7FFFFFFF), (0x00000000), (0x7FD8878C), (0xF9B82681), (0x7F62368D), + (0xF3742C9D), (0x7E9D55FB), (0xED37EF91), (0x7D8A5F3C), (0xE70747B9), + (0x7C29FBEF), (0xE0E6068F), (0x7A7D0559), (0xDAD7F3A2), (0x78848419), + (0xD4E0CB28), (0x7641AF32), (0xCF043A9E), (0x73B5EBCF), (0xC945DFEB), + (0x70E2CBCD), (0xC3A945A1), (0x6DCA0D27), (0xBE31E1BF), (0x6A6D98A1), + (0xB8E31318), (0x66CF8103), (0xB3C01FE9), (0x62F201C4), (0xAECC338B), + (0x5ED77C86), (0xAA0A5B2C), (0x5A827978), (0xA57D8646), (0x55F5A4ED), + (0xA1288391), (0x5133CC8F), (0x9D0DFE52), (0x4C3FDFCC), (0x99307EC5), + (0x471CED05), (0x95926772), (0x41CE1ECD), (0x9235F32C), (0x3C56BAB5), + (0x8F1D3461), (0x36BA2034), (0x8C4A1440), (0x30FBC547), (0x89BE50C2), + (0x2B1F34BC), (0x877B7BDD), (0x25280C05), (0x8582FA8C), (0x1F19F9F0), + (0x83D60431), (0x18F8B888), (0x8275A0D1), (0x12C81090), (0x8162AA0A), + (0x0C8BD356), (0x809DC971), (0x0647D949), (0x80277871), (0xFFFFFFA3), + (0x80000002), (0xF9B826FB), (0x8027786E), (0xF3742CEE), (0x809DC96B), + (0xED37EFB3), (0x8162AA00), (0xE70747BB), (0x8275A0C3), (0xE0E60653), + (0x83D60420), (0xDAD7F348), (0x8582FAC2), (0xD4E0CB84), (0x877B7BC6), + (0xCF043AF8), (0x89BE50A8), (0xC945E00A), (0x8C4A1423), (0xC3A94669), + (0x8F1D33C8), (0xBE31E16E), (0x9235F309), (0xB8E3139E), (0x95926705), + (0xB3C01F9D), (0x99307F35), (0xAECC33A5), (0x9D0DFE27), (0xAA0A5A88), + (0xA128840F), (0xA57D865E), (0xA57D8670), (0xA12883FE), (0xAA0A5A9B), + (0x9D0DFE16), (0xAECC33B9), (0x99307F26), (0xB3C01FB2), (0x959266F7), + (0xB8E313B4), (0x9235F2FC), (0xBE31E184), (0x8F1D34AD), (0xC3A944BC), + (0x8C4A1418), (0xC945E021), (0x89BE5100), (0xCF043A24), (0x877B7BBD), + (0xD4E0CB9C), (0x8582FABB), (0xDAD7F360), (0x83D603DC), (0xE0E60764), + (0x8275A0BE), (0xE70747D4), (0x8162AA22), (0xED37EECF), (0x809DC968), + (0xF3742D08), (0x80277879), (0xF9B82615), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0xA4370000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0xFF770000), (0x2E8050F1), (0x1A214462), + (0x04D6D583), (0x40031282), (0x6469A735), (0x0B4C99A3), (0x0AF88594), + (0xF90969D7), (0x96131C92), (0x025EEA10), (0x3A1FE421), (0x614FF390), + (0x1CFDC327), (0xC177E04F), (0xF4D87E82), (0x78253F39), (0xBB839F94), + (0x998B3EB1), (0x0CBCC021), (0x41BEC843), (0xAC0EE121), (0x52719643), + (0x909A2B1D), (0xF38931E1), (0xF41327FF), (0xF6099847), (0xA70D219C), + (0x7BD52135), (0x78060F71), (0xEA3C87D8), (0x3FAF3A24), (0xE4B2C421), + (0xB99D1453), (0x2741E264), (0x2239813A), (0x2944DA20), (0x441EF7C4), + (0x0BD0B720), (0xED84EA26), (0x73E0C0D2), (0x678E3039), (0x21420109), + (0x8607492E), (0x28CEF440), (0x022768C8), (0xF68E3611), (0x84E84D55), + (0x73004C04), (0xF9B6630E), (0x677FFA8F), (0x530CB18F), (0x2C4EE310), + (0xABC7537C), (0x82CFDBCB), (0x100C63A2), (0x876D75BA), (0xC683F888), + (0x0CDC1E1E), (0xA600E833), (0x33036066), (0x4305049C), (0x40890713), + (0x9D12532E), (0x7B6E2FE2), (0xE244CC09), (0x9FFB2082), (0xAB3735D3), + (0x00000080), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0x00000000)}; + +static const INT __twiddles_mips_fft32_256[] = { + (0x7FFFFFFF), (0x00000000), (0x7FF62181), (0xFCDBD540), (0x7FD8878C), + (0xF9B82681), (0x7FA736B2), (0xF6956FB7), (0x7F62368D), (0xF3742C9D), + (0x7F0991C3), (0xF054D8DA), (0x7E9D55FB), (0xED37EF91), (0x7E1D93EA), + (0xEA1DEBC6), (0x7D8A5F3C), (0xE70747B9), (0x7CE3CEB0), (0xE3F47D95), + (0x7C29FBEF), (0xE0E6068F), (0x7B5D03A1), (0xDDDC5B4F), (0x7A7D0559), + (0xDAD7F3A2), (0x798A23A8), (0xD7D946C3), (0x78848419), (0xD4E0CB28), + (0x776C4ED9), (0xD1EEF59D), (0x7641AF32), (0xCF043A9E), (0x7504D34C), + (0xCC210D8B), (0x73B5EBCF), (0xC945DFEB), (0x72552C79), (0xC67322B9), + (0x70E2CBCD), (0xC3A945A1), (0x6F5F02CF), (0xC0E8B67E), (0x6DCA0D27), + (0xBE31E1BF), (0x6C242969), (0xBB8532C0), (0x6A6D98A1), (0xB8E31318), + (0x68A69E72), (0xB64BEAB9), (0x66CF8103), (0xB3C01FE9), (0x64E8894A), + (0xB140178C), (0x62F201C4), (0xAECC338B), (0x60EC383A), (0xAC64D51F), + (0x5ED77C86), (0xAA0A5B2C), (0x5CB420CD), (0xA7BD229A), (0x5A827978), + (0xA57D8646), (0x5842DD7E), (0xA34BDF4B), (0x55F5A4ED), (0xA1288391), + (0x539B2AFB), (0x9F13C7DC), (0x5133CC8F), (0x9D0DFE52), (0x4EBFE88F), + (0x9B1776CB), (0x4C3FDFCC), (0x99307EC5), (0x49B41562), (0x975961A2), + (0x471CED05), (0x95926772), (0x447ACD5D), (0x93DBD6AA), (0x41CE1ECD), + (0x9235F32C), (0x3F17499F), (0x90A0FD42), (0x3C56BAB5), (0x8F1D3461), + (0x398CDCF3), (0x8DAAD35D), (0x36BA2034), (0x8C4A1440), (0x33DEF21F), + (0x8AFB2C8E), (0x30FBC547), (0x89BE50C2), (0x2E110ABF), (0x8893B14A), + (0x2B1F34BC), (0x877B7BDD), (0x2826B95E), (0x8675DC62), (0x25280C05), + (0x8582FA8C), (0x2223A4D2), (0x84A2FC68), (0x1F19F9F0), (0x83D60431), + (0x1C0B824E), (0x831C314A), (0x18F8B888), (0x8275A0D1), (0x15E213FD), + (0x81E26C0B), (0x12C81090), (0x8162AA0A), (0x0FAB26B9), (0x80F66E30), + (0x0C8BD356), (0x809DC971), (0x096A90AB), (0x8058C955), (0x0647D949), + (0x80277871), (0x03242AF6), (0x8009DE81), (0xFFFFFFA3), (0x80000002), + (0xFCDBD54E), (0x8009DE7F), (0xF9B826FB), (0x8027786E), (0xF6956F99), + (0x8058C950), (0xF3742CEE), (0x809DC96B), (0xF054D88D), (0x80F66E47), + (0xED37EFB3), (0x8162AA00), (0xEA1DEB4A), (0x81E26C2C), (0xE70747BB), + (0x8275A0C3), (0xE3F47DF5), (0x831C313B), (0xE0E60653), (0x83D60420), + (0xDDDC5B6F), (0x84A2FC55), (0xDAD7F348), (0x8582FAC2), (0xD7D946E3), + (0x8675DC4D), (0xD4E0CB84), (0x877B7BC6), (0xD1EEF581), (0x8893B132), + (0xCF043AF8), (0x89BE50A8), (0xCC210D35), (0x8AFB2CDB), (0xC945E00A), + (0x8C4A1423), (0xC6732265), (0x8DAAD3B2), (0xC3A94669), (0x8F1D33C8), + (0xC0E8B69C), (0x90A0FD21), (0xBE31E16E), (0x9235F309), (0xBB853205), + (0x93DBD70E), (0xB8E3139E), (0x95926705), (0xB64BEAD5), (0x9759617B), + (0xB3C01F9D), (0x99307F35), (0xB140180C), (0x9B177652), (0xAECC33A5), + (0x9D0DFE27), (0xAC64D4D8), (0x9F13C803), (0xAA0A5A88), (0xA128840F), + (0xA7BD2310), (0xA34BDEC3), (0xA57D865E), (0xA57D8670), (0xA34BDEB2), + (0xA7BD2322), (0xA12883FE), (0xAA0A5A9B), (0x9F13C7F2), (0xAC64D4EB), + (0x9D0DFE16), (0xAECC33B9), (0x9B177642), (0xB1401820), (0x99307F26), + (0xB3C01FB2), (0x9759616C), (0xB64BEAEA), (0x959266F7), (0xB8E313B4), + (0x93DBD700), (0xBB85321A), (0x9235F2FC), (0xBE31E184), (0x90A0FD14), + (0xC0E8B6B2), (0x8F1D34AD), (0xC3A944BC), (0x8DAAD3A6), (0xC673227C), + (0x8C4A1418), (0xC945E021), (0x8AFB2C68), (0xCC210E37), (0x89BE5100), + (0xCF043A24), (0x8893B128), (0xD1EEF599), (0x877B7BBD), (0xD4E0CB9C), + (0x8675DC95), (0xD7D94608), (0x8582FABB), (0xDAD7F360), (0x84A2FC4F), + (0xDDDC5B88), (0x83D603DC), (0xE0E60764), (0x831C316D), (0xE3F47D14), + (0x8275A0BE), (0xE70747D4), (0x81E26BFB), (0xEA1DEC5F), (0x8162AA22), + (0xED37EECF), (0x80F66E44), (0xF054D8A6), (0x809DC968), (0xF3742D08), + (0x8058C93B), (0xF69570B2), (0x80277879), (0xF9B82615), (0x8009DE7E), + (0xFCDBD568), (0x00000000), (0x00000000), (0x00000000), (0x00000000), + (0xF1FF7A00), (0xE23A8050), (0x841A2114), (0xC588DA75), (0x02400143), + (0xAED6AAD7), (0x94C2545B), (0x3E46156C), (0x05BFDF27), (0xB0822075), + (0xD24C7BC4), (0x62122054), (0x8CC41C49), (0x2C414972), (0x718D7C5E), + (0xDEE2A3D8), (0x4544C135), (0x64292573), (0x76B51F8A), (0x4B7D6557), + (0x87164907), (0xF59DBFEC), (0x04CEE9DE), (0xB4BC4C90), (0x9AFCCD30), + (0x8C7A316F), (0x90FDACA7), (0x4E0D6383), (0xAEF16C0B), (0x0622020A), + (0x37B6A738), (0xFFBB7D71), (0x5FEDD12F), (0xEE47FDC8), (0x3DC7913F), + (0xEAEEF7FD), (0x219DADEC), (0xF9E53F5F), (0xB3D82D9E), (0xBBB79BCB), + (0x43AD2AAB), (0x0E7ADBC0), (0xABBD0952), (0x1A6EF43A), (0xCD9B2A9D), + (0x7222B366), (0x979E89E9), (0x02C9113F), (0x1D511466), (0x57A92206), + (0x4A412075), (0xFD31D783), (0xA7542EFC), (0x24B76975), (0xB99962C7), + (0x19F1D356), (0x9D12C3CB), (0x6D37D542), (0x29E7214D), (0x8900F645), + (0xB154AD4A), (0xF047D988), (0x3F2E5E77), (0xAFB68C49), (0xC9F19E51), + (0x6192F53A), (0x5AE3D080), (0x1DA6C677), (0xD485D50C), (0x9AA7E8B2), + (0xF55EE1D5), (0xC00B6932), (0x85ACE912), (0x8208B1B9), (0x80E14170), + (0xA1D67C3F), (0x058035B3), (0xA4FE36CA), (0xBEE547E4), (0xEF276052), + (0x42AA4388), (0x9C11A2ED), (0x10202541), (0x2D480910), (0xB09B1AC4), + (0x19E7D17D), (0x52082450), (0x3EED1705), (0xF20FF8A1), (0x89F6E17F), + (0x17D7DC00), (0x09B9F2C3), (0x6378968C), (0xAF0607F6), (0xFDFDE0C9), + (0x3CE3DFEE), (0x5168229E), (0x7CF79734), (0xF5FFF56F), (0x30700093), + (0x135F5C75), (0xE6D73EEE), (0x6E400DF9), (0x58252ACB), (0x557311CA), + (0x5539B303), (0x56557355), (0xB6BDACEF), (0x59F9428D), (0x9AE63020), + (0x558FF7E7), (0x7955806D), (0x09D549F3), (0x603BF5B7), (0x3134413B), + (0xBCA7C1AA), (0xA98D1339), (0x57B29C97), (0x50F1FF07), (0xE4A13980), + (0xD0881A21), (0xC1FFE30A), (0xB0A66C19), (0x18416490), (0x160E0214), + (0xA584CBB5), (0x02AAA82A), (0x73981340), (0x964A24DE), (0x6E829FC4), + (0xDFD62360), (0x4C3BF152), (0x38721574), (0xD46BC912), (0x1EB7FDD8), + (0x1CA6CBC0), (0xBBCBC111), (0xA6FD1403), (0x76C688D9), (0xB47186CB), + (0x5E98936D), (0x9BBF7E2E), (0x8B7FBCEC), (0x9DAF7EF5), (0x7E3A79F1), + (0x9C896ACD), (0x628F249A), (0xDD6E51AF), (0xAF73994B), (0x5966995D), + (0xB7620597), (0x369B1E54), (0x7CEDC787), (0xE7B15B1F), (0xB36F5F7D), + (0xB5B73EF6), (0xD76EEEE2), (0x14E86186), (0xCC159291), (0x4EC85CA3), + (0xEC3C704E), (0x0B6633B3), (0x4D992D4B), (0xEB1B5774), (0xDFB9D508), + (0x11783719), (0x77BB10B0), (0xFCDF8350), (0xD34A7C65), (0xEF6E57BB), + (0xECD56C68), (0x8EB7CA36), (0x2F26B136), (0x55631269), (0xEF1213E1), + (0xA56AB844), (0xAA4B1D64), (0x64341EA9), (0x0CE9DB48), (0x460C2144), + (0xADC50205), (0x515C472F), (0x304C29BD), (0x76AF8711), (0x557CADB7), + (0x2A9BBC8E), (0xE50E145B), (0x9C2031FD), (0xD9121A8C), (0xF51A96FD), + (0x45CCBEBF), (0x5F884871), (0x66DAE291), (0x95ADC9E5), (0x33CF304D), + (0x23C87DCE), (0xA7014FB3), (0xFB351E71), (0x8D60F66F), (0xBFD6DDD5), + (0x151FE6F1), (0xDCC7935A), (0x0CACFBF0), (0xEE55A371), (0xBE46B755), + (0x0F79DCD2), (0x23DFF76D), (0x83DE76D7), (0x8B0E3AEE), (0xB01BFB44), + (0x4E3619FA), (0xA19F9E64), (0xBD492AD9), (0x0899E45F), (0x8156E41D), + (0x5DA539BA), (0x0AF35B2C), (0xDB89BAAE), (0xA128C966), (0xA02CEAEE), + (0xC5A1B291), (0x08CBA93E), (0x90FD887A), (0x60304386), (0x6A59F1EA), + (0xA461E67B), (0xC1622B76), (0x6FA2F906), (0xAA3A401A), (0xB68EA47B), + (0xC617A889), (0x6024A57B), (0x2DD53555), (0xF1FFEA30), (0x813A8050), + (0x8D1A21B4), (0xFFE72CF7), (0xA37415E1), (0x30A2C830), (0xA3A1CA28), + (0x4C5E3586), (0x309861B9), (0x1F49850D), (0x6164C748), (0x9D7048E5), + (0xC124569E), (0xCCB0E111), (0x15B2BB86), (0x18371D9C), (0xB2ABD94D), + (0x8EC656B3), (0xBF010995)}; + +static const INT __twiddles_mips_fft32_512[] = { + (0x7FFFFFFF), (0x00000000), (0x7FFD8859), (0xFE6DE2E0), (0x7FF62181), + (0xFCDBD540), (0x7FE9CBBE), (0xFB49E6A3), (0x7FD8878C), (0xF9B82681), + (0x7FC25595), (0xF826A464), (0x7FA736B2), (0xF6956FB7), (0x7F872BF2), + (0xF5049800), (0x7F62368D), (0xF3742C9D), (0x7F3857F4), (0xF1E43D1C), + (0x7F0991C3), (0xF054D8DA), (0x7ED5E5C6), (0xEEC60F3C), (0x7E9D55FB), + (0xED37EF91), (0x7E5FE490), (0xEBAA8944), (0x7E1D93EA), (0xEA1DEBC6), + (0x7DD6668D), (0xE8922621), (0x7D8A5F3C), (0xE70747B9), (0x7D3980ED), + (0xE57D5FE4), (0x7CE3CEB0), (0xE3F47D95), (0x7C894BDA), (0xE26CB010), + (0x7C29FBEF), (0xE0E6068F), (0x7BC5E296), (0xDF609002), (0x7B5D03A1), + (0xDDDC5B4F), (0x7AEF6325), (0xDC59778B), (0x7A7D0559), (0xDAD7F3A2), + (0x7A05EEA8), (0xD957DE6F), (0x798A23A8), (0xD7D946C3), (0x7909A935), + (0xD65C3B98), (0x78848419), (0xD4E0CB28), (0x77FAB98A), (0xD367044F), + (0x776C4ED9), (0xD1EEF59D), (0x76D94983), (0xD078AD93), (0x7641AF32), + (0xCF043A9E), (0x75A585D9), (0xCD91AB55), (0x7504D34C), (0xCC210D8B), + (0x745F9DD3), (0xCAB26FB2), (0x73B5EBCF), (0xC945DFEB), (0x7307C3C9), + (0xC7DB6C45), (0x72552C79), (0xC67322B9), (0x719E2CDE), (0xC50D1164), + (0x70E2CBCD), (0xC3A945A1), (0x7023109C), (0xC247CD62), (0x6F5F02CF), + (0xC0E8B67E), (0x6E96A995), (0xBF8C0DD8), (0x6DCA0D27), (0xBE31E1BF), + (0x6CF934E8), (0xBCDA3EAE), (0x6C242969), (0xBB8532C0), (0x6B4AF258), + (0xBA32CA42), (0x6A6D98A1), (0xB8E31318), (0x698C2487), (0xB79619C6), + (0x68A69E72), (0xB64BEAB9), (0x67BD0FCC), (0xB5049380), (0x66CF8103), + (0xB3C01FE9), (0x65DDFBD6), (0xB27E9D43), (0x64E8894A), (0xB140178C), + (0x63EF3286), (0xB0049AA9), (0x62F201C4), (0xAECC338B), (0x61F10027), + (0xAD96ED77), (0x60EC383A), (0xAC64D51F), (0x5FE3B366), (0xAB35F58C), + (0x5ED77C86), (0xAA0A5B2C), (0x5DC79D9C), (0xA8E2112C), (0x5CB420CD), + (0xA7BD229A), (0x5B9D1166), (0xA69B9B7D), (0x5A827978), (0xA57D8646), + (0x5964649B), (0xA462EEB2), (0x5842DD7E), (0xA34BDF4B), (0x571DEEED), + (0xA238627B), (0x55F5A4ED), (0xA1288391), (0x54CA0A2E), (0xA01C4C5C), + (0x539B2AFB), (0x9F13C7DC), (0x52691241), (0x9E0EFF9D), (0x5133CC8F), + (0x9D0DFE52), (0x4FFB6572), (0x9C10CD90), (0x4EBFE88F), (0x9B1776CB), + (0x4D8162D8), (0x9A22043F), (0x4C3FDFCC), (0x99307EC5), (0x4AFB6C9B), + (0x9842F048), (0x49B41562), (0x975961A2), (0x4869E657), (0x9673DB8C), + (0x471CED05), (0x95926772), (0x45CD356F), (0x94B50D74), (0x447ACD5D), + (0x93DBD6AA), (0x4325C102), (0x9306CAE7), (0x41CE1ECD), (0x9235F32C), + (0x4073F245), (0x9169567D), (0x3F17499F), (0x90A0FD42), (0x3DB8324C), + (0x8FDCEF37), (0x3C56BAB5), (0x8F1D3461), (0x3AF2EEBA), (0x8E61D331), + (0x398CDCF3), (0x8DAAD35D), (0x38249413), (0x8CF83C62), (0x36BA2034), + (0x8C4A1440), (0x354D9033), (0x8BA06221), (0x33DEF21F), (0x8AFB2C8E), + (0x326E5505), (0x8A5A7A4D), (0x30FBC547), (0x89BE50C2), (0x2F875216), + (0x8926B65A), (0x2E110ABF), (0x8893B14A), (0x2C98FBD1), (0x88054682), + (0x2B1F34BC), (0x877B7BDD), (0x29A3C40F), (0x86F656AC), (0x2826B95E), + (0x8675DC62), (0x26A82174), (0x85FA114F), (0x25280C05), (0x8582FA8C), + (0x23A688D3), (0x85109CF7), (0x2223A4D2), (0x84A2FC68), (0x209F6FE1), + (0x843A1D62), (0x1F19F9F0), (0x83D60431), (0x1D935011), (0x8376B42E), + (0x1C0B824E), (0x831C314A), (0x1A829FC0), (0x82C67F00), (0x18F8B888), + (0x8275A0D1), (0x176DD9E1), (0x82299974), (0x15E213FD), (0x81E26C0B), + (0x1455771D), (0x81A01B80), (0x12C81090), (0x8162AA0A), (0x1139F0A7), + (0x812A1A36), (0x0FAB26B9), (0x80F66E30), (0x0E1BC326), (0x80C7A813), + (0x0C8BD356), (0x809DC971), (0x0AFB67B2), (0x8078D407), (0x096A90AB), + (0x8058C955), (0x07D95BB6), (0x803DAA6D), (0x0647D949), (0x80277871), + (0x04B618DF), (0x8016343D), (0x03242AF6), (0x8009DE81), (0x01921D0C), + (0x800277A7), (0xFFFFFFA3), (0x80000002), (0xFE6DE338), (0x800277A6), + (0xFCDBD54E), (0x8009DE7F), (0xFB49E665), (0x80163444), (0xF9B826FB), + (0x8027786E), (0xF826A48E), (0x803DAA69), (0xF6956F99), (0x8058C950), + (0xF5049793), (0x8078D418), (0xF3742CEE), (0x809DC96B), (0xF1E43D1E), + (0x80C7A80C), (0xF054D88D), (0x80F66E47), (0xEEC60F9D), (0x812A1A2D), + (0xED37EFB3), (0x8162AA00), (0xEBAA8927), (0x81A01B75), (0xEA1DEB4A), + (0x81E26C2C), (0xE8922662), (0x82299967), (0xE70747BB), (0x8275A0C3), + (0xE57D5F89), (0x82C67F27), (0xE3F47DF5), (0x831C313B), (0xE26CB031), + (0x8376B41E), (0xE0E60653), (0x83D60420), (0xDF608F69), (0x843A1D92), + (0xDDDC5B6F), (0x84A2FC55), (0xDC59776E), (0x85109CE4), (0xDAD7F348), + (0x8582FAC2), (0xD957DECD), (0x85FA113A), (0xD7D946E3), (0x8675DC4D), + (0xD65C3B40), (0x86F656E9), (0xD4E0CB84), (0x877B7BC6), (0xD367046F), + (0x8805466A), (0xD1EEF581), (0x8893B132), (0xD078AD3C), (0x8926B6A0), + (0xCF043AF8), (0x89BE50A8), (0xCD91AB39), (0x8A5A7A32), (0xCC210D35), + (0x8AFB2CDB), (0xCAB2700B), (0x8BA06204), (0xC945E00A), (0x8C4A1423), + (0xC7DB6C2A), (0x8CF83C44), (0xC6732265), (0x8DAAD3B2), (0xC50D109F), + (0x8E61D388), (0xC3A94669), (0x8F1D33C8), (0xC247CDF0), (0x8FDCEF16), + (0xC0E8B69C), (0x90A0FD21), (0xBF8C0DF6), (0x9169565A), (0xBE31E16E), + (0x9235F309), (0xBCDA3E5E), (0x9306CB49), (0xBB853205), (0x93DBD70E), + (0xBA32CB35), (0x94B50D09), (0xB8E3139E), (0x95926705), (0xB79619E2), + (0x9673DB66), (0xB64BEAD5), (0x9759617B), (0xB5049334), (0x9842F06B), + (0xB3C01F9D), (0x99307F35), (0xB27E9C92), (0x9A2204B0), (0xB140180C), + (0x9B177652), (0xB0049B27), (0x9C10CD15), (0xAECC33A5), (0x9D0DFE27), + (0xAD96ED91), (0x9E0EFFC3), (0xAC64D4D8), (0x9F13C803), (0xAB35F545), + (0xA01C4CD8), (0xAA0A5A88), (0xA128840F), (0xA8E211A2), (0xA23861F5), + (0xA7BD2310), (0xA34BDEC3), (0xA69B9B96), (0xA462EE82), (0xA57D865E), + (0xA57D8670), (0xA462EE70), (0xA69B9BA8), (0xA34BDEB2), (0xA7BD2322), + (0xA23861E4), (0xA8E211B5), (0xA12883FE), (0xAA0A5A9B), (0xA01C4CC7), + (0xAB35F559), (0x9F13C7F2), (0xAC64D4EB), (0x9E0EFFB3), (0xAD96EDA5), + (0x9D0DFE16), (0xAECC33B9), (0x9C10CD05), (0xB0049B3B), (0x9B177642), + (0xB1401820), (0x9A2204A1), (0xB27E9CA6), (0x99307F26), (0xB3C01FB2), + (0x9842F05C), (0xB5049349), (0x9759616C), (0xB64BEAEA), (0x9673DB57), + (0xB79619F7), (0x959266F7), (0xB8E313B4), (0x94B50E13), (0xBA32C99E), + (0x93DBD700), (0xBB85321A), (0x9306CB3C), (0xBCDA3E74), (0x9235F2FC), + (0xBE31E184), (0x9169564D), (0xBF8C0E0C), (0x90A0FD14), (0xC0E8B6B2), + (0x8FDCEF09), (0xC247CE07), (0x8F1D34AD), (0xC3A944BC), (0x8E61D37C), + (0xC50D10B6), (0x8DAAD3A6), (0xC673227C), (0x8CF83C39), (0xC7DB6C41), + (0x8C4A1418), (0xC945E021), (0x8BA061F9), (0xCAB27022), (0x8AFB2C68), + (0xCC210E37), (0x8A5A7A8D), (0xCD91AA66), (0x89BE5100), (0xCF043A24), + (0x8926B697), (0xD078AD53), (0x8893B128), (0xD1EEF599), (0x88054661), + (0xD3670487), (0x877B7BBD), (0xD4E0CB9C), (0x86F6568E), (0xD65C3C4A), + (0x8675DC95), (0xD7D94608), (0x85FA1180), (0xD957DDF1), (0x8582FABB), + (0xDAD7F360), (0x85109CDD), (0xDC597787), (0x84A2FC4F), (0xDDDC5B88), + (0x843A1D4B), (0xDF60907A), (0x83D603DC), (0xE0E60764), (0x8376B454), + (0xE26CAF51), (0x831C316D), (0xE3F47D14), (0x82C67F21), (0xE57D5FA2), + (0x8275A0BE), (0xE70747D4), (0x82299962), (0xE892267C), (0x81E26BFB), + (0xEA1DEC5F), (0x81A01B48), (0xEBAA8A3D), (0x8162AA22), (0xED37EECF), + (0x812A1A4C), (0xEEC60EB9), (0x80F66E44), (0xF054D8A6), (0x80C7A809), + (0xF1E43D38), (0x809DC968), (0xF3742D08), (0x8078D3FF), (0xF50498AB), + (0x8058C93B), (0xF69570B2), (0x803DAA77), (0xF826A3A8), (0x80277879), + (0xF9B82615), (0x80163443), (0xFB49E67F), (0x8009DE7E), (0xFCDBD568), + (0x800277A6), (0xFE6DE352), (0x465220BB), (0xC66E1FFC), (0x2C61D356), + (0xAFFB176D), (0x88067E23), (0x3796F008), (0xC8D128F3), (0xB661A5FA), + (0xF19CE4F0), (0x3F7D0345), (0xE97E6030), (0x4ABA91CF), (0xDEEDAB0C), + (0x35FD1D77), (0xDD636439), (0x2F8B794C), (0x764E1D32), (0x7A8D0B1B), + (0x8EACB27F), (0x577AD67B), (0x2B3FE2C5), (0x8ACD024A), (0xEDF5C42C), + (0xF1CA951C), (0xB98B6D04), (0x6D12B864), (0x50E74D08), (0x73D1503B), + (0xC7D3F6A9), (0x1F365E97), (0xE1340E59), (0x89D21B9D), (0x9B756733), + (0x9024CD50), (0xE2C7FF52), (0xD9F061EF), (0x77151392), (0xA0E4A004), + (0x60BE820F), (0xC7603BAF), (0xA62E3DA9), (0xA400E11F), (0x155111D4), + (0x9030A374), (0x14185124), (0x8D043A00), (0x50945258), (0x20A6653E), + (0xA19BA8B9), (0x3CFBE692), (0x91471D98), (0x0B9D03FF), (0xA5BA8E29), + (0xFFC8EB22), (0x142CB1B0), (0x55317319), (0x33ADC77C), (0xF69BADCE), + (0x78423D3C), (0xBE67BBF0), (0x7D88BD15), (0x1E9EF673), (0x512098B3), + (0x326A3D3D), (0x161EF3B6), (0x0E4C4ED5), (0x4E9F9982), (0xD0AB6A36), + (0xF17DD377), (0x5E53F31C), (0xBE9112EA), (0x3DE1B0FF), (0xD7F39AE7), + (0xA34B9635), (0x49CFEE6C), (0x8A063AC6), (0xBA79BC0D), (0x6A588782), + (0x439BE593), (0x0A5F7E8D), (0xD2FC2561), (0x4698AC8F), (0x247C3BC2), + (0x5826523D), (0x4D2BD753), (0x4B8BCC17), (0x9B743503), (0x9F84E434), + (0x8B97B41A), (0x3CFCE75F), (0x32D2D487), (0x3E80B4AF), (0x42F8B0EA), + (0xEC0C81EE), (0x17279309), (0x681FA0F3), (0x8BAD208E), (0xD11792C6), + (0xF1FF07B3), (0x21338050), (0x8A1A21A4), (0xFF0358D8), (0x416C13C1), + (0x46348858), (0x83820519), (0xABC08822), (0x6A1A5200), (0x0C83122A), + (0xA67FDF06), (0x0629F970), (0xEFAA2743), (0x0C00AD95), (0xFF09F5CF), + (0xC784DB8B), (0xCB00BA7D), (0x6220909F), (0x7149B7DF), (0x5BD3EBEC), + (0x0485EF71), (0x07FE23B1), (0x80737668), (0x42A32645), (0xD6EDBB18), + (0x407E72C5), (0x901402E0), (0x0C1B7905), (0x01CE11FC), (0x00C64914), + (0x3037978A), (0xFABC9190), (0x43A0AC89), (0xB9998370), (0xD6D69209), + (0xF132455E), (0x9DAFF482), (0xA2D635C2), (0xBD976B5E), (0x79ED93ED), + (0x7D42CA22), (0x2E23F9C1), (0xCF0E7521), (0x96D88AC1), (0x420C2845), + (0x1E19573D), (0xF8FE9279), (0xC1495100), (0x201249C2), (0x8B183723), + (0x450615A5), (0x004C0112), (0x85EB5235), (0x1BD8BD48), (0xA2914F03), + (0x51420EAC), (0xCE788470), (0x0508030B), (0xA4CD2A6C), (0x9626C062), + (0xF88D2DE5), (0xA9D6B399), (0xB3C57BFD), (0xCB1E9C4C), (0x004A5094), + (0xD0CBC42A), (0x3BE1A694), (0x3C353FA7), (0xA5697C57), (0xFE961665), + (0xED6B7C7D), (0x433DCF8D), (0xDA7D6C24), (0x407112C1), (0x4B9D285D), + (0x6C9A2F57), (0x1BF9FAEF), (0x4EE3E2E9), (0xE5AE7E92), (0x60A11D3F), + (0x4B441B63), (0xC8419BB1), (0x2C4F6DDD), (0xCEC3CF6D), (0x325A65CA), + (0x818FC6A4), (0xC55E5E5B), (0x277445A3), (0x6B3289F7), (0x09147D55), + (0x4F378D53), (0x588B0DC8), (0xF70BA347), (0xCBC43FAE), (0xD98E6639), + (0x07AF9ED0), (0xE2E6305A), (0x5E003571), (0x18523E7A), (0xF70D1E27), + (0xD7288950), (0x12C11132), (0xFF1C9D17), (0x318050F1), (0x1A219821), + (0xBF21998A), (0x6C13C1FF), (0x8C605861), (0x0A183954), (0x7BE4C1B6), + (0xA2CBC410), (0x7CC00A55), (0x5E58A973), (0x1122EF86), (0x80568E39), + (0x2310C300), (0x0E152D0E), (0x9E017C1C), (0x851DFC26), (0xD1B1E662), + (0x81BA10B0), (0x96C2E977), (0x8688E419), (0x97C94989), (0x250D535E), + (0x35FDE732), (0x147AD183), (0xCF9D75C0), (0x6B2C183C), (0x1D326489), + (0xC0807D98), (0xC081622E), (0x15C87B87), (0x7404598C), (0xFC3C7FA6), + (0x28BA8CF5), (0xE311EA9B), (0xEABFD4A5), (0x8768834A), (0x0F7D7440), + (0x40593152), (0xCF1E8BF5), (0xE32017B6), (0x39E66070), (0x560ECE9D), + (0xF4132C77), (0x722945C1), (0x96ECB5D5), (0x0C100C06), (0x30E96C02), + (0xE0B0159B), (0x163A40CB), (0x1B28B750), (0x11420E11), (0x34DC5981), + (0xD2769C3C), (0x569402D0), (0xE4F157C0), (0x120DF24C), (0x40D86153), + (0x1942CD11), (0x22484C3B), (0x8B299144), (0x58F1AAF8), (0xB2CD4777), + (0x4A53AB02), (0x55A5DAD4), (0xC8D58D79), (0x6CAEC011), (0x1C955C84), + (0xDE08A6C6), (0xD402AF7D), (0x695E6FA4), (0x4DA863B9), (0x5118070C), + (0x5A97EF1C), (0x8880B388), (0x4D596B2D), (0x37D74DCF), (0x58138B38), + (0x5B7BCD4E), (0xAE6C4422), (0x4E5D1AF1), (0xDE7396A5), (0xB442F217), + (0x0DF7A006), (0x96EEF8A2), (0xE2847B26), (0x68B9F67B), (0x8FE1FA65), + (0xE0A87E56), (0x1BE8FC4C), (0xBBD65F9D), (0xE6F02C9D), (0x867C6EEC), + (0x43FAB725), (0xA4144419), (0x69BB6AAF), (0xCE27B744), (0x022241A9), + (0xC05DF14E), (0x8050F1FF), (0x218C2131), (0xBE25941A), (0x9041CD06), + (0x1EE8A9C0), (0xD530FEDD), (0x7495C808), (0x050918A6), (0x3CE732E9), + (0xF87262FC), (0x01B812F1), (0x1FBA4842), (0x3E86C7F2), (0x270DB358), + (0xF9D22834), (0x74D4F469), (0x9A6E87D2), (0x8CBB0A50), (0xC0784B92), + (0x278DA581), (0x9221A7D5), (0xDE801B54), (0x4B531FDA), (0xC8B91F91), + (0x7A90DA40), (0x2967A429), (0x50CC1D8D), (0x9AE9110E), (0x50F250EE), + (0xD695B072), (0xFC7A5718), (0x1F1A26E6), (0x7D5ADD4D), (0xC8978597), + (0xEB326DC3), (0x384E9824), (0xC3B9D78C), (0xD8D2E214), (0xEFFBB048), + (0x00AB7714), (0x9D89CA13), (0xF70688D0), (0xADDA3A37), (0x5FBE5943), + (0x4ED9D613), (0x8A9DCC93), (0x19814236), (0x09A68BCC), (0xCEAC33AC), + (0x0BA70BB3), (0x326272E1), (0x2A8C6D20), (0x23083D0B), (0xFA809C02), + (0x5825C6C2), (0x061B4695), (0x8DB97748), (0x5071E584), (0x08760959), + (0x44EA8D04), (0x5CE6E2AA), (0x009AD176), (0xAEC64F19), (0xCADDA632), + (0x8D795445), (0x16E3EA24), (0xF12648CA), (0xD5CC350C), (0x615EBAD7), + (0x4E769FB6), (0x6C5EB380), (0x5BB46425), (0xEAB6C77C), (0x10945408), + (0xC1291B86), (0x913B71A5), (0x003BA329), (0x91812854), (0xE200CB12), + (0x7A4696A8), (0x76E55D25), (0xD6D3C577), (0x8B1B79B1), (0x296B04CD), + (0xA024CC35), (0x3341A477), (0x8EC12358), (0xF5982B2F), (0x36F120C9), + (0x79DBE799), (0xED74F092), (0xA1031AE3), (0xB2D98C6B), (0x358CAB73), + (0x41153C19), (0x474D4548), (0xA7E834A9), (0x999738AE), (0x50F1FFE8), + (0x88612F80), (0xFD931A21), (0x23839ABD), (0xBE604701), (0x812274B9), + (0x4CA9EA32), (0xE5F2D207), (0xC1CF4653), (0x43561B23), (0x53B2E277), + (0x4F2B00EC), (0xF2B3BA80), (0xFC708CC5), (0xE7F63F00), (0x26120342), + (0x1A49C7A8), (0xA9350A7C), (0xE530A06C), (0x5CB9E550), (0xB1672913), + (0x65FA76F9), (0xC9F92DCA), (0x7D4E9195), (0x4DBB8265), (0x2036E26C), + (0xEDC026E6), (0xB9A617E0), (0x6469F0EE), (0xE9DAABB2), (0x26063210), + (0xAC545DF4), (0x134E035A), (0x216EDE10), (0xEC81158D), (0x122A2CAE), + (0xA263D0E1), (0x6CA1FB28), (0xBE287DF0), (0x548104E8), (0x35987D93), + (0xBC3E549C), (0x3ACEFD64), (0x3348CD92), (0x914472FD), (0x80F28098), + (0xDF3FABCD), (0x24D840AC), (0xBA95321C), (0xDC211D20), (0x15041942), + (0x61858ABD), (0x546084A1), (0xCEDC07F4), (0xEAB2DE00), (0x045BC1E8), + (0x82B2AE86), (0xE4BF2823), (0x9A01B47A), (0x1769438E), (0x015C7986), + (0x5FDFF97D), (0x5F28D62C), (0x83C84C8C), (0xDBAC601A), (0x1AE2844F), + (0x79F9DC1C), (0x01C3AB5C), (0xC971D839), (0x44DEA398), (0xC0A64EA1), + (0x387E24A5), (0x0600D59F), (0x5169B371), (0xEC782B6B), (0xF7FF769D), + (0x317B0AE8), (0xE33846C7), (0x2FE05849), (0x03273853), (0x2ED27A88), + (0x24DF4343), (0xFB03C70F), (0x82783231), (0xD31C0D29), (0xADC5BD8B), + (0x7D024F1B), (0x91C18D19), (0xA8EE58E2), (0x4C23A59F), (0xC61DCA9F), + (0x03BC91EC), (0x51986147), (0x05B8BE24), (0x872AC918), (0x8050F1FF), + (0x2184812F), (0xB20D941A), (0x9141CB0C), (0xF600A340), (0x80E82AC2), + (0x66028631), (0x120FFA45), (0x889F24CB), (0x81F0BB27), (0x3100D51A), + (0x2309A0B3), (0xAE004718), (0xAA584A8D), (0x9432DD2E), (0xDD0E93FA), + (0xC12993A6), (0x6E28035D), (0x9BF7772B), (0x1D608C32)}; + +static const INT __twiddles_mips_fft32_1024[] = { + (0x7FFFFFFF), (0x00000000), (0x7FFF6215), (0xFF36F078), (0x7FFD8859), + (0xFE6DE2E0), (0x7FFA72D0), (0xFDA4D929), (0x7FF62181), (0xFCDBD540), + (0x7FF09476), (0xFC12D91B), (0x7FE9CBBE), (0xFB49E6A3), (0x7FE1C76A), + (0xFA80FFCE), (0x7FD8878C), (0xF9B82681), (0x7FCE0C3D), (0xF8EF5CBC), + (0x7FC25595), (0xF826A464), (0x7FB563B2), (0xF75DFF6B), (0x7FA736B2), + (0xF6956FB7), (0x7F97CEBB), (0xF5CCF73E), (0x7F872BF2), (0xF5049800), + (0x7F754E7E), (0xF43C53CB), (0x7F62368D), (0xF3742C9D), (0x7F4DE450), + (0xF2AC2473), (0x7F3857F4), (0xF1E43D1C), (0x7F2191B2), (0xF11C7895), + (0x7F0991C3), (0xF054D8DA), (0x7EF05860), (0xEF8D5FC8), (0x7ED5E5C6), + (0xEEC60F3C), (0x7EBA3A38), (0xEDFEE930), (0x7E9D55FB), (0xED37EF91), + (0x7E7F3954), (0xEC71244A), (0x7E5FE490), (0xEBAA8944), (0x7E3F5800), + (0xEAE4208A), (0x7E1D93EA), (0xEA1DEBC6), (0x7DFA98A7), (0xE957ED00), + (0x7DD6668D), (0xE8922621), (0x7DB0FDF5), (0xE7CC9912), (0x7D8A5F3C), + (0xE70747B9), (0x7D628AC7), (0xE642341C), (0x7D3980ED), (0xE57D5FE4), + (0x7D0F4217), (0xE4B8CD16), (0x7CE3CEB0), (0xE3F47D95), (0x7CB72721), + (0xE3307347), (0x7C894BDA), (0xE26CB010), (0x7C5A3D52), (0xE1A935F1), + (0x7C29FBEF), (0xE0E6068F), (0x7BF88830), (0xE02323EA), (0x7BC5E296), + (0xDF609002), (0x7B920B86), (0xDE9E4C5B), (0x7B5D03A1), (0xDDDC5B4F), + (0x7B26CB49), (0xDD1ABE41), (0x7AEF6325), (0xDC59778B), (0x7AB6CB9A), + (0xDB98888E), (0x7A7D0559), (0xDAD7F3A2), (0x7A4210DE), (0xDA17BA63), + (0x7A05EEA8), (0xD957DE6F), (0x79C89F71), (0xD898621A), (0x798A23A8), + (0xD7D946C3), (0x794A7C11), (0xD71A8EBA), (0x7909A935), (0xD65C3B98), + (0x78C7AB9E), (0xD59E4EF9), (0x78848419), (0xD4E0CB28), (0x78403321), + (0xD423B181), (0x77FAB98A), (0xD367044F), (0x77B417D4), (0xD2AAC4EB), + (0x776C4ED9), (0xD1EEF59D), (0x77235F35), (0xD13397FA), (0x76D94983), + (0xD078AD93), (0x768E0EA9), (0xCFBE38AD), (0x7641AF32), (0xCF043A9E), + (0x75F42C0B), (0xCE4AB5A6), (0x75A585D9), (0xCD91AB55), (0x7555BD47), + (0xCCD91D37), (0x7504D34C), (0xCC210D8B), (0x74B2C87B), (0xCB697DA0), + (0x745F9DD3), (0xCAB26FB2), (0x740B53ED), (0xC9FBE50E), (0x73B5EBCF), + (0xC945DFEB), (0x735F662F), (0xC89061D1), (0x7307C3C9), (0xC7DB6C45), + (0x72AF05AB), (0xC727017A), (0x72552C79), (0xC67322B9), (0x71FA3948), + (0xC5BFD232), (0x719E2CDE), (0xC50D1164), (0x71410800), (0xC45AE1D1), + (0x70E2CBCD), (0xC3A945A1), (0x708378F4), (0xC2F83E1B), (0x7023109C), + (0xC247CD62), (0x6FC19376), (0xC197F4BB), (0x6F5F02CF), (0xC0E8B67E), + (0x6EFB5F1D), (0xC03A137E), (0x6E96A995), (0xBF8C0DD8), (0x6E30E32F), + (0xBEDEA73A), (0x6DCA0D27), (0xBE31E1BF), (0x6D6227FA), (0xBD85BE33), + (0x6CF934E8), (0xBCDA3EAE), (0x6C8F3538), (0xBC2F6544), (0x6C242969), + (0xBB8532C0), (0x6BB812C5), (0xBADBA934), (0x6B4AF258), (0xBA32CA42), + (0x6ADCC976), (0xB98A97F6), (0x6A6D98A1), (0xB8E31318), (0x69FD6132), + (0xB83C3DB1), (0x698C2487), (0xB79619C6), (0x6919E326), (0xB6F0A81D), + (0x68A69E72), (0xB64BEAB9), (0x68325786), (0xB5A7E331), (0x67BD0FCC), + (0xB5049380), (0x6746C7D1), (0xB461FC6A), (0x66CF8103), (0xB3C01FE9), + (0x66573CD5), (0xB31EFFF0), (0x65DDFBD6), (0xB27E9D43), (0x6563BF7E), + (0xB1DEF9D2), (0x64E8894A), (0xB140178C), (0x646C59CC), (0xB0A1F730), + (0x63EF3286), (0xB0049AA9), (0x637114AB), (0xAF68037B), (0x62F201C4), + (0xAECC338B), (0x6271FA69), (0xAE312B94), (0x61F10027), (0xAD96ED77), + (0x616F148E), (0xACFD7B13), (0x60EC383A), (0xAC64D51F), (0x60686CC0), + (0xABCCFD75), (0x5FE3B366), (0xAB35F58C), (0x5F5E0DC8), (0xAA9FBF38), + (0x5ED77C86), (0xAA0A5B2C), (0x5E500140), (0xA975CB39), (0x5DC79D9C), + (0xA8E2112C), (0x5D3E523E), (0xA84F2DB4), (0x5CB420CD), (0xA7BD229A), + (0x5C290AA0), (0xA72BF148), (0x5B9D1166), (0xA69B9B7D), (0x5B1035C7), + (0xA60C21E8), (0x5A827978), (0xA57D8646), (0x59F3DE30), (0xA4EFCA51), + (0x5964649B), (0xA462EEB2), (0x58D40E75), (0xA3D6F51F), (0x5842DD7E), + (0xA34BDF4B), (0x57B0D265), (0xA2C1ADDA), (0x571DEEED), (0xA238627B), + (0x568A3482), (0xA1AFFE81), (0x55F5A4ED), (0xA1288391), (0x556040E2), + (0xA0A1F24F), (0x54CA0A2E), (0xA01C4C5C), (0x543302A5), (0x9F979356), + (0x539B2AFB), (0x9F13C7DC), (0x53028507), (0x9E90EB88), (0x52691241), + (0x9E0EFF9D), (0x51CED486), (0x9D8E05AD), (0x5133CC8F), (0x9D0DFE52), + (0x5097FC3C), (0x9C8EEB1A), (0x4FFB6572), (0x9C10CD90), (0x4F5E08EB), + (0x9B93A649), (0x4EBFE88F), (0x9B1776CB), (0x4E2105E4), (0x9A9C4048), + (0x4D8162D8), (0x9A22043F), (0x4CE1002B), (0x99A8C340), (0x4C3FDFCC), + (0x99307EC5), (0x4B9E03B1), (0x98B93843), (0x4AFB6C9B), (0x9842F048), + (0x4A581C83), (0x97CDA844), (0x49B41562), (0x975961A2), (0x490F57FF), + (0x96E61CED), (0x4869E657), (0x9673DB8C), (0x47C3C202), (0x96029E99), + (0x471CED05), (0x95926772), (0x46756827), (0x9523369D), (0x45CD356F), + (0x94B50D74), (0x452456E9), (0x9447ED4D), (0x447ACD5D), (0x93DBD6AA), + (0x43D09AD9), (0x9370CADA), (0x4325C102), (0x9306CAE7), (0x427A417D), + (0x929DD7D5), (0x41CE1ECD), (0x9235F32C), (0x412158E3), (0x91CF1CE3), + (0x4073F245), (0x9169567D), (0x3FC5ECA0), (0x9104A0F4), (0x3F17499F), + (0x90A0FD42), (0x3E680AF3), (0x903E6C5D), (0x3DB8324C), (0x8FDCEF37), + (0x3D07C23C), (0x8F7C873A), (0x3C56BAB5), (0x8F1D3461), (0x3BA51E4D), + (0x8EBEF810), (0x3AF2EEBA), (0x8E61D331), (0x3A402DB4), (0x8E05C6AA), + (0x398CDCF3), (0x8DAAD35D), (0x38D8FE32), (0x8D50FA2B), (0x38249413), + (0x8CF83C62), (0x376F9E88), (0x8CA099FB), (0x36BA2034), (0x8C4A1440), + (0x36041AD7), (0x8BF4AC06), (0x354D9033), (0x8BA06221), (0x3496820A), + (0x8B4D375F), (0x33DEF21F), (0x8AFB2C8E), (0x3326E323), (0x8AAA42E0), + (0x326E5505), (0x8A5A7A4D), (0x31B54A79), (0x8A0BD403), (0x30FBC547), + (0x89BE50C2), (0x3041C737), (0x8971F14B), (0x2F875216), (0x8926B65A), + (0x2ECC67AF), (0x88DCA0A9), (0x2E110ABF), (0x8893B14A), (0x2D553B35), + (0x884BE838), (0x2C98FBD1), (0x88054682), (0x2BDC4E63), (0x87BFCCD5), + (0x2B1F34BC), (0x877B7BDD), (0x2A61B0AF), (0x87385443), (0x29A3C40F), + (0x86F656AC), (0x28E571A3), (0x86B5840E), (0x2826B95E), (0x8675DC62), + (0x27679E06), (0x8637609A), (0x26A82174), (0x85FA114F), (0x25E84581), + (0x85BDEF19), (0x25280C05), (0x8582FA8C), (0x246777D0), (0x85493482), + (0x23A688D3), (0x85109CF7), (0x22E541E0), (0x84D934C0), (0x2223A4D2), + (0x84A2FC68), (0x2161B389), (0x846DF472), (0x209F6FE1), (0x843A1D62), + (0x1FDCDBBB), (0x840777B9), (0x1F19F9F0), (0x83D60431), (0x1E56CA6E), + (0x83A5C2C5), (0x1D935011), (0x8376B42E), (0x1CCF8CBB), (0x8348D8DF), + (0x1C0B824E), (0x831C314A), (0x1B4732AE), (0x82F0BDDB), (0x1A829FC0), + (0x82C67F00), (0x19BDCC63), (0x829D7553), (0x18F8B888), (0x8275A0D1), + (0x18336710), (0x824F0211), (0x176DD9E1), (0x82299974), (0x16A812E3), + (0x82056754), (0x15E213FD), (0x81E26C0B), (0x151BDF19), (0x81C0A7F1), + (0x1455771D), (0x81A01B80), (0x138EDBF8), (0x8180C6B6), (0x12C81090), + (0x8162AA0A), (0x120116D2), (0x8145C5C8), (0x1139F0A7), (0x812A1A36), + (0x10729FFB), (0x810FA798), (0x0FAB26B9), (0x80F66E30), (0x0EE387CD), + (0x80DE6E5A), (0x0E1BC326), (0x80C7A813), (0x0D53DBAF), (0x80B21BB4), + (0x0C8BD356), (0x809DC971), (0x0BC3AC07), (0x808AB17E), (0x0AFB67B2), + (0x8078D407), (0x0A330844), (0x8068313B), (0x096A90AB), (0x8058C955), + (0x08A200D7), (0x804A9C53), (0x07D95BB6), (0x803DAA6D), (0x0710A337), + (0x8031F3C3), (0x0647D949), (0x80277871), (0x057EFFDC), (0x801E3892), + (0x04B618DF), (0x8016343D), (0x03ED2743), (0x800F6B8D), (0x03242AF6), + (0x8009DE81), (0x025B26E9), (0x80058D31), (0x01921D0C), (0x800277A7), + (0x00C90F4F), (0x80009DEB), (0xFFFFFFA3), (0x80000002), (0xFF36F0F5), + (0x80009DEB), (0xFE6DE338), (0x800277A6), (0xFDA4D95B), (0x80058D2F), + (0xFCDBD54E), (0x8009DE7F), (0xFC12D902), (0x800F6B8A), (0xFB49E665), + (0x80163444), (0xFA80FF69), (0x801E389A), (0xF9B826FB), (0x8027786E), + (0xF8EF5D0E), (0x8031F3BF), (0xF826A48E), (0x803DAA69), (0xF75DFF6D), + (0x804A9C4E), (0xF6956F99), (0x8058C950), (0xF5CCF701), (0x8068314A), + (0xF5049793), (0x8078D418), (0xF43C543D), (0x808AB177), (0xF3742CEE), + (0x809DC96B), (0xF2AC2495), (0x80B21BAD), (0xF1E43D1E), (0x80C7A80C), + (0xF11C7877), (0x80DE6E52), (0xF054D88D), (0x80F66E47), (0xEF8D5F4B), + (0x810FA7B0), (0xEEC60F9D), (0x812A1A2D), (0xEDFEE972), (0x8145C5BE), + (0xED37EFB3), (0x8162AA00), (0xEC71244C), (0x8180C6AB), (0xEBAA8927), + (0x81A01B75), (0xEAE4202D), (0x81C0A810), (0xEA1DEB4A), (0x81E26C2C), + (0xE957ED61), (0x82056748), (0xE8922662), (0x82299967), (0xE7CC9933), + (0x824F0204), (0xE70747BB), (0x8275A0C3), (0xE64233E0), (0x829D7545), + (0xE57D5F89), (0x82C67F27), (0xE4B8CC9B), (0x82F0BE03), (0xE3F47DF5), + (0x831C313B), (0xE3307388), (0x8348D8D0), (0xE26CB031), (0x8376B41E), + (0xE1A935D4), (0x83A5C2B5), (0xE0E60653), (0x83D60420), (0xE023238F), + (0x840777E8), (0xDF608F69), (0x843A1D92), (0xDE9E4CB9), (0x846DF460), + (0xDDDC5B6F), (0x84A2FC55), (0xDD1ABE62), (0x84D934AE), (0xDC59776E), + (0x85109CE4), (0xDB988872), (0x8549346E), (0xDAD7F348), (0x8582FAC2), + (0xDA17BAC1), (0x85BDEF05), (0xD957DECD), (0x85FA113A), (0xD898623B), + (0x86376085), (0xD7D946E3), (0x8675DC4D), (0xD71A8E9D), (0x86B583F8), + (0xD65C3B40), (0x86F656E9), (0xD59E4EA0), (0x87385481), (0xD4E0CB84), + (0x877B7BC6), (0xD423B1DD), (0x87BFCCBD), (0xD367046F), (0x8805466A), + (0xD2AAC50A), (0x884BE820), (0xD1EEF581), (0x8893B132), (0xD13397A2), + (0x88DCA0EE), (0xD078AD3C), (0x8926B6A0), (0xCFBE3908), (0x8971F132), + (0xCF043AF8), (0x89BE50A8), (0xCE4AB5C6), (0x8A0BD3E8), (0xCD91AB39), + (0x8A5A7A32), (0xCCD91D1C), (0x8AAA42C5), (0xCC210D35), (0x8AFB2CDB), + (0xCB697D4B), (0x8B4D37AC), (0xCAB2700B), (0x8BA06204), (0xC9FBE567), + (0x8BF4ABE9), (0xC945E00A), (0x8C4A1423), (0xC89061B6), (0x8CA099DE), + (0xC7DB6C2A), (0x8CF83C44), (0xC7270126), (0x8D50FA7F), (0xC6732265), + (0x8DAAD3B2), (0xC5BFD1A5), (0x8E05C6FF), (0xC50D109F), (0x8E61D388), + (0xC45AE10D), (0x8EBEF868), (0xC3A94669), (0x8F1D33C8), (0xC2F83EE1), + (0x8F7C86A0), (0xC247CDF0), (0x8FDCEF16), (0xC197F548), (0x903E6C3B), + (0xC0E8B69C), (0x90A0FD21), (0xC03A139B), (0x9104A0D2), (0xBF8C0DF6), + (0x9169565A), (0xBEDEA758), (0x91CF1CC0), (0xBE31E16E), (0x9235F309), + (0xBD85BDE2), (0x929DD837), (0xBCDA3E5E), (0x9306CB49), (0xBC2F6487), + (0x9370CB3D), (0xBB853205), (0x93DBD70E), (0xBADBA879), (0x9447EDB3), + (0xBA32CB35), (0x94B50D09), (0xB98A987D), (0x95233631), (0xB8E3139E), + (0x95926705), (0xB83C3E37), (0x96029E73), (0xB79619E2), (0x9673DB66), + (0xB6F0A839), (0x96E61CC6), (0xB64BEAD5), (0x9759617B), (0xB5A7E34D), + (0x97CDA867), (0xB5049334), (0x9842F06B), (0xB461FC1F), (0x98B93866), + (0xB3C01F9D), (0x99307F35), (0xB31EFF3F), (0x99A8C3B0), (0xB27E9C92), + (0x9A2204B0), (0xB1DEF922), (0x9A9C4109), (0xB140180C), (0x9B177652), + (0xB0A1F7AF), (0x9B93A5CF), (0xB0049B27), (0x9C10CD15), (0xAF6803F9), + (0x9C8EEAEF), (0xAECC33A5), (0x9D0DFE27), (0xAE312BAE), (0x9D8E0581), + (0xAD96ED91), (0x9E0EFFC3), (0xACFD7ACC), (0x9E90EBAF), (0xAC64D4D8), + (0x9F13C803), (0xABCCFD2E), (0x9F97937D), (0xAB35F545), (0xA01C4CD8), + (0xAA9FBE92), (0xA0A1F2CC), (0xAA0A5A88), (0xA128840F), (0xA975CC0F), + (0xA1AFFDFC), (0xA8E211A2), (0xA23861F5), (0xA84F2E2A), (0xA2C1AD53), + (0xA7BD2310), (0xA34BDEC3), (0xA72BF1BC), (0xA3D6F4F0), (0xA69B9B96), + (0xA462EE82), (0xA60C2200), (0xA4EFCA21), (0xA57D865E), (0xA57D8670), + (0xA4EFCA0F), (0xA60C2213), (0xA462EE70), (0xA69B9BA8), (0xA3D6F4DE), + (0xA72BF1CF), (0xA34BDEB2), (0xA7BD2322), (0xA2C1AD42), (0xA84F2E3D), + (0xA23861E4), (0xA8E211B5), (0xA1AFFF45), (0xA975CAA9), (0xA12883FE), + (0xAA0A5A9B), (0xA0A1F2BB), (0xAA9FBEA5), (0xA01C4CC7), (0xAB35F559), + (0x9F97936C), (0xABCCFD41), (0x9F13C7F2), (0xAC64D4EB), (0x9E90EB9E), + (0xACFD7ADF), (0x9E0EFFB3), (0xAD96EDA5), (0x9D8E0571), (0xAE312BC2), + (0x9D0DFE16), (0xAECC33B9), (0x9C8EEADF), (0xAF68040D), (0x9C10CD05), + (0xB0049B3B), (0x9B93A5BF), (0xB0A1F7C3), (0x9B177642), (0xB1401820), + (0x9A9C40F9), (0xB1DEF936), (0x9A2204A1), (0xB27E9CA6), (0x99A8C3A1), + (0xB31EFF54), (0x99307F26), (0xB3C01FB2), (0x98B93857), (0xB461FC33), + (0x9842F05C), (0xB5049349), (0x97CDA858), (0xB5A7E362), (0x9759616C), + (0xB64BEAEA), (0x96E61CB8), (0xB6F0A84E), (0x9673DB57), (0xB79619F7), + (0x96029E64), (0xB83C3E4C), (0x959266F7), (0xB8E313B4), (0x95233623), + (0xB98A9893), (0x94B50E13), (0xBA32C99E), (0x9447EDA5), (0xBADBA88F), + (0x93DBD700), (0xBB85321A), (0x9370CB30), (0xBC2F649D), (0x9306CB3C), + (0xBCDA3E74), (0x929DD829), (0xBD85BDF8), (0x9235F2FC), (0xBE31E184), + (0x91CF1CB3), (0xBEDEA76E), (0x9169564D), (0xBF8C0E0C), (0x9104A0C5), + (0xC03A13B2), (0x90A0FD14), (0xC0E8B6B2), (0x903E6C2F), (0xC197F55F), + (0x8FDCEF09), (0xC247CE07), (0x8F7C8694), (0xC2F83EF8), (0x8F1D34AD), + (0xC3A944BC), (0x8EBEF85C), (0xC45AE123), (0x8E61D37C), (0xC50D10B6), + (0x8E05C6F4), (0xC5BFD1BC), (0x8DAAD3A6), (0xC673227C), (0x8D50FA73), + (0xC727013D), (0x8CF83C39), (0xC7DB6C41), (0x8CA099D3), (0xC89061CD), + (0x8C4A1418), (0xC945E021), (0x8BF4ABDF), (0xC9FBE57E), (0x8BA061F9), + (0xCAB27022), (0x8B4D3738), (0xCB697E4C), (0x8AFB2C68), (0xCC210E37), + (0x8AAA4254), (0xCCD91E1E), (0x8A5A7A8D), (0xCD91AA66), (0x8A0BD442), + (0xCE4AB4F1), (0x89BE5100), (0xCF043A24), (0x8971F188), (0xCFBE3833), + (0x8926B697), (0xD078AD53), (0x88DCA0E4), (0xD13397BA), (0x8893B128), + (0xD1EEF599), (0x884BE817), (0xD2AAC522), (0x88054661), (0xD3670487), + (0x87BFCCB5), (0xD423B1F5), (0x877B7BBD), (0xD4E0CB9C), (0x87385424), + (0xD59E4FAA), (0x86F6568E), (0xD65C3C4A), (0x86B5839E), (0xD71A8FA8), + (0x8675DC95), (0xD7D94608), (0x863760CC), (0xD8986160), (0x85FA1180), + (0xD957DDF1), (0x85BDEF49), (0xDA17B9E5), (0x8582FABB), (0xDAD7F360), + (0x85493467), (0xDB98888A), (0x85109CDD), (0xDC597787), (0x84D934A7), + (0xDD1ABE7A), (0x84A2FC4F), (0xDDDC5B88), (0x846DF45A), (0xDE9E4CD2), + (0x843A1D4B), (0xDF60907A), (0x840777A2), (0xE02324A0), (0x83D603DC), + (0xE0E60764), (0x83A5C2EC), (0xE1A934F4), (0x8376B454), (0xE26CAF51), + (0x8348D904), (0xE33072A7), (0x831C316D), (0xE3F47D14), (0x82F0BDFE), + (0xE4B8CCB4), (0x82C67F21), (0xE57D5FA2), (0x829D7540), (0xE64233F9), + (0x8275A0BE), (0xE70747D4), (0x824F0200), (0xE7CC994C), (0x82299962), + (0xE892267C), (0x82056743), (0xE957ED7A), (0x81E26BFB), (0xEA1DEC5F), + (0x81C0A7E1), (0xEAE42143), (0x81A01B48), (0xEBAA8A3D), (0x8180C6CF), + (0xEC712368), (0x8162AA22), (0xED37EECF), (0x8145C5DF), (0xEDFEE88E), + (0x812A1A4C), (0xEEC60EB9), (0x810FA7AD), (0xEF8D5F65), (0x80F66E44), + (0xF054D8A6), (0x80DE6E4F), (0xF11C7891), (0x80C7A809), (0xF1E43D38), + (0x80B21BAA), (0xF2AC24AF), (0x809DC968), (0xF3742D08), (0x808AB175), + (0xF43C5456), (0x8078D3FF), (0xF50498AB), (0x80683134), (0xF5CCF819), + (0x8058C93B), (0xF69570B2), (0x804A9C5E), (0xF75DFE87), (0x803DAA77), + (0xF826A3A8), (0x8031F3CB), (0xF8EF5C28), (0x80277879), (0xF9B82615), + (0x801E3899), (0xFA80FF82), (0x80163443), (0xFB49E67F), (0x800F6B8A), + (0xFC12D91B), (0x8009DE7E), (0xFCDBD568), (0x80058D2F), (0xFDA4D975), + (0x800277A6), (0xFE6DE352), (0x80009DEA), (0xFF36F10F), (0x656DBCC8), + (0x7A9108CA), (0xBA3670F0), (0x699195A2), (0x172D2FD0), (0xBE386D51), + (0xC4AEA51C), (0x2AA77D7D), (0x8B51D3B4), (0xCF490FD9), (0x4A7BEBCA), + (0x91072E04), (0xA175872D), (0x54464A9E), (0x67A6CD02), (0x9E8204A8), + (0x10C14BF6), (0x75ACDA16), (0xF78D7B3E), (0x6AB3CF69), (0xA4D8C756), + (0xCB8FCD24), (0x75CC5713), (0xC13E5AE3), (0xA8C3176D), (0x5EE6D416), + (0x80C5DA0E), (0xD84A007C), (0x719E73C0), (0x765014B0), (0x0A391BC8), + (0x60A70223), (0x54CDA46B), (0x4606D455), (0xA606FB2A), (0xE4CE1557), + (0x73240820), (0x8037A8B4), (0xA1D88032), (0x75A3F1C7), (0x32BB0370), + (0x5F850242), (0x85EC8F5B), (0x8AA2B33C), (0x91B370C2), (0x938E9DDB), + (0xE6B6983E), (0x49602AA9), (0x6C2D9965), (0x5B16AE72), (0x69579B6B), + (0xCD3AB415), (0x5B7CF03C), (0xD7B27637), (0x2D69B79A), (0x3237B468), + (0x5F94D650), (0xAB37106D), (0x0B831457), (0xAFD80334), (0xB5A0B27B), + (0x16B763E9), (0x3B454756), (0x3167CD98), (0x707239AF), (0x0A4F132A), + (0x2782C8CA), (0x1AC1DD4E), (0x121CADFE), (0x9A911D90), (0x0157ADD6), + (0x1559BB95), (0x2854C84A), (0xD97E3685), (0x76308AA0), (0x8050F1FF), + (0x2180612F), (0xFFFB8A1A), (0x0BC1FFFF), (0x1032846C), (0x002A30C2), + (0x654C58F2), (0xA58ABACC), (0xC3E9831C), (0x27531B8C), (0xADBB8698), + (0x06801C12), (0xAFAEEC8E), (0xC3269291), (0x5C2E01A0), (0x4A61087C), + (0x60F21E7B), (0x6B92C670), (0xC9872364), (0x48464C97), (0x342E6499), + (0xA6849A48), (0xF034002D), (0x442B4488), (0x160B0442), (0xED52CF50), + (0x4D436C05), (0x6841C602), (0xA14F8A82), (0x9AC20DDE), (0x5B9251EE), + (0x8ED998D5), (0x92B6EA22), (0x5B136C4B), (0x97C0A45B), (0x459C94A4), + (0xCD9583C0), (0x6C589DF8), (0x3C9A17CD), (0x906601BF), (0x84D612E1), + (0x67176F5F), (0xE47D5A44), (0x37386D5E), (0x92A4D61B), (0x28C513FB), + (0x6E91599A), (0x653DA16D), (0xA19C39C0), (0x427690AD), (0x7005461C), + (0xAB6C1EE4), (0x80BACC2D), (0x780A18C5), (0x822DC774), (0xB6043036), + (0x00789C18), (0x106C9507), (0x4103A864), (0xC511585B), (0xF3E9B7F8), + (0x24D79C4D), (0x31B20EB5), (0xB1C0483E), (0xE25C56B9), (0x96991096), + (0x7CD4121F), (0x8A3B83F4), (0x704271C2), (0xB5C26ACC), (0x2B131AF0), + (0x549CB16C), (0x74649E69), (0xD8D48ADE), (0x1253AEDD), (0x80410FD2), + (0x5B36889D), (0x880CE1E7), (0x56C498E7), (0xFA2BAAB2), (0xD4154F5C), + (0x79516EED), (0xA42FDA7D), (0x278D2873), (0x19121535), (0x9C6EC6C7), + (0x402340CB), (0x5A6A32B3), (0xE4345F27), (0x8DC2D901), (0x02E7F88E), + (0x7B3C6BEB), (0xE0946A4F), (0x9452886C), (0xFF2F6187), (0x2F8050F1), + (0x2A217C61), (0x0AB21594), (0x801145C4), (0x1CF200A5), (0x82C544F1), + (0xCF3C50B0), (0xD577FEF7), (0x60AD3C6E), (0x91AFF79E), (0x070723B3), + (0x5870ECF6), (0x64C224E2), (0x24FB1EC8), (0xC3481048), (0x151ABF3C), + (0x136AC219), (0x4716CED1), (0xC8B8CE4E), (0x1D168210), (0x92334A81), + (0x90DC910C), (0x49A00220), (0xE5F2C831), (0xB67DC785), (0x3C495174), + (0x0D1F4C2A), (0x3AD787FD), (0xE9C9FB27), (0x7DFC2713), (0xEB39C4B3), + (0x96F75F18), (0x883CCC47), (0x91390BD1), (0x0EE25F6D), (0x6B688EF0), + (0x2C8557DC), (0xE80C9172), (0xDE63DE06), (0x3E1B707B), (0xB2CF2E76), + (0x490D1DF3), (0xCD1B51E1), (0xC228F0F9), (0xEEE2A00A), (0x081D834A), + (0x1D2C1403), (0x083FE940), (0x7614EDA0), (0x8282095A), (0xA7C08821), + (0x4CD47D20), (0x32299191), (0x52A030E6), (0xDF7CB76E), (0x232ED44B), + (0x8DAA150A), (0x1B593C51), (0x449CBA82), (0xABE6D3C4), (0xCCF6F5C3), + (0x9064C1C2), (0x031FF59C), (0x4159FE4E), (0x421482C0), (0x20F6F00A), + (0xB866CA49), (0x75A66FAA), (0x5453515F), (0xB545D486), (0x885D9493), + (0xEEC4EEB4), (0x88F9C893), (0xBBAA38B4), (0x5A57BA83), (0x12E848CC), + (0x2FB62160), (0x840A1A54), (0x2A7AEDD6), (0x89AF2DBD), (0xC8BAAE2E), + (0x56EEBD75), (0xE595B86D), (0xEEB123C6), (0x3F94EBC1), (0x78CFBEE2), + (0xCF901F11), (0x5A35A350), (0xDA22CB58), (0xBE4B8287), (0x25E078C0), + (0x2BD4F0D3), (0x6A464B99), (0x4884B156), (0xF1FF7630), (0xC1328050), + (0xD84C216C), (0x84A4D942), (0x2157A0A0), (0xF30A1412), (0x54AF6011), + (0x00D70542), (0xBDABE7DB), (0x1FF3534C), (0xD8672B4E), (0x7BE3BB3A), + (0xC5595540), (0x161E1BFF), (0xD4372309), (0x7BC2ED52), (0xC1C636ED), + (0x4DD32AA4), (0x86163246), (0x614EF688), (0x4EB44270), (0x88ED077C), + (0x2F229466), (0x1A585201), (0x65BB2EE2), (0xDBADA0DD), (0xE50995CB), + (0xCA1E2760), (0x583FD81F), (0xE48D4859), (0xC2006152), (0x8F1F770C), + (0x27CAA86F), (0x9610B845), (0xFC25BCE3), (0x37B8B39F), (0x10DCCDD1), + (0xD57A4CAB), (0x7D543DE8), (0x6F45B958), (0x12F0B979), (0x818E79F9), + (0xB4B2B01F), (0xF3035901), (0x372F7BD9), (0x5D592E67), (0xDB5A552F), + (0x6E61E625), (0x4E8A6A42), (0x2458ADB8), (0x5F12528C), (0x272B3ADE), + (0xDE666A83), (0x7F18CFD7), (0x2F877DD8), (0xD73FFFB6), (0x79867956), + (0x4E05FCAD), (0x19E78EEE), (0xE1BA6512), (0x99F6F091), (0x91690516), + (0x16AE4041), (0x04B96805), (0x7CA052FC), (0xA4D05EFD), (0x413D1F04), + (0x53E91CC0), (0x6F87A082), (0x604FD202), (0x0B368D9F), (0xD5F22E5C), + (0x2BE5A74E), (0x2F69EADE), (0x8BE537E1), (0x96975789), (0x3675A3A0), + (0x0A272B71), (0x754B1D61), (0x98600581), (0x659A2BE3), (0xB21BEF54), + (0xF26351B0), (0x1C599573), (0x6B423B59), (0xEA371C96), (0xC9BDA499), + (0xDDF25F37), (0xFBCAC4AD), (0x40CA788B), (0x13BC3981), (0x4176DA58), + (0xD848DA74), (0x94740642), (0x54FD5479), (0x71502362), (0x25E81CF9), + (0x53249562), (0x52814827), (0x55DC5F2C), (0x8825BC50), (0x8E4D04D9), + (0x8050F1FF), (0x212CC13E), (0x00C0D84C), (0x07711003), (0x406A5F45), + (0xED0A98DE), (0x8A619731), (0x796A3B04), (0x7EAECF71), (0x7DF3DABE), + (0x2B0FFB4A), (0xBA8A3FB8), (0x6202F8F2), (0x632C37B2), (0x205271AA), + (0xBA1C438C), (0xAA1C1182), (0xE6442A65), (0xD736E043), (0x95715C5C), + (0x3D604C28), (0xD21D0D74), (0xA1FB0C21), (0xCE8F065D), (0xB8B36463), + (0x7F788C33), (0x84AB53A5), (0x4B33AF46), (0x40C2736A), (0x0D6571B7), + (0xFC8D8292), (0x9D1C5182), (0xF7B670E2), (0xBB2B9E91), (0x137851D5), + (0xBCF87CA8), (0xE082A7A6), (0x502404E5), (0x5025A6E0), (0x25494EA6), + (0x5A6A8A14), (0xE301A689), (0x70CBEE6B), (0xC80644C1), (0xE9914CE6), + (0x9481F1E6), (0xB9E4DA34), (0x584B1ED8), (0xACC39648), (0x31EFCD62), + (0x07C82AE9), (0xEE9D90E5), (0x59BAEC75), (0x40178B0E), (0x9FDC1C9C), + (0xF3A6488F), (0x4B6C1367), (0x9F7DF109), (0xCBDF8EDF), (0xBA76ED33), + (0xF15DBB9F), (0xD48A197F), (0xF11E75EE), (0xA76B479B), (0x706DE78B), + (0x6559AC65), (0xC013C182), (0x461E93C7), (0xA989EAF1), (0x59448C00), + (0x721FAC38), (0x546DEA79), (0x223F67C0), (0x5434647C), (0xB3EF4F0A), + (0xD4FAF1F1), (0x0BD4E38A), (0xFF61527E), (0xD6EA5DD2), (0x644C7105), + (0x31AE2189), (0x11EC0A1A), (0x18B3AD80), (0x47D0E80A), (0x773D8BB2), + (0xEFA6747E), (0xF23DE8B0), (0x026BB1E7), (0x03C14060), (0xC1997DF7), + (0x95986B9C), (0x8A5D6170), (0x54DB3A56), (0x22961D41), (0x46813471), + (0xABED16A4), (0xD1F83E8C), (0x2594ACAC), (0x1D5560EA), (0x0432EFF4), + (0xA389D7E8), (0xAFE92C62), (0xFBBAF1E7), (0x42D0D0A1), (0xA2C3ECB2), + (0x603DD635), (0xEBBC5915), (0x5B0C7CE0), (0x8D03640C), (0x22E298DB), + (0x38CE3BDC), (0x21E6B6B4), (0xC9742C3F), (0x4BDF7448), (0xBAD09D00), + (0xED6A8397), (0xF6F8001A), (0x31E3591E), (0xAEC37EFE), (0x22D9AD06), + (0x5E254AEC), (0xD852D32E), (0xE1C968AE), (0xA3C3C265), (0xD67BD78A), + (0xF1FF9D8C), (0xC03A8050), (0x847A21FC), (0x810EDA5D), (0x63808951), + (0xC8FE9E9E), (0xFB6DD3E5), (0x77BD7A03), (0x6DC14677), (0xFF81D831), + (0x43201100), (0xA78E16FE), (0x393CD0A0), (0x514F6DDD), (0x427BA4BC), + (0xEBE7A676), (0xB771639B), (0x8DABB9E7), (0x812FA5AD), (0x3F102120), + (0x60E42454), (0xEFFBFFC5), (0xBEB1D5DD), (0x7A59DDFD), (0xE8968D7A), + (0x8AAD3462), (0xAB65327D), (0x0CF2ECFB), (0xFA3249A4), (0x97FC3A42), + (0x314A7089), (0x2991E6DC), (0xA98693C4), (0x65EB2011), (0xCB4D8594), + (0x1AAFF14E), (0x1D0D0492), (0x2E5A784D), (0xAE4EC738), (0xF16D667A), + (0xB0C26030), (0xADA3DFC9), (0x4ED874E5), (0xD441A6AE), (0x19E3AC05), + (0xC6B865DC), (0xE8E4285A), (0x99248C2B), (0xC2981122), (0x1B014288), + (0x442A0580), (0x84A0A1C1), (0x216F0248), (0x202E5602), (0xEAEBAACA), + (0xDD5ABEE7), (0x8B9C4B43), (0x5D5D46D7), (0x8FBE7C1D), (0x6F9CAB87), + (0xB0AB0AAE), (0x98BC7936), (0xF251B911), (0x4469F2D1), (0xA9099088), + (0xD219BD66), (0x7490AE22), (0xBC0A9820), (0x119D0136), (0x8592661C), + (0x260C0D18), (0xB9A1C5B1), (0xA68591E4), (0xFCBD4F29), (0x5965A3C7), + (0x7D1ED664), (0x9BDDEEE3), (0x92237D5A), (0xB7332DA6), (0xEA5632E5), + (0x9BFE1624), (0x6A2BB18A), (0x8C0DD72C), (0x4F319F56), (0xEE8B5B03), + (0x60967BC8), (0xB4918F75), (0xF295D5F6), (0x652AD80D), (0x0CCE9552), + (0x0BCAA0A6), (0x3CF2D28E), (0x1853956E), (0x7B38DEAA), (0xEAAB970B), + (0x64086D1F), (0x3E7645DD), (0x986F1342), (0xBBB0E188), (0x7D6D5642), + (0x6821827D), (0xFCBC4729), (0x3D114FB9), (0x2D2542E5), (0x654CC1F0), + (0x04F1B75E), (0x290B54AF), (0x7D79AB1A), (0xF34E31A2), (0x73A9F300), + (0x7ABCA89E), (0xB56DA974), (0xCACDB07C), (0x4EE1ADD4), (0xEF859B34), + (0x89F47B47), (0x515C155A), (0x38D06757), (0x8050F1FF), (0x21C8E03A), + (0xB155841A), (0x30716685), (0x0A2B48AC), (0x7041C40A), (0x104C44D0), + (0x1F51B618), (0xF0D4F39B), (0xFCAEBA52), (0x30EA62CD), (0xA294B772), + (0x221E0417), (0xAA8EF192), (0x3E568C78), (0xD386EF9A), (0x13B54FB1), + (0x84818EC3), (0xB87669F8), (0xCD90565A), (0x73D7C876), (0xD6191512), + (0xAC228704), (0xA7785D48), (0x17CF34DD), (0x8AF5AB40), (0x365C6AFA), + (0x17DFD59E), (0xB924C26E), (0xE9DE5844), (0x3DCDDCD9), (0xCDA2DFB4), + (0x8A5B534E), (0xA2D9DACA), (0x11679569), (0xAEF6E7E9), (0xC9D2417C), + (0x515DC9C3), (0x157A5B12), (0x4C960DD6), (0xD413CC01), (0x65319545), + (0x6CF1309D), (0x000338C7), (0x460AA7FC), (0xC1FA4440), (0x0E3AE048), + (0xF4B212B5), (0xC7895D2B), (0x676AFAF3), (0xEF404F75), (0xBFCDB17C), + (0xA37FE6C6), (0x20123DD5), (0xEE96BD3B), (0x3EB8A62E), (0x068845E1), + (0xC4960216), (0x7BB11D8D), (0x2D657467), (0xFC6FACC5), (0xC21AAD31), + (0x642745F4), (0x4507E139), (0xF7369DC9), (0x6198ADEB), (0x63B98B10), + (0xDEE585AB), (0xA38EFFAC), (0x30AE1E41), (0x820667A9), (0x6B77A007), + (0x240040A7), (0xB77A7D95), (0x208893CA), (0x085B4610), (0x14234854), + (0xAC022786), (0x2D57346F), (0xB64A1A67), (0x605D45B2), (0xE051C001), + (0x9176C11D), (0x23BBE945), (0x2C03E26A), (0xC2811BAD), (0x1DD814D4), + (0x3C674B68), (0x28EC33C7), (0xD9EDE5E4), (0x5C46C248), (0x4098898F), + (0x5BA96280), (0xEFF77B91), (0x3332CA5B), (0x661CAF6B), (0x6E0D564E), + (0xB70D0863), (0x240285C0), (0xBBBD3EA7), (0xCA2E568D), (0xD1D3F612), + (0xC916115E), (0xB7FC0A6C), (0x1961AE9A), (0xB5DF3965), (0xC1B95065), + (0x89E29665), (0x3F29FBED), (0x3F1BED73), (0xC155BE1D), (0x7256AE4C), + (0x4A59797B), (0x6009D13B), (0x91850385), (0xE4545920), (0x15ECCDA1), + (0xFFC7BA20), (0x2B8050F1), (0x1A21D4C0), (0x3008BE89), (0x6C0FF317), + (0x7444D852), (0x05841411), (0x84C80022), (0x07C630E0), (0x7E6F8FA3), + (0xF3BDF3C7), (0x4C55DFF7), (0xE0B1C8D1), (0xC3F5CF4D), (0x1C22A836), + (0xB29D3315), (0xD4966541), (0x45C85800), (0xAD8DBD46), (0x2C19CFAA), + (0x540FA674), (0xC3C913D8), (0xD2183753), (0xCB9FCF26), (0x8346FC89), + (0xA3408078), (0xCFD84CC1), (0xF580F035), (0x7FD067A7), (0x87E7FCB8), + (0x09C09406), (0xDDBB3131), (0xFF79FFE1), (0xEAFBEEF1), (0xB660BCE8), + (0x99899C31), (0x9FEB22C1), (0xC75EF68F), (0x13800B99), (0xCD7F3100), + (0x09502ADC), (0x101E00E8), (0x406CB945), (0x820A1B2B), (0x68A0B082), + (0x0C1B1864), (0xB3690354), (0x63C5B5A3), (0x535EB4C8), (0xF7D86918), + (0xD1BA58FC), (0xF42910FA), (0xFBDB1929), (0xC7C0C2A4), (0xD2074752), + (0xB96803B4), (0x84065E38), (0x819AF48E), (0xE9864FF3), (0xA6E41D0E), + (0x50E7442B), (0xC7574D7B), (0x196B6AB3), (0x041D5854), (0x629162D3), + (0x042713E0), (0x9AE31297), (0x4B2F4E36), (0xCB8CE0E0), (0xB2F0682A), + (0xAB33D6F5), (0x2F53D82E), (0x66A43815), (0x4433AAA8), (0x82EA0ED5), + (0x457876F2), (0xD30BD36C), (0x8D49D28C), (0x0E68260E), (0xD056512C), + (0x7B86DB11), (0x64633661), (0x8265FF25), (0x6D2B7148), (0x529DA0D8), + (0xBC180017), (0x19AB803B), (0x83F00020), (0x50F1FF07), (0xD4C02D80), + (0xFC881A21), (0xC1BF0100), (0x5841680B), (0x103B2CC0), (0xB042C28A), + (0x2324E8A8), (0x31531430), (0xEF71DD0E), (0x7C1B9D8E), (0x0998C228), + (0xD9EC6548), (0x8EEF8448), (0x0C561CAF), (0x4BA39DFD), (0x58947FE2), + (0x959B12A2), (0x6D52EAEC), (0x1D95DDD5), (0x310C222B), (0x63634B18), + (0x4DE6C5B8), (0x526C9106), (0x49B5E8CC), (0xC3C33004), (0x605CD287), + (0x09A6390C), (0x350C33BC), (0x953050CC), (0x960552A3), (0x54F01186), + (0x0E8D7CFE), (0x459A0022), (0xC3576966), (0xB0D6F6E8), (0xB8F13AAC), + (0xE440034C), (0x36118851), (0xF51BE727), (0x2E1689A0), (0xE82CCF55), + (0x6DF4E3CB), (0xEA665663), (0xC2E53D6F), (0x9DC1F06B), (0xFCC2E878), + (0x4292D162), (0x4840C433), (0xB618DB43), (0x06092C15), (0x500134C1), + (0xA6DB8955), (0xD5E8A5BB), (0x142B7829), (0x75F42939), (0x0EBF4D10), + (0x1A2B078C), (0x7C2A5A46), (0x3EA1B9A7), (0x31AAC898), (0x1327B852), + (0x277C65A1), (0x5280CE27), (0xFF512213), (0x39B47EBF), (0x154CA000), + (0x106E7DA2), (0xAFA4C925), (0xC48CE379), (0xAB2E4573), (0x5E44B8FD), + (0xECD2A424), (0x8C5300AA), (0xE425A180), (0x6D5D0D3B), (0xA70540A8), + (0xF8ECF432), (0x884696B0), (0xB79755BF), (0x62CAD419), (0x4BBB38B6), + (0xCD5C79D7), (0x82D4E29B), (0x6DD48E91), (0xA128A3A9), (0xF2ED6726), + (0x339A63F6), (0x35D6F4EA), (0x8DC8B491), (0xCA04D09C), (0xFF074FD0), + (0x2D8050F1), (0x1A21D880), (0x1900FE88), (0x6C09D1BF), (0x56483001), + (0xC20A1A29), (0x449180A3), (0x028C5160), (0x75FAECDD), (0x6250705B), + (0x89EA010A), (0x7B9F9851), (0x9D6C5994), (0x8602C3E4), (0x03D0E863), + (0x04322251), (0x116095B7), (0x789276CA), (0x00000000), (0x00000978), + (0x8000C688), (0x8000BCD8), (0x80010000), (0x9FC3F7B8), (0xDE47BC1B), + (0xE60FB4F8), (0xEA27469D), (0xCCA1E66D), (0x8FFF7010), (0x8000BCD8), + (0x000000D0), (0x8000B4B0), (0x8FFFFB24), (0x9FC3F7B8), (0x00000000), + (0x8000B418), (0x8FFF7010), (0x8000C688), (0x000000D0), (0x9FC3FD3C), + (0xD625F8C0), (0x478D832A), (0xF693D922), (0x3617D816), (0x80000648), + (0x00000000), (0x00000003), (0x00000012), (0x9FC49964), (0x46141924), + (0x4D834205), (0x16B799A6), (0xA39494A6), (0xCCF23C60), (0x00000001), + (0x9FC47468), (0x00000000), (0x00000072), (0x00008001), (0x8FFFFB58), + (0x00000003), (0x402C7413), (0x00000016), (0x402C7413), (0x9FC48498), + (0x00000000), (0x00000002), (0x00000001), (0x00000072), (0x9FC4783C), + (0x8000C690), (0x0358CDD5), (0x00000000), (0x00008001), (0x00000072), + (0x80000648), (0x00000000), (0x00008001), (0x8000BD40), (0x1A19F8D8), + (0x00008001), (0x800003C0), (0x00000003), (0x9FC428CC), (0xF6192015), + (0xFBB77F92), (0x8F2C8BFC), (0x3C391923), (0x4014428C), (0x140045AE), + (0xFFFD2BB6), (0x2D8050F1), (0x8000BD40), (0x00000003), (0x00000000), + (0x2CC05811), (0x00008001), (0x800003C0), (0x80000648), (0x80000648), + (0x9FC4206C), (0x8FFFFD78), (0x8FFFFEEC), (0x8000C668), (0x80000648), + (0x8FFFFD78), (0x00000000), (0x00003040), (0x8000FFC0), (0x8000BCD8), + (0x80010000), (0x9FC3F7B8), (0x00000000), (0x00002CC0), (0x80013340), + (0x8000BCD8), (0x80010FD0), (0x80012548)}; diff --git a/fdk-aac/libFDK/src/mips/scale_mips.cpp b/fdk-aac/libFDK/src/mips/scale_mips.cpp new file mode 100644 index 0000000..1a3d33c --- /dev/null +++ b/fdk-aac/libFDK/src/mips/scale_mips.cpp @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: + +*******************************************************************************/ + +#if defined(__mips_dsp) + +#ifndef FUNCTION_getScalefactor_DBL +#define FUNCTION_getScalefactor_DBL +/*! + * + * \brief Calculate max possible scale factor for input vector + * + * \return Maximum scale factor + * + * This function can constitute a significant amount of computational + * complexity - very much depending on the bitrate. Since it is a rather small + * function, effective assembler optimization might be possible. + * + */ +SCALE_INLINE +INT getScalefactor(const FIXP_DBL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + + for (i = len; i != 0; i--) { + maxVal |= __builtin_mips_absq_s_w(*vector++); + } + + return fixMax((INT)0, (CntLeadingZeros(maxVal) - 1)); +} +#endif + +#endif /*__mips_dsp */ diff --git a/fdk-aac/libFDK/src/nlc_dec.cpp b/fdk-aac/libFDK/src/nlc_dec.cpp new file mode 100644 index 0000000..6e98ce0 --- /dev/null +++ b/fdk-aac/libFDK/src/nlc_dec.cpp @@ -0,0 +1,1071 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Omer Osman + + Description: SAC/SAOC Dec Noiseless Coding + +*******************************************************************************/ + +#include "nlc_dec.h" +#include "FDK_tools_rom.h" + +/* MAX_PARAMETER_BANDS defines array length in huffdec */ + +#ifndef min +#define min(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +ERROR_t sym_restoreIPD(HANDLE_FDK_BITSTREAM strm, int lav, SCHAR data[2]) { + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + + if (sum_val > lav) { + data[0] = -sum_val + (2 * lav + 1); + data[1] = -diff_val; + } else { + data[0] = sum_val; + data[1] = diff_val; + } + + if (data[0] - data[1] != 0) { + ULONG sym_bit; + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + int tmp; + tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; + } + } + + return HUFFDEC_OK; +} + +static int ilog2(unsigned int i) { + int l = 0; + + if (i) i--; + while (i > 0) { + i >>= 1; + l++; + } + + return l; +} + +static ERROR_t pcm_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1, + SCHAR* out_data_2, int offset, int num_val, + int num_levels) { + int i = 0, j = 0, idx = 0; + int max_grp_len = 0, next_val = 0; + ULONG tmp; + + int pcm_chunk_size[7] = {0}; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + case 4: + case 8: + case 15: + case 16: + case 26: + case 31: + max_grp_len = 1; + break; + default: + return HUFFDEC_NOTOK; + } + + tmp = 1; + for (i = 1; i <= max_grp_len; i++) { + tmp *= num_levels; + pcm_chunk_size[i] = ilog2(tmp); + } + + for (i = 0; i < num_val; i += max_grp_len) { + int grp_len, grp_val, data; + grp_len = min(max_grp_len, num_val - i); + data = FDKreadBits(strm, pcm_chunk_size[grp_len]); + + grp_val = data; + + for (j = 0; j < grp_len; j++) { + idx = i + (grp_len - j - 1); + next_val = grp_val % num_levels; + + if (out_data_2 == NULL) { + out_data_1[idx] = next_val - offset; + } else if (out_data_1 == NULL) { + out_data_2[idx] = next_val - offset; + } else { + if (idx % 2) { + out_data_2[idx / 2] = next_val - offset; + } else { + out_data_1[idx / 2] = next_val - offset; + } + } + + grp_val = (grp_val - next_val) / num_levels; + } + } + + return HUFFDEC_OK; +} + +static ERROR_t huff_read(HANDLE_FDK_BITSTREAM strm, + const SHORT (*nodeTab)[MAX_ENTRIES][2], + int* out_data) { + int node = 0; + int len = 0; + + do { + ULONG next_bit; + next_bit = FDKreadBits(strm, 1); + len++; + node = (*nodeTab)[node][next_bit]; + } while (node > 0); + + *out_data = node; + + return HUFFDEC_OK; +} + +static ERROR_t huff_read_2D(HANDLE_FDK_BITSTREAM strm, + const SHORT (*nodeTab)[MAX_ENTRIES][2], + SCHAR out_data[2], int* escape) { + ERROR_t err = HUFFDEC_OK; + + int huff_2D_8bit = 0; + int node = 0; + + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *escape = (node == 0); + + if (*escape) { + out_data[0] = 0; + out_data[1] = 1; + } else { + huff_2D_8bit = -(node + 1); + out_data[0] = huff_2D_8bit >> 4; + out_data[1] = huff_2D_8bit & 0xf; + } + +bail: + return err; +} + +static ERROR_t sym_restore(HANDLE_FDK_BITSTREAM strm, int lav, SCHAR data[2]) { + ULONG sym_bit = 0; + + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + + if (sum_val > lav) { + data[0] = -sum_val + (2 * lav + 1); + data[1] = -diff_val; + } else { + data[0] = sum_val; + data[1] = diff_val; + } + + if (data[0] + data[1] != 0) { + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + data[0] = -data[0]; + data[1] = -data[1]; + } + } + + if (data[0] - data[1] != 0) { + sym_bit = FDKreadBits(strm, 1); + if (sym_bit) { + int tmp; + tmp = data[0]; + data[0] = data[1]; + data[1] = tmp; + } + } + + return HUFFDEC_OK; +} + +static ERROR_t huff_dec_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, SCHAR* out_data, const INT num_val, + const INT p0_flag) + +{ + ERROR_t err = HUFFDEC_OK; + int i = 0, node = 0, offset = 0; + int od = 0, od_sign = 0; + ULONG data = 0; + int bitsAvail = 0; + + const SHORT(*partTab)[MAX_ENTRIES][2] = NULL; + const SHORT(*nodeTab)[MAX_ENTRIES][2] = NULL; + + switch (data_type) { + case t_CLD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.cld[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_ICC: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.icc[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_OLD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.old[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h1D[dim1]->nodeTab[0][0]; + break; + case t_IPD: + partTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.ipd[0][0]; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h1D[dim1].nodeTab[0][0]; + break; + default: + FDK_ASSERT(0); + err = HUFFDEC_NOTOK; + goto bail; + } + + if (p0_flag) { + if ((err = huff_read(strm, partTab, &node)) != HUFFDEC_OK) { + goto bail; + } + + out_data[0] = -(node + 1); + offset = 1; + } + + for (i = offset; i < num_val; i++) { + bitsAvail = FDKgetValidBits(strm); + if (bitsAvail < 1) { + err = HUFFDEC_NOTOK; + goto bail; + } + + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + od = -(node + 1); + + if (data_type != t_IPD) { + if (od != 0) { + bitsAvail = FDKgetValidBits(strm); + if (bitsAvail < 1) { + err = HUFFDEC_NOTOK; + goto bail; + } + + data = FDKreadBits(strm, 1); + od_sign = data; + + if (od_sign) od = -od; + } + } + + out_data[i] = od; + } + +bail: + return err; +} + +static ERROR_t huff_dec_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, const INT dim2, SCHAR out_data[][2], + const INT num_val, const INT stride, + SCHAR* p0_data[2]) { + ERROR_t err = HUFFDEC_OK; + int i = 0, lav = 0, escape = 0, escCntr = 0; + int node = 0; + unsigned long data = 0; + + SCHAR esc_data[2][28] = {{0}}; + int escIdx[28] = {0}; + const SHORT(*nodeTab)[MAX_ENTRIES][2] = NULL; + + /* LAV */ + if ((err = + huff_read(strm, (HANDLE_HUFF_NODE)&FDK_huffLavIdxNodes.nodeTab[0][0], + &node)) != HUFFDEC_OK) { + goto bail; + } + data = -(node + 1); + + switch (data_type) { + case t_CLD: + lav = 2 * data + 3; /* 3, 5, 7, 9 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.cld[0][0]; + break; + case t_ICC: + lav = 2 * data + 1; /* 1, 3, 5, 7 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.icc[0][0]; + break; + case t_OLD: + lav = 3 * data + 3; + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.old[0][0]; + break; + case t_IPD: + if (data == 0) + data = 3; + else + data--; + lav = 2 * data + 1; /* 1, 3, 5, 7 */ + nodeTab = (HANDLE_HUFF_NODE)&FDK_huffPart0Nodes.ipd[0][0]; + break; + default: + FDK_ASSERT(0); + err = HUFFDEC_NOTOK; + goto bail; + } + + /* Partition 0 */ + if (p0_data[0] != NULL) { + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *p0_data[0] = -(node + 1); + } + if (p0_data[1] != NULL) { + if ((err = huff_read(strm, nodeTab, &node)) != HUFFDEC_OK) { + goto bail; + } + *p0_data[1] = -(node + 1); + } + + switch (data_type) { + case t_CLD: + switch (lav) { + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav7[0][0]; + break; + case 9: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffCLDNodes.h2D[dim1][dim2]->lav9[0][0]; + break; + } + break; + case t_ICC: + switch (lav) { + case 1: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav1[0][0]; + break; + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffICCNodes.h2D[dim1][dim2]->lav7[0][0]; + break; + } + break; + case t_OLD: + switch (lav) { + case 3: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav3[0][0]; + break; + case 6: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav6[0][0]; + break; + case 9: + nodeTab = (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav9[0][0]; + break; + case 12: + nodeTab = + (HANDLE_HUFF_NODE)&huffOLDNodes.h2D[dim1][dim2]->lav12[0][0]; + break; + } + break; + case t_IPD: + switch (lav) { + case 1: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav1[0][0]; + break; + case 3: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav3[0][0]; + break; + case 5: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav5[0][0]; + break; + case 7: + nodeTab = + (HANDLE_HUFF_NODE)&FDK_huffIPDNodes.h2D[dim1][dim2].lav7[0][0]; + break; + } + break; + default: + break; + } + + for (i = 0; i < num_val; i += stride) { + if ((err = huff_read_2D(strm, nodeTab, out_data[i], &escape)) != + HUFFDEC_OK) { + goto bail; + } + + if (escape) { + escIdx[escCntr++] = i; + } else { + if (data_type == t_IPD) { + if ((err = sym_restoreIPD(strm, lav, out_data[i])) != HUFFDEC_OK) { + goto bail; + } + } else { + if ((err = sym_restore(strm, lav, out_data[i])) != HUFFDEC_OK) { + goto bail; + } + } + } + } /* i */ + + if (escCntr > 0) { + if ((err = pcm_decode(strm, esc_data[0], esc_data[1], 0, 2 * escCntr, + (2 * lav + 1))) != HUFFDEC_OK) { + goto bail; + } + + for (i = 0; i < escCntr; i++) { + out_data[escIdx[i]][0] = esc_data[0][i] - lav; + out_data[escIdx[i]][1] = esc_data[1][i] - lav; + } + } +bail: + return err; +} + +static ERROR_t huff_decode(HANDLE_FDK_BITSTREAM strm, SCHAR* out_data_1, + SCHAR* out_data_2, DATA_TYPE data_type, + DIFF_TYPE diff_type_1, DIFF_TYPE diff_type_2, + int num_val, CODING_SCHEME* cdg_scheme, int ldMode) { + ERROR_t err = HUFFDEC_OK; + DIFF_TYPE diff_type; + + int i = 0; + ULONG data = 0; + + SCHAR pair_vec[28][2]; + + SCHAR* p0_data_1[2] = {NULL, NULL}; + SCHAR* p0_data_2[2] = {NULL, NULL}; + + int p0_flag[2]; + + int num_val_1_int = num_val; + int num_val_2_int = num_val; + + SCHAR* out_data_1_int = out_data_1; + SCHAR* out_data_2_int = out_data_2; + + int df_rest_flag_1 = 0; + int df_rest_flag_2 = 0; + + int hufYY1; + int hufYY2; + int hufYY; + + /* Coding scheme */ + data = FDKreadBits(strm, 1); + *cdg_scheme = (CODING_SCHEME)(data << PAIR_SHIFT); + + if (*cdg_scheme >> PAIR_SHIFT == HUFF_2D) { + if ((out_data_1 != NULL) && (out_data_2 != NULL) && (ldMode == 0)) { + data = FDKreadBits(strm, 1); + *cdg_scheme = (CODING_SCHEME)(*cdg_scheme | data); + } else { + *cdg_scheme = (CODING_SCHEME)(*cdg_scheme | FREQ_PAIR); + } + } + + { + hufYY1 = diff_type_1; + hufYY2 = diff_type_2; + } + + switch (*cdg_scheme >> PAIR_SHIFT) { + case HUFF_1D: + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + if (out_data_1 != NULL) { + if ((err = huff_dec_1D(strm, data_type, hufYY1, out_data_1, + num_val_1_int, p0_flag[0])) != HUFFDEC_OK) { + goto bail; + } + } + if (out_data_2 != NULL) { + if ((err = huff_dec_1D(strm, data_type, hufYY2, out_data_2, + num_val_2_int, p0_flag[1])) != HUFFDEC_OK) { + goto bail; + } + } + + break; /* HUFF_1D */ + + case HUFF_2D: + + switch (*cdg_scheme & PAIR_MASK) { + case FREQ_PAIR: + + if (out_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &out_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_int -= 1; + out_data_1_int += 1; + } + df_rest_flag_1 = num_val_1_int % 2; + if (df_rest_flag_1) num_val_1_int -= 1; + if (num_val_1_int < 0) { + err = HUFFDEC_NOTOK; + goto bail; + } + } + if (out_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &out_data_2[0]; + + num_val_2_int -= 1; + out_data_2_int += 1; + } + df_rest_flag_2 = num_val_2_int % 2; + if (df_rest_flag_2) num_val_2_int -= 1; + if (num_val_2_int < 0) { + err = HUFFDEC_NOTOK; + goto bail; + } + } + + if (out_data_1 != NULL) { + if ((err = huff_dec_2D(strm, data_type, hufYY1, FREQ_PAIR, pair_vec, + num_val_1_int, 2, p0_data_1)) != + HUFFDEC_OK) { + goto bail; + } + if (df_rest_flag_1) { + if ((err = huff_dec_1D(strm, data_type, hufYY1, + out_data_1_int + num_val_1_int, 1, 0)) != + HUFFDEC_OK) { + goto bail; + } + } + } + if (out_data_2 != NULL) { + if ((err = huff_dec_2D(strm, data_type, hufYY2, FREQ_PAIR, + pair_vec + 1, num_val_2_int, 2, + p0_data_2)) != HUFFDEC_OK) { + goto bail; + } + if (df_rest_flag_2) { + if ((err = huff_dec_1D(strm, data_type, hufYY2, + out_data_2_int + num_val_2_int, 1, 0)) != + HUFFDEC_OK) { + goto bail; + } + } + } + + if (out_data_1 != NULL) { + for (i = 0; i < num_val_1_int - 1; i += 2) { + out_data_1_int[i] = pair_vec[i][0]; + out_data_1_int[i + 1] = pair_vec[i][1]; + } + } + if (out_data_2 != NULL) { + for (i = 0; i < num_val_2_int - 1; i += 2) { + out_data_2_int[i] = pair_vec[i + 1][0]; + out_data_2_int[i + 1] = pair_vec[i + 1][1]; + } + } + break; /* FREQ_PAIR */ + + case TIME_PAIR: + if (((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ))) { + p0_data_1[0] = &out_data_1[0]; + p0_data_1[1] = &out_data_2[0]; + + out_data_1_int += 1; + out_data_2_int += 1; + + num_val_1_int -= 1; + } + + if ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) { + diff_type = DIFF_TIME; + } else { + diff_type = DIFF_FREQ; + } + { hufYY = diff_type; } + + if ((err = huff_dec_2D(strm, data_type, hufYY, TIME_PAIR, pair_vec, + num_val_1_int, 1, p0_data_1)) != HUFFDEC_OK) { + goto bail; + } + + for (i = 0; i < num_val_1_int; i++) { + out_data_1_int[i] = pair_vec[i][0]; + out_data_2_int[i] = pair_vec[i][1]; + } + + break; /* TIME_PAIR */ + + default: + break; + } + + break; /* HUFF_2D */ + + default: + break; + } +bail: + return err; +} + +static void diff_freq_decode(const SCHAR* const diff_data, + SCHAR* const out_data, const int num_val) { + int i = 0; + out_data[0] = diff_data[0]; + + for (i = 1; i < num_val; i++) { + out_data[i] = out_data[i - 1] + diff_data[i]; + } +} + +static void diff_time_decode_backwards(const SCHAR* const prev_data, + const SCHAR* const diff_data, + SCHAR* const out_data, + const int mixed_diff_type, + const int num_val) { + int i = 0; /* default start value*/ + + if (mixed_diff_type) { + out_data[0] = diff_data[0]; + i = 1; /* new start value */ + } + for (; i < num_val; i++) { + out_data[i] = prev_data[i] + diff_data[i]; + } +} + +static void diff_time_decode_forwards(const SCHAR* const prev_data, + const SCHAR* const diff_data, + SCHAR* const out_data, + const int mixed_diff_type, + const int num_val) { + int i = 0; /* default start value*/ + + if (mixed_diff_type) { + out_data[0] = diff_data[0]; + i = 1; /* new start value */ + } + for (; i < num_val; i++) { + out_data[i] = prev_data[i] - diff_data[i]; + } +} + +static ERROR_t attach_lsb(HANDLE_FDK_BITSTREAM strm, SCHAR* in_data_msb, + int offset, int num_lsb, int num_val, + SCHAR* out_data) { + int i = 0, lsb = 0; + ULONG data = 0; + + for (i = 0; i < num_val; i++) { + int msb; + msb = in_data_msb[i]; + + if (num_lsb > 0) { + data = FDKreadBits(strm, num_lsb); + lsb = data; + + out_data[i] = ((msb << num_lsb) | lsb) - offset; + } else + out_data[i] = msb - offset; + } + + return HUFFDEC_OK; /* dummy */ +} + +ERROR_t EcDataPairDec(DECODER_TYPE DECODER, HANDLE_FDK_BITSTREAM strm, + SCHAR* aaOutData1, SCHAR* aaOutData2, SCHAR* aHistory, + DATA_TYPE data_type, int startBand, int dataBands, + int pair_flag, int coarse_flag, + int allowDiffTimeBack_flag) + +{ + ERROR_t err = HUFFDEC_OK; + + // int allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + int attachLsb_flag = 0; + int pcmCoding_flag = 0; + + int mixed_time_pair = 0, numValPcm = 0; + int quant_levels = 0, quant_offset = 0; + ULONG data = 0; + + SCHAR aaDataPair[2][28] = {{0}}; + SCHAR aaDataDiff[2][28] = {{0}}; + + SCHAR aHistoryMsb[28] = {0}; + + SCHAR* pDataVec[2] = {NULL, NULL}; + + DIFF_TYPE diff_type[2] = {DIFF_FREQ, DIFF_FREQ}; + CODING_SCHEME cdg_scheme = HUFF_1D; + DIRECTION direction = BACKWARDS; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + attachLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + + break; + + case t_ICC: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + + break; + + case t_OLD: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 16; + quant_offset = 0; + } + break; + + case t_NRG: + if (coarse_flag) { + attachLsb_flag = 0; + quant_levels = 32; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 64; + quant_offset = 0; + } + break; + + case t_IPD: + if (!coarse_flag) { + attachLsb_flag = 1; + quant_levels = 16; + quant_offset = 0; + } else { + attachLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + + default: + return HUFFDEC_NOTOK; + } + + data = FDKreadBits(strm, 1); + pcmCoding_flag = data; + + if (pcmCoding_flag) { + if (pair_flag) { + pDataVec[0] = aaDataPair[0]; + pDataVec[1] = aaDataPair[1]; + numValPcm = 2 * dataBands; + } else { + pDataVec[0] = aaDataPair[0]; + pDataVec[1] = NULL; + numValPcm = dataBands; + } + + err = pcm_decode(strm, pDataVec[0], pDataVec[1], quant_offset, numValPcm, + quant_levels); + if (err != HUFFDEC_OK) return HUFFDEC_NOTOK; + + } else { /* Differential/Huffman/LSB Coding */ + + if (pair_flag) { + pDataVec[0] = aaDataDiff[0]; + pDataVec[1] = aaDataDiff[1]; + } else { + pDataVec[0] = aaDataDiff[0]; + pDataVec[1] = NULL; + } + + diff_type[0] = DIFF_FREQ; + diff_type[1] = DIFF_FREQ; + + direction = BACKWARDS; + { + if (pair_flag || allowDiffTimeBack_flag) { + data = FDKreadBits(strm, 1); + diff_type[0] = (DIFF_TYPE)data; + } + + if (pair_flag && + ((diff_type[0] == DIFF_FREQ) || allowDiffTimeBack_flag)) { + data = FDKreadBits(strm, 1); + diff_type[1] = (DIFF_TYPE)data; + } + } + /* Huffman decoding */ + err = huff_decode(strm, pDataVec[0], pDataVec[1], data_type, diff_type[0], + diff_type[1], dataBands, &cdg_scheme, + (DECODER == SAOC_DECODER)); + if (err != HUFFDEC_OK) { + return HUFFDEC_NOTOK; + } + + { + /* Differential decoding */ + if ((diff_type[0] == DIFF_TIME) || (diff_type[1] == DIFF_TIME)) { + if (DECODER == SAOC_DECODER) { + direction = BACKWARDS; + } else { + if (pair_flag) { + if ((diff_type[0] == DIFF_TIME) && !allowDiffTimeBack_flag) { + direction = FORWARDS; + } else if (diff_type[1] == DIFF_TIME) { + direction = BACKWARDS; + } else { + data = FDKreadBits(strm, 1); + direction = (DIRECTION)data; + } + } else { + direction = BACKWARDS; + } + } + } + + mixed_time_pair = (diff_type[0] != diff_type[1]) && + ((cdg_scheme & PAIR_MASK) == TIME_PAIR); + + if (direction == BACKWARDS) { + if (diff_type[0] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[0], aaDataPair[0], dataBands); + } else { + int i; + for (i = 0; i < dataBands; i++) { + aHistoryMsb[i] = aHistory[i + startBand] + quant_offset; + if (attachLsb_flag) { + aHistoryMsb[i] >>= 1; + } + } + diff_time_decode_backwards(aHistoryMsb, aaDataDiff[0], aaDataPair[0], + mixed_time_pair, dataBands); + } + if (diff_type[1] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[1], aaDataPair[1], dataBands); + } else { + diff_time_decode_backwards(aaDataPair[0], aaDataDiff[1], + aaDataPair[1], mixed_time_pair, dataBands); + } + } else { + /* diff_type[1] MUST BE DIFF_FREQ */ + diff_freq_decode(aaDataDiff[1], aaDataPair[1], dataBands); + + if (diff_type[0] == DIFF_FREQ) { + diff_freq_decode(aaDataDiff[0], aaDataPair[0], dataBands); + } else { + diff_time_decode_forwards(aaDataPair[1], aaDataDiff[0], aaDataPair[0], + mixed_time_pair, dataBands); + } + } + } + + /* LSB decoding */ + err = attach_lsb(strm, aaDataPair[0], quant_offset, attachLsb_flag ? 1 : 0, + dataBands, aaDataPair[0]); + if (err != HUFFDEC_OK) goto bail; + + if (pair_flag) { + err = attach_lsb(strm, aaDataPair[1], quant_offset, + attachLsb_flag ? 1 : 0, dataBands, aaDataPair[1]); + if (err != HUFFDEC_OK) goto bail; + } + } /* End: Differential/Huffman/LSB Coding */ + + /* Copy data to output arrays */ + FDKmemcpy(aaOutData1 + startBand, aaDataPair[0], sizeof(SCHAR) * dataBands); + if (pair_flag) { + FDKmemcpy(aaOutData2 + startBand, aaDataPair[1], sizeof(SCHAR) * dataBands); + } + +bail: + return err; +} + +ERROR_t huff_dec_reshape(HANDLE_FDK_BITSTREAM strm, int* out_data, + int num_val) { + ERROR_t err = HUFFDEC_OK; + int val_rcvd = 0, dummy = 0, i = 0, val = 0, len = 0; + SCHAR rl_data[2] = {0}; + + while (val_rcvd < num_val) { + err = huff_read_2D(strm, + (HANDLE_HUFF_NODE)&FDK_huffReshapeNodes.nodeTab[0][0], + rl_data, &dummy); + if (err != HUFFDEC_OK) goto bail; + val = rl_data[0]; + len = rl_data[1] + 1; + if (val_rcvd + len > num_val) { + err = HUFFDEC_NOTOK; + goto bail; + } + for (i = val_rcvd; i < val_rcvd + len; i++) { + out_data[i] = val; + } + val_rcvd += len; + } +bail: + return err; +} diff --git a/fdk-aac/libFDK/src/qmf.cpp b/fdk-aac/libFDK/src/qmf.cpp new file mode 100644 index 0000000..6fca043 --- /dev/null +++ b/fdk-aac/libFDK/src/qmf.cpp @@ -0,0 +1,1135 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): Markus Lohwasser, Josef Hoepfl, Manuel Jander + + Description: QMF filterbank + +*******************************************************************************/ + +/*! + \file + \brief Complex qmf analysis/synthesis + This module contains the qmf filterbank for analysis [ + cplxAnalysisQmfFiltering() ] and synthesis [ cplxSynthesisQmfFiltering() ]. It + is a polyphase implementation of a complex exponential modulated filter bank. + The analysis part usually runs at half the sample rate than the synthesis + part. (So called "dual-rate" mode.) + + The coefficients of the prototype filter are specified in #qmf_pfilt640 (in + sbr_rom.cpp). Thus only a 64 channel version (32 on the analysis side) with a + 640 tap prototype filter are used. + + \anchor PolyphaseFiltering

About polyphase filtering

+ The polyphase implementation of a filterbank requires filtering at the input + and output. This is implemented as part of cplxAnalysisQmfFiltering() and + cplxSynthesisQmfFiltering(). The implementation requires the filter + coefficients in a specific structure as described in #sbr_qmf_64_640_qmf (in + sbr_rom.cpp). + + This module comprises the computationally most expensive functions of the SBR + decoder. The accuracy of computations is also important and has a direct + impact on the overall sound quality. Therefore a special test program is + available which can be used to only test the filterbank: main_audio.cpp + + This modules also uses scaling of data to provide better SNR on fixed-point + processors. See #QMF_SCALE_FACTOR (in sbr_scale.h) for details. An interesting + note: The function getScalefactor() can constitute a significant amount of + computational complexity - very much depending on the bitrate. Since it is a + rather small function, effective assembler optimization might be possible. + +*/ + +#include "qmf.h" + +#include "FDK_trigFcts.h" +#include "fixpoint_math.h" +#include "dct.h" + +#define QSSCALE (0) +#define FX_DBL2FX_QSS(x) (x) +#define FX_QSS2FX_DBL(x) (x) + +/* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot */ +/* moved to qmf_pcm.h: -> qmfSynPrototypeFirSlot_NonSymmetric */ +/* moved to qmf_pcm.h: -> qmfSynthesisFilteringSlot */ + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot( + FIXP_DBL *analysisBuffer, + INT no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, INT p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + INT k; + + FIXP_DBL accu; + const FIXP_PFT *RESTRICT p_flt = p_filter; + FIXP_DBL *RESTRICT pData_0 = analysisBuffer + 2 * no_channels - 1; + FIXP_DBL *RESTRICT pData_1 = analysisBuffer; + + FIXP_QAS *RESTRICT sta_0 = (FIXP_QAS *)pFilterStates; + FIXP_QAS *RESTRICT sta_1 = + (FIXP_QAS *)pFilterStates + (2 * QMF_NO_POLY * no_channels) - 1; + INT pfltStep = QMF_NO_POLY * (p_stride); + INT staStep1 = no_channels << 1; + INT staStep2 = (no_channels << 3) - 1; /* Rewind one less */ + + /* FIR filters 127..64 0..63 */ + for (k = 0; k < no_channels; k++) { + accu = fMultDiv2(p_flt[0], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[1], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[2], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[3], *sta_1); + sta_1 -= staStep1; + accu += fMultDiv2(p_flt[4], *sta_1); + *pData_1++ = (accu << 1); + sta_1 += staStep2; + + p_flt += pfltStep; + accu = fMultDiv2(p_flt[0], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[1], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[2], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[3], *sta_0); + sta_0 += staStep1; + accu += fMultDiv2(p_flt[4], *sta_0); + *pData_0-- = (accu << 1); + sta_0 -= staStep2; + } +} +#endif /* !defined(FUNCTION_qmfAnaPrototypeFirSlot) */ + +#ifndef FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric +/*! + \brief Perform Analysis Prototype Filtering on a single slot of input data. +*/ +static void qmfAnaPrototypeFirSlot_NonSymmetric( + FIXP_DBL *analysisBuffer, + int no_channels, /*!< Number channels of analysis filter */ + const FIXP_PFT *p_filter, int p_stride, /*!< Stride of analysis filter */ + FIXP_QAS *RESTRICT pFilterStates) { + const FIXP_PFT *RESTRICT p_flt = p_filter; + int p, k; + + for (k = 0; k < 2 * no_channels; k++) { + FIXP_DBL accu = (FIXP_DBL)0; + + p_flt += QMF_NO_POLY * (p_stride - 1); + + /* + Perform FIR-Filter + */ + for (p = 0; p < QMF_NO_POLY; p++) { + accu += fMultDiv2(*p_flt++, pFilterStates[2 * no_channels * p]); + } + analysisBuffer[2 * no_channels - 1 - k] = (accu << 1); + pFilterStates++; + } +} +#endif /* FUNCTION_qmfAnaPrototypeFirSlot_NonSymmetric */ + +/*! + * + * \brief Perform real-valued forward modulation of the time domain + * data of timeIn and stores the real part of the subband + * samples in rSubband + * + */ +static void qmfForwardModulationLP_even( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL *timeIn, /*!< Time Signal */ + FIXP_DBL *rSubband) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L >> 1; + int scale; + FIXP_DBL accu; + + const FIXP_DBL *timeInTmp1 = (FIXP_DBL *)&timeIn[3 * M]; + const FIXP_DBL *timeInTmp2 = timeInTmp1; + FIXP_DBL *rSubbandTmp = rSubband; + + rSubband[0] = timeIn[3 * M] >> 1; + + for (i = M - 1; i != 0; i--) { + accu = ((*--timeInTmp1) >> 1) + ((*++timeInTmp2) >> 1); + *++rSubbandTmp = accu; + } + + timeInTmp1 = &timeIn[2 * M]; + timeInTmp2 = &timeIn[0]; + rSubbandTmp = &rSubband[M]; + + for (i = L - M; i != 0; i--) { + accu = ((*timeInTmp1--) >> 1) - ((*timeInTmp2++) >> 1); + *rSubbandTmp++ = accu; + } + + dct_III(rSubband, timeIn, L, &scale); +} + +#if !defined(FUNCTION_qmfForwardModulationLP_odd) +static void qmfForwardModulationLP_odd( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_DBL *timeIn, /*!< Time Signal */ + FIXP_DBL *rSubband) /*!< Real Output */ +{ + int i; + int L = anaQmf->no_channels; + int M = L >> 1; + int shift = (anaQmf->no_channels >> 6) + 1; + + for (i = 0; i < M; i++) { + rSubband[M + i] = (timeIn[L - 1 - i] >> 1) - (timeIn[i] >> shift); + rSubband[M - 1 - i] = + (timeIn[L + i] >> 1) + (timeIn[2 * L - 1 - i] >> shift); + } + + dct_IV(rSubband, L, &shift); +} +#endif /* !defined(FUNCTION_qmfForwardModulationLP_odd) */ + +/*! + * + * \brief Perform complex-valued forward modulation of the time domain + * data of timeIn and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * + */ +#if !defined(FUNCTION_qmfForwardModulationHQ) +static void qmfForwardModulationHQ( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + const FIXP_DBL *RESTRICT timeIn, /*!< Time Signal */ + FIXP_DBL *RESTRICT rSubband, /*!< Real Output */ + FIXP_DBL *RESTRICT iSubband /*!< Imaginary Output */ +) { + int i; + int L = anaQmf->no_channels; + int L2 = L << 1; + int shift = 0; + + /* Time advance by one sample, which is equivalent to the complex + rotation at the end of the analysis. Works only for STD mode. */ + if ((L == 64) && !(anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + FIXP_DBL x, y; + + /*rSubband[0] = u[1] + u[0]*/ + /*iSubband[0] = u[1] - u[0]*/ + x = timeIn[1] >> 1; + y = timeIn[0]; + rSubband[0] = x + (y >> 1); + iSubband[0] = x - (y >> 1); + + /*rSubband[n] = u[n+1] - u[2M-n], n=1,...,M-1*/ + /*iSubband[n] = u[n+1] + u[2M-n], n=1,...,M-1*/ + for (i = 1; i < L; i++) { + x = timeIn[i + 1] >> 1; /*u[n+1] */ + y = timeIn[L2 - i]; /*u[2M-n] */ + rSubband[i] = x - (y >> 1); + iSubband[i] = x + (y >> 1); + } + } else { + for (i = 0; i < L; i += 2) { + FIXP_DBL x0, x1, y0, y1; + + x0 = timeIn[i + 0] >> 1; + x1 = timeIn[i + 1] >> 1; + y0 = timeIn[L2 - 1 - i]; + y1 = timeIn[L2 - 2 - i]; + + rSubband[i + 0] = x0 - (y0 >> 1); + rSubband[i + 1] = x1 - (y1 >> 1); + iSubband[i + 0] = x0 + (y0 >> 1); + iSubband[i + 1] = x1 + (y1 >> 1); + } + } + + dct_IV(rSubband, L, &shift); + dst_IV(iSubband, L, &shift); + + /* Do the complex rotation except for the case of 64 bands (in STD mode). */ + if ((L != 64) || (anaQmf->flags & (QMF_FLAG_CLDFB | QMF_FLAG_MPSLDFB))) { + if (anaQmf->flags & QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION) { + FIXP_DBL iBand; + for (i = 0; i < fMin(anaQmf->lsb, L); i += 2) { + iBand = rSubband[i]; + rSubband[i] = -iSubband[i]; + iSubband[i] = iBand; + + iBand = -rSubband[i + 1]; + rSubband[i + 1] = iSubband[i + 1]; + iSubband[i + 1] = iBand; + } + } else { + const FIXP_QTW *sbr_t_cos; + const FIXP_QTW *sbr_t_sin; + const int len = L; /* was len = fMin(anaQmf->lsb, L) but in case of USAC + the signal above lsb is actually needed in some + cases (HBE?) */ + sbr_t_cos = anaQmf->t_cos; + sbr_t_sin = anaQmf->t_sin; + + for (i = 0; i < len; i++) { + cplxMult(&iSubband[i], &rSubband[i], iSubband[i], rSubband[i], + sbr_t_cos[i], sbr_t_sin[i]); + } + } + } +} +#endif /* FUNCTION_qmfForwardModulationHQ */ + +/* + * \brief Perform one QMF slot analysis of the time domain data of timeIn + * with specified stride and stores the real part of the subband + * samples in rSubband, and the imaginary part in iSubband + * + * Note: anaQmf->lsb can be greater than anaQmf->no_channels in case + * of implicit resampling (USAC with reduced 3/4 core frame length). + */ +#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const LONG *RESTRICT timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); + /* + Feed time signal into oldest anaQmf->no_channels states + */ + { + FIXP_DBL *FilterStatesAnaTmp = ((FIXP_DBL *)anaQmf->FilterStates) + offset; + + /* Feed and scale actual time in slot */ + for (int i = anaQmf->no_channels >> 1; i != 0; i--) { + /* Place INT_PCM value left aligned in scaledTimeIn */ + + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + } + } + + if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, + anaQmf->p_filter, anaQmf->p_stride, + (FIXP_QAS *)anaQmf->FilterStates); + } else { + qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, + anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); + } + + if (anaQmf->flags & QMF_FLAG_LP) { + if (anaQmf->flags & QMF_FLAG_CLDFB) + qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); + else + qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); + + } else { + qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); + } + /* + Shift filter states + + Should be realized with modulo adressing on a DSP instead of a true buffer + shift + */ + FDKmemmove(anaQmf->FilterStates, + (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, + offset * sizeof(FIXP_QAS)); +} +#endif + +void qmfAnalysisFilteringSlot( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL *qmfReal, /*!< Low and High band, real */ + FIXP_DBL *qmfImag, /*!< Low and High band, imag */ + const INT_PCM *RESTRICT timeIn, /*!< Pointer to input */ + const int stride, /*!< stride factor of input */ + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int offset = anaQmf->no_channels * (QMF_NO_POLY * 2 - 1); + /* + Feed time signal into oldest anaQmf->no_channels states + */ + { + FIXP_QAS *FilterStatesAnaTmp = ((FIXP_QAS *)anaQmf->FilterStates) + offset; + + /* Feed and scale actual time in slot */ + for (int i = anaQmf->no_channels >> 1; i != 0; i--) { + /* Place INT_PCM value left aligned in scaledTimeIn */ +#if (QAS_BITS == SAMPLE_BITS) + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)*timeIn; + timeIn += stride; +#elif (QAS_BITS > SAMPLE_BITS) + *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); + timeIn += stride; + *FilterStatesAnaTmp++ = ((FIXP_QAS)*timeIn) << (QAS_BITS - SAMPLE_BITS); + timeIn += stride; +#else + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); + timeIn += stride; + *FilterStatesAnaTmp++ = (FIXP_QAS)((*timeIn) >> (SAMPLE_BITS - QAS_BITS)); + timeIn += stride; +#endif + } + } + + if (anaQmf->flags & QMF_FLAG_NONSYMMETRIC) { + qmfAnaPrototypeFirSlot_NonSymmetric(pWorkBuffer, anaQmf->no_channels, + anaQmf->p_filter, anaQmf->p_stride, + (FIXP_QAS *)anaQmf->FilterStates); + } else { + qmfAnaPrototypeFirSlot(pWorkBuffer, anaQmf->no_channels, anaQmf->p_filter, + anaQmf->p_stride, (FIXP_QAS *)anaQmf->FilterStates); + } + + if (anaQmf->flags & QMF_FLAG_LP) { + if (anaQmf->flags & QMF_FLAG_CLDFB) + qmfForwardModulationLP_odd(anaQmf, pWorkBuffer, qmfReal); + else + qmfForwardModulationLP_even(anaQmf, pWorkBuffer, qmfReal); + + } else { + qmfForwardModulationHQ(anaQmf, pWorkBuffer, qmfReal, qmfImag); + } + /* + Shift filter states + + Should be realized with modulo adressing on a DSP instead of a true buffer + shift + */ + FDKmemmove(anaQmf->FilterStates, + (FIXP_QAS *)anaQmf->FilterStates + anaQmf->no_channels, + offset * sizeof(FIXP_QAS)); +} + +/*! + * + * \brief Perform complex-valued subband filtering of the time domain + * data of timeIn and stores the real part of the subband + * samples in rAnalysis, and the imaginary part in iAnalysis + * The qmf coefficient table is symmetric. The symmetry is expoited by + * shrinking the coefficient table to half the size. The addressing mode + * takes care of the symmetries. + * + * + * \sa PolyphaseFiltering + */ +#if (SAMPLE_BITS != DFRACT_BITS) && (QAS_BITS == DFRACT_BITS) +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, const LONG *timeIn, /*!< Time signal */ + const int timeIn_e, const int stride, + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int no_channels = anaQmf->no_channels; + + scaleFactor->lb_scale = + -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; + scaleFactor->lb_scale -= anaQmf->filterScale; + + for (i = 0; i < anaQmf->no_col; i++) { + FIXP_DBL *qmfImagSlot = NULL; + + if (!(anaQmf->flags & QMF_FLAG_LP)) { + qmfImagSlot = qmfImag[i]; + } + + qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, + pWorkBuffer); + + timeIn += no_channels * stride; + + } /* no_col loop i */ +} +#endif + +void qmfAnalysisFiltering( + HANDLE_QMF_FILTER_BANK anaQmf, /*!< Handle of Qmf Analysis Bank */ + FIXP_DBL **qmfReal, /*!< Pointer to real subband slots */ + FIXP_DBL **qmfImag, /*!< Pointer to imag subband slots */ + QMF_SCALE_FACTOR *scaleFactor, const INT_PCM *timeIn, /*!< Time signal */ + const int timeIn_e, const int stride, + FIXP_DBL *pWorkBuffer /*!< pointer to temporal working buffer */ +) { + int i; + int no_channels = anaQmf->no_channels; + + scaleFactor->lb_scale = + -ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK - timeIn_e; + scaleFactor->lb_scale -= anaQmf->filterScale; + + for (i = 0; i < anaQmf->no_col; i++) { + FIXP_DBL *qmfImagSlot = NULL; + + if (!(anaQmf->flags & QMF_FLAG_LP)) { + qmfImagSlot = qmfImag[i]; + } + + qmfAnalysisFilteringSlot(anaQmf, qmfReal[i], qmfImagSlot, timeIn, stride, + pWorkBuffer); + + timeIn += no_channels * stride; + + } /* no_col loop i */ +} + +/*! + * + * \brief Perform low power inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline static void qmfInverseModulationLP_even( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int scale; + FIXP_DBL tmp; + FIXP_DBL *RESTRICT tReal = pTimeOut; + FIXP_DBL *RESTRICT tImag = pTimeOut + L; + + /* Move input to output vector with offset */ + scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand); + scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); + FDKmemclear(&tReal[0 + synQmf->usb], (L - synQmf->usb) * sizeof(FIXP_DBL)); + + /* Dct type-2 transform */ + dct_II(tReal, tImag, L, &scale); + + /* Expand output and replace inplace the output buffers */ + tImag[0] = tReal[M]; + tImag[M] = (FIXP_DBL)0; + tmp = tReal[0]; + tReal[0] = tReal[M]; + tReal[M] = tmp; + + for (i = 1; i < M / 2; i++) { + /* Imag */ + tmp = tReal[L - i]; + tImag[M - i] = tmp; + tImag[i + M] = -tmp; + + tmp = tReal[M + i]; + tImag[i] = tmp; + tImag[L - i] = -tmp; + + /* Real */ + tReal[M + i] = tReal[i]; + tReal[L - i] = tReal[M - i]; + tmp = tReal[i]; + tReal[i] = tReal[M - i]; + tReal[M - i] = tmp; + } + /* Remaining odd terms */ + tmp = tReal[M + M / 2]; + tImag[M / 2] = tmp; + tImag[M / 2 + M] = -tmp; + + tReal[M + M / 2] = tReal[M / 2]; +} + +inline static void qmfInverseModulationLP_odd( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot (input) */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pTimeOut /*!< Pointer to qmf subband slot (output)*/ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int shift = 0; + + /* Move input to output vector with offset */ + scaleValues(pTimeOut + M, qmfReal, synQmf->lsb, scaleFactorLowBand); + scaleValues(pTimeOut + M + synQmf->lsb, qmfReal + synQmf->lsb, + synQmf->usb - synQmf->lsb, scaleFactorHighBand); + FDKmemclear(pTimeOut + M + synQmf->usb, (L - synQmf->usb) * sizeof(FIXP_DBL)); + + dct_IV(pTimeOut + M, L, &shift); + for (i = 0; i < M; i++) { + pTimeOut[i] = pTimeOut[L - 1 - i]; + pTimeOut[2 * L - 1 - i] = -pTimeOut[L + i]; + } +} + +#ifndef FUNCTION_qmfInverseModulationHQ +/*! + * + * \brief Perform complex-valued inverse modulation of the subband + * samples stored in rSubband (real part) and iSubband (imaginary + * part) and stores the result in pWorkBuffer. + * + */ +inline static void qmfInverseModulationHQ( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + const FIXP_DBL *qmfReal, /*!< Pointer to qmf real subband slot */ + const FIXP_DBL *qmfImag, /*!< Pointer to qmf imag subband slot */ + const int scaleFactorLowBand, /*!< Scalefactor for Low band */ + const int scaleFactorHighBand, /*!< Scalefactor for High band */ + FIXP_DBL *pWorkBuffer /*!< WorkBuffer (output) */ +) { + int i; + int L = synQmf->no_channels; + int M = L >> 1; + int shift = 0; + FIXP_DBL *RESTRICT tReal = pWorkBuffer; + FIXP_DBL *RESTRICT tImag = pWorkBuffer + L; + + if (synQmf->flags & QMF_FLAG_CLDFB) { + for (i = 0; i < synQmf->lsb; i++) { + cplxMult(&tImag[i], &tReal[i], scaleValue(qmfImag[i], scaleFactorLowBand), + scaleValue(qmfReal[i], scaleFactorLowBand), synQmf->t_cos[i], + synQmf->t_sin[i]); + } + for (; i < synQmf->usb; i++) { + cplxMult(&tImag[i], &tReal[i], + scaleValue(qmfImag[i], scaleFactorHighBand), + scaleValue(qmfReal[i], scaleFactorHighBand), synQmf->t_cos[i], + synQmf->t_sin[i]); + } + } + + if ((synQmf->flags & QMF_FLAG_CLDFB) == 0) { + scaleValues(&tReal[0], &qmfReal[0], synQmf->lsb, (int)scaleFactorLowBand); + scaleValues(&tReal[0 + synQmf->lsb], &qmfReal[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); + scaleValues(&tImag[0], &qmfImag[0], synQmf->lsb, (int)scaleFactorLowBand); + scaleValues(&tImag[0 + synQmf->lsb], &qmfImag[0 + synQmf->lsb], + synQmf->usb - synQmf->lsb, (int)scaleFactorHighBand); + } + + FDKmemclear(&tReal[synQmf->usb], + (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); + FDKmemclear(&tImag[synQmf->usb], + (synQmf->no_channels - synQmf->usb) * sizeof(FIXP_DBL)); + + dct_IV(tReal, L, &shift); + dst_IV(tImag, L, &shift); + + if (synQmf->flags & QMF_FLAG_CLDFB) { + for (i = 0; i < M; i++) { + FIXP_DBL r1, i1, r2, i2; + r1 = tReal[i]; + i2 = tImag[L - 1 - i]; + r2 = tReal[L - i - 1]; + i1 = tImag[i]; + + tReal[i] = (r1 - i1) >> 1; + tImag[L - 1 - i] = -(r1 + i1) >> 1; + tReal[L - i - 1] = (r2 - i2) >> 1; + tImag[i] = -(r2 + i2) >> 1; + } + } else { + /* The array accesses are negative to compensate the missing minus sign in + * the low and hi band gain. */ + /* 26 cycles on ARM926 */ + for (i = 0; i < M; i++) { + FIXP_DBL r1, i1, r2, i2; + r1 = -tReal[i]; + i2 = -tImag[L - 1 - i]; + r2 = -tReal[L - i - 1]; + i1 = -tImag[i]; + + tReal[i] = (r1 - i1) >> 1; + tImag[L - 1 - i] = -(r1 + i1) >> 1; + tReal[L - i - 1] = (r2 - i2) >> 1; + tImag[i] = -(r2 + i2) >> 1; + } + } +} +#endif /* #ifndef FUNCTION_qmfInverseModulationHQ */ + +/*! + * + * \brief Create QMF filter bank instance + * + * \return 0 if successful + * + */ +static int qmfInitFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Handle to return */ + void *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< Lower end of QMF frequency range */ + int usb, /*!< Upper end of QMF frequency range */ + int no_channels, /*!< Number of channels (bands) */ + UINT flags, /*!< flags */ + int synflag) /*!< 1: synthesis; 0: analysis */ +{ + FDKmemclear(h_Qmf, sizeof(QMF_FILTER_BANK)); + + if (flags & QMF_FLAG_MPSLDFB) { + flags |= QMF_FLAG_NONSYMMETRIC; + flags |= QMF_FLAG_MPSLDFB_OPTIMIZE_MODULATION; + + h_Qmf->t_cos = NULL; + h_Qmf->t_sin = NULL; + h_Qmf->filterScale = QMF_MPSLDFB_PFT_SCALE; + h_Qmf->p_stride = 1; + + switch (no_channels) { + case 64: + h_Qmf->p_filter = qmf_mpsldfb_640; + h_Qmf->FilterSize = 640; + break; + case 32: + h_Qmf->p_filter = qmf_mpsldfb_320; + h_Qmf->FilterSize = 320; + break; + default: + return -1; + } + } + + if (!(flags & QMF_FLAG_MPSLDFB) && (flags & QMF_FLAG_CLDFB)) { + flags |= QMF_FLAG_NONSYMMETRIC; + h_Qmf->filterScale = QMF_CLDFB_PFT_SCALE; + + h_Qmf->p_stride = 1; + switch (no_channels) { + case 64: + h_Qmf->t_cos = qmf_phaseshift_cos64_cldfb; + h_Qmf->t_sin = qmf_phaseshift_sin64_cldfb; + h_Qmf->p_filter = qmf_cldfb_640; + h_Qmf->FilterSize = 640; + break; + case 32: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos32_cldfb_syn + : qmf_phaseshift_cos32_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin32_cldfb; + h_Qmf->p_filter = qmf_cldfb_320; + h_Qmf->FilterSize = 320; + break; + case 16: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos16_cldfb_syn + : qmf_phaseshift_cos16_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin16_cldfb; + h_Qmf->p_filter = qmf_cldfb_160; + h_Qmf->FilterSize = 160; + break; + case 8: + h_Qmf->t_cos = (synflag) ? qmf_phaseshift_cos8_cldfb_syn + : qmf_phaseshift_cos8_cldfb_ana; + h_Qmf->t_sin = qmf_phaseshift_sin8_cldfb; + h_Qmf->p_filter = qmf_cldfb_80; + h_Qmf->FilterSize = 80; + break; + default: + return -1; + } + } + + if (!(flags & QMF_FLAG_MPSLDFB) && ((flags & QMF_FLAG_CLDFB) == 0)) { + switch (no_channels) { + case 64: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->t_cos = qmf_phaseshift_cos64; + h_Qmf->t_sin = qmf_phaseshift_sin64; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 40: + if (synflag) { + break; + } else { + h_Qmf->p_filter = qmf_pfilt400; /* Scaling factor 0.8 */ + h_Qmf->t_cos = qmf_phaseshift_cos40; + h_Qmf->t_sin = qmf_phaseshift_sin40; + h_Qmf->filterScale = 1; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = no_channels * 10; + } + break; + case 32: + h_Qmf->p_filter = qmf_pfilt640; + if (flags & QMF_FLAG_DOWNSAMPLED) { + h_Qmf->t_cos = qmf_phaseshift_cos_downsamp32; + h_Qmf->t_sin = qmf_phaseshift_sin_downsamp32; + } else { + h_Qmf->t_cos = qmf_phaseshift_cos32; + h_Qmf->t_sin = qmf_phaseshift_sin32; + } + h_Qmf->p_stride = 2; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 20: + h_Qmf->p_filter = qmf_pfilt200; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 200; + h_Qmf->filterScale = 0; + break; + case 12: + h_Qmf->p_filter = qmf_pfilt120; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 120; + h_Qmf->filterScale = 0; + break; + case 8: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->p_stride = 8; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 16: + h_Qmf->p_filter = qmf_pfilt640; + h_Qmf->t_cos = qmf_phaseshift_cos16; + h_Qmf->t_sin = qmf_phaseshift_sin16; + h_Qmf->p_stride = 4; + h_Qmf->FilterSize = 640; + h_Qmf->filterScale = 0; + break; + case 24: + h_Qmf->p_filter = qmf_pfilt240; + h_Qmf->t_cos = qmf_phaseshift_cos24; + h_Qmf->t_sin = qmf_phaseshift_sin24; + h_Qmf->p_stride = 1; + h_Qmf->FilterSize = 240; + h_Qmf->filterScale = 1; + break; + default: + return -1; + } + } + + h_Qmf->synScalefactor = h_Qmf->filterScale; + // DCT|DST dependency + switch (no_channels) { + case 128: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; + break; + case 40: { + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + } break; + case 64: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; + break; + case 8: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 3; + break; + case 12: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK; + break; + case 20: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK + 1; + break; + case 32: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + break; + case 16: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 2; + break; + case 24: + h_Qmf->synScalefactor += ALGORITHMIC_SCALING_IN_SYNTHESIS_FILTERBANK - 1; + break; + default: + return -1; + } + + h_Qmf->flags = flags; + + h_Qmf->no_channels = no_channels; + h_Qmf->no_col = noCols; + + h_Qmf->lsb = fMin(lsb, h_Qmf->no_channels); + h_Qmf->usb = synflag + ? fMin(usb, h_Qmf->no_channels) + : usb; /* was: h_Qmf->usb = fMin(usb, h_Qmf->no_channels); */ + + h_Qmf->FilterStates = (void *)pFilterStates; + + h_Qmf->outScalefactor = + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + h_Qmf->filterScale) + + h_Qmf->synScalefactor; + + h_Qmf->outGain_m = + (FIXP_DBL)0x80000000; /* default init value will be not applied */ + h_Qmf->outGain_e = 0; + + return (0); +} + +/*! + * + * \brief Adjust synthesis qmf filter states + * + * \return void + * + */ +static inline void qmfAdaptFilterStates( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Filter Bank */ + int scaleFactorDiff) /*!< Scale factor difference to be applied */ +{ + if (synQmf == NULL || synQmf->FilterStates == NULL) { + return; + } + if (scaleFactorDiff > 0) { + scaleValuesSaturate((FIXP_QSS *)synQmf->FilterStates, + synQmf->no_channels * (QMF_NO_POLY * 2 - 1), + scaleFactorDiff); + } else { + scaleValues((FIXP_QSS *)synQmf->FilterStates, + synQmf->no_channels * (QMF_NO_POLY * 2 - 1), scaleFactorDiff); + } +} + +/*! + * + * \brief Create QMF filter bank instance + * + * + * \return 0 if succesful + * + */ +int qmfInitAnalysisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QAS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, + no_channels, flags, 0); + if (!(flags & QMF_FLAG_KEEP_STATES) && (h_Qmf->FilterStates != NULL)) { + FDKmemclear(h_Qmf->FilterStates, + (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QAS)); + } + + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); + + return err; +} + +/*! + * + * \brief Create QMF filter bank instance + * + * + * \return 0 if succesful + * + */ +int qmfInitSynthesisFilterBank( + HANDLE_QMF_FILTER_BANK h_Qmf, /*!< Returns handle */ + FIXP_QSS *pFilterStates, /*!< Handle to filter states */ + int noCols, /*!< Number of timeslots per frame */ + int lsb, /*!< lower end of QMF */ + int usb, /*!< upper end of QMF */ + int no_channels, /*!< Number of channels (bands) */ + int flags) /*!< Low Power flag */ +{ + int oldOutScale = h_Qmf->outScalefactor; + int err = qmfInitFilterBank(h_Qmf, pFilterStates, noCols, lsb, usb, + no_channels, flags, 1); + if (h_Qmf->FilterStates != NULL) { + if (!(flags & QMF_FLAG_KEEP_STATES)) { + FDKmemclear( + h_Qmf->FilterStates, + (2 * QMF_NO_POLY - 1) * h_Qmf->no_channels * sizeof(FIXP_QSS)); + } else { + qmfAdaptFilterStates(h_Qmf, oldOutScale - h_Qmf->outScalefactor); + } + } + + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->lsb); + FDK_ASSERT(h_Qmf->no_channels >= h_Qmf->usb); + + return err; +} + +/*! + * + * \brief Change scale factor for output data and adjust qmf filter states + * + * \return void + * + */ +void qmfChangeOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + int outScalefactor /*!< New scaling factor for output data */ +) { + if (synQmf == NULL) { + return; + } + + /* Add internal filterbank scale */ + outScalefactor += + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + synQmf->filterScale) + + synQmf->synScalefactor; + + /* adjust filter states when scale factor has been changed */ + if (synQmf->outScalefactor != outScalefactor) { + int diff; + + diff = synQmf->outScalefactor - outScalefactor; + + qmfAdaptFilterStates(synQmf, diff); + + /* save new scale factor */ + synQmf->outScalefactor = outScalefactor; + } +} + +/*! + * + * \brief Get scale factor change which was set by qmfChangeOutScalefactor() + * + * \return scaleFactor + * + */ +int qmfGetOutScalefactor( + HANDLE_QMF_FILTER_BANK synQmf) /*!< Handle of Qmf Synthesis Bank */ +{ + int scaleFactor = synQmf->outScalefactor + ? (synQmf->outScalefactor - + (ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK + + synQmf->filterScale + synQmf->synScalefactor)) + : 0; + return scaleFactor; +} + +/*! + * + * \brief Change gain for output data + * + * \return void + * + */ +void qmfChangeOutGain( + HANDLE_QMF_FILTER_BANK synQmf, /*!< Handle of Qmf Synthesis Bank */ + FIXP_DBL outputGain, /*!< New gain for output data (mantissa) */ + int outputGainScale /*!< New gain for output data (exponent) */ +) { + synQmf->outGain_m = outputGain; + synQmf->outGain_e = outputGainScale; +} + +/* When QMF_16IN_32OUT is set, synthesis functions for 16 and 32 bit parallel + * output is compiled */ +#define INT_PCM_QMFOUT INT_PCM +#define SAMPLE_BITS_QMFOUT SAMPLE_BITS +#include "qmf_pcm.h" diff --git a/fdk-aac/libFDK/src/scale.cpp b/fdk-aac/libFDK/src/scale.cpp new file mode 100644 index 0000000..24a8a5b --- /dev/null +++ b/fdk-aac/libFDK/src/scale.cpp @@ -0,0 +1,720 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* Library for basic calculation routines ******************** + + Author(s): + + Description: Scaling operations + +*******************************************************************************/ + +#include "common_fix.h" + +#include "genericStds.h" + +/************************************************** + * Inline definitions + **************************************************/ + +#include "scale.h" + +#if defined(__mips__) +#include "mips/scale_mips.cpp" + +#elif defined(__arm__) +#include "arm/scale_arm.cpp" + +#endif + +#ifndef FUNCTION_scaleValues_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_SGL +void scaleValues(FIXP_SGL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)(FRACT_BITS - 1)); + for (i = len & 3; i--;) { + *(vector++) <<= scalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)FRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) >>= negScalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValues_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValues_DBL +SCALE_INLINE +void scaleValues(FIXP_DBL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) <<= scalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + *(vector++) <<= scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(vector++) >>= negScalefactor; + } + for (i = len >> 2; i--;) { + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + *(vector++) >>= negScalefactor; + } + } +} +#endif + +#ifndef FUNCTION_scaleValuesSaturate_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param vector source/destination buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_DBL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + vector[i] = scaleValueSaturate(vector[i], scalefactor); + } +} +#endif /* FUNCTION_scaleValuesSaturate_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_DBL_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer + * \param src source buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_DBL_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_DBL *dst, /*!< Output */ + FIXP_DBL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + return; + } + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = scaleValueSaturate(src[i], scalefactor); + } +} +#endif /* FUNCTION_scaleValuesSaturate_DBL_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer (FIXP_SGL) + * \param src source buffer (FIXP_DBL) + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL_DBL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */ + FIXP_DBL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor) /*!< Scalefactor */ +{ + INT i; + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = FX_DBL2FX_SGL(fAddSaturate(scaleValueSaturate(src[i], scalefactor), + (FIXP_DBL)0x8000)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL_DBL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param vector source/destination buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *vector, /*!< Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) return; + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + vector[i] = FX_DBL2FX_SGL( + scaleValueSaturate(FX_SGL2FX_DBL(vector[i]), scalefactor)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL */ + +#ifndef FUNCTION_scaleValuesSaturate_SGL_SGL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param dst destination buffer + * \param src source buffer + * \param len length of vector + * \param scalefactor amount of shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValuesSaturate_SGL_SGL +SCALE_INLINE +void scaleValuesSaturate(FIXP_SGL *dst, /*!< Output */ + FIXP_SGL *src, /*!< Input */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + FDKmemmove(dst, src, len * sizeof(FIXP_SGL)); + return; + } + + scalefactor = fixmax_I(fixmin_I(scalefactor, (INT)DFRACT_BITS - 1), + (INT) - (DFRACT_BITS - 1)); + + for (i = 0; i < len; i++) { + dst[i] = + FX_DBL2FX_SGL(scaleValueSaturate(FX_SGL2FX_DBL(src[i]), scalefactor)); + } +} +#endif /* FUNCTION_scaleValuesSaturate_SGL_SGL */ + +#ifndef FUNCTION_scaleValues_DBLDBL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_DBLDBL +SCALE_INLINE +void scaleValues(FIXP_DBL *dst, /*!< dst Vector */ + const FIXP_DBL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + if (dst != src) FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + } else { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) << scalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) >> negScalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + } + } + } +} +#endif + +#if (SAMPLE_BITS == 16) +#ifndef FUNCTION_scaleValues_PCMDBL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_PCMDBL +SCALE_INLINE +void scaleValues(FIXP_PCM *dst, /*!< dst Vector */ + const FIXP_DBL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + scalefactor -= DFRACT_BITS - SAMPLE_BITS; + + /* Return if scalefactor is Zero */ + { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + } + for (i = len >> 2; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + *(dst++) = (FIXP_PCM)(*(src++) << scalefactor); + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + } + for (i = len >> 2; i--;) { + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + *(dst++) = (FIXP_PCM)(*(src++) >> negScalefactor); + } + } + } +} +#endif +#endif /* (SAMPLE_BITS == 16) */ + +#ifndef FUNCTION_scaleValues_SGLSGL +/*! + * + * \brief Multiply input vector src by \f$ 2^{scalefactor} \f$ + * and place result into dst + * \param dst detination buffer + * \param src source buffer + * \param len must be larger than 4 + * \param scalefactor amount of left shifts to be applied + * \return void + * + */ +#define FUNCTION_scaleValues_SGLSGL +SCALE_INLINE +void scaleValues(FIXP_SGL *dst, /*!< dst Vector */ + const FIXP_SGL *src, /*!< src Vector */ + INT len, /*!< Length */ + INT scalefactor /*!< Scalefactor */ +) { + INT i; + + /* Return if scalefactor is Zero */ + if (scalefactor == 0) { + if (dst != src) FDKmemmove(dst, src, len * sizeof(FIXP_DBL)); + } else { + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) << scalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + *(dst++) = *(src++) << scalefactor; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *(dst++) = *(src++) >> negScalefactor; + } + for (i = len >> 2; i--;) { + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + *(dst++) = *(src++) >> negScalefactor; + } + } + } +} +#endif + +#ifndef FUNCTION_scaleValuesWithFactor_DBL +/*! + * + * \brief Multiply input vector by \f$ 2^{scalefactor} \f$ + * \param len must be larger than 4 + * \return void + * + */ +#define FUNCTION_scaleValuesWithFactor_DBL +SCALE_INLINE +void scaleValuesWithFactor(FIXP_DBL *vector, FIXP_DBL factor, INT len, + INT scalefactor) { + INT i; + + /* Compensate fMultDiv2 */ + scalefactor++; + + if (scalefactor > 0) { + scalefactor = fixmin_I(scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + } + for (i = len >> 2; i--;) { + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) << scalefactor; + vector++; + } + } else { + INT negScalefactor = fixmin_I(-scalefactor, (INT)DFRACT_BITS - 1); + for (i = len & 3; i--;) { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + } + for (i = len >> 2; i--;) { + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + *vector = fMultDiv2(*vector, factor) >> negScalefactor; + vector++; + } + } +} +#endif /* FUNCTION_scaleValuesWithFactor_DBL */ + + /******************************************* + + IMPORTANT NOTE for usage of getScalefactor() + + If the input array contains negative values too, then these functions may + sometimes return the actual maximum value minus 1, due to the nature of the + applied algorithm. So be careful with possible fractional -1 values that may + lead to overflows when being fPow2()'ed. + + ********************************************/ + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor / possible left shift + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len /*!< Length of input vector */ +) { + INT i; + SHORT temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector++); + maxVal |= (temp ^ (temp >> (SHORT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorPCM +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorPCM +SCALE_INLINE +INT getScalefactorPCM(const INT_PCM *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride) { + INT i; + INT_PCM temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (INT_PCM)(*vector); + vector += stride; + maxVal |= (temp ^ (temp >> ((sizeof(INT_PCM) * 8) - 1))); + } + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SAMPLE_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactorShort +/*! + * + * \brief Calculate max possible scale factor for input vector of shorts + * \param stride, item increment between vector members. + * \return Maximum scale factor + * + */ +#define FUNCTION_getScalefactorShort +SCALE_INLINE +INT getScalefactorShort(const SHORT *vector, /*!< Pointer to input vector */ + INT len, /*!< Length of input vector */ + INT stride) { + INT i; + SHORT temp, maxVal = 0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector); + vector += stride; + maxVal |= (temp ^ (temp >> (SHORT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D((INT)maxVal) - (INT)1 - + (INT)(DFRACT_BITS - SHORT_BITS))); +} +#endif + +#ifndef FUNCTION_getScalefactor_DBL +/*! + * + * \brief Calculate max possible scale factor for input vector + * + * \return Maximum scale factor + * + * This function can constitute a significant amount of computational + * complexity - very much depending on the bitrate. Since it is a rather small + * function, effective assembler optimization might be possible. + * + * If all data is 0xFFFF.FFFF or 0x0000.0000 function returns 31 + * Note: You can skip data normalization only if return value is 0 + * + */ +#define FUNCTION_getScalefactor_DBL +SCALE_INLINE +INT getScalefactor(const FIXP_DBL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + FIXP_DBL temp, maxVal = (FIXP_DBL)0; + + for (i = len; i != 0; i--) { + temp = (LONG)(*vector++); + maxVal |= (FIXP_DBL)((LONG)temp ^ (LONG)(temp >> (DFRACT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_D(maxVal) - 1)); +} +#endif + +#ifndef FUNCTION_getScalefactor_SGL +#define FUNCTION_getScalefactor_SGL +SCALE_INLINE +INT getScalefactor(const FIXP_SGL *vector, /*!< Pointer to input vector */ + INT len) /*!< Length of input vector */ +{ + INT i; + SHORT temp, maxVal = (FIXP_SGL)0; + + for (i = len; i != 0; i--) { + temp = (SHORT)(*vector++); + maxVal |= (temp ^ (temp >> (FRACT_BITS - 1))); + } + + return fixmax_I((INT)0, (INT)(fixnormz_S((FIXP_SGL)maxVal)) - 1); +} +#endif diff --git a/fdk-aac/libMpegTPDec/include/tp_data.h b/fdk-aac/libMpegTPDec/include/tp_data.h new file mode 100644 index 0000000..b015332 --- /dev/null +++ b/fdk-aac/libMpegTPDec/include/tp_data.h @@ -0,0 +1,466 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport data tables + +*******************************************************************************/ + +#ifndef TP_DATA_H +#define TP_DATA_H + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ + +#define TP_USAC_MAX_SPEAKERS (24) + +#define TP_USAC_MAX_EXT_ELEMENTS ((24)) + +#define TP_USAC_MAX_ELEMENTS ((24) + TP_USAC_MAX_EXT_ELEMENTS) + +#define TP_USAC_MAX_CONFIG_LEN \ + 512 /* next power of two of maximum of escapedValue(hBs, 4, 4, 8) in \ + AudioPreRoll() (285) */ + +#define TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES \ + (1) /* Number of frames for config change in USAC */ + +enum { + TPDEC_FLUSH_OFF = 0, + TPDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + TPDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + TPDEC_BUILD_UP_OFF = 0, + TPDEC_RSV60_BUILD_UP_ON = 1, + TPDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + TPDEC_USAC_BUILD_UP_ON = 3, + TPDEC_RSV60_BUILD_UP_IDLE = 4, + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 + +typedef struct { + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR + NumChannels; /*!< Amount of audio channels summing all channel elements + including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs + and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag; + UINT m_dependsOnCoreCoder; + UINT m_coreCoderDelay; + + UINT m_extensionFlag; + UINT m_extensionFlag3; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2, /* LD MPEG Surround config */ + ELDEXT_DOWNSCALEINFO = 0x3 /* ELD sample rate adaptation */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR + m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + UINT m_downscaledSamplingFrequency; + +} CSEldSpecificConfig; + +typedef struct { + USAC_EXT_ELEMENT_TYPE usacExtElementType; + USHORT usacExtElementConfigLength; + USHORT usacExtElementDefaultLength; + UCHAR usacExtElementPayloadFrag; + UCHAR usacExtElementHasAudioPreRoll; +} CSUsacExtElementConfig; + +typedef struct { + MP4_ELEMENT_ID usacElementType; + UCHAR m_noiseFilling; + UCHAR m_harmonicSBR; + UCHAR m_interTes; + UCHAR m_pvc; + UCHAR m_stereoConfigIndex; + CSUsacExtElementConfig extElement; +} CSUsacElementConfig; + +typedef struct { + UCHAR m_frameLengthFlag; + UCHAR m_coreSbrFrameLengthIndex; + UCHAR m_sbrRatioIndex; + UCHAR m_nUsacChannels; /* number of audio channels signaled in + UsacDecoderConfig() / rsv603daDecoderConfig() via + numElements and usacElementType */ + UCHAR m_channelConfigurationIndex; + UINT m_usacNumElements; + CSUsacElementConfig element[TP_USAC_MAX_ELEMENTS]; + + UCHAR numAudioChannels; + UCHAR m_usacConfigExtensionPresent; + UCHAR elementLengthPresent; + UCHAR UsacConfig[TP_USAC_MAX_CONFIG_LEN]; + USHORT UsacConfigBits; +} CSUsacConfig; + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + /* XYZ Specific Data */ + union { + CSGaSpecificConfig + m_gaSpecificConfig; /**< General audio specific configuration. */ + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ + CSUsacConfig m_usacConfig; /**< USAC specific configuration */ + } m_sc; + + /* Common ASC parameters */ + CProgramConfig m_progrConfigElement; /**< Program configuration. */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the + bitstream */ + SCHAR + m_psPresentFlag; /**< Flag indicating the presence of parametric stereo + data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + + UCHAR + configMode; /**< The flag indicates if the callback shall work in memory + allocation mode or in config change detection mode */ + UCHAR AacConfigChanged; /**< The flag will be set if at least one aac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SbrConfigChanged; /**< The flag will be set if at least one sbr config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SacConfigChanged; /**< The flag will be set if at least one sac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + + UCHAR + config[TP_USAC_MAX_CONFIG_LEN]; /**< Configuration stored as bitstream */ + UINT configBits; /**< Configuration length in bits */ + +} CSAudioSpecificConfig; + +typedef struct { + SCHAR flushCnt; /**< Flush frame counter */ + UCHAR flushStatus; /**< Flag indicates flush mode: on|off */ + SCHAR buildUpCnt; /**< Build up frame counter */ + UCHAR buildUpStatus; /**< Flag indicates build up mode: on|off */ + UCHAR cfgChanged; /**< Flag indicates that the config changed and the decoder + needs to be initialized again via callback. Make sure + that memory is freed before initialization. */ + UCHAR contentChanged; /**< Flag indicates that the content changed i.e. a + right truncation occured before */ + UCHAR forceCfgChange; /**< Flag indicates if config change has to be forced + even if new config is the same */ +} CCtrlCFGChange; + +typedef INT (*cbUpdateConfig_t)(void *, const CSAudioSpecificConfig *, + const UCHAR configMode, UCHAR *configChanged); +typedef INT (*cbFreeMem_t)(void *, const CSAudioSpecificConfig *); +typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *); +typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +typedef INT (*cbSbr_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSbr, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +typedef INT (*cbUsac_t)(void *self, HANDLE_FDK_BITSTREAM hBs); + +typedef INT (*cbUniDrc_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, const INT payloadType, + const INT subStreamIndex, const INT payloadStart, + const AUDIO_OBJECT_TYPE); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change + notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify + callback. */ + cbFreeMem_t cbFreeMem; /*!< Function pointer for free memory callback. */ + void *cbFreeMemData; /*!< User data pointer for free memory callback. */ + cbCtrlCFGChange_t cbCtrlCFGChange; /*!< Function pointer for config change + control callback. */ + void *cbCtrlCFGChangeData; /*!< User data pointer for config change control + callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ + cbUsac_t cbUsac; + void *cbUsacData; + cbUniDrc_t cbUniDrc; /*!< Function pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ + void *cbUniDrcData; /*!< User data pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, + 8000, 7350, 0, 0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, + 20000, 19200, 17075, 14400, 12800, 9600, 0, 0, 0, 0}; + +static inline int getSamplingRateIndex(UINT samplingRate, UINT nBits) { + UINT sf_index; + UINT tableSize = (1 << nBits) - 1; + + for (sf_index = 0; sf_index < tableSize; sf_index++) { + if (SamplingRateTable[sf_index] == samplingRate) break; + } + + if (sf_index > tableSize) { + return tableSize - 1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) { + switch (channelConfig) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return channelConfig; + case 7: + case 12: + case 14: + return 8; + case 11: + return 7; + case 13: + return 24; + default: + return 0; + } +} + +static inline int getNumberOfEffectiveChannels( + const int + channelConfig) { /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0, 1, 2, 3, 4, 5, 5, 7, 0, 0, 0, 6, 7, 22, 7, 0}; + return n[channelConfig]; +} + +#endif /* TP_DATA_H */ diff --git a/fdk-aac/libMpegTPDec/include/tpdec_lib.h b/fdk-aac/libMpegTPDec/include/tpdec_lib.h new file mode 100644 index 0000000..30e53c1 --- /dev/null +++ b/fdk-aac/libMpegTPDec/include/tpdec_lib.h @@ -0,0 +1,664 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport decoder + +*******************************************************************************/ + +#ifndef TPDEC_LIB_H +#define TPDEC_LIB_H + +#include "tp_data.h" + +#include "FDK_bitstream.h" + +typedef enum { + TRANSPORTDEC_OK = 0, /*!< All fine. */ + + /* Synchronization errors. Wait for new input data and try again. */ + tpdec_sync_error_start = 0x100, + TRANSPORTDEC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try + again. */ + TRANSPORTDEC_SYNC_ERROR, /*!< No sync was found or sync got lost. Keep trying. + */ + tpdec_sync_error_end, + + /* Decode errors. Mostly caused due to bit errors. */ + tpdec_decode_error_start = 0x400, + TRANSPORTDEC_PARSE_ERROR, /*!< Bitstream data showed inconsistencies (wrong + syntax). */ + TRANSPORTDEC_UNSUPPORTED_FORMAT, /*!< Unsupported format or feature found in + the bitstream data. */ + TRANSPORTDEC_CRC_ERROR, /*!< CRC error encountered in bitstream data. */ + tpdec_decode_error_end, + + /* Fatal errors. Stop immediately on one of these errors! */ + tpdec_fatal_error_start = 0x200, + TRANSPORTDEC_UNKOWN_ERROR, /*!< An unknown error occured. */ + TRANSPORTDEC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a + function. */ + TRANSPORTDEC_NEED_TO_RESTART, /*!< The decoder needs to be restarted, since + the requiered configuration change cannot + be performed. */ + TRANSPORTDEC_TOO_MANY_BITS, /*!< In case of packet based formats: Supplied + number of bits exceed the size of the + internal bit buffer. */ + tpdec_fatal_error_end + +} TRANSPORTDEC_ERROR; + +/** Macro to identify decode errors. */ +#define TPDEC_IS_DECODE_ERROR(err) \ + (((err >= tpdec_decode_error_start) && (err <= tpdec_decode_error_end)) ? 1 \ + : 0) +/** Macro to identify fatal errors. */ +#define TPDEC_IS_FATAL_ERROR(err) \ + (((err >= tpdec_fatal_error_start) && (err <= tpdec_fatal_error_end)) ? 1 : 0) + +/** + * \brief Parameter identifiers for transportDec_SetParam() + */ +typedef enum { + TPDEC_PARAM_MINIMIZE_DELAY = 1, /** Delay minimization strategy. 0: none, 1: + discard as many frames as possible. */ + TPDEC_PARAM_EARLY_CONFIG, /** Enable early config discovery. */ + TPDEC_PARAM_IGNORE_BUFFERFULLNESS, /** Ignore buffer fullness. */ + TPDEC_PARAM_SET_BITRATE, /** Set average bit rate for bit stream interruption + frame misses estimation. */ + TPDEC_PARAM_RESET, /** Reset transport decoder instance status. */ + TPDEC_PARAM_BURST_PERIOD, /** Set data reception burst period in mili seconds. + */ + TPDEC_PARAM_TARGETLAYOUT, /** Set CICP target layout */ + TPDEC_PARAM_FORCE_CONFIG_CHANGE, /** Force config change for next received + config */ + TPDEC_PARAM_USE_ELEM_SKIPPING +} TPDEC_PARAM; + +/*! + \brief Reset Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Reset(CProgramConfig *pPce); + +/*! + \brief Initialize Program Config Element. + \param pPce Program Config Element structure. + \return void +*/ +void CProgramConfig_Init(CProgramConfig *pPce); + +/*! + \brief Inquire state of present Program Config Element + structure. \param pPce Program Config Element structure. \return + 1 if the PCE structure is filled correct, 0 if no valid PCE present. +*/ +int CProgramConfig_IsValid(const CProgramConfig *pPce); + +/*! + \brief Read Program Config Element. + \param pPce Program Config Element structure. + \param bs Bitstream buffer to read from. + \param alignAnchor Align bitstream to alignAnchor bits after all read + operations. \return void +*/ +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignAnchor); + +/*! + \brief Compare two Program Config Elements. + \param pPce1 Pointer to first Program Config Element structure. + \param pPce2 Pointer to second Program Config Element structure. + \return -1 if PCEs are completely different, + 0 if PCEs are completely equal, + 1 if PCEs are different but have the same channel + config, 2 if PCEs have different channel config but same number of channels. +*/ +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2); + +/*! + \brief Get a Program Config Element that matches the predefined + MPEG-4 channel configurations 1-14. \param pPce Program Config + Element structure. \param channelConfig MPEG-4 channel configuration. \return + void +*/ +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig); + +/** + * \brief Lookup and verify a given element. The decoder calls this + * method with every new element ID found in the bitstream. + * + * \param pPce A valid Program config structure. + * \param chConfig MPEG-4 channel configuration. + * \param tag Tag of the current element to be looked up. + * \param channelIdx The current channel count of the decoder parser. + * \param chMapping Array to store the canonical channel mapping indexes. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \param chDescrLen Length of the output channel description array. + * \param elMapping Pointer where the canonical element index is stored. + * \param elType The element id of the current element to be looked up. + * + * \return Non-zero if the element belongs to the current program, + * zero if it does not. + */ +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT chConfig, + const UINT tag, const UINT channelIdx, + UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], const UINT chDescrLen, + UCHAR *elMapping, MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType); + +/** + * \brief Get table of channel indices in the order of their + * appearance in by the program config field. + * \param pPce A valid program config structure. + * \param pceChMap Array to store the channel mapping indices like they + * appear in the PCE. + * \param pceChMapLen Lenght of the channel mapping index array (pceChMap). + * + * \return Non-zero if any error occured otherwise zero. + */ +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen); + +/** + * \brief Get table of elements in canonical order from a + * give program config field. + * \param pPce A valid program config structure. + * \param table An array where the element IDs are stored. + * \param elListSize The length of the table array. + * \param pChMapIdx Pointer to a field receiving the corresponding + * implicit channel configuration index of the given + * PCE. If none can be found it receives the value 0. + * \return Total element count including all SCE, CPE and LFE. + */ +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID table[], const INT elListSize, + UCHAR *pChMapIdx); + +/** + * \brief Get channel description (type and index) for implicit + configurations (chConfig > 0) in MPEG canonical order. + * \param chConfig MPEG-4 channel configuration. + * \param chType Array to store the audio channel type. + * \param chIndex Array to store the individual audio channel type index. + * \return void + */ +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]); + +/** + * \brief Initialize a given AudioSpecificConfig structure. + * \param pAsc A pointer to an allocated CSAudioSpecificConfig struct. + * \return void + */ +void AudioSpecificConfig_Init(CSAudioSpecificConfig *pAsc); + +/** + * \brief Parse a AudioSpecificConfig from a given bitstream handle. + * + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * \param fExplicitBackwardCompatible Do explicit backward compatibility + * parsing if set (flag). + * \param cb pointer to structure holding callback information + * \param configMode Config modes: memory allocation mode or config change + * detection mode. + * \param configChanged Indicates a config change. + * \param m_aot in case of unequal AOT_NULL_OBJECT only the specific config is + * parsed. + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *pAsc, HANDLE_FDK_BITSTREAM hBs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot); + +/* CELP stuff */ +enum { MPE = 0, RPE = 1, fs8KHz = 0, fs16KHz = 1 }; + +/* Defintion of flags that can be passed to transportDecOpen() */ +#define TP_FLAG_MPEG4 1 + +/* Capability flags */ +#define CAPF_TPDEC_ADIF \ + 0x00001000 /**< Flag indicating support for ADIF transport format. */ +#define CAPF_TPDEC_ADTS \ + 0x00002000 /**< Flag indicating support for ADTS transport format. */ +#define CAPF_TPDEC_LOAS \ + 0x00004000 /**< Flag indicating support for LOAS transport format. */ +#define CAPF_TPDEC_LATM \ + 0x00008000 /**< Flag indicating support for LATM transport format. */ +#define CAPF_TPDEC_RAWPACKETS \ + 0x00010000 /**< Flag indicating support for raw packets transport format. */ + +typedef struct TRANSPORTDEC *HANDLE_TRANSPORTDEC; + +/** + * \brief Configure Transport Decoder via a binary coded AudioSpecificConfig or + * StreamMuxConfig. The previously requested configuration callback will be + * called as well. The buffer conf must containt a SMC in case of + * LOAS/LATM transport format, and an ASC elseways. + * + * \param hTp Handle of a transport decoder. + * \param conf UCHAR buffer of the binary coded config (ASC or SMC). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(const HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + const UINT layer); + +/** + * \brief Configure Transport Decoder via a binary coded USAC/RSV603DA Config. + * The buffer newConfig contains a binary coded USAC/RSV603DA config of + * length newConfigLength bytes. If the new config and the previous config are + * different configChanged is set to 1 otherwise it is set to 0. + * + * \param hTp Handle of a transport decoder. + * \param newConfig buffer of the binary coded config. + * \param newConfigLength Length of new config in bytes. + * \param buildUpStatus Indicates build up status: off|on|idle. + * \param configChanged Indicates if config changed. + * \param layer Instance layer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_InBandConfig( + const HANDLE_TRANSPORTDEC hTp, UCHAR *newConfig, const UINT newConfigLength, + const UCHAR buildUpStatus, UCHAR *configChanged, const UINT layer, + UCHAR *implicitExplicitCfgDiff); + +/** + * \brief Open Transport medium for reading. + * + * \param transportDecFmt Format of the transport decoder medium to be accessed. + * \param flags Transport decoder flags. Currently only TP_FLAG_MPEG4, + * which signals a MPEG4 capable decoder (relevant for ADTS only). + * + * \return A pointer to a valid and allocated HANDLE_TRANSPORTDEC or a null + * pointer on failure. + */ +HANDLE_TRANSPORTDEC transportDec_Open(TRANSPORT_TYPE transportDecFmt, + const UINT flags, const UINT nrOfLayer); + +/** + * \brief Register configuration change callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle audio config + * changes. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTp, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data); + +/** + * \brief Register free memory callback. + * \param hTp Handle of transport decoder. + * \param cbFreeMem Pointer to a callback function to free config dependent + * memory. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTp, + const cbFreeMem_t cbFreeMem, + void *user_data); + +/** + * \brief Register config change control callback. + * \param hTp Handle of transport decoder. + * \param cbCtrlCFGChange Pointer to a callback function for config change + * control. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTp, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data); + +/** + * \brief Register SSC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTp, + const cbSsc_t cbSscParse, void *user_data); + +/** + * \brief Register SBR header parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data); + +/** + * \brief Register USAC SC parser callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle USAC SC + * parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data); + +/** + * \brief Register uniDrcConfig and loudnessInfoSet parser + * callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle uniDrcConfig + * and loudnessInfoSet parsing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition); + +/** + * \brief Fill internal input buffer with bitstream data from the external input + * buffer. The function only copies such data as long as the decoder-internal + * input buffer is not full. So it grabs whatever it can from pBuffer and + * returns information (bytesValid) so that at a subsequent call of + * %transportDec_FillData(), the right position in pBuffer can be determined to + * grab the next data. + * + * \param hTp Handle of transportDec. + * \param pBuffer Pointer to external input buffer. + * \param bufferSize Size of external input buffer. This argument is required + * because decoder-internally we need the information to calculate the offset to + * pBuffer, where the next available data is, which is then + * fed into the decoder-internal buffer (as much as + * possible). Our example framework implementation fills the + * buffer at pBuffer again, once it contains no available valid bytes anymore + * (meaning bytesValid equal 0). + * \param bytesValid Number of bitstream bytes in the external bitstream buffer + * that have not yet been copied into the decoder's internal bitstream buffer by + * calling this function. The value is updated according to + * the amount of newly copied bytes. + * \param layer The layer the bitstream belongs to. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer); + +/** + * \brief Get transportDec bitstream handle. + * \param hTp Pointer to a transport decoder handle. + * \return HANDLE_FDK_BITSTREAM bitstream handle. + */ +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get transport format. + * \param hTp Pointer to a transport decoder handle. + * \return The transport format. + */ +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Get the current buffer fullness value. + * + * \param hTp Handle of a transport decoder. + * + * \return Buffer fullness + */ +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Close and deallocate transportDec. + * \param phTp Pointer to a previously allocated transport decoder handle. + * \return void + */ +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp); + +/** + * \brief Read one access unit from the transportDec medium. + * \param hTp Handle of transportDec. + * \param length On return, this value is overwritten with the actual access + * unit length in bits. Set to -1 if length is unknown. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get AudioSpecificConfig. + * \param hTp Handle of transportDec. + * \param layer Transport layer. + * \param asc Pointer to AudioSpecificConfig. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc); + +/** + * \brief Get the remaining amount of bits of the current access unit. The + * result can be below zero, meaning that too many bits have been read. + * \param hTp Handle of transportDec. + * \return amount of remaining bits. + */ +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief Get the total amount of bits of the current access unit. + * \param hTp Handle of transportDec. + * \return amount of total bits. + */ +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer); + +/** + * \brief This function is required to be called when the decoder has + * finished parsing one Access Unit for bitstream housekeeping. + * \param hTp Transport Handle. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Obtain the amount of missing access units if applicable in case + * of a bit stream synchronization error. Each time + * transportDec_ReadAccessUnit() returns TRANSPORTDEC_SYNC_ERROR + * this function can be called to retrieve an estimate of the amount + * of missing access units. This works only in case of constant + * average bit rate (has to be known) and if the parameter + * TPDEC_PARAM_SET_BITRATE has been set accordingly. + * \param hTp Transport Handle. + * \param pNAccessUnits pointer to a memory location where the estimated lost + * frame count will be stored into. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Set a given setting. + * \param hTp Transport Handle. + * \param param Identifier of the parameter to be changed. + * \param value Value for the parameter to be changed. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value); + +/** + * \brief Get number of subframes (for LATM or ADTS) + * \param hTp Transport Handle. + * \return Number of ADTS/LATM subframes (return 1 for all other transport + * types). + */ +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Get info structure of transport decoder library. + * \param info A pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTp Transport handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be + * of a fixed size. + * \return Data region ID, which should be used when calling + * transportDec_CrcEndReg(). + */ +int transportDec_CrcStartReg(const HANDLE_TRANSPORTDEC hTp, const INT mBits); + +/** + * \brief Set end of data region. + * \param hTp Transport handle. + * \param reg Data region ID, opbtained from transportDec_CrcStartReg(). + * \return void + */ +void transportDec_CrcEndReg(const HANDLE_TRANSPORTDEC hTp, const INT reg); + +/** + * \brief Calculate ADTS crc and check if it is correct. The ADTS checksum + * is held internally. + * \param hTp Transport handle. + * \return Return TRANSPORTDEC_OK if the CRC is ok, or error if CRC is not + * correct. + */ +TRANSPORTDEC_ERROR transportDec_CrcCheck(const HANDLE_TRANSPORTDEC hTp); + +/** + * \brief Only check whether a given config seems to be valid without modifying + * internal states. + * + * \param conf UCHAR buffer of the binary coded config (SDC type 9). + * \param length The length in bytes of the conf buffer. + * + * \return Error code. + */ +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length); + +#endif /* #ifndef TPDEC_LIB_H */ diff --git a/fdk-aac/libMpegTPDec/src/tp_version.h b/fdk-aac/libMpegTPDec/src/tp_version.h new file mode 100644 index 0000000..4faed8c --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tp_version.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(TP_VERSION_H) +#define TP_VERSION_H + +/* library info */ +#define TP_LIB_VL0 3 +#define TP_LIB_VL1 0 +#define TP_LIB_VL2 0 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif +#endif /* !defined(TP_VERSION_H) */ diff --git a/fdk-aac/libMpegTPDec/src/tpdec_adif.cpp b/fdk-aac/libMpegTPDec/src/tpdec_adif.cpp new file mode 100644 index 0000000..ec20b9b --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_adif.cpp @@ -0,0 +1,158 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADIF reader + +*******************************************************************************/ + +#include "tpdec_adif.h" + +#include "FDK_bitstream.h" +#include "genericStds.h" + +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs) { + int i; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT startAnchor = FDKgetValidBits(bs); + + if ((INT)startAnchor < MIN_ADIF_HEADERLENGTH) { + return (TRANSPORTDEC_NOT_ENOUGH_BITS); + } + + if (FDKreadBits(bs, 8) != 'A') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'D') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'I') { + return (TRANSPORTDEC_SYNC_ERROR); + } + if (FDKreadBits(bs, 8) != 'F') { + return (TRANSPORTDEC_SYNC_ERROR); + } + + if ((pAdifHeader->CopyrightIdPresent = FDKreadBits(bs, 1)) != 0) + FDKpushBiDirectional(bs, 72); /* CopyrightId */ + + pAdifHeader->OriginalCopy = FDKreadBits(bs, 1); + pAdifHeader->Home = FDKreadBits(bs, 1); + pAdifHeader->BitstreamType = FDKreadBits(bs, 1); + + /* pAdifHeader->BitRate = FDKreadBits(bs, 23); */ + pAdifHeader->BitRate = FDKreadBits(bs, 16); + pAdifHeader->BitRate <<= 7; + pAdifHeader->BitRate |= FDKreadBits(bs, 7); + + pAdifHeader->NumProgramConfigElements = FDKreadBits(bs, 4) + 1; + + if (pAdifHeader->BitstreamType == 0) { + FDKpushBiDirectional(bs, 20); /* adif_buffer_fullness */ + } + + /* Parse all PCEs but keep only one */ + for (i = 0; i < pAdifHeader->NumProgramConfigElements; i++) { + CProgramConfig_Read(pPce, bs, startAnchor); + } + + FDKbyteAlign(bs, startAnchor); + + return (ErrorStatus); +} diff --git a/fdk-aac/libMpegTPDec/src/tpdec_adif.h b/fdk-aac/libMpegTPDec/src/tpdec_adif.h new file mode 100644 index 0000000..72ccc6a --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_adif.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADIF reader + +*******************************************************************************/ + +#ifndef TPDEC_ADIF_H +#define TPDEC_ADIF_H + +#include "tpdec_lib.h" + +#define MIN_ADIF_HEADERLENGTH 63 /* in bits */ + +typedef struct { + INT NumProgramConfigElements; + UINT BitRate; + UCHAR CopyrightIdPresent; + UCHAR OriginalCopy; + UCHAR Home; + UCHAR BitstreamType; +} CAdifHeader; + +/** + * \brief Parse a ADIF header at the given bitstream and store the parsed data + * into a given CAdifHeader and CProgramConfig struct + * + * \param pAdifHeader pointer to a CAdifHeader structure to hold the parsed ADIF + * header data. + * \param pPce pointer to a CProgramConfig structure where the last PCE will + * remain. + * + * \return TRANSPORTDEC_ERROR error code + */ +TRANSPORTDEC_ERROR adifRead_DecodeHeader(CAdifHeader *pAdifHeader, + CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs); + +#endif /* TPDEC_ADIF_H */ diff --git a/fdk-aac/libMpegTPDec/src/tpdec_adts.cpp b/fdk-aac/libMpegTPDec/src/tpdec_adts.cpp new file mode 100644 index 0000000..1a4e3fd --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_adts.cpp @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADTS interface + +*******************************************************************************/ + +#include "tpdec_adts.h" + +#include "FDK_bitstream.h" + +void adtsRead_CrcInit( + HANDLE_ADTS pAdts) /*!< pointer to adts crc info stucture */ +{ + FDKcrcInit(&pAdts->crcInfo, 0x8005, 0xFFFF, 16); +} + +int adtsRead_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + if (pAdts->bs.protection_absent) { + return 0; + } + + return (FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits)); +} + +void adtsRead_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + if (pAdts->bs.protection_absent == 0) { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + if (pAdts->bs.protection_absent) return TRANSPORTDEC_OK; + + crc = FDKcrcGetCRC(&pAdts->crcInfo); + if (crc != pAdts->crcReadValue) { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} + +#define Adts_Length_SyncWord 12 +#define Adts_Length_Id 1 +#define Adts_Length_Layer 2 +#define Adts_Length_ProtectionAbsent 1 +#define Adts_Length_Profile 2 +#define Adts_Length_SamplingFrequencyIndex 4 +#define Adts_Length_PrivateBit 1 +#define Adts_Length_ChannelConfiguration 3 +#define Adts_Length_OriginalCopy 1 +#define Adts_Length_Home 1 +#define Adts_Length_CopyrightIdentificationBit 1 +#define Adts_Length_CopyrightIdentificationStart 1 +#define Adts_Length_FrameLength 13 +#define Adts_Length_BufferFullness 11 +#define Adts_Length_NumberOfRawDataBlocksInFrame 2 +#define Adts_Length_CrcCheck 16 + +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + const INT ignoreBufferFullness) { + INT crcReg; + + INT valBits; + INT cmp_buffer_fullness; + int i, adtsHeaderLength; + + STRUCT_ADTS_BS bs; + + CProgramConfig oldPce; + /* Store the old PCE temporarily. Maybe we'll need it later if we + have channelConfig=0 and no PCE in this frame. */ + FDKmemcpy(&oldPce, &pAsc->m_progrConfigElement, sizeof(CProgramConfig)); + + valBits = FDKgetValidBits(hBs) + ADTS_SYNCLENGTH; + + if (valBits < ADTS_HEADERLENGTH) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + /* adts_fixed_header */ + bs.mpeg_id = FDKreadBits(hBs, Adts_Length_Id); + bs.layer = FDKreadBits(hBs, Adts_Length_Layer); + bs.protection_absent = FDKreadBits(hBs, Adts_Length_ProtectionAbsent); + bs.profile = FDKreadBits(hBs, Adts_Length_Profile); + bs.sample_freq_index = FDKreadBits(hBs, Adts_Length_SamplingFrequencyIndex); + bs.private_bit = FDKreadBits(hBs, Adts_Length_PrivateBit); + bs.channel_config = FDKreadBits(hBs, Adts_Length_ChannelConfiguration); + bs.original = FDKreadBits(hBs, Adts_Length_OriginalCopy); + bs.home = FDKreadBits(hBs, Adts_Length_Home); + + /* adts_variable_header */ + bs.copyright_id = FDKreadBits(hBs, Adts_Length_CopyrightIdentificationBit); + bs.copyright_start = + FDKreadBits(hBs, Adts_Length_CopyrightIdentificationStart); + bs.frame_length = FDKreadBits(hBs, Adts_Length_FrameLength); + bs.adts_fullness = FDKreadBits(hBs, Adts_Length_BufferFullness); + bs.num_raw_blocks = + FDKreadBits(hBs, Adts_Length_NumberOfRawDataBlocksInFrame); + bs.num_pce_bits = 0; + + adtsHeaderLength = ADTS_HEADERLENGTH; + + if (valBits < bs.frame_length * 8) { + goto bail; + } + + if (!bs.protection_absent) { + FDKcrcReset(&pAdts->crcInfo); + FDKpushBack(hBs, 56); /* complete fixed and variable header! */ + crcReg = FDKcrcStartReg(&pAdts->crcInfo, hBs, 0); + FDKpushFor(hBs, 56); + } + + if (!bs.protection_absent && bs.num_raw_blocks > 0) { + if ((INT)FDKgetValidBits(hBs) < bs.num_raw_blocks * 16) { + goto bail; + } + for (i = 0; i < bs.num_raw_blocks; i++) { + pAdts->rawDataBlockDist[i] = (USHORT)FDKreadBits(hBs, 16); + adtsHeaderLength += 16; + } + /* Change raw data blocks to delta values */ + pAdts->rawDataBlockDist[bs.num_raw_blocks] = + bs.frame_length - 7 - bs.num_raw_blocks * 2 - 2; + for (i = bs.num_raw_blocks; i > 0; i--) { + pAdts->rawDataBlockDist[i] -= pAdts->rawDataBlockDist[i - 1]; + } + } + + /* adts_error_check */ + if (!bs.protection_absent) { + USHORT crc_check; + + FDKcrcEndReg(&pAdts->crcInfo, hBs, crcReg); + + if ((INT)FDKgetValidBits(hBs) < Adts_Length_CrcCheck) { + goto bail; + } + + crc_check = FDKreadBits(hBs, Adts_Length_CrcCheck); + adtsHeaderLength += Adts_Length_CrcCheck; + + pAdts->crcReadValue = crc_check; + /* Check header CRC in case of multiple raw data blocks */ + if (bs.num_raw_blocks > 0) { + if (pAdts->crcReadValue != FDKcrcGetCRC(&pAdts->crcInfo)) { + return TRANSPORTDEC_CRC_ERROR; + } + /* Reset CRC for the upcoming raw_data_block() */ + FDKcrcReset(&pAdts->crcInfo); + } + } + + /* check if valid header */ + if ((bs.layer != 0) || // we only support MPEG ADTS + (bs.sample_freq_index >= 13) // we only support 96kHz - 7350kHz + ) { + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* special treatment of id-bit */ + if ((bs.mpeg_id == 0) && (pAdts->decoderCanDoMpeg4 == 0)) { + /* MPEG-2 decoder cannot play MPEG-4 bitstreams */ + + FDKpushFor(hBs, bs.frame_length * 8); // try again one frame later + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (!ignoreBufferFullness) { + cmp_buffer_fullness = + bs.frame_length * 8 + + bs.adts_fullness * 32 * getNumberOfEffectiveChannels(bs.channel_config); + + /* Evaluate buffer fullness */ + if (bs.adts_fullness != 0x7FF) { + if (pAdts->BufferFullnesStartFlag) { + if (valBits < cmp_buffer_fullness) { + /* Condition for start of decoding is not fulfilled */ + + /* The current frame will not be decoded */ + FDKpushBack(hBs, adtsHeaderLength); + + if ((cmp_buffer_fullness + adtsHeaderLength) > + (((8192 * 4) << 3) - 7)) { + return TRANSPORTDEC_SYNC_ERROR; + } else { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } else { + pAdts->BufferFullnesStartFlag = 0; + } + } + } + } + + /* Get info from ADTS header */ + AudioSpecificConfig_Init(pAsc); + pAsc->m_aot = (AUDIO_OBJECT_TYPE)(bs.profile + 1); + pAsc->m_samplingFrequencyIndex = bs.sample_freq_index; + pAsc->m_samplingFrequency = SamplingRateTable[bs.sample_freq_index]; + pAsc->m_channelConfiguration = bs.channel_config; + pAsc->m_samplesPerFrame = 1024; + + if (bs.channel_config == 0) { + int pceBits = 0; + UINT alignAnchor = FDKgetValidBits(hBs); + + if (FDKreadBits(hBs, 3) == ID_PCE) { + /* Got luck! Parse the PCE */ + crcReg = adtsRead_CrcStartReg(pAdts, hBs, 0); + + CProgramConfig_Read(&pAsc->m_progrConfigElement, hBs, alignAnchor); + + adtsRead_CrcEndReg(pAdts, hBs, crcReg); + pceBits = alignAnchor - FDKgetValidBits(hBs); + /* store the number of PCE bits */ + bs.num_pce_bits = pceBits; + } else { + /* No PCE in this frame! Push back the ID tag bits. */ + FDKpushBack(hBs, 3); + + /* Encoders do not have to write a PCE in each frame. + So if we already have a valid PCE we have to use it. */ + if (oldPce.isValid && + (bs.sample_freq_index == + pAdts->bs.sample_freq_index) /* we could compare the complete fixed + header (bytes) here! */ + && (bs.channel_config == pAdts->bs.channel_config) /* == 0 */ + && + (bs.mpeg_id == + pAdts->bs.mpeg_id)) { /* Restore previous PCE which is still valid */ + FDKmemcpy(&pAsc->m_progrConfigElement, &oldPce, sizeof(CProgramConfig)); + } else if (bs.mpeg_id == 0) { + /* If not it seems that we have a implicit channel configuration. + This mode is not allowed in the context of ISO/IEC 14496-3. + Skip this frame and try the next one. */ + FDKpushFor(hBs, (bs.frame_length << 3) - adtsHeaderLength - 3); + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + /* else { + ISO/IEC 13818-7 implicit channel mapping is allowed. + So just open the box of chocolates to see what we got. + } */ + } + } + + /* Copy bit stream data struct to persistent memory now, once we passed all + * sanity checks above. */ + FDKmemcpy(&pAdts->bs, &bs, sizeof(STRUCT_ADTS_BS)); + + return TRANSPORTDEC_OK; + +bail: + FDKpushBack(hBs, adtsHeaderLength); + return TRANSPORTDEC_NOT_ENOUGH_BITS; +} + +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum) { + int length; + + if (pAdts->bs.num_raw_blocks == 0) { + length = + (pAdts->bs.frame_length - 7) + << 3; /* aac_frame_length subtracted by the header size (7 bytes). */ + if (pAdts->bs.protection_absent == 0) + length -= 16; /* substract 16 bit CRC */ + } else { + if (pAdts->bs.protection_absent) { + length = -1; /* raw data block length is unknown */ + } else { + if (blockNum < 0 || blockNum > 3) { + length = -1; + } else { + length = (pAdts->rawDataBlockDist[blockNum] << 3) - 16; + } + } + } + if (blockNum == 0 && length > 0) { + length -= pAdts->bs.num_pce_bits; + } + return length; +} diff --git a/fdk-aac/libMpegTPDec/src/tpdec_adts.h b/fdk-aac/libMpegTPDec/src/tpdec_adts.h new file mode 100644 index 0000000..68f3f63 --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_adts.h @@ -0,0 +1,234 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: ADTS interface + +*******************************************************************************/ + +#ifndef TPDEC_ADTS_H +#define TPDEC_ADTS_H + +#include "tpdec_lib.h" + +#define ADTS_SYNCWORD (0xfff) +#define ADTS_SYNCLENGTH (12) /* in bits */ +#define ADTS_HEADERLENGTH (56) /* minimum header size in bits */ +#define ADTS_FIXED_HEADERLENGTH (28) /* in bits */ +#define ADTS_VARIABLE_HEADERLENGTH (ADTS_HEADERLENGTH - ADTS_FIXED_HEADERLENGTH) + +#ifdef CHECK_TWO_SYNCS +#define ADTS_MIN_TP_BUF_SIZE (8191 + 2) +#else +#define ADTS_MIN_TP_BUF_SIZE (8191) +#endif + +#include "FDK_crc.h" + +typedef struct { + /* ADTS header fields */ + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR channel_config; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + USHORT adts_fullness; + UCHAR num_raw_blocks; + UCHAR num_pce_bits; +} STRUCT_ADTS_BS; + +struct STRUCT_ADTS { + STRUCT_ADTS_BS bs; + + UCHAR decoderCanDoMpeg4; + UCHAR BufferFullnesStartFlag; + + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + USHORT rawDataBlockDist[4]; /* distance between each raw data block. Not the + same as found in the bitstream */ +}; + +typedef struct STRUCT_ADTS *HANDLE_ADTS; + +/*! + \brief Initialize ADTS CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void adtsRead_CrcInit(HANDLE_ADTS pAdts); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int adtsRead_CrcStartReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, + int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by adtsRead_CrcStartReg() + * + * \return none + */ +void adtsRead_CrcEndReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, int reg); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. + * + * \param pAdts ADTS data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR adtsRead_CrcCheck(HANDLE_ADTS pAdts); + +/** + * \brief Check if we have a valid ADTS frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. + * + * \param pAdts ADTS data handle which is filled with parsed ADTS header data + * \param bs handle of bitstream from whom the ADTS header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR adtsRead_DecodeHeader(HANDLE_ADTS pAdts, + CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM bs, + const INT ignoreBufferFullness); + +/** + * \brief Get the raw data block length of the given block number. + * + * \param pAdts ADTS data handle + * \param blockNum current raw data block index + * \param pLength pointer to an INT where the length of the given raw data block + * is stored into the returned value might be -1, in which case the raw data + * block length is unknown. + * + * \return error status + */ +int adtsRead_GetRawDataBlockLength(HANDLE_ADTS pAdts, INT blockNum); + +#endif /* TPDEC_ADTS_H */ diff --git a/fdk-aac/libMpegTPDec/src/tpdec_asc.cpp b/fdk-aac/libMpegTPDec/src/tpdec_asc.cpp new file mode 100644 index 0000000..28bc22d --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_asc.cpp @@ -0,0 +1,2592 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#include "tpdec_lib.h" +#include "tp_data.h" + +#include "FDK_crc.h" + +#include "common_fix.h" + +/** + * The following arrays provide the IDs of the consecutive elements for each + * channel configuration. Every channel_configuration has to be finalized with + * ID_NONE. + */ +static const MP4_ELEMENT_ID channel_configuration_0[] = {ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_1[] = {ID_SCE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_2[] = {ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_3[] = {ID_SCE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_4[] = {ID_SCE, ID_CPE, ID_SCE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_5[] = {ID_SCE, ID_CPE, ID_CPE, + ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_6[] = {ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_7[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_8[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_9[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_10[] = { + ID_NONE}; /* reserved */ +static const MP4_ELEMENT_ID channel_configuration_11[] = { + ID_SCE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_12[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_13[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_CPE, ID_SCE, ID_LFE, ID_LFE, ID_SCE, + ID_CPE, ID_CPE, ID_SCE, ID_CPE, ID_SCE, ID_SCE, ID_CPE, ID_NONE}; +static const MP4_ELEMENT_ID channel_configuration_14[] = { + ID_SCE, ID_CPE, ID_CPE, ID_LFE, ID_CPE, ID_NONE}; + +static const MP4_ELEMENT_ID *channel_configuration_array[] = { + channel_configuration_0, channel_configuration_1, + channel_configuration_2, channel_configuration_3, + channel_configuration_4, channel_configuration_5, + channel_configuration_6, channel_configuration_7, + channel_configuration_8, channel_configuration_9, + channel_configuration_10, channel_configuration_11, + channel_configuration_12, channel_configuration_13, + channel_configuration_14}; + +#define TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX (13) +#define SC_CHANNEL_CONFIG_TAB_SIZE (TP_USAC_MAX_CHANNEL_CONFIGURATION_INDEX + 1) + +/* channel config structure used for sanity check */ +typedef struct { + SCHAR nCh; /* number of channels */ + SCHAR nSCE; /* number of SCE's */ + SCHAR nCPE; /* number of CPE's */ + SCHAR nLFE; /* number of LFE's */ +} SC_CHANNEL_CONFIG; + +static const SC_CHANNEL_CONFIG sc_chan_config_tab[SC_CHANNEL_CONFIG_TAB_SIZE] = + { + /* nCh, nSCE, nCPE, nLFE, cci */ + {0, 0, 0, 0}, /* 0 */ + {1, 1, 0, 0}, /* 1 */ + {2, 0, 1, 0}, /* 2 */ + {3, 1, 1, 0}, /* 3 */ + {4, 2, 1, 0}, /* 4 */ + {5, 1, 2, 0}, /* 5 */ + {6, 1, 2, 1}, /* 6 */ + {8, 1, 3, 1}, /* 7 */ + {2, 2, 0, 0}, /* 8 */ + {3, 1, 1, 0}, /* 9 */ + {4, 0, 2, 0}, /* 10 */ + {7, 2, 2, 1}, /* 11 */ + {8, 1, 3, 1}, /* 12 */ + {24, 6, 8, 2} /* 13 */ +}; + +void CProgramConfig_Reset(CProgramConfig *pPce) { pPce->elCounter = 0; } + +void CProgramConfig_Init(CProgramConfig *pPce) { + FDKmemclear(pPce, sizeof(CProgramConfig)); + pPce->SamplingFrequencyIndex = 0xf; +} + +int CProgramConfig_IsValid(const CProgramConfig *pPce) { + return ((pPce->isValid) ? 1 : 0); +} + +#define PCE_HEIGHT_EXT_SYNC (0xAC) + +/* + * Read the extension for height info. + * return 0 if successfull, + * -1 if the CRC failed, + * -2 if invalid HeightInfo. + */ +static int CProgramConfig_ReadHeightExt(CProgramConfig *pPce, + HANDLE_FDK_BITSTREAM bs, + int *const bytesAvailable, + const UINT alignmentAnchor) { + int err = 0; + FDK_CRCINFO crcInfo; /* CRC state info */ + INT crcReg; + FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); + crcReg = FDKcrcStartReg(&crcInfo, bs, 0); + UINT startAnchor = FDKgetValidBits(bs); + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(bs != NULL); + FDK_ASSERT(bytesAvailable != NULL); + + if ((startAnchor >= 24) && (*bytesAvailable >= 3) && + (FDKreadBits(bs, 8) == PCE_HEIGHT_EXT_SYNC)) { + int i; + + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + if ((pPce->FrontElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + for (i = 0; i < pPce->NumSideChannelElements; i++) { + if ((pPce->SideElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + for (i = 0; i < pPce->NumBackChannelElements; i++) { + if ((pPce->BackElementHeightInfo[i] = (UCHAR)FDKreadBits(bs, 2)) >= + PC_NUM_HEIGHT_LAYER) { + err = -2; /* height information is out of the valid range */ + } + } + FDKbyteAlign(bs, alignmentAnchor); + + FDKcrcEndReg(&crcInfo, bs, crcReg); + if ((USHORT)FDKreadBits(bs, 8) != FDKcrcGetCRC(&crcInfo)) { + /* CRC failed */ + err = -1; + } + if (err != 0) { + /* Reset whole height information in case an error occured during parsing. + The return value ensures that pPce->isValid is set to 0 and implicit + channel mapping is used. */ + FDKmemclear(pPce->FrontElementHeightInfo, + sizeof(pPce->FrontElementHeightInfo)); + FDKmemclear(pPce->SideElementHeightInfo, + sizeof(pPce->SideElementHeightInfo)); + FDKmemclear(pPce->BackElementHeightInfo, + sizeof(pPce->BackElementHeightInfo)); + } + } else { + /* No valid extension data found -> restore the initial bitbuffer state */ + FDKpushBack(bs, (INT)startAnchor - (INT)FDKgetValidBits(bs)); + } + + /* Always report the bytes read. */ + *bytesAvailable -= ((INT)startAnchor - (INT)FDKgetValidBits(bs)) >> 3; + + return (err); +} + +void CProgramConfig_Read(CProgramConfig *pPce, HANDLE_FDK_BITSTREAM bs, + UINT alignmentAnchor) { + int i, err = 0; + int commentBytes; + + pPce->NumEffectiveChannels = 0; + pPce->NumChannels = 0; + pPce->ElementInstanceTag = (UCHAR)FDKreadBits(bs, 4); + pPce->Profile = (UCHAR)FDKreadBits(bs, 2); + pPce->SamplingFrequencyIndex = (UCHAR)FDKreadBits(bs, 4); + pPce->NumFrontChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumSideChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumBackChannelElements = (UCHAR)FDKreadBits(bs, 4); + pPce->NumLfeChannelElements = (UCHAR)FDKreadBits(bs, 2); + pPce->NumAssocDataElements = (UCHAR)FDKreadBits(bs, 3); + pPce->NumValidCcElements = (UCHAR)FDKreadBits(bs, 4); + + if ((pPce->MonoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MonoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); + } + + if ((pPce->StereoMixdownPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->StereoMixdownElementNumber = (UCHAR)FDKreadBits(bs, 4); + } + + if ((pPce->MatrixMixdownIndexPresent = (UCHAR)FDKreadBits(bs, 1)) != 0) { + pPce->MatrixMixdownIndex = (UCHAR)FDKreadBits(bs, 2); + pPce->PseudoSurroundEnable = (UCHAR)FDKreadBits(bs, 1); + } + + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + pPce->FrontElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->FrontElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->FrontElementIsCpe[i] ? 2 : 1; + } + + for (i = 0; i < pPce->NumSideChannelElements; i++) { + pPce->SideElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->SideElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->SideElementIsCpe[i] ? 2 : 1; + } + + for (i = 0; i < pPce->NumBackChannelElements; i++) { + pPce->BackElementIsCpe[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->BackElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += pPce->BackElementIsCpe[i] ? 2 : 1; + } + + pPce->NumEffectiveChannels = pPce->NumChannels; + + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + pPce->LfeElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + pPce->NumChannels += 1; + } + + for (i = 0; i < pPce->NumAssocDataElements; i++) { + pPce->AssocDataElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + } + + for (i = 0; i < pPce->NumValidCcElements; i++) { + pPce->CcElementIsIndSw[i] = (UCHAR)FDKreadBits(bs, 1); + pPce->ValidCcElementTagSelect[i] = (UCHAR)FDKreadBits(bs, 4); + } + + FDKbyteAlign(bs, alignmentAnchor); + + pPce->CommentFieldBytes = (UCHAR)FDKreadBits(bs, 8); + commentBytes = pPce->CommentFieldBytes; + + /* Search for height info extension and read it if available */ + err = CProgramConfig_ReadHeightExt(pPce, bs, &commentBytes, alignmentAnchor); + + for (i = 0; i < commentBytes; i++) { + UCHAR text; + + text = (UCHAR)FDKreadBits(bs, 8); + + if (i < PC_COMMENTLENGTH) { + pPce->Comment[i] = text; + } + } + + pPce->isValid = (err) ? 0 : 1; +} + +/* + * Compare two program configurations. + * Returns the result of the comparison: + * -1 - completely different + * 0 - completely equal + * 1 - different but same channel configuration + * 2 - different channel configuration but same number of channels + */ +int CProgramConfig_Compare(const CProgramConfig *const pPce1, + const CProgramConfig *const pPce2) { + int result = 0; /* Innocent until proven false. */ + + if (FDKmemcmp(pPce1, pPce2, sizeof(CProgramConfig)) != + 0) { /* Configurations are not completely equal. + So look into details and analyse the channel configurations: */ + result = -1; + + if (pPce1->NumChannels == + pPce2->NumChannels) { /* Now the logic changes. We first assume to have + the same channel configuration and then prove + if this assumption is true. */ + result = 1; + + /* Front channels */ + if (pPce1->NumFrontChannelElements != pPce2->NumFrontChannelElements) { + result = 2; /* different number of front channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumFrontChannelElements; el += 1) { + if (pPce1->FrontElementHeightInfo[el] != + pPce2->FrontElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->FrontElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->FrontElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of front channels */ + } + } + /* Side channels */ + if (pPce1->NumSideChannelElements != pPce2->NumSideChannelElements) { + result = 2; /* different number of side channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumSideChannelElements; el += 1) { + if (pPce1->SideElementHeightInfo[el] != + pPce2->SideElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->SideElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->SideElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of side channels */ + } + } + /* Back channels */ + if (pPce1->NumBackChannelElements != pPce2->NumBackChannelElements) { + result = 2; /* different number of back channel elements */ + } else { + int el, numCh1 = 0, numCh2 = 0; + for (el = 0; el < pPce1->NumBackChannelElements; el += 1) { + if (pPce1->BackElementHeightInfo[el] != + pPce2->BackElementHeightInfo[el]) { + result = 2; /* different height info */ + break; + } + numCh1 += pPce1->BackElementIsCpe[el] ? 2 : 1; + numCh2 += pPce2->BackElementIsCpe[el] ? 2 : 1; + } + if (numCh1 != numCh2) { + result = 2; /* different number of back channels */ + } + } + /* LFE channels */ + if (pPce1->NumLfeChannelElements != pPce2->NumLfeChannelElements) { + result = 2; /* different number of lfe channels */ + } + /* LFEs are always SCEs so we don't need to count the channels. */ + } + } + + return result; +} + +void CProgramConfig_GetDefault(CProgramConfig *pPce, const UINT channelConfig) { + FDK_ASSERT(pPce != NULL); + + /* Init PCE */ + CProgramConfig_Init(pPce); + pPce->Profile = + 1; /* Set AAC LC because it is the only supported object type. */ + + switch (channelConfig) { + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 32: /* 7.1 side channel configuration as defined in FDK_audio.h */ + pPce->NumFrontChannelElements = 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumSideChannelElements = 1; + pPce->SideElementIsCpe[0] = 1; + pPce->NumBackChannelElements = 1; + pPce->BackElementIsCpe[0] = 1; + pPce->NumLfeChannelElements = 1; + pPce->NumChannels = 8; + pPce->NumEffectiveChannels = 7; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 12: /* 3/0/4.1ch surround back */ + pPce->BackElementIsCpe[1] = 1; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + FDK_FALLTHROUGH; + case 11: /* 3/0/3.1ch */ + pPce->NumFrontChannelElements += 2; + pPce->FrontElementIsCpe[0] = 0; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumBackChannelElements += 2; + pPce->BackElementIsCpe[0] = 1; + pPce->BackElementIsCpe[1] += 0; + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 7; + pPce->NumEffectiveChannels += 6; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 14: /* 2/0/0-3/0/2-0.1ch front height */ + pPce->FrontElementHeightInfo[2] = 1; /* Top speaker */ + FDK_FALLTHROUGH; + case 7: /* 5/0/2.1ch front */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[2] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + FDK_FALLTHROUGH; + case 6: /* 3/0/2.1ch */ + pPce->NumLfeChannelElements += 1; + pPce->NumChannels += 1; + FDK_FALLTHROUGH; + case 5: /* 3/0/2.0ch */ + case 4: /* 3/0/1.0ch */ + pPce->NumBackChannelElements += 1; + pPce->BackElementIsCpe[0] = (channelConfig > 4) ? 1 : 0; + pPce->NumChannels += (channelConfig > 4) ? 2 : 1; + pPce->NumEffectiveChannels += (channelConfig > 4) ? 2 : 1; + FDK_FALLTHROUGH; + case 3: /* 3/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[1] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + FDK_FALLTHROUGH; + case 1: /* 1/0/0.0ch */ + pPce->NumFrontChannelElements += 1; + pPce->FrontElementIsCpe[0] = 0; + pPce->NumChannels += 1; + pPce->NumEffectiveChannels += 1; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + case 2: /* 2/0/0.ch */ + pPce->NumFrontChannelElements = 1; + pPce->FrontElementIsCpe[0] = 1; + pPce->NumChannels += 2; + pPce->NumEffectiveChannels += 2; + pPce->isValid = 1; + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + default: + pPce->isValid = 0; /* To be explicit! */ + break; + } + + if (pPce->isValid) { + /* Create valid element instance tags */ + int el, elTagSce = 0, elTagCpe = 0; + + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + pPce->FrontElementTagSelect[el] = + (pPce->FrontElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + pPce->SideElementTagSelect[el] = + (pPce->SideElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + pPce->BackElementTagSelect[el] = + (pPce->BackElementIsCpe[el]) ? elTagCpe++ : elTagSce++; + } + elTagSce = 0; + for (el = 0; el < pPce->NumLfeChannelElements; el += 1) { + pPce->LfeElementTagSelect[el] = elTagSce++; + } + } +} + +/** + * \brief get implicit audio channel type for given channelConfig and MPEG + * ordered channel index + * \param channelConfig MPEG channelConfiguration from 1 upto 14 + * \param index MPEG channel order index + * \return audio channel type. + */ +static void getImplicitAudioChannelTypeAndIndex(AUDIO_CHANNEL_TYPE *chType, + UCHAR *chIndex, + UINT channelConfig, + UINT index) { + if (index < 3) { + *chType = ACT_FRONT; + *chIndex = index; + } else { + switch (channelConfig) { + case 4: /* SCE, CPE, SCE */ + case 5: /* SCE, CPE, CPE */ + case 6: /* SCE, CPE, CPE, LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 7: /* SCE,CPE,CPE,CPE,LFE */ + switch (index) { + case 3: + case 4: + *chType = ACT_FRONT; + *chIndex = index; + break; + case 5: + case 6: + *chType = ACT_BACK; + *chIndex = index - 5; + break; + case 7: + *chType = ACT_LFE; + *chIndex = 0; + break; + } + break; + case 11: /* SCE,CPE,CPE,SCE,LFE */ + if (index < 6) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 12: /* SCE,CPE,CPE,CPE,LFE */ + if (index < 7) { + *chType = ACT_BACK; + *chIndex = index - 3; + } else { + *chType = ACT_LFE; + *chIndex = 0; + } + break; + case 14: /* SCE,CPE,CPE,LFE,CPE */ + switch (index) { + case 3: + case 4: + *chType = ACT_BACK; + *chIndex = index - 3; + break; + case 5: + *chType = ACT_LFE; + *chIndex = 0; + break; + case 6: + case 7: + *chType = ACT_FRONT_TOP; + *chIndex = index - 6; /* handle the top layer independently */ + break; + } + break; + default: + *chType = ACT_NONE; + break; + } + } +} + +int CProgramConfig_LookupElement(CProgramConfig *pPce, UINT channelConfig, + const UINT tag, const UINT channelIdx, + UCHAR chMapping[], AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[], const UINT chDescrLen, + UCHAR *elMapping, MP4_ELEMENT_ID elList[], + MP4_ELEMENT_ID elType) { + if (channelConfig > 0) { + /* Constant channel mapping must have + been set during initialization. */ + if (IS_CHANNEL_ELEMENT(elType)) { + *elMapping = pPce->elCounter; + if (elList[pPce->elCounter] != elType && + !IS_USAC_CHANNEL_ELEMENT(elType)) { + /* Not in the list */ + if ((channelConfig == 2) && + (elType == ID_SCE)) { /* This scenario occurs with HE-AAC v2 streams + of buggy encoders. In other decoder + implementations decoding of this kind of + streams is desired. */ + channelConfig = 1; + } else if ((elList[pPce->elCounter] == ID_LFE) && + (elType == + ID_SCE)) { /* Decode bitstreams which wrongly use ID_SCE + instead of ID_LFE element type. */ + ; + } else { + return 0; + } + } + /* Assume all front channels */ + getImplicitAudioChannelTypeAndIndex( + &chType[channelIdx], &chIndex[channelIdx], channelConfig, channelIdx); + if (elType == ID_CPE || elType == ID_USAC_CPE) { + chType[channelIdx + 1] = chType[channelIdx]; + chIndex[channelIdx + 1] = chIndex[channelIdx] + 1; + } + pPce->elCounter++; + } + /* Accept all non-channel elements, too. */ + return 1; + } else { + if ((!pPce->isValid) || (pPce->NumChannels > chDescrLen)) { + /* Implicit channel mapping. */ + if (IS_USAC_CHANNEL_ELEMENT(elType)) { + *elMapping = pPce->elCounter++; + } else if (IS_MP4_CHANNEL_ELEMENT(elType)) { + /* Store all channel element IDs */ + elList[pPce->elCounter] = elType; + *elMapping = pPce->elCounter++; + } + } else { + /* Accept the additional channel(s), only if the tag is in the lists */ + int isCpe = 0, i; + /* Element counter */ + int ec[PC_NUM_HEIGHT_LAYER] = {0}; + /* Channel counters */ + int cc[PC_NUM_HEIGHT_LAYER] = {0}; + int fc[PC_NUM_HEIGHT_LAYER] = {0}; /* front channel counter */ + int sc[PC_NUM_HEIGHT_LAYER] = {0}; /* side channel counter */ + int bc[PC_NUM_HEIGHT_LAYER] = {0}; /* back channel counter */ + int lc = 0; /* lfe channel counter */ + + /* General MPEG (PCE) composition rules: + - Over all: + + - Within each height layer: + + - Exception: + The LFE channels have no height info and thus they are arranged at + the very end of the normal height layer channels. + */ + + switch (elType) { + case ID_CPE: + isCpe = 1; + FDK_FALLTHROUGH; + case ID_SCE: + /* search in front channels */ + for (i = 0; i < pPce->NumFrontChannelElements; i++) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + if (isCpe == pPce->FrontElementIsCpe[i] && + pPce->FrontElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_FRONT); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = fc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = fc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->FrontElementIsCpe[i]) { + cc[heightLayer] += 2; + fc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + fc[heightLayer] += 1; + } + } + /* search in side channels */ + for (i = 0; i < pPce->NumSideChannelElements; i++) { + int heightLayer = pPce->SideElementHeightInfo[i]; + if (isCpe == pPce->SideElementIsCpe[i] && + pPce->SideElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_SIDE); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == + 0) { /* LFE channels belong to the normal height layer */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = sc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = sc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->SideElementIsCpe[i]) { + cc[heightLayer] += 2; + sc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + sc[heightLayer] += 1; + } + } + /* search in back channels */ + for (i = 0; i < pPce->NumBackChannelElements; i++) { + int heightLayer = pPce->BackElementHeightInfo[i]; + if (isCpe == pPce->BackElementIsCpe[i] && + pPce->BackElementTagSelect[i] == tag) { + int h, elIdx = ec[heightLayer], chIdx = cc[heightLayer]; + AUDIO_CHANNEL_TYPE aChType = + (AUDIO_CHANNEL_TYPE)((heightLayer << 4) | ACT_BACK); + for (h = heightLayer - 1; h >= 0; h -= 1) { + int el; + /* Count front channels/elements */ + for (el = 0; el < pPce->NumFrontChannelElements; el += 1) { + if (pPce->FrontElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->FrontElementIsCpe[el]) ? 2 : 1; + } + } + /* Count side channels/elements */ + for (el = 0; el < pPce->NumSideChannelElements; el += 1) { + if (pPce->SideElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->SideElementIsCpe[el]) ? 2 : 1; + } + } + /* Count back channels/elements */ + for (el = 0; el < pPce->NumBackChannelElements; el += 1) { + if (pPce->BackElementHeightInfo[el] == h) { + elIdx += 1; + chIdx += (pPce->BackElementIsCpe[el]) ? 2 : 1; + } + } + if (h == 0) { /* normal height */ + elIdx += pPce->NumLfeChannelElements; + chIdx += pPce->NumLfeChannelElements; + } + } + chMapping[chIdx] = channelIdx; + chType[chIdx] = aChType; + chIndex[chIdx] = bc[heightLayer]; + if (isCpe) { + chMapping[chIdx + 1] = channelIdx + 1; + chType[chIdx + 1] = aChType; + chIndex[chIdx + 1] = bc[heightLayer] + 1; + } + *elMapping = elIdx; + return 1; + } + ec[heightLayer] += 1; + if (pPce->BackElementIsCpe[i]) { + cc[heightLayer] += 2; + bc[heightLayer] += 2; + } else { + cc[heightLayer] += 1; + bc[heightLayer] += 1; + } + } + break; + + case ID_LFE: { /* Unfortunately we have to go through all normal height + layer elements to get the position of the LFE + channels. Start with counting the front + channels/elements at normal height */ + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + int heightLayer = pPce->FrontElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->FrontElementIsCpe[i]) ? 2 : 1; + } + /* Count side channels/elements at normal height */ + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + int heightLayer = pPce->SideElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->SideElementIsCpe[i]) ? 2 : 1; + } + /* Count back channels/elements at normal height */ + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + int heightLayer = pPce->BackElementHeightInfo[i]; + ec[heightLayer] += 1; + cc[heightLayer] += (pPce->BackElementIsCpe[i]) ? 2 : 1; + } + + /* search in lfe channels */ + for (i = 0; i < pPce->NumLfeChannelElements; i++) { + int elIdx = + ec[0]; /* LFE channels belong to the normal height layer */ + int chIdx = cc[0]; + if (pPce->LfeElementTagSelect[i] == tag) { + chMapping[chIdx] = channelIdx; + *elMapping = elIdx; + chType[chIdx] = ACT_LFE; + chIndex[chIdx] = lc; + return 1; + } + ec[0] += 1; + cc[0] += 1; + lc += 1; + } + } break; + + /* Non audio elements */ + case ID_CCE: + /* search in cce channels */ + for (i = 0; i < pPce->NumValidCcElements; i++) { + if (pPce->ValidCcElementTagSelect[i] == tag) { + return 1; + } + } + break; + case ID_DSE: + /* search associated data elements */ + for (i = 0; i < pPce->NumAssocDataElements; i++) { + if (pPce->AssocDataElementTagSelect[i] == tag) { + return 1; + } + } + break; + default: + return 0; + } + return 0; /* not found in any list */ + } + } + + return 1; +} + +#define SPEAKER_PLANE_NORMAL 0 +#define SPEAKER_PLANE_TOP 1 +#define SPEAKER_PLANE_BOTTOM 2 + +void CProgramConfig_GetChannelDescription(const UINT chConfig, + const CProgramConfig *pPce, + AUDIO_CHANNEL_TYPE chType[], + UCHAR chIndex[]) { + FDK_ASSERT(chType != NULL); + FDK_ASSERT(chIndex != NULL); + + if ((chConfig == 0) && (pPce != NULL)) { + if (pPce->isValid) { + int spkPlane, chIdx = 0; + for (spkPlane = SPEAKER_PLANE_NORMAL; spkPlane <= SPEAKER_PLANE_BOTTOM; + spkPlane += 1) { + int elIdx, grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumFrontChannelElements; elIdx += 1) { + if (pPce->FrontElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + if (pPce->FrontElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_FRONT); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumSideChannelElements; elIdx += 1) { + if (pPce->SideElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + if (pPce->SideElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_SIDE); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + for (elIdx = 0; elIdx < pPce->NumBackChannelElements; elIdx += 1) { + if (pPce->BackElementHeightInfo[elIdx] == spkPlane) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + if (pPce->BackElementIsCpe[elIdx]) { + chType[chIdx] = (AUDIO_CHANNEL_TYPE)((spkPlane << 4) | ACT_BACK); + chIndex[chIdx++] = grpChIdx++; + } + } + } + grpChIdx = 0; + if (spkPlane == SPEAKER_PLANE_NORMAL) { + for (elIdx = 0; elIdx < pPce->NumLfeChannelElements; elIdx += 1) { + chType[chIdx] = ACT_LFE; + chIndex[chIdx++] = grpChIdx++; + } + } + } + } + } else { + int chIdx; + for (chIdx = 0; chIdx < getNumberOfTotalChannels(chConfig); chIdx += 1) { + getImplicitAudioChannelTypeAndIndex(&chType[chIdx], &chIndex[chIdx], + chConfig, chIdx); + } + } +} + +int CProgramConfig_GetPceChMap(const CProgramConfig *pPce, UCHAR pceChMap[], + const UINT pceChMapLen) { + const UCHAR *nElements = &pPce->NumFrontChannelElements; + const UCHAR *elHeight[3], *elIsCpe[3]; + unsigned chIdx, plane, grp, offset, totCh[3], numCh[3][4]; + + FDK_ASSERT(pPce != NULL); + FDK_ASSERT(pceChMap != NULL); + + /* Init counter: */ + FDKmemclear(totCh, 3 * sizeof(unsigned)); + FDKmemclear(numCh, 3 * 4 * sizeof(unsigned)); + + /* Analyse PCE: */ + elHeight[0] = pPce->FrontElementHeightInfo; + elIsCpe[0] = pPce->FrontElementIsCpe; + elHeight[1] = pPce->SideElementHeightInfo; + elIsCpe[1] = pPce->SideElementIsCpe; + elHeight[2] = pPce->BackElementHeightInfo; + elIsCpe[2] = pPce->BackElementIsCpe; + + for (plane = 0; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + for (grp = 0; grp < 3; grp += 1) { /* front, side, back */ + unsigned el; + for (el = 0; el < nElements[grp]; el += 1) { + if (elHeight[grp][el] == plane) { + unsigned elCh = elIsCpe[grp][el] ? 2 : 1; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; + } + } + } + if (plane == SPEAKER_PLANE_NORMAL) { + unsigned elCh = pPce->NumLfeChannelElements; + numCh[plane][grp] += elCh; + totCh[plane] += elCh; + } + } + /* Sanity checks: */ + chIdx = totCh[SPEAKER_PLANE_NORMAL] + totCh[SPEAKER_PLANE_TOP] + + totCh[SPEAKER_PLANE_BOTTOM]; + if (chIdx > pceChMapLen) { + return -1; + } + + /* Create map: */ + offset = grp = 0; + unsigned grpThresh = numCh[SPEAKER_PLANE_NORMAL][grp]; + for (chIdx = 0; chIdx < totCh[SPEAKER_PLANE_NORMAL]; chIdx += 1) { + while ((chIdx >= grpThresh) && (grp < 3)) { + offset += numCh[1][grp] + numCh[2][grp]; + grp += 1; + grpThresh += numCh[SPEAKER_PLANE_NORMAL][grp]; + } + pceChMap[chIdx] = chIdx + offset; + } + offset = 0; + for (grp = 0; grp < 4; grp += 1) { /* front, side, back and lfe */ + offset += numCh[SPEAKER_PLANE_NORMAL][grp]; + for (plane = SPEAKER_PLANE_TOP; plane <= SPEAKER_PLANE_BOTTOM; plane += 1) { + unsigned mapCh; + for (mapCh = 0; mapCh < numCh[plane][grp]; mapCh += 1) { + pceChMap[chIdx++] = offset; + offset += 1; + } + } + } + return 0; +} + +int CProgramConfig_GetElementTable(const CProgramConfig *pPce, + MP4_ELEMENT_ID elList[], + const INT elListSize, UCHAR *pChMapIdx) { + int i, el = 0; + + FDK_ASSERT(elList != NULL); + FDK_ASSERT(pChMapIdx != NULL); + FDK_ASSERT(pPce != NULL); + + *pChMapIdx = 0; + + if ((elListSize < + pPce->NumFrontChannelElements + pPce->NumSideChannelElements + + pPce->NumBackChannelElements + pPce->NumLfeChannelElements) || + (pPce->NumChannels == 0)) { + return 0; + } + + for (i = 0; i < pPce->NumFrontChannelElements; i += 1) { + elList[el++] = (pPce->FrontElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumSideChannelElements; i += 1) { + elList[el++] = (pPce->SideElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumBackChannelElements; i += 1) { + elList[el++] = (pPce->BackElementIsCpe[i]) ? ID_CPE : ID_SCE; + } + + for (i = 0; i < pPce->NumLfeChannelElements; i += 1) { + elList[el++] = ID_LFE; + } + + /* Find an corresponding channel configuration if possible */ + switch (pPce->NumChannels) { + case 1: + case 2: + /* One and two channels have no alternatives. */ + *pChMapIdx = pPce->NumChannels; + break; + case 3: + case 4: + case 5: + case 6: { /* Test if the number of channels can be used as channel config: + */ + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, pPce->NumChannels); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) + ? pPce->NumChannels + : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + case 7: { + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, 11); + /* ... and compare it with the given one. */ + *pChMapIdx = (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) ? 11 : 0; + /* If compare result is 0 or 1 we can be sure that it is channel + * config 11. */ + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + case 8: { /* Try the four possible 7.1ch configurations. One after the + other. */ + UCHAR testCfg[4] = {32, 14, 12, 7}; + C_ALLOC_SCRATCH_START(tmpPce, CProgramConfig, 1); + for (i = 0; i < 4; i += 1) { + /* Create a PCE for the config to test ... */ + CProgramConfig_GetDefault(tmpPce, testCfg[i]); + /* ... and compare it with the given one. */ + if (!(CProgramConfig_Compare(pPce, tmpPce) & 0xE)) { + /* If the compare result is 0 or 1 than the two channel configurations + * match. */ + /* Explicit mapping of 7.1 side channel configuration to 7.1 rear + * channel mapping. */ + *pChMapIdx = (testCfg[i] == 32) ? 12 : testCfg[i]; + } + } + C_ALLOC_SCRATCH_END(tmpPce, CProgramConfig, 1); + } break; + default: + /* The PCE does not match any predefined channel configuration. */ + *pChMapIdx = 0; + break; + } + + return el; +} + +static AUDIO_OBJECT_TYPE getAOT(HANDLE_FDK_BITSTREAM bs) { + int tmp = 0; + + tmp = FDKreadBits(bs, 5); + if (tmp == AOT_ESCAPE) { + int tmp2 = FDKreadBits(bs, 6); + tmp = 32 + tmp2; + } + + return (AUDIO_OBJECT_TYPE)tmp; +} + +static INT getSampleRate(HANDLE_FDK_BITSTREAM bs, UCHAR *index, int nBits) { + INT sampleRate; + int idx; + + idx = FDKreadBits(bs, nBits); + if (idx == (1 << nBits) - 1) { + if (FDKgetValidBits(bs) < 24) { + return 0; + } + sampleRate = FDKreadBits(bs, 24); + } else { + sampleRate = SamplingRateTable[idx]; + } + + *index = idx; + + return sampleRate; +} + +static TRANSPORTDEC_ERROR GaSpecificConfig_Parse(CSGaSpecificConfig *self, + CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM bs, + UINT ascStartAnchor) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + self->m_frameLengthFlag = FDKreadBits(bs, 1); + + self->m_dependsOnCoreCoder = FDKreadBits(bs, 1); + + if (self->m_dependsOnCoreCoder) self->m_coreCoderDelay = FDKreadBits(bs, 14); + + self->m_extensionFlag = FDKreadBits(bs, 1); + + if (asc->m_channelConfiguration == 0) { + CProgramConfig_Read(&asc->m_progrConfigElement, bs, ascStartAnchor); + } + + if ((asc->m_aot == AOT_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_SCAL)) { + self->m_layer = FDKreadBits(bs, 3); + } + + if (self->m_extensionFlag) { + if (asc->m_aot == AOT_ER_BSAC) { + self->m_numOfSubFrame = FDKreadBits(bs, 5); + self->m_layerLength = FDKreadBits(bs, 11); + } + + if ((asc->m_aot == AOT_ER_AAC_LC) || (asc->m_aot == AOT_ER_AAC_LTP) || + (asc->m_aot == AOT_ER_AAC_SCAL) || (asc->m_aot == AOT_ER_AAC_LD)) { + asc->m_vcb11Flag = FDKreadBits(bs, 1); /* aacSectionDataResilienceFlag */ + asc->m_rvlcFlag = + FDKreadBits(bs, 1); /* aacScalefactorDataResilienceFlag */ + asc->m_hcrFlag = FDKreadBits(bs, 1); /* aacSpectralDataResilienceFlag */ + } + + self->m_extensionFlag3 = FDKreadBits(bs, 1); + } + return (ErrorStatus); +} + +static INT skipSbrHeader(HANDLE_FDK_BITSTREAM hBs, int isUsac) { + /* Dummy parse SbrDfltHeader() */ + INT dflt_header_extra1, dflt_header_extra2, bitsToSkip = 0; + + if (!isUsac) { + bitsToSkip = 6; + FDKpushFor(hBs, 6); /* amp res 1, xover freq 3, reserved 2 */ + } + bitsToSkip += 8; + FDKpushFor(hBs, 8); /* start / stop freq */ + bitsToSkip += 2; + dflt_header_extra1 = FDKreadBit(hBs); + dflt_header_extra2 = FDKreadBit(hBs); + bitsToSkip += 5 * dflt_header_extra1 + 6 * dflt_header_extra2; + FDKpushFor(hBs, 5 * dflt_header_extra1 + 6 * dflt_header_extra2); + + return bitsToSkip; +} + +static INT ld_sbr_header(CSAudioSpecificConfig *asc, const INT dsFactor, + HANDLE_FDK_BITSTREAM hBs, CSTpCallBacks *cb) { + const int channelConfiguration = asc->m_channelConfiguration; + int i = 0, j = 0; + INT error = 0; + MP4_ELEMENT_ID element = ID_NONE; + + /* check whether the channelConfiguration is defined in + * channel_configuration_array */ + if (channelConfiguration < 0 || + channelConfiguration > (INT)(sizeof(channel_configuration_array) / + sizeof(MP4_ELEMENT_ID **) - + 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + + /* read elements of the passed channel_configuration until there is ID_NONE */ + while ((element = channel_configuration_array[channelConfiguration][j]) != + ID_NONE) { + /* Setup LFE element for upsampling too. This is essential especially for + * channel configs where the LFE element is not at the last position for + * example in channel config 13 or 14. It leads to memory leaks if the setup + * of the LFE element would be done later in the core. */ + if (element == ID_SCE || element == ID_CPE || element == ID_LFE) { + error |= cb->cbSbr( + cb->cbSbrData, hBs, asc->m_samplingFrequency / dsFactor, + asc->m_extensionSamplingFrequency / dsFactor, + asc->m_samplesPerFrame / dsFactor, AOT_ER_AAC_ELD, element, i++, 0, 0, + asc->configMode, &asc->SbrConfigChanged, dsFactor); + if (error != TRANSPORTDEC_OK) { + goto bail; + } + } + j++; + } +bail: + return error; +} + +static TRANSPORTDEC_ERROR EldSpecificConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSEldSpecificConfig *esc = &asc->m_sc.m_eldSpecificConfig; + ASC_ELD_EXT_TYPE eldExtType; + int eldExtLen, len, cnt, ldSbrLen = 0, eldExtLenSum, numSbrHeader = 0, + sbrIndex; + + unsigned char downscale_fill_nibble; + + FDKmemclear(esc, sizeof(CSEldSpecificConfig)); + + esc->m_frameLengthFlag = FDKreadBits(hBs, 1); + if (esc->m_frameLengthFlag) { + asc->m_samplesPerFrame = 480; + } else { + asc->m_samplesPerFrame = 512; + } + + asc->m_vcb11Flag = FDKreadBits(hBs, 1); + asc->m_rvlcFlag = FDKreadBits(hBs, 1); + asc->m_hcrFlag = FDKreadBits(hBs, 1); + + esc->m_sbrPresentFlag = FDKreadBits(hBs, 1); + + if (esc->m_sbrPresentFlag == 1) { + esc->m_sbrSamplingRate = + FDKreadBits(hBs, 1); /* 0: single rate, 1: dual rate */ + esc->m_sbrCrcFlag = FDKreadBits(hBs, 1); + + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency + << esc->m_sbrSamplingRate; + + if (cb->cbSbr != NULL) { + /* ELD reduced delay mode: LD-SBR initialization has to know the downscale + information. Postpone LD-SBR initialization and read ELD extension + information first. */ + switch (asc->m_channelConfiguration) { + case 1: + case 2: + numSbrHeader = 1; + break; + case 3: + numSbrHeader = 2; + break; + case 4: + case 5: + case 6: + numSbrHeader = 3; + break; + case 7: + case 11: + case 12: + case 14: + numSbrHeader = 4; + break; + default: + numSbrHeader = 0; + break; + } + for (sbrIndex = 0; sbrIndex < numSbrHeader; sbrIndex++) { + ldSbrLen += skipSbrHeader(hBs, 0); + } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } + esc->m_useLdQmfTimeAlign = 0; + + /* new ELD syntax */ + eldExtLenSum = FDKgetValidBits(hBs); + esc->m_downscaledSamplingFrequency = asc->m_samplingFrequency; + /* parse ExtTypeConfigData */ + while ( + ((eldExtType = (ASC_ELD_EXT_TYPE)FDKreadBits(hBs, 4)) != ELDEXT_TERM) && + ((INT)FDKgetValidBits(hBs) >= 0)) { + eldExtLen = len = FDKreadBits(hBs, 4); + if (len == 0xf) { + len = FDKreadBits(hBs, 8); + eldExtLen += len; + + if (len == 0xff) { + len = FDKreadBits(hBs, 16); + eldExtLen += len; + } + } + + switch (eldExtType) { + case ELDEXT_LDSAC: + esc->m_useLdQmfTimeAlign = 1; + if (cb->cbSsc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, asc->m_aot, + asc->m_samplingFrequency << esc->m_sbrSamplingRate, + asc->m_samplesPerFrame << esc->m_sbrSamplingRate, + 1, /* stereoConfigIndex */ + -1, /* nTimeSlots: read from bitstream */ + eldExtLen, asc->configMode, &asc->SacConfigChanged); + if (ErrorStatus != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + if (esc->m_downscaledSamplingFrequency != asc->m_samplingFrequency) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled + mode not allowed */ + } + break; + } + + FDK_FALLTHROUGH; + default: + for (cnt = 0; cnt < eldExtLen; cnt++) { + FDKreadBits(hBs, 8); + } + break; + + case ELDEXT_DOWNSCALEINFO: + UCHAR tmpDownscaleFreqIdx; + esc->m_downscaledSamplingFrequency = + getSampleRate(hBs, &tmpDownscaleFreqIdx, 4); + if (esc->m_downscaledSamplingFrequency == 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + downscale_fill_nibble = FDKreadBits(hBs, 4); + if (downscale_fill_nibble != 0x0) { + return TRANSPORTDEC_PARSE_ERROR; + } + if (esc->m_useLdQmfTimeAlign == 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* ELDv2 w/ ELD downscaled + mode not allowed */ + } + break; + } + } + + if ((INT)FDKgetValidBits(hBs) < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (esc->m_sbrPresentFlag == 1 && numSbrHeader != 0) { + INT dsFactor = 1; /* Downscale factor must be 1 or even for SBR */ + if (esc->m_downscaledSamplingFrequency != 0) { + if (asc->m_samplingFrequency % esc->m_downscaledSamplingFrequency != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + dsFactor = asc->m_samplingFrequency / esc->m_downscaledSamplingFrequency; + if (dsFactor != 1 && (dsFactor)&1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* SBR needs an even downscale + factor */ + } + if (dsFactor != 1 && dsFactor != 2 && dsFactor != 4) { + dsFactor = 1; /* don't apply dsf for not yet supported even dsfs */ + } + if ((INT)asc->m_samplesPerFrame % dsFactor != 0) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; /* frameSize/dsf must be an + integer number */ + } + } + eldExtLenSum = eldExtLenSum - FDKgetValidBits(hBs); + FDKpushBack(hBs, eldExtLenSum + ldSbrLen); + if (0 != ld_sbr_header(asc, dsFactor, hBs, cb)) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, eldExtLenSum); + } + return (ErrorStatus); +} + +/* +Subroutine to store config in UCHAR buffer. Bit stream position does not change. +*/ +static UINT StoreConfigAsBitstream( + HANDLE_FDK_BITSTREAM hBs, const INT configSize_bits, /* If < 0 (> 0) config + to read is before + (after) current bit + stream position. */ + UCHAR *configTargetBuffer, const USHORT configTargetBufferSize_bytes) { + FDK_BITSTREAM usacConf; + UINT const nBits = fAbs(configSize_bits); + UINT j, tmp; + + if (nBits > 8 * (UINT)configTargetBufferSize_bytes) { + return 1; + } + FDKmemclear(configTargetBuffer, configTargetBufferSize_bytes); + + FDKinitBitStream(&usacConf, configTargetBuffer, configTargetBufferSize_bytes, + nBits, BS_WRITER); + if (configSize_bits < 0) { + FDKpushBack(hBs, nBits); + } + for (j = nBits; j > 31; j -= 32) { + tmp = FDKreadBits(hBs, 32); + FDKwriteBits(&usacConf, tmp, 32); + } + if (j > 0) { + tmp = FDKreadBits(hBs, j); + FDKwriteBits(&usacConf, tmp, j); + } + FDKsyncCache(&usacConf); + if (configSize_bits > 0) { + FDKpushBack(hBs, nBits); + } + + return 0; +} + +/* maps coreSbrFrameLengthIndex to coreCoderFrameLength */ +static const USHORT usacFrameLength[8] = {768, 1024, 2048, 2048, 4096, 0, 0, 0}; +/* maps coreSbrFrameLengthIndex to sbrRatioIndex */ +static const UCHAR sbrRatioIndex[8] = {0, 0, 2, 3, 1, 0, 0, 0}; + +/* + subroutine for parsing extension element configuration: + UsacExtElementConfig() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 14 + rsv603daExtElementConfig() q.v. ISO/IEC DIS 23008-3 Table 13 +*/ +static TRANSPORTDEC_ERROR extElementConfig(CSUsacExtElementConfig *extElement, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb, + const UCHAR numSignalsInGroup, + const UINT coreFrameLength, + const int subStreamIndex, + const AUDIO_OBJECT_TYPE aot) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + USAC_EXT_ELEMENT_TYPE usacExtElementType = + (USAC_EXT_ELEMENT_TYPE)escapedValue(hBs, 4, 8, 16); + + /* recurve extension elements which are invalid for USAC */ + if (aot == AOT_USAC) { + switch (usacExtElementType) { + case ID_EXT_ELE_FILL: + case ID_EXT_ELE_MPEGS: + case ID_EXT_ELE_SAOC: + case ID_EXT_ELE_AUDIOPREROLL: + case ID_EXT_ELE_UNI_DRC: + break; + default: + usacExtElementType = ID_EXT_ELE_UNKNOWN; + break; + } + } + + extElement->usacExtElementType = usacExtElementType; + int usacExtElementConfigLength = escapedValue(hBs, 4, 8, 16); + extElement->usacExtElementConfigLength = (USHORT)usacExtElementConfigLength; + INT bsAnchor; + + if (FDKreadBit(hBs)) /* usacExtElementDefaultLengthPresent */ + extElement->usacExtElementDefaultLength = escapedValue(hBs, 8, 16, 0) + 1; + else + extElement->usacExtElementDefaultLength = 0; + + extElement->usacExtElementPayloadFrag = FDKreadBit(hBs); + + bsAnchor = (INT)FDKgetValidBits(hBs); + + switch (usacExtElementType) { + case ID_EXT_ELE_UNKNOWN: + case ID_EXT_ELE_FILL: + break; + case ID_EXT_ELE_AUDIOPREROLL: + /* No configuration element */ + extElement->usacExtElementHasAudioPreRoll = 1; + break; + case ID_EXT_ELE_UNI_DRC: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacExtElementConfigLength, + 0, /* uniDrcConfig */ + subStreamIndex, 0, aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + } break; + default: + break; + } + + /* Adjust bit stream position. This is required because of byte alignment and + * unhandled extensions. */ + { + INT left_bits = (usacExtElementConfigLength << 3) - + (bsAnchor - (INT)FDKgetValidBits(hBs)); + if (left_bits >= 0) { + FDKpushFor(hBs, left_bits); + } else { + /* parsed too many bits */ + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + + return ErrorStatus; +} + +/* + subroutine for parsing the USAC / RSVD60 configuration extension: + UsacConfigExtension() q.v. ISO/IEC FDIS 23003-3:2011(E) Table 15 + rsv603daConfigExtension() q.v. ISO/IEC DIS 23008-3 Table 14 +*/ +static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, + HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + int numConfigExtensions; + CONFIG_EXT_ID usacConfigExtType; + int usacConfigExtLength; + + numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1; + for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) { + INT nbits; + int loudnessInfoSetConfigExtensionPosition = FDKgetValidBits(hBs); + usacConfigExtType = (CONFIG_EXT_ID)escapedValue(hBs, 4, 8, 16); + usacConfigExtLength = (int)escapedValue(hBs, 4, 8, 16); + + /* Start bit position of config extension */ + nbits = (INT)FDKgetValidBits(hBs); + + /* Return an error in case the bitbuffer fill level is too low. */ + if (nbits < usacConfigExtLength * 8) { + return TRANSPORTDEC_PARSE_ERROR; + } + + switch (usacConfigExtType) { + case ID_CONFIG_EXT_FILL: + for (int i = 0; i < usacConfigExtLength; i++) { + if (FDKreadBits(hBs, 8) != 0xa5) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case ID_CONFIG_EXT_LOUDNESS_INFO: { + if (cb->cbUniDrc != NULL) { + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, hBs, usacConfigExtLength, + 1, /* loudnessInfoSet */ + 0, loudnessInfoSetConfigExtensionPosition, AOT_USAC); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + } break; + default: + break; + } + + /* Skip remaining bits. If too many bits were parsed, assume error. */ + usacConfigExtLength = + 8 * usacConfigExtLength - (nbits - (INT)FDKgetValidBits(hBs)); + if (usacConfigExtLength < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + FDKpushFor(hBs, usacConfigExtLength); + } + + return ErrorStatus; +} + +/* This function unifies decoder config parsing of USAC and RSV60: + rsv603daDecoderConfig() ISO/IEC DIS 23008-3 Table 8 + UsacDecoderConfig() ISO/IEC FDIS 23003-3 Table 6 + */ +static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, + const CSTpCallBacks *cb) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int i, numberOfElements; + int channelElementIdx = + 0; /* index for elements which contain audio channels (sce, cpe, lfe) */ + SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0}; + + numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1; + usc->m_usacNumElements = numberOfElements; + if (numberOfElements > TP_USAC_MAX_ELEMENTS) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->m_nUsacChannels = 0; + usc->m_channelConfigurationIndex = asc->m_channelConfiguration; + + if (asc->m_aot == AOT_USAC) { + sc_chan_config = sc_chan_config_tab[usc->m_channelConfigurationIndex]; + + if (sc_chan_config.nCh > (SCHAR)TP_USAC_MAX_SPEAKERS) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + + for (i = 0; i < numberOfElements; i++) { + MP4_ELEMENT_ID usacElementType = (MP4_ELEMENT_ID)( + FDKreadBits(hBs, 2) | USAC_ID_BIT); /* set USAC_ID_BIT to map + usacElementType to + MP4_ELEMENT_ID enum */ + usc->element[i].usacElementType = usacElementType; + + /* sanity check: update element counter */ + if (asc->m_aot == AOT_USAC) { + switch (usacElementType) { + case ID_USAC_SCE: + sc_chan_config.nSCE--; + break; + case ID_USAC_CPE: + sc_chan_config.nCPE--; + break; + case ID_USAC_LFE: + sc_chan_config.nLFE--; + break; + default: + break; + } + if (usc->m_channelConfigurationIndex) { + /* sanity check: no element counter may be smaller zero */ + if (sc_chan_config.nCPE < 0 || sc_chan_config.nSCE < 0 || + sc_chan_config.nLFE < 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } + + switch (usacElementType) { + case ID_USAC_SCE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + /* SbrConfig() ISO/IEC FDIS 23003-3 Table 11 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of SbrConfig() */ + } + usc->m_nUsacChannels += 1; + channelElementIdx++; + break; + + case ID_USAC_CPE: + /* UsacCoreConfig() ISO/IEC FDIS 23003-3 Table 10 */ + if (FDKreadBit(hBs)) { /* tw_mdct */ + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + usc->element[i].m_noiseFilling = FDKreadBits(hBs, 1); + /* end of UsacCoreConfig() */ + if (usc->m_sbrRatioIndex > 0) { + if (cb->cbSbr == NULL) return TRANSPORTDEC_UNKOWN_ERROR; + /* SbrConfig() ISO/IEC FDIS 23003-3 */ + usc->element[i].m_harmonicSBR = FDKreadBit(hBs); + usc->element[i].m_interTes = FDKreadBit(hBs); + usc->element[i].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[i].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + { + MP4_ELEMENT_ID el_type = + (usc->element[i].m_stereoConfigIndex == 1 || + usc->element[i].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + /* end of SbrConfig() */ + + usc->element[i].m_stereoConfigIndex = + FDKreadBits(hBs, 2); /* Needed in RM5 syntax */ + + if (usc->element[i].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + int samplesPerFrame = asc->m_samplesPerFrame; + + if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2; + if (usc->m_sbrRatioIndex == 2) + samplesPerFrame = (samplesPerFrame * 8) / 3; + if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1; + + /* Mps212Config() ISO/IEC FDIS 23003-3 */ + if (cb->cbSsc(cb->cbSscData, hBs, asc->m_aot, + asc->m_extensionSamplingFrequency, samplesPerFrame, + usc->element[i].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, + 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged)) { + return TRANSPORTDEC_PARSE_ERROR; + } + /* end of Mps212Config() */ + } else { + return TRANSPORTDEC_UNKOWN_ERROR; + } + } + } else { + usc->element[i].m_stereoConfigIndex = 0; + } + usc->m_nUsacChannels += 2; + + channelElementIdx++; + break; + + case ID_USAC_LFE: + usc->element[i].m_noiseFilling = 0; + usc->m_nUsacChannels += 1; + if (usc->m_sbrRatioIndex > 0) { + /* Use SBR for upsampling */ + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + usc->element[i].m_harmonicSBR = (UCHAR)0; + usc->element[i].m_interTes = (UCHAR)0; + usc->element[i].m_pvc = (UCHAR)0; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_LFE, + channelElementIdx, usc->element[i].m_harmonicSBR, + usc->element[i].m_stereoConfigIndex, asc->configMode, + &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + channelElementIdx++; + break; + + case ID_USAC_EXT: + ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0, + asc->m_samplesPerFrame, 0, asc->m_aot); + + if (ErrorStatus) { + return ErrorStatus; + } + break; + + default: + /* non USAC-element encountered */ + return TRANSPORTDEC_PARSE_ERROR; + } + } + + if (asc->m_aot == AOT_USAC) { + if (usc->m_channelConfigurationIndex) { + /* sanity check: all element counter must be zero */ + if (sc_chan_config.nCPE | sc_chan_config.nSCE | sc_chan_config.nLFE) { + return TRANSPORTDEC_PARSE_ERROR; + } + } else { + /* sanity check: number of audio channels shall be equal to or smaller + * than the accumulated sum of all channels */ + if ((INT)(-2 * sc_chan_config.nCPE - sc_chan_config.nSCE - + sc_chan_config.nLFE) < (INT)usc->numAudioChannels) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + } + + return ErrorStatus; +} + +/* Mapping of coreSbrFrameLengthIndex defined by Table 70 in ISO/IEC 23003-3 */ +static TRANSPORTDEC_ERROR UsacConfig_SetCoreSbrFrameLengthIndex( + CSAudioSpecificConfig *asc, int coreSbrFrameLengthIndex) { + int sbrRatioIndex_val; + + if (coreSbrFrameLengthIndex > 4) { + return TRANSPORTDEC_PARSE_ERROR; /* reserved values */ + } + asc->m_sc.m_usacConfig.m_coreSbrFrameLengthIndex = coreSbrFrameLengthIndex; + asc->m_samplesPerFrame = usacFrameLength[coreSbrFrameLengthIndex]; + sbrRatioIndex_val = sbrRatioIndex[coreSbrFrameLengthIndex]; + asc->m_sc.m_usacConfig.m_sbrRatioIndex = sbrRatioIndex_val; + + if (sbrRatioIndex_val > 0) { + asc->m_sbrPresentFlag = 1; + asc->m_extensionSamplingFrequency = asc->m_samplingFrequency; + asc->m_extensionSamplingFrequencyIndex = asc->m_samplingFrequencyIndex; + switch (sbrRatioIndex_val) { + case 1: /* sbrRatio = 4:1 */ + asc->m_samplingFrequency >>= 2; + asc->m_samplesPerFrame >>= 2; + break; + case 2: /* sbrRatio = 8:3 */ + asc->m_samplingFrequency = (asc->m_samplingFrequency * 3) / 8; + asc->m_samplesPerFrame = (asc->m_samplesPerFrame * 3) / 8; + break; + case 3: /* sbrRatio = 2:1 */ + asc->m_samplingFrequency >>= 1; + asc->m_samplesPerFrame >>= 1; + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + asc->m_samplingFrequencyIndex = + getSamplingRateIndex(asc->m_samplingFrequency, 4); + } + + return TRANSPORTDEC_OK; +} + +static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb) { + int usacSamplingFrequency, channelConfigurationIndex, coreSbrFrameLengthIndex; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + /* Start bit position of usacConfig */ + INT nbits = (INT)FDKgetValidBits(hBs); + + usacSamplingFrequency = getSampleRate(hBs, &asc->m_samplingFrequencyIndex, 5); + asc->m_samplingFrequency = (UINT)usacSamplingFrequency; + + coreSbrFrameLengthIndex = FDKreadBits(hBs, 3); + if (UsacConfig_SetCoreSbrFrameLengthIndex(asc, coreSbrFrameLengthIndex) != + TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + channelConfigurationIndex = FDKreadBits(hBs, 5); + if (channelConfigurationIndex > 2) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + + if (channelConfigurationIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; /* only channelConfigurationIndex = [1,2] + are supported */ + } + asc->m_channelConfiguration = channelConfigurationIndex; + + err = UsacRsv60DecoderConfig_Parse(asc, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + + if (FDKreadBits(hBs, 1)) { /* usacConfigExtensionPresent */ + err = configExtension(&asc->m_sc.m_usacConfig, hBs, cb); + if (err != TRANSPORTDEC_OK) { + return err; + } + } + + /* sanity check whether number of channels signaled in UsacDecoderConfig() + matches the number of channels required by channelConfigurationIndex */ + if ((channelConfigurationIndex > 0) && + (sc_chan_config_tab[channelConfigurationIndex].nCh != + asc->m_sc.m_usacConfig.m_nUsacChannels)) { + return TRANSPORTDEC_PARSE_ERROR; + } + + /* Copy UsacConfig() to asc->m_sc.m_usacConfig.UsacConfig[] buffer. */ + INT configSize_bits = (INT)FDKgetValidBits(hBs) - nbits; + StoreConfigAsBitstream(hBs, configSize_bits, + asc->m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + asc->m_sc.m_usacConfig.UsacConfigBits = fAbs(configSize_bits); + + return err; +} + +static TRANSPORTDEC_ERROR AudioSpecificConfig_ExtensionParse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, CSTpCallBacks *cb) { + TP_ASC_EXTENSION_ID lastAscExt, ascExtId = ASCEXT_UNKOWN; + INT bitsAvailable = (INT)FDKgetValidBits(bs); + + while (bitsAvailable >= 11) { + lastAscExt = ascExtId; + ascExtId = (TP_ASC_EXTENSION_ID)FDKreadBits(bs, 11); + bitsAvailable -= 11; + + switch (ascExtId) { + case ASCEXT_SBR: /* 0x2b7 */ + if ((self->m_extensionAudioObjectType != AOT_SBR) && + (bitsAvailable >= 5)) { + self->m_extensionAudioObjectType = getAOT(bs); + + if ((self->m_extensionAudioObjectType == AOT_SBR) || + (self->m_extensionAudioObjectType == + AOT_ER_BSAC)) { /* Get SBR extension configuration */ + self->m_sbrPresentFlag = FDKreadBits(bs, 1); + if (self->m_aot == AOT_USAC && self->m_sbrPresentFlag > 0 && + self->m_sc.m_usacConfig.m_sbrRatioIndex == 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + + if (self->m_sbrPresentFlag == 1) { + self->m_extensionSamplingFrequency = getSampleRate( + bs, &self->m_extensionSamplingFrequencyIndex, 4); + + if ((INT)self->m_extensionSamplingFrequency <= 0) { + return TRANSPORTDEC_PARSE_ERROR; + } + } + if (self->m_extensionAudioObjectType == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } + /* Update counter because of variable length fields (AOT and sampling + * rate) */ + bitsAvailable = (INT)FDKgetValidBits(bs); + } + break; + case ASCEXT_PS: /* 0x548 */ + if ((lastAscExt == ASCEXT_SBR) && + (self->m_extensionAudioObjectType == AOT_SBR) && + (bitsAvailable > 0)) { /* Get PS extension configuration */ + self->m_psPresentFlag = FDKreadBits(bs, 1); + bitsAvailable -= 1; + } + break; + case ASCEXT_MPS: /* 0x76a */ + if (self->m_extensionAudioObjectType == AOT_MPEGS) break; + FDK_FALLTHROUGH; + case ASCEXT_LDMPS: /* 0x7cc */ + if ((ascExtId == ASCEXT_LDMPS) && + (self->m_extensionAudioObjectType == AOT_LD_MPEGS)) + break; + if (bitsAvailable >= 1) { + bitsAvailable -= 1; + if (FDKreadBits(bs, 1)) { /* self->m_mpsPresentFlag */ + int sscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (sscLen == 0xFF) { + sscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, sscLen); /* Skip SSC to be able to read the next + extension if there is one. */ + + bitsAvailable -= sscLen * 8; + } + } + break; + case ASCEXT_SAOC: + if ((ascExtId == ASCEXT_SAOC) && + (self->m_extensionAudioObjectType == AOT_SAOC)) + break; + if (FDKreadBits(bs, 1)) { /* saocPresent */ + int saocscLen = FDKreadBits(bs, 8); + bitsAvailable -= 8; + if (saocscLen == 0xFF) { + saocscLen += FDKreadBits(bs, 16); + bitsAvailable -= 16; + } + FDKpushFor(bs, saocscLen); + bitsAvailable -= saocscLen * 8; + } + break; + default: + /* Just ignore anything. */ + return TRANSPORTDEC_OK; + } + } + + return TRANSPORTDEC_OK; +} + +/* + * API Functions + */ + +void AudioSpecificConfig_Init(CSAudioSpecificConfig *asc) { + FDKmemclear(asc, sizeof(CSAudioSpecificConfig)); + + /* Init all values that should not be zero. */ + asc->m_aot = AOT_NONE; + asc->m_samplingFrequencyIndex = 0xf; + asc->m_epConfig = -1; + asc->m_extensionAudioObjectType = AOT_NULL_OBJECT; + CProgramConfig_Init(&asc->m_progrConfigElement); +} + +TRANSPORTDEC_ERROR AudioSpecificConfig_Parse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + int fExplicitBackwardCompatible, CSTpCallBacks *cb, UCHAR configMode, + UCHAR configChanged, AUDIO_OBJECT_TYPE m_aot) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UINT ascStartAnchor = FDKgetValidBits(bs); + int frameLengthFlag = -1; + + AudioSpecificConfig_Init(self); + + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; + + if (m_aot != AOT_NULL_OBJECT) { + self->m_aot = m_aot; + } else { + self->m_aot = getAOT(bs); + self->m_samplingFrequency = + getSampleRate(bs, &self->m_samplingFrequencyIndex, 4); + if (self->m_samplingFrequency <= 0 || + (self->m_samplingFrequency > 96000 && self->m_aot != 39) || + self->m_samplingFrequency > 4 * 96000) { + return TRANSPORTDEC_PARSE_ERROR; + } + + self->m_channelConfiguration = FDKreadBits(bs, 4); + + /* SBR extension ( explicit non-backwards compatible mode ) */ + self->m_sbrPresentFlag = 0; + self->m_psPresentFlag = 0; + + if (self->m_aot == AOT_SBR || self->m_aot == AOT_PS) { + self->m_extensionAudioObjectType = AOT_SBR; + + self->m_sbrPresentFlag = 1; + if (self->m_aot == AOT_PS) { + self->m_psPresentFlag = 1; + } + + self->m_extensionSamplingFrequency = + getSampleRate(bs, &self->m_extensionSamplingFrequencyIndex, 4); + self->m_aot = getAOT(bs); + + switch (self->m_aot) { + case AOT_AAC_LC: + break; + case AOT_ER_BSAC: + break; + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + if (self->m_aot == AOT_ER_BSAC) { + self->m_extensionChannelConfiguration = FDKreadBits(bs, 4); + } + } else { + self->m_extensionAudioObjectType = AOT_NULL_OBJECT; + } + } + + /* Parse whatever specific configs */ + switch (self->m_aot) { + case AOT_AAC_LC: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + if ((ErrorStatus = GaSpecificConfig_Parse(&self->m_sc.m_gaSpecificConfig, + self, bs, ascStartAnchor)) != + TRANSPORTDEC_OK) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_gaSpecificConfig.m_frameLengthFlag; + break; + case AOT_MPEGS: + if (cb->cbSsc != NULL) { + if (cb->cbSsc(cb->cbSscData, bs, self->m_aot, self->m_samplingFrequency, + self->m_samplesPerFrame, 1, + -1, /* nTimeSlots: read from bitstream */ + 0, /* don't know the length */ + self->configMode, &self->SacConfigChanged)) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + } else { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + break; + case AOT_ER_AAC_ELD: + if ((ErrorStatus = EldSpecificConfig_Parse(self, bs, cb)) != + TRANSPORTDEC_OK) { + return (ErrorStatus); + } + frameLengthFlag = self->m_sc.m_eldSpecificConfig.m_frameLengthFlag; + self->m_sbrPresentFlag = self->m_sc.m_eldSpecificConfig.m_sbrPresentFlag; + self->m_extensionSamplingFrequency = + (self->m_sc.m_eldSpecificConfig.m_sbrSamplingRate + 1) * + self->m_samplingFrequency; + break; + case AOT_USAC: + if ((ErrorStatus = UsacConfig_Parse(self, bs, cb)) != TRANSPORTDEC_OK) { + return (ErrorStatus); + } + break; + + default: + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* Frame length */ + switch (self->m_aot) { + case AOT_AAC_LC: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_SCAL: + case AOT_ER_BSAC: + /*case AOT_USAC:*/ + if (!frameLengthFlag) + self->m_samplesPerFrame = 1024; + else + self->m_samplesPerFrame = 960; + break; + case AOT_ER_AAC_LD: + if (!frameLengthFlag) + self->m_samplesPerFrame = 512; + else + self->m_samplesPerFrame = 480; + break; + default: + break; + } + + switch (self->m_aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_SCAL: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_BSAC: + self->m_epConfig = FDKreadBits(bs, 2); + + if (self->m_epConfig > 1) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; // EPCONFIG; + } + break; + default: + break; + } + + if (fExplicitBackwardCompatible && + (self->m_aot == AOT_AAC_LC || self->m_aot == AOT_ER_AAC_LD || + self->m_aot == AOT_ER_BSAC)) { + ErrorStatus = AudioSpecificConfig_ExtensionParse(self, bs, cb); + } + + /* Copy config() to asc->config[] buffer. */ + if ((ErrorStatus == TRANSPORTDEC_OK) && (self->m_aot == AOT_USAC)) { + INT configSize_bits = (INT)FDKgetValidBits(bs) - (INT)ascStartAnchor; + StoreConfigAsBitstream(bs, configSize_bits, self->config, + TP_USAC_MAX_CONFIG_LEN); + self->configBits = fAbs(configSize_bits); + } + + return (ErrorStatus); +} + +static TRANSPORTDEC_ERROR Drm_xHEAACDecoderConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM hBs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + CSUsacConfig *usc = &asc->m_sc.m_usacConfig; + int elemIdx = 0; + + usc->element[elemIdx].m_stereoConfigIndex = 0; + + usc->m_usacNumElements = 1; /* Currently all extension elements are skipped + -> only one SCE or CPE. */ + + switch (audioMode) { + case 0: /* mono: ID_USAC_SCE */ + usc->element[elemIdx].usacElementType = ID_USAC_SCE; + usc->m_nUsacChannels = 1; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + if (cb == NULL) { + return ErrorStatus; + } + if (cb->cbSbr != NULL) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, ID_SCE, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + } + break; + case 2: /* stereo: ID_USAC_CPE */ + usc->element[elemIdx].usacElementType = ID_USAC_CPE; + usc->m_nUsacChannels = 2; + usc->element[elemIdx].m_noiseFilling = FDKreadBits(hBs, 1); + if (usc->m_sbrRatioIndex > 0) { + usc->element[elemIdx].m_harmonicSBR = FDKreadBit(hBs); + usc->element[elemIdx].m_interTes = FDKreadBit(hBs); + usc->element[elemIdx].m_pvc = FDKreadBit(hBs); + { + INT bitsToSkip = skipSbrHeader(hBs, 1); + /* read stereoConfigIndex */ + usc->element[elemIdx].m_stereoConfigIndex = FDKreadBits(hBs, 2); + /* rewind */ + FDKpushBack(hBs, bitsToSkip + 2); + } + /* + The application of the following tools is mutually exclusive per audio + stream configuration (see clause 5.3.2, xHE-AAC codec configuration): + - MPS212 parametric stereo tool with residual coding + (stereoConfigIndex>1); and + - QMF based Harmonic Transposer (harmonicSBR==1). + */ + if ((usc->element[elemIdx].m_stereoConfigIndex > 1) && + usc->element[elemIdx].m_harmonicSBR) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + /* + The 4:1 sbrRatio (sbrRatioIndex==1 in [11]) may only be employed: + - in mono operation; or + - in stereo operation if parametric stereo (MPS212) without residual + coding is applied, i.e. if stereoConfigIndex==1 (see clause 5.3.2, + xHE-AAC codec configuration). + */ + if ((usc->m_sbrRatioIndex == 1) && + (usc->element[elemIdx].m_stereoConfigIndex != 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + if (cb == NULL) { + return ErrorStatus; + } + { + MP4_ELEMENT_ID el_type = + (usc->element[elemIdx].m_stereoConfigIndex == 1 || + usc->element[elemIdx].m_stereoConfigIndex == 2) + ? ID_SCE + : ID_CPE; + if (cb->cbSbr == NULL) return ErrorStatus = TRANSPORTDEC_UNKOWN_ERROR; + if (cb->cbSbr(cb->cbSbrData, hBs, asc->m_samplingFrequency, + asc->m_extensionSamplingFrequency, + asc->m_samplesPerFrame, asc->m_aot, el_type, elemIdx, + usc->element[elemIdx].m_harmonicSBR, + usc->element[elemIdx].m_stereoConfigIndex, + asc->configMode, &asc->SbrConfigChanged, 1)) { + return ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + } + } + /*usc->element[elemIdx].m_stereoConfigIndex =*/FDKreadBits(hBs, 2); + if (usc->element[elemIdx].m_stereoConfigIndex > 0) { + if (cb->cbSsc != NULL) { + int samplesPerFrame = asc->m_samplesPerFrame; + + if (usc->m_sbrRatioIndex == 1) samplesPerFrame <<= 2; + if (usc->m_sbrRatioIndex == 2) + samplesPerFrame = (samplesPerFrame * 8) / 3; + if (usc->m_sbrRatioIndex == 3) samplesPerFrame <<= 1; + + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbSsc( + cb->cbSscData, hBs, + AOT_DRM_USAC, /* syntax differs from MPEG Mps212Config() */ + asc->m_extensionSamplingFrequency, samplesPerFrame, + usc->element[elemIdx].m_stereoConfigIndex, + usc->m_coreSbrFrameLengthIndex, 0, /* don't know the length */ + asc->configMode, &asc->SacConfigChanged); + } else { + /* ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; */ + } + } + } + break; + default: + return TRANSPORTDEC_PARSE_ERROR; + } + + return ErrorStatus; +} + +TRANSPORTDEC_ERROR Drm_xHEAACStaticConfig( + CSAudioSpecificConfig *asc, HANDLE_FDK_BITSTREAM bs, int audioMode, + CSTpCallBacks *cb /* use cb == NULL to signal config check only mode */ +) { + int coreSbrFrameLengthIndexDrm = FDKreadBits(bs, 2); + if (UsacConfig_SetCoreSbrFrameLengthIndex( + asc, coreSbrFrameLengthIndexDrm + 1) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + asc->m_channelConfiguration = (audioMode) ? 2 : 1; + + if (Drm_xHEAACDecoderConfig(asc, bs, audioMode, cb) != TRANSPORTDEC_OK) { + return TRANSPORTDEC_PARSE_ERROR; + } + + return TRANSPORTDEC_OK; +} + +/* Mapping of DRM audio sampling rate field to MPEG usacSamplingFrequencyIndex + */ +const UCHAR mapSr2MPEGIdx[8] = { + 0x1b, /* 9.6 kHz */ + 0x09, /* 12.0 kHz */ + 0x08, /* 16.0 kHz */ + 0x17, /* 19.2 kHz */ + 0x06, /* 24.0 kHz */ + 0x05, /* 32.0 kHz */ + 0x12, /* 38.4 kHz */ + 0x03 /* 48.0 kHz */ +}; + +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse( + CSAudioSpecificConfig *self, HANDLE_FDK_BITSTREAM bs, + CSTpCallBacks *cb, /* use cb == NULL to signal config check only mode */ + UCHAR configMode, UCHAR configChanged) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + AudioSpecificConfig_Init(self); + + if ((INT)FDKgetValidBits(bs) < 16) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } else { + /* DRM - Audio information data entity - type 9 + - Short Id 2 bits (not part of the config buffer) + - Stream Id 2 bits (not part of the config buffer) + - audio coding 2 bits + - SBR flag 1 bit + - audio mode 2 bits + - audio sampling rate 3 bits + - text flag 1 bit + - enhancement flag 1 bit + - coder field 5 bits + - rfa 1 bit */ + + int audioCoding, audioMode, cSamplingFreq, coderField, sfIdx, sbrFlag; + + self->configMode = configMode; + self->AacConfigChanged = configChanged; + self->SbrConfigChanged = configChanged; + self->SacConfigChanged = configChanged; + + /* Read the SDC field */ + audioCoding = FDKreadBits(bs, 2); + sbrFlag = FDKreadBits(bs, 1); + audioMode = FDKreadBits(bs, 2); + cSamplingFreq = FDKreadBits(bs, 3); /* audio sampling rate */ + + FDKreadBits(bs, 2); /* Text and enhancement flag */ + coderField = FDKreadBits(bs, 5); + FDKreadBits(bs, 1); /* rfa */ + + /* Evaluate configuration and fill the ASC */ + if (audioCoding == 3) { + sfIdx = (int)mapSr2MPEGIdx[cSamplingFreq]; + sbrFlag = 0; /* rfa */ + } else { + switch (cSamplingFreq) { + case 0: /* 8 kHz */ + sfIdx = 11; + break; + case 1: /* 12 kHz */ + sfIdx = 9; + break; + case 2: /* 16 kHz */ + sfIdx = 8; + break; + case 3: /* 24 kHz */ + sfIdx = 6; + break; + case 5: /* 48 kHz */ + sfIdx = 3; + break; + case 4: /* reserved */ + case 6: /* reserved */ + case 7: /* reserved */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + self->m_samplingFrequencyIndex = sfIdx; + self->m_samplingFrequency = SamplingRateTable[sfIdx]; + + if (sbrFlag) { + UINT i; + int tmp = -1; + self->m_sbrPresentFlag = 1; + self->m_extensionAudioObjectType = AOT_SBR; + self->m_extensionSamplingFrequency = self->m_samplingFrequency << 1; + for (i = 0; + i < (sizeof(SamplingRateTable) / sizeof(SamplingRateTable[0])); + i++) { + if (SamplingRateTable[i] == self->m_extensionSamplingFrequency) { + tmp = i; + break; + } + } + self->m_extensionSamplingFrequencyIndex = tmp; + } + + switch (audioCoding) { + case 0: /* AAC */ + if ((coderField >> 2) && (audioMode != 1)) { + self->m_aot = AOT_DRM_SURROUND; /* Set pseudo AOT for Drm Surround */ + } else { + self->m_aot = AOT_DRM_AAC; /* Set pseudo AOT for Drm AAC */ + } + switch (audioMode) { + case 1: /* parametric stereo */ + self->m_psPresentFlag = 1; + FDK_FALLTHROUGH; + case 0: /* mono */ + self->m_channelConfiguration = 1; + break; + case 2: /* stereo */ + self->m_channelConfiguration = 2; + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + self->m_vcb11Flag = 1; + self->m_hcrFlag = 1; + self->m_samplesPerFrame = 960; + self->m_epConfig = 1; + break; + case 1: /* CELP */ + self->m_aot = AOT_ER_CELP; + self->m_channelConfiguration = 1; + break; + case 2: /* HVXC */ + self->m_aot = AOT_ER_HVXC; + self->m_channelConfiguration = 1; + break; + case 3: /* xHE-AAC */ + { + /* payload is MPEG conform -> no pseudo DRM AOT needed */ + self->m_aot = AOT_USAC; + } + switch (audioMode) { + case 0: /* mono */ + case 2: /* stereo */ + /* codec specific config 8n bits */ + ErrorStatus = Drm_xHEAACStaticConfig(self, bs, audioMode, cb); + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + break; + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + self->m_aot = AOT_NONE; + break; + } + + if (self->m_psPresentFlag && !self->m_sbrPresentFlag) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + +bail: + return (ErrorStatus); +} diff --git a/fdk-aac/libMpegTPDec/src/tpdec_drm.cpp b/fdk-aac/libMpegTPDec/src/tpdec_drm.cpp new file mode 100644 index 0000000..27c1c1d --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_drm.cpp @@ -0,0 +1,148 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Christian Griebel + + Description: DRM transport stuff + +*******************************************************************************/ + +#include "tpdec_drm.h" + +#include "FDK_bitstream.h" + +void drmRead_CrcInit(HANDLE_DRM pDrm) /*!< pointer to drm crc info stucture */ +{ + FDK_ASSERT(pDrm != NULL); + + FDKcrcInit(&pDrm->crcInfo, 0x001d, 0xFFFF, 8); +} + +int drmRead_CrcStartReg( + HANDLE_DRM pDrm, /*!< pointer to drm stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + FDK_ASSERT(pDrm != NULL); + + FDKcrcReset(&pDrm->crcInfo); + + pDrm->crcReadValue = FDKreadBits(hBs, 8); + + return (FDKcrcStartReg(&pDrm->crcInfo, hBs, mBits)); +} + +void drmRead_CrcEndReg( + HANDLE_DRM pDrm, /*!< pointer to drm crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + FDK_ASSERT(pDrm != NULL); + + FDKcrcEndReg(&pDrm->crcInfo, hBs, reg); +} + +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + USHORT crc; + + crc = FDKcrcGetCRC(&pDrm->crcInfo) ^ 0xFF; + if (crc != pDrm->crcReadValue) { + return (TRANSPORTDEC_CRC_ERROR); + } + + return (ErrorStatus); +} diff --git a/fdk-aac/libMpegTPDec/src/tpdec_drm.h b/fdk-aac/libMpegTPDec/src/tpdec_drm.h new file mode 100644 index 0000000..09822dc --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_drm.h @@ -0,0 +1,202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Josef Hoepfl + + Description: DRM interface + +*******************************************************************************/ + +#ifndef TPDEC_DRM_H +#define TPDEC_DRM_H + +#include "tpdec_lib.h" + +#include "FDK_crc.h" + +typedef struct { + FDK_CRCINFO crcInfo; /* CRC state info */ + USHORT crcReadValue; /* CRC value read from bitstream data */ + +} STRUCT_DRM; + +typedef STRUCT_DRM *HANDLE_DRM; + +/*! + \brief Initialize DRM CRC + + The function initialzes the crc buffer and the crc lookup table. + + \return none +*/ +void drmRead_CrcInit(HANDLE_DRM pDrm); + +/** + * \brief Starts CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param mBits max number of bits in crc region to be considered + * + * \return ID for the created region, -1 in case of an error + */ +int drmRead_CrcStartReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDrm DRM data handle + * \param hBs bitstream handle, on which the CRC region referes to + * \param reg CRC regions ID returned by drmRead_CrcStartReg() + * + * \return none + */ +void drmRead_CrcEndReg(HANDLE_DRM pDrm, HANDLE_FDK_BITSTREAM hBs, int reg); + +/** + * \brief Check CRC + * + * Checks if the currently calculated CRC matches the CRC field read from the + * bitstream Deletes all CRC regions. + * + * \param pDrm DRM data handle + * + * \return Returns 0 if they are identical otherwise 1 + */ +TRANSPORTDEC_ERROR drmRead_CrcCheck(HANDLE_DRM pDrm); + +/** + * \brief Check if we have a valid DRM frame at the current bitbuffer position + * + * This function assumes enough bits in buffer for the current frame. + * It reads out the header bits to prepare the bitbuffer for the decode loop. + * In case the header bits show an invalid bitstream/frame, the whole frame is + * skipped. + * + * \param pDrm DRM data handle which is filled with parsed DRM header data + * \param bs handle of bitstream from whom the DRM header is read + * + * \return error status + */ +TRANSPORTDEC_ERROR drmRead_DecodeHeader(HANDLE_DRM pDrm, + HANDLE_FDK_BITSTREAM bs); + +/** + * \brief Parse a Drm specific SDC audio config from a given bitstream handle. + * + * \param pAsc A pointer to an allocated + * CSAudioSpecificConfig struct. + * \param hBs Bitstream handle. + * \param cb A pointer to structure holding callback + * information Note: A NULL pointer for cb can be used to signal a "Check Config + * only functionality" + * \param configMode Config modes: memory allocation mode or + * config change detection mode + * \param configChanged Indicates a config change + * + * \return Total element count including all SCE, CPE and LFE. + */ +TRANSPORTDEC_ERROR DrmRawSdcAudioConfig_Parse(CSAudioSpecificConfig *pAsc, + HANDLE_FDK_BITSTREAM hBs, + CSTpCallBacks *cb, + const UCHAR configMode, + const UCHAR configChanged); + +#endif /* TPDEC_DRM_H */ diff --git a/fdk-aac/libMpegTPDec/src/tpdec_latm.cpp b/fdk-aac/libMpegTPDec/src/tpdec_latm.cpp new file mode 100644 index 0000000..2edf055 --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_latm.cpp @@ -0,0 +1,676 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#include "tpdec_latm.h" + +#include "FDK_bitstream.h" + +#define TPDEC_TRACKINDEX(p, l) (1 * (p) + (l)) + +static UINT CLatmDemux_GetValue(HANDLE_FDK_BITSTREAM bs) { + UCHAR bytesForValue = 0, tmp = 0; + int value = 0; + + bytesForValue = (UCHAR)FDKreadBits(bs, 2); + + for (UINT i = 0; i <= bytesForValue; i++) { + value <<= 8; + tmp = (UCHAR)FDKreadBits(bs, 8); + value += tmp; + } + + return value; +} + +static TRANSPORTDEC_ERROR CLatmDemux_ReadAudioMuxElement( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, int m_muxConfigPresent, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + if (m_muxConfigPresent) { + pLatmDemux->m_useSameStreamMux = FDKreadBits(bs, 1); + + if (!pLatmDemux->m_useSameStreamMux) { + int i; + UCHAR configChanged = 0; + UCHAR configMode = 0; + + FDK_BITSTREAM bsAnchor; + + FDK_BITSTREAM bsAnchorDummyParse; + + if (!pLatmDemux->applyAsc) { + bsAnchorDummyParse = *bs; + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* do dummy-parsing of ASC to determine if there is an audioPreRoll */ + configMode |= AC_CM_DET_CFG_CHANGE; + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + /* Allow flushing only when audioPreroll functionality is enabled in + * current and new config otherwise the new config can be applied + * immediately. */ + if (pAsc->m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll && + pLatmDemux->newCfgHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = 0; + /* with audioPreRoll we must flush before applying new cfg */ + pLatmDemux->applyAsc = 0; + } else { + *bs = bsAnchorDummyParse; + pLatmDemux->applyAsc = 1; /* apply new config immediate */ + } + } + + if (pLatmDemux->applyAsc) { + for (i = 0; i < 2; i++) { + configMode = 0; + + if (i == 0) { + configMode |= AC_CM_DET_CFG_CHANGE; + bsAnchor = *bs; + } else { + configMode |= AC_CM_ALLOC_MEM; + *bs = bsAnchor; + } + + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadStreamMuxConfig( + bs, pLatmDemux, pTpDecCallbacks, pAsc, pfConfigFound, + configMode, configChanged))) { + goto bail; + } + + if (ErrorStatus == TRANSPORTDEC_OK) { + if ((i == 0) && (pAsc->AacConfigChanged || pAsc->SbrConfigChanged || + pAsc->SacConfigChanged)) { + int errC; + + configChanged = 1; + errC = pTpDecCallbacks->cbFreeMem(pTpDecCallbacks->cbFreeMemData, + pAsc); + if (errC != 0) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + } + } + } + } + } + + /* If there was no configuration read, its not possible to parse + * PayloadLengthInfo below. */ + if (!*pfConfigFound) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + /* Do only once per call, because parsing and decoding is done in-line. */ + if (TRANSPORTDEC_OK != + (ErrorStatus = CLatmDemux_ReadPayloadLengthInfo(bs, pLatmDemux))) { + *pfConfigFound = 0; + goto bail; + } + } else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + *pfConfigFound = 0; + goto bail; + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + pLatmDemux->applyAsc = 1; + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness) { + UINT cntBits; + UINT cmpBufferFullness; + UINT audioMuxLengthBytesLast = 0; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + + cntBits = FDKgetValidBits(bs); + + if ((INT)cntBits < MIN_LATM_HEADERLENGTH) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + if (TRANSPORTDEC_OK != (ErrorStatus = CLatmDemux_ReadAudioMuxElement( + bs, pLatmDemux, (tt != TT_MP4_LATM_MCP0), + pTpDecCallbacks, pAsc, pfConfigFound))) + return (ErrorStatus); + + if (!ignoreBufferFullness) { + cmpBufferFullness = + 24 + audioMuxLengthBytesLast * 8 + + pLatmDemux->m_linfo[0][0].m_bufferFullness * + pAsc[TPDEC_TRACKINDEX(0, 0)].m_channelConfiguration * 32; + + /* evaluate buffer fullness */ + + if (pLatmDemux->m_linfo[0][0].m_bufferFullness != 0xFF) { + if (!pLatmDemux->BufferFullnessAchieved) { + if (cntBits < cmpBufferFullness) { + /* condition for start of decoding is not fulfilled */ + + /* the current frame will not be decoded */ + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } else { + pLatmDemux->BufferFullnessAchieved = 1; + } + } + } + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged) { + CSAudioSpecificConfig ascDummy; /* the actual config is needed for flushing, + after that new config can be parsed */ + CSAudioSpecificConfig *pAscDummy; + pAscDummy = &ascDummy; + pLatmDemux->usacExplicitCfgChanged = 0; + LATM_LAYER_INFO *p_linfo = NULL; + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + UCHAR updateConfig[1 * 1] = {0}; + + pLatmDemux->m_AudioMuxVersion = FDKreadBits(bs, 1); + + if (pLatmDemux->m_AudioMuxVersion == 0) { + pLatmDemux->m_AudioMuxVersionA = 0; + } else { + pLatmDemux->m_AudioMuxVersionA = FDKreadBits(bs, 1); + } + + if (pLatmDemux->m_AudioMuxVersionA == 0) { + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_taraBufferFullness = CLatmDemux_GetValue(bs); + } + pLatmDemux->m_allStreamsSameTimeFraming = FDKreadBits(bs, 1); + pLatmDemux->m_noSubFrames = FDKreadBits(bs, 6) + 1; + pLatmDemux->m_numProgram = FDKreadBits(bs, 4) + 1; + + if (pLatmDemux->m_numProgram > LATM_MAX_PROG) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; + } + + int idCnt = 0; + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + pLatmDemux->m_numLayer[prog] = FDKreadBits(bs, 3) + 1; + if (pLatmDemux->m_numLayer[prog] > LATM_MAX_LAYER) { + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + goto bail; + } + + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + int useSameConfig; + p_linfo = &pLatmDemux->m_linfo[prog][lay]; + + p_linfo->m_streamID = idCnt++; + p_linfo->m_frameLengthInBits = 0; + + if ((prog == 0) && (lay == 0)) { + useSameConfig = 0; + } else { + useSameConfig = FDKreadBits(bs, 1); + } + + if (useSameConfig) { + if (lay > 0) { + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)], + &pAsc[TPDEC_TRACKINDEX(prog, lay - 1)], + sizeof(CSAudioSpecificConfig)); + } else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } else { + UINT usacConfigLengthPrev = 0; + UCHAR usacConfigPrev[TP_USAC_MAX_CONFIG_LEN]; + + if (!(pLatmDemux->applyAsc) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_USAC)) { + usacConfigLengthPrev = + (UINT)(pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits + + 7) >> + 3; /* store previous USAC config length */ + if (usacConfigLengthPrev > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKmemclear(usacConfigPrev, TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy( + usacConfigPrev, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev); /* store previous USAC config */ + } + if (pLatmDemux->m_AudioMuxVersion == 1) { + FDK_BITSTREAM tmpBs; + UINT ascLen = 0; + ascLen = CLatmDemux_GetValue(bs); + /* The ascLen could be wrong, so check if validBits<=bufBits*/ + if (ascLen > FDKgetValidBits(bs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKsyncCache(bs); + tmpBs = *bs; + tmpBs.hBitBuf.ValidBits = ascLen; + + /* Read ASC */ + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], &tmpBs, 1, + pTpDecCallbacks, configMode, configChanged, + AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, &tmpBs, 1, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } + + /* The field p_linfo->m_ascLen could be wrong, so check if */ + if (0 > (INT)FDKgetValidBits(&tmpBs)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + FDKpushFor(bs, ascLen); /* position bitstream after ASC */ + } else { + /* Read ASC */ + if (pLatmDemux->applyAsc) { + if (TRANSPORTDEC_OK != (ErrorStatus = AudioSpecificConfig_Parse( + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } else { + if (TRANSPORTDEC_OK != + (ErrorStatus = AudioSpecificConfig_Parse( + pAscDummy, bs, 0, pTpDecCallbacks, configMode, + configChanged, AOT_NULL_OBJECT))) + goto bail; + } + } + if (!pLatmDemux->applyAsc) { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 0; + } else { + updateConfig[TPDEC_TRACKINDEX(prog, lay)] = 1; + } + + if (!pLatmDemux->applyAsc) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_USAC) { /* flush in case SMC has changed */ + const UINT usacConfigLength = + (UINT)(pAscDummy->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3; + if (usacConfigLength > TP_USAC_MAX_CONFIG_LEN) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + if (usacConfigLength != usacConfigLengthPrev) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } else { + if (FDKmemcmp(usacConfigPrev, + pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLengthPrev)) { + FDKmemclear(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + TP_USAC_MAX_CONFIG_LEN); + FDKmemcpy(&pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfig, + &pAscDummy->m_sc.m_usacConfig.UsacConfig, + usacConfigLength); /* store new USAC config */ + pAsc[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.UsacConfigBits = + pAscDummy->m_sc.m_usacConfig.UsacConfigBits; + pLatmDemux->usacExplicitCfgChanged = 1; + } + } + + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.m_usacNumElements) { + if (pAscDummy[TPDEC_TRACKINDEX(prog, lay)] + .m_sc.m_usacConfig.element[0] + .extElement.usacExtElementHasAudioPreRoll) { + pLatmDemux->newCfgHasAudioPreRoll = + 1; /* if dummy parsed cfg has audioPreRoll we first flush + before applying new cfg */ + } + } + } + } + } + + p_linfo->m_frameLengthType = FDKreadBits(bs, 3); + switch (p_linfo->m_frameLengthType) { + case 0: + p_linfo->m_bufferFullness = FDKreadBits(bs, 8); + + if (!pLatmDemux->m_allStreamsSameTimeFraming) { + if ((lay > 0) && + (pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == AOT_AAC_SCAL || + pAsc[TPDEC_TRACKINDEX(prog, lay)].m_aot == + AOT_ER_AAC_SCAL) && + (pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == AOT_CELP || + pAsc[TPDEC_TRACKINDEX(prog, lay - 1)].m_aot == + AOT_ER_CELP)) { /* The layer maybe + ignored later so + read it anyway: */ + /* coreFrameOffset = */ FDKreadBits(bs, 6); + } + } + break; + case 1: + p_linfo->m_frameLengthInBits = FDKreadBits(bs, 9); + break; + case 3: + case 4: + case 5: + /* CELP */ + case 6: + case 7: + /* HVXC */ + default: + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } /* switch framelengthtype*/ + + } /* layer loop */ + } /* prog loop */ + + pLatmDemux->m_otherDataPresent = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength = 0; + + if (pLatmDemux->m_otherDataPresent) { + if (pLatmDemux->m_AudioMuxVersion == 1) { + pLatmDemux->m_otherDataLength = CLatmDemux_GetValue(bs); + } else { + int otherDataLenEsc = 0; + do { + pLatmDemux->m_otherDataLength <<= 8; // *= 256 + otherDataLenEsc = FDKreadBits(bs, 1); + pLatmDemux->m_otherDataLength += FDKreadBits(bs, 8); + } while (otherDataLenEsc); + } + if (pLatmDemux->m_audioMuxLengthBytes < + (pLatmDemux->m_otherDataLength >> 3)) { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + pLatmDemux->m_crcCheckPresent = FDKreadBits(bs, 1); + + if (pLatmDemux->m_crcCheckPresent) { + FDKreadBits(bs, 8); + } + + } else { + /* audioMuxVersionA > 0 is reserved for future extensions */ + ErrorStatus = TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + + /* Configure source decoder: */ + if (ErrorStatus == TRANSPORTDEC_OK) { + UINT prog; + for (prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + UINT lay; + for (lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + if (updateConfig[TPDEC_TRACKINDEX(prog, lay)] != 0) { + int cbError; + cbError = pTpDecCallbacks->cbUpdateConfig( + pTpDecCallbacks->cbUpdateConfigData, + &pAsc[TPDEC_TRACKINDEX(prog, lay)], + pAsc[TPDEC_TRACKINDEX(prog, lay)].configMode, + &pAsc[TPDEC_TRACKINDEX(prog, lay)].AacConfigChanged); + if (cbError == TRANSPORTDEC_NEED_TO_RESTART) { + *pfConfigFound = 0; + ErrorStatus = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } + if (cbError != 0) { + *pfConfigFound = 0; + if (lay == 0) { + ErrorStatus = TRANSPORTDEC_SYNC_ERROR; + goto bail; + } + } else { + *pfConfigFound = 1; + } + } else { + *pfConfigFound = 1; + } + } + } + } + +bail: + if (ErrorStatus != TRANSPORTDEC_OK) { + UCHAR applyAsc = pLatmDemux->applyAsc; + FDKmemclear(pLatmDemux, sizeof(CLatmDemux)); /* reset structure */ + pLatmDemux->applyAsc = applyAsc; + } else { + /* no error and config parsing is finished */ + if (configMode == AC_CM_ALLOC_MEM) pLatmDemux->applyAsc = 0; + } + + return (ErrorStatus); +} + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux) { + TRANSPORTDEC_ERROR ErrorStatus = TRANSPORTDEC_OK; + int totalPayloadBits = 0; + + if (pLatmDemux->m_allStreamsSameTimeFraming == 1) { + FDK_ASSERT(pLatmDemux->m_numProgram <= LATM_MAX_PROG); + for (UINT prog = 0; prog < pLatmDemux->m_numProgram; prog++) { + FDK_ASSERT(pLatmDemux->m_numLayer[prog] <= LATM_MAX_LAYER); + for (UINT lay = 0; lay < pLatmDemux->m_numLayer[prog]; lay++) { + LATM_LAYER_INFO *p_linfo = &pLatmDemux->m_linfo[prog][lay]; + + switch (p_linfo->m_frameLengthType) { + case 0: + p_linfo->m_frameLengthInBits = CLatmDemux_ReadAuChunkLengthInfo(bs); + totalPayloadBits += p_linfo->m_frameLengthInBits; + break; + case 3: + case 5: + case 7: + default: + return TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_INVALIDFRAMELENGTHTYPE; + } + } + } + } else { + ErrorStatus = TRANSPORTDEC_PARSE_ERROR; // AAC_DEC_LATM_TIMEFRAMING; + } + if (pLatmDemux->m_audioMuxLengthBytes > (UINT)0 && + totalPayloadBits > (int)pLatmDemux->m_audioMuxLengthBytes * 8) { + return TRANSPORTDEC_PARSE_ERROR; + } + + return (ErrorStatus); +} + +int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs) { + UCHAR endFlag; + int len = 0; + + do { + UCHAR tmp = (UCHAR)FDKreadBits(bs, 8); + endFlag = (tmp < 255); + + len += tmp; + + } while (endFlag == 0); + + len <<= 3; /* convert from bytes to bits */ + + return len; +} + +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer) { + UINT nFrameLenBits = 0; + if (prog < pLatmDemux->m_numProgram) { + if (layer < pLatmDemux->m_numLayer[prog]) { + nFrameLenBits = pLatmDemux->m_linfo[prog][layer].m_frameLengthInBits; + } + } + return nFrameLenBits; +} + +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_otherDataPresent ? 1 : 0; +} + +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_otherDataLength; +} + +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux) { + return pLatmDemux->m_noSubFrames; +} + +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT prog) { + UINT numLayer = 0; + if (prog < pLatmDemux->m_numProgram) { + numLayer = pLatmDemux->m_numLayer[prog]; + } + return numLayer; +} diff --git a/fdk-aac/libMpegTPDec/src/tpdec_latm.h b/fdk-aac/libMpegTPDec/src/tpdec_latm.h new file mode 100644 index 0000000..6af553d --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_latm.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Daniel Homm + + Description: + +*******************************************************************************/ + +#ifndef TPDEC_LATM_H +#define TPDEC_LATM_H + +#include "tpdec_lib.h" + +#include "FDK_bitstream.h" + +#define MIN_LATM_HEADERLENGTH 9 +#define MIN_LOAS_HEADERLENGTH MIN_LATM_HEADERLENGTH + 24 /* both in bits */ +#define MIN_TP_BUF_SIZE_LOAS (8194) + +enum { + LATM_MAX_PROG = 1, + LATM_MAX_LAYER = 1, + LATM_MAX_VAR_CHUNKS = 16, + LATM_MAX_ID = 16 +}; + +typedef struct { + UINT m_frameLengthType; + UINT m_bufferFullness; + UINT m_streamID; + UINT m_frameLengthInBits; +} LATM_LAYER_INFO; + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROG][LATM_MAX_LAYER]; + UINT m_taraBufferFullness; + UINT m_otherDataLength; + UINT m_audioMuxLengthBytes; /* Length of LOAS payload */ + + UCHAR m_useSameStreamMux; + UCHAR m_AudioMuxVersion; + UCHAR m_AudioMuxVersionA; + UCHAR m_allStreamsSameTimeFraming; + UCHAR m_noSubFrames; + UCHAR m_numProgram; + UCHAR m_numLayer[LATM_MAX_PROG]; + + UCHAR m_otherDataPresent; + UCHAR m_crcCheckPresent; + + SCHAR BufferFullnessAchieved; + UCHAR + usacExplicitCfgChanged; /* explicit config in case of USAC and LOAS/LATM + must be compared to IPF cfg */ + UCHAR applyAsc; /* apply ASC immediate without flushing */ + UCHAR newCfgHasAudioPreRoll; /* the new (dummy parsed) config has an + AudioPreRoll */ +} CLatmDemux; + +int CLatmDemux_ReadAuChunkLengthInfo(HANDLE_FDK_BITSTREAM bs); + +TRANSPORTDEC_ERROR CLatmDemux_Read(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux, TRANSPORT_TYPE tt, + CSTpCallBacks *pTpDecCallbacks, + CSAudioSpecificConfig *pAsc, + int *pfConfigFound, + const INT ignoreBufferFullness); + +/** + * \brief Read StreamMuxConfig + * \param bs bit stream handle as data source + * \param pLatmDemux pointer to CLatmDemux struct of current LATM context + * \param pTpDecCallbacks Call back structure for configuration callbacks + * \param pAsc pointer to a ASC for configuration storage + * \param pfConfigFound pointer to a flag which is set to 1 if a configuration + * was found and processed successfully + * \param configMode Config modes: memory allocation mode or config change + * detection mode + * \param configChanged Indicates a config change + * \return error code + */ +TRANSPORTDEC_ERROR CLatmDemux_ReadStreamMuxConfig( + HANDLE_FDK_BITSTREAM bs, CLatmDemux *pLatmDemux, + CSTpCallBacks *pTpDecCallbacks, CSAudioSpecificConfig *pAsc, + int *pfConfigFound, UCHAR configMode, UCHAR configChanged); + +TRANSPORTDEC_ERROR CLatmDemux_ReadPayloadLengthInfo(HANDLE_FDK_BITSTREAM bs, + CLatmDemux *pLatmDemux); + +UINT CLatmDemux_GetFrameLengthInBits(CLatmDemux *pLatmDemux, const UINT prog, + const UINT layer); +UINT CLatmDemux_GetOtherDataPresentFlag(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetOtherDataLength(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfSubFrames(CLatmDemux *pLatmDemux); +UINT CLatmDemux_GetNrOfLayers(CLatmDemux *pLatmDemux, const UINT program); + +#endif /* TPDEC_LATM_H */ diff --git a/fdk-aac/libMpegTPDec/src/tpdec_lib.cpp b/fdk-aac/libMpegTPDec/src/tpdec_lib.cpp new file mode 100644 index 0000000..1976cb9 --- /dev/null +++ b/fdk-aac/libMpegTPDec/src/tpdec_lib.cpp @@ -0,0 +1,1820 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format decoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport decoder + +*******************************************************************************/ + +#include "tpdec_lib.h" + +/* library version */ +#include "tp_version.h" + +#include "tp_data.h" + +#include "tpdec_adts.h" + +#include "tpdec_adif.h" + +#include "tpdec_latm.h" + +#include "tpdec_drm.h" + +#include "FDK_crc.h" + +#define MODULE_NAME "transportDec" + +typedef union { + STRUCT_ADTS adts; + + CAdifHeader adif; + + CLatmDemux latm; + + STRUCT_DRM drm; + +} transportdec_parser_t; + +#define MHAS_CONFIG_PRESENT 0x001 +#define MHAS_UI_PRESENT 0x002 + +struct TRANSPORTDEC { + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transportDec type. */ + + CSTpCallBacks callbacks; /*!< Struct holding callback and its data */ + + FDK_BITSTREAM bitStream[1]; /* Bitstream reader */ + UCHAR *bsBuffer; /* Internal bitstreamd data buffer */ + + transportdec_parser_t parser; /* Format specific parser structs. */ + + CSAudioSpecificConfig asc[(1 * 1) + 1]; /* Audio specific config from the last + config found. One additional + CSAudioSpecificConfig is used + temporarily for parsing. */ + CCtrlCFGChange ctrlCFGChange[(1 * 1)]; /* Controls config change */ + + UINT globalFramePos; /* Global transport frame reference bit position. */ + UINT accessUnitAnchor[1]; /* Current access unit start bit position. */ + INT auLength[1]; /* Length of current access unit. */ + INT numberOfRawDataBlocks; /* Current number of raw data blocks contained + remaining from the current transport frame. */ + UINT avgBitRate; /* Average bit rate used for frame loss estimation. */ + UINT lastValidBufferFullness; /* Last valid buffer fullness value for frame + loss estimation */ + INT remainder; /* Reminder in division during lost access unit estimation. */ + INT missingAccessUnits; /* Estimated missing access units. */ + UINT burstPeriod; /* Data burst period in mili seconds. */ + UINT holdOffFrames; /* Amount of frames that were already hold off due to + buffer fullness condition not being met. */ + UINT flags; /* Flags. */ + INT targetLayout; /* CICP target layout. */ + UINT *pLoudnessInfoSetPosition; /* Reference and start position (bits) and + length (bytes) of loudnessInfoSet within + rsv603daConfig. */ +}; + +/* Flag bitmasks for "flags" member of struct TRANSPORTDEC */ +#define TPDEC_SYNCOK 1 +#define TPDEC_MINIMIZE_DELAY 2 +#define TPDEC_IGNORE_BUFFERFULLNESS 4 +#define TPDEC_EARLY_CONFIG 8 +#define TPDEC_LOST_FRAMES_PENDING 16 +#define TPDEC_CONFIG_FOUND 32 +#define TPDEC_USE_ELEM_SKIPPING 64 + +/* force config/content change */ +#define TPDEC_FORCE_CONFIG_CHANGE 1 +#define TPDEC_FORCE_CONTENT_CHANGE 2 + +/* skip packet */ +#define TPDEC_SKIP_PACKET 1 + +C_ALLOC_MEM(Ram_TransportDecoder, struct TRANSPORTDEC, 1) +C_ALLOC_MEM(Ram_TransportDecoderBuffer, UCHAR, (8192 * 4)) + +HANDLE_TRANSPORTDEC transportDec_Open(const TRANSPORT_TYPE transportFmt, + const UINT flags, const UINT nrOfLayers) { + HANDLE_TRANSPORTDEC hInput; + + hInput = GetRam_TransportDecoder(0); + if (hInput == NULL) { + return NULL; + } + + /* Init transportDec struct. */ + hInput->transportFmt = transportFmt; + + switch (transportFmt) { + case TT_MP4_ADIF: + break; + + case TT_MP4_ADTS: + if (flags & TP_FLAG_MPEG4) + hInput->parser.adts.decoderCanDoMpeg4 = 1; + else + hInput->parser.adts.decoderCanDoMpeg4 = 0; + adtsRead_CrcInit(&hInput->parser.adts); + hInput->parser.adts.BufferFullnesStartFlag = 1; + hInput->numberOfRawDataBlocks = 0; + break; + + case TT_DRM: + drmRead_CrcInit(&hInput->parser.drm); + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_LOAS: + hInput->parser.latm.usacExplicitCfgChanged = 0; + hInput->parser.latm.applyAsc = 1; + break; + case TT_MP4_RAW: + break; + + default: + FreeRam_TransportDecoder(&hInput); + hInput = NULL; + break; + } + + if (hInput != NULL) { + /* Create bitstream */ + { + hInput->bsBuffer = GetRam_TransportDecoderBuffer(0); + if (hInput->bsBuffer == NULL) { + transportDec_Close(&hInput); + return NULL; + } + if (nrOfLayers > 1) { + transportDec_Close(&hInput); + return NULL; + } + for (UINT i = 0; i < nrOfLayers; i++) { + FDKinitBitStream(&hInput->bitStream[i], hInput->bsBuffer, (8192 * 4), 0, + BS_READER); + } + } + hInput->burstPeriod = 0; + } + + return hInput; +} + +TRANSPORTDEC_ERROR transportDec_OutOfBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *conf, const UINT length, + UINT layer) { + int i; + + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + int fConfigFound = 0; + + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + UCHAR tmpConf[1024]; + if (length > 1024) { + return TRANSPORTDEC_UNSUPPORTED_FORMAT; + } + FDKmemcpy(tmpConf, conf, length); + FDKinitBitStream(hBs, tmpConf, 1024, length << 3, BS_READER); + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, (INT)length * 8 - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + /* config transport decoder */ + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: { + if (layer != 0) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + CLatmDemux *pLatmDemux = &hTp->parser.latm; + err = CLatmDemux_ReadStreamMuxConfig(hBs, pLatmDemux, &hTp->callbacks, + hTp->asc, &fConfigFound, + configMode, configChanged); + if (err != TRANSPORTDEC_OK) { + return err; + } + } break; + default: + fConfigFound = 1; + err = AudioSpecificConfig_Parse(&hTp->asc[(1 * 1)], hBs, 1, + &hTp->callbacks, configMode, + configChanged, AOT_NULL_OBJECT); + if (err == TRANSPORTDEC_OK) { + int errC; + + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + case TT_DRM: + fConfigFound = 1; + err = DrmRawSdcAudioConfig_Parse(&hTp->asc[layer], hBs, &hTp->callbacks, + configMode, configChanged); + if (err == TRANSPORTDEC_OK) { + int errC; + + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + break; + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { + int errC; + + configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_InBandConfig(HANDLE_TRANSPORTDEC hTp, + UCHAR *newConfig, + const UINT newConfigLength, + const UCHAR buildUpStatus, + UCHAR *configChanged, UINT layer, + UCHAR *implicitExplicitCfgDiff) { + int errC; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int fConfigFound = 0; + UCHAR configMode = AC_CM_ALLOC_MEM; + *implicitExplicitCfgDiff = 0; + + FDK_ASSERT(hTp->asc->m_aot == AOT_USAC); + + FDKinitBitStream(hBs, newConfig, TP_USAC_MAX_CONFIG_LEN, newConfigLength << 3, + BS_READER); + + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + if (hTp->asc->m_aot == AOT_USAC) { + if ((UINT)(hTp->asc->m_sc.m_usacConfig.UsacConfigBits + 7) >> 3 == + newConfigLength) { + if (0 == FDKmemcmp(newConfig, hTp->asc->m_sc.m_usacConfig.UsacConfig, + newConfigLength)) { + if (hTp->parser.latm.usacExplicitCfgChanged) { /* configChange from + LOAS/LATM parser */ + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = + TPDEC_USAC_DASH_IPF_FLUSH_ON; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } else { + *configChanged = 0; + return err; + } + } else { + *implicitExplicitCfgDiff = 1; + } + } else { + *implicitExplicitCfgDiff = 1; + } + /* ISO/IEC 23003-3:2012/FDAM 3:2016(E) Annex F.2: explicit and implicit + * config shall be identical. */ + if (*implicitExplicitCfgDiff) { + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + /* reset decoder to initial state to achieve definite behavior after + * error in config */ + hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + hTp->parser.latm.usacExplicitCfgChanged = 0; + hTp->parser.latm.applyAsc = 1; + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + default: + break; + } + } + } + } + + { + if ((hTp->ctrlCFGChange[layer].flushStatus == TPDEC_FLUSH_OFF) && + (hTp->ctrlCFGChange[layer].buildUpStatus != + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND)) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_USAC_DASH_IPF_FLUSH_ON; + } + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + SCHAR counter = 0; + if (hTp->asc->m_aot == AOT_USAC) { + counter = TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES; + } + if (hTp->ctrlCFGChange[layer].flushCnt >= counter) { + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + if (hTp->asc->m_aot == AOT_USAC) { + hTp->ctrlCFGChange[layer].buildUpCnt = + TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES - 1; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_USAC_BUILD_UP_ON; + } + } + + /* Activate flush mode. After that continue with build up mode in core */ + if (hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]) != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + + if ((hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON) || + (hTp->ctrlCFGChange[layer].flushStatus == + TPDEC_USAC_DASH_IPF_FLUSH_ON)) { + hTp->ctrlCFGChange[layer].flushCnt++; + return err; + } + } + + if (hTp->asc->m_aot == AOT_USAC) { + fConfigFound = 1; + + if (err == TRANSPORTDEC_OK) { + *configChanged = 0; + configMode = AC_CM_DET_CFG_CHANGE; + + for (int i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, newConfigLength * 8 - FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + /* config transport decoder */ + err = AudioSpecificConfig_Parse( + &hTp->asc[(1 * 1)], hBs, 0, &hTp->callbacks, configMode, + *configChanged, hTp->asc[layer].m_aot); + if (err == TRANSPORTDEC_OK) { + hTp->asc[layer] = hTp->asc[(1 * 1)]; + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[layer], + hTp->asc[layer].configMode, &hTp->asc[layer].AacConfigChanged); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && (hTp->asc[layer].AacConfigChanged || + hTp->asc[layer].SbrConfigChanged || + hTp->asc[layer].SacConfigChanged)) { + *configChanged = 1; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[layer]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + + /* if an error is detected terminate config parsing to avoid that an + * invalid config is accepted in the second pass */ + if (err != TRANSPORTDEC_OK) { + break; + } + } + } + } + + bail: + /* save new config */ + if (err == TRANSPORTDEC_OK) { + if (hTp->asc->m_aot == AOT_USAC) { + hTp->asc->m_sc.m_usacConfig.UsacConfigBits = newConfigLength << 3; + FDKmemcpy(hTp->asc->m_sc.m_usacConfig.UsacConfig, newConfig, + newConfigLength); + /* in case of USAC reset transportDecoder variables here because + * otherwise without IPF they are not reset */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + } + } else { + hTp->numberOfRawDataBlocks = 0; + + /* If parsing error while config found, clear ctrlCFGChange-struct */ + hTp->ctrlCFGChange[layer].flushCnt = 0; + hTp->ctrlCFGChange[layer].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[layer].buildUpCnt = 0; + hTp->ctrlCFGChange[layer].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[layer].cfgChanged = 0; + hTp->ctrlCFGChange[layer].contentChanged = 0; + hTp->ctrlCFGChange[layer].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[layer]); + } + } + + if (err == TRANSPORTDEC_OK && fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + return err; +} + +int transportDec_RegisterAscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUpdateConfig_t cbUpdateConfig, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUpdateConfig = cbUpdateConfig; + hTpDec->callbacks.cbUpdateConfigData = user_data; + return 0; +} + +int transportDec_RegisterFreeMemCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbFreeMem_t cbFreeMem, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbFreeMem = cbFreeMem; + hTpDec->callbacks.cbFreeMemData = user_data; + return 0; +} + +int transportDec_RegisterCtrlCFGChangeCallback( + HANDLE_TRANSPORTDEC hTpDec, const cbCtrlCFGChange_t cbCtrlCFGChange, + void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbCtrlCFGChange = cbCtrlCFGChange; + hTpDec->callbacks.cbCtrlCFGChangeData = user_data; + return 0; +} + +int transportDec_RegisterSscCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSsc_t cbSsc, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSsc = cbSsc; + hTpDec->callbacks.cbSscData = user_data; + return 0; +} + +int transportDec_RegisterSbrCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbSbr_t cbSbr, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbSbr = cbSbr; + hTpDec->callbacks.cbSbrData = user_data; + return 0; +} + +int transportDec_RegisterUsacCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUsac_t cbUsac, void *user_data) { + if (hTpDec == NULL) { + return -1; + } + hTpDec->callbacks.cbUsac = cbUsac; + hTpDec->callbacks.cbUsacData = user_data; + return 0; +} + +int transportDec_RegisterUniDrcConfigCallback(HANDLE_TRANSPORTDEC hTpDec, + const cbUniDrc_t cbUniDrc, + void *user_data, + UINT *pLoudnessInfoSetPosition) { + if (hTpDec == NULL) { + return -1; + } + + hTpDec->callbacks.cbUniDrc = cbUniDrc; + hTpDec->callbacks.cbUniDrcData = user_data; + + hTpDec->pLoudnessInfoSetPosition = pLoudnessInfoSetPosition; + return 0; +} + +TRANSPORTDEC_ERROR transportDec_FillData(const HANDLE_TRANSPORTDEC hTp, + UCHAR *pBuffer, const UINT bufferSize, + UINT *pBytesValid, const INT layer) { + HANDLE_FDK_BITSTREAM hBs; + + if ((hTp == NULL) || (layer >= 1)) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + /* set bitbuffer shortcut */ + hBs = &hTp->bitStream[layer]; + + if (TT_IS_PACKET(hTp->transportFmt)) { + if (hTp->numberOfRawDataBlocks == 0) { + FDKresetBitbuffer(hBs); + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); + if (*pBytesValid != 0) { + return TRANSPORTDEC_TOO_MANY_BITS; + } + } + } else { + /* ... else feed bitbuffer with new stream data (append). */ + + if (*pBytesValid == 0) { + /* nothing to do */ + return TRANSPORTDEC_OK; + } + + if (hTp->numberOfRawDataBlocks <= 0) { + FDKfeedBuffer(hBs, pBuffer, bufferSize, pBytesValid); + } + } + + return TRANSPORTDEC_OK; +} + +HANDLE_FDK_BITSTREAM transportDec_GetBitstream(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + return &hTp->bitStream[layer]; +} + +TRANSPORT_TYPE transportDec_GetFormat(const HANDLE_TRANSPORTDEC hTp) { + return hTp->transportFmt; +} + +INT transportDec_GetBufferFullness(const HANDLE_TRANSPORTDEC hTp) { + INT bufferFullness = -1; + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.adts_fullness != 0x7ff) { + bufferFullness = hTp->parser.adts.bs.frame_length * 8 + + hTp->parser.adts.bs.adts_fullness * 32 * + getNumberOfEffectiveChannels( + hTp->parser.adts.bs.channel_config); + } + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hTp->parser.latm.m_linfo[0][0].m_bufferFullness != 0xff) { + bufferFullness = hTp->parser.latm.m_linfo[0][0].m_bufferFullness; + } + break; + default: + break; + } + + return bufferFullness; +} + +/** + * \brief adjust bit stream position and the end of an access unit. + * \param hTp transport decoder handle. + * \return error code. + */ +static TRANSPORTDEC_ERROR transportDec_AdjustEndOfAccessUnit( + HANDLE_TRANSPORTDEC hTp) { + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + /* Do byte align at the end of raw_data_block() because UsacFrame() is not + * byte aligned. */ + FDKbyteAlign(hBs, hTp->accessUnitAnchor[0]); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hTp->numberOfRawDataBlocks == 0) { + /* Do byte align at the end of AudioMuxElement. */ + FDKbyteAlign(hBs, hTp->globalFramePos); + + /* Check global frame length */ + if (hTp->transportFmt == TT_MP4_LOAS && + hTp->parser.latm.m_audioMuxLengthBytes > 0) { + int loasOffset; + + loasOffset = ((INT)hTp->parser.latm.m_audioMuxLengthBytes * 8 + + (INT)FDKgetValidBits(hBs)) - + (INT)hTp->globalFramePos; + if (loasOffset != 0) { + FDKpushBiDirectional(hBs, loasOffset); + /* For ELD and other payloads there is an unknown amount of padding, + so ignore unread bits, but throw an error only if too many bits + where read. */ + if (loasOffset < 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + break; + + case TT_MP4_ADTS: + if (hTp->parser.adts.bs.protection_absent == 0) { + int offset; + + /* Calculate offset to end of AU */ + offset = hTp->parser.adts + .rawDataBlockDist[hTp->parser.adts.bs.num_raw_blocks - + hTp->numberOfRawDataBlocks] + << 3; + /* CAUTION: The PCE (if available) is declared to be a part of the + * header! */ + offset -= (INT)hTp->accessUnitAnchor[0] - (INT)FDKgetValidBits(hBs) + + 16 + hTp->parser.adts.bs.num_pce_bits; + FDKpushBiDirectional(hBs, offset); + } + if (hTp->parser.adts.bs.num_raw_blocks > 0 && + hTp->parser.adts.bs.protection_absent == 0) { + /* Note this CRC read currently happens twice because of + * transportDec_CrcCheck() */ + hTp->parser.adts.crcReadValue = FDKreadBits(hBs, 16); + } + if (hTp->numberOfRawDataBlocks == 0) { + /* Check global frame length */ + if (hTp->parser.adts.bs.protection_absent == 0) { + int offset; + + offset = (hTp->parser.adts.bs.frame_length * 8 - ADTS_SYNCLENGTH + + (INT)FDKgetValidBits(hBs)) - + (INT)hTp->globalFramePos; + if (offset != 0) { + FDKpushBiDirectional(hBs, offset); + } + } + } + break; + + default: + break; + } + + return err; +} + +/** + * \brief Determine additional buffer fullness contraint due to burst data + * reception. The parameter TPDEC_PARAM_BURSTPERIOD must have been set as a + * precondition. + * \param hTp transport decoder handle. + * \param bufferFullness the buffer fullness value of the first frame to be + * decoded. + * \param bitsAvail the amount of available bits at the end of the first frame + * to be decoded. + * \return error code + */ +static TRANSPORTDEC_ERROR additionalHoldOffNeeded(HANDLE_TRANSPORTDEC hTp, + INT bufferFullness, + INT bitsAvail) { + INT checkLengthBits, avgBitsPerFrame; + INT maxAU; /* maximum number of frames per Master Frame */ + INT samplesPerFrame = hTp->asc->m_samplesPerFrame; + INT samplingFrequency = (INT)hTp->asc->m_samplingFrequency; + + if ((hTp->avgBitRate == 0) || (hTp->burstPeriod == 0)) { + return TRANSPORTDEC_OK; + } + if ((samplesPerFrame == 0) || (samplingFrequency == 0)) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + + /* One Master Frame is sent every hTp->burstPeriod ms */ + maxAU = hTp->burstPeriod * samplingFrequency + (samplesPerFrame * 1000 - 1); + maxAU = maxAU / (samplesPerFrame * 1000); + /* Subtract number of frames which were already held off. */ + maxAU -= hTp->holdOffFrames; + + avgBitsPerFrame = hTp->avgBitRate * samplesPerFrame + (samplingFrequency - 1); + avgBitsPerFrame = avgBitsPerFrame / samplingFrequency; + + /* Consider worst case of bufferFullness quantization. */ + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_ADTS: + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness += 31; + break; + default: /* added to avoid compiler warning */ + break; /* added to avoid compiler warning */ + } + + checkLengthBits = bufferFullness + (maxAU - 1) * avgBitsPerFrame; + + /* Check if buffer is big enough to fullfill buffer fullness condition */ + if ((checkLengthBits /*+headerBits*/) > (((8192 * 4) << 3) - 7)) { + return TRANSPORTDEC_SYNC_ERROR; + } + + if (bitsAvail < checkLengthBits) { + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } else { + return TRANSPORTDEC_OK; + } +} + +static TRANSPORTDEC_ERROR transportDec_readHeader( + HANDLE_TRANSPORTDEC hTp, HANDLE_FDK_BITSTREAM hBs, int syncLength, + int ignoreBufferFullness, int *pRawDataBlockLength, + int *pfTraverseMoreFrames, int *pSyncLayerFrameBits, int *pfConfigFound, + int *pHeaderBits) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + int rawDataBlockLength = *pRawDataBlockLength; + int fTraverseMoreFrames = + (pfTraverseMoreFrames != NULL) ? *pfTraverseMoreFrames : 0; + int syncLayerFrameBits = + (pSyncLayerFrameBits != NULL) ? *pSyncLayerFrameBits : 0; + int fConfigFound = (pfConfigFound != NULL) ? *pfConfigFound : 0; + int startPos; + + startPos = (INT)FDKgetValidBits(hBs); + + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + if (hTp->numberOfRawDataBlocks <= 0) { + int i, errC; + + hTp->globalFramePos = FDKgetValidBits(hBs); + + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, + (INT)hTp->globalFramePos - (INT)FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + /* Parse ADTS header */ + err = adtsRead_DecodeHeader(&hTp->parser.adts, &hTp->asc[0], hBs, + ignoreBufferFullness); + if (err != TRANSPORTDEC_OK) { + if (err != TRANSPORTDEC_NOT_ENOUGH_BITS) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC != 0) { + if (errC == TRANSPORTDEC_NEED_TO_RESTART) { + err = TRANSPORTDEC_NEED_TO_RESTART; + goto bail; + } else { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + fConfigFound = 1; + hTp->numberOfRawDataBlocks = + hTp->parser.adts.bs.num_raw_blocks + 1; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + } else { + /* Reset CRC because the next bits are the beginning of a + * raw_data_block() */ + FDKcrcReset(&hTp->parser.adts.crcInfo); + hTp->parser.adts.bs.num_pce_bits = 0; + } + if (err == TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks--; + rawDataBlockLength = adtsRead_GetRawDataBlockLength( + &hTp->parser.adts, + (hTp->parser.adts.bs.num_raw_blocks - hTp->numberOfRawDataBlocks)); + if (rawDataBlockLength <= 0) { + /* No further frame traversal possible. */ + fTraverseMoreFrames = 0; + } + syncLayerFrameBits = (hTp->parser.adts.bs.frame_length << 3) - + (startPos - (INT)FDKgetValidBits(hBs)) - + syncLength; + if (syncLayerFrameBits <= 0) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + case TT_MP4_LOAS: + if (hTp->numberOfRawDataBlocks <= 0) { + syncLayerFrameBits = (INT)FDKreadBits(hBs, 13); + hTp->parser.latm.m_audioMuxLengthBytes = syncLayerFrameBits; + syncLayerFrameBits <<= 3; + } + FDK_FALLTHROUGH; + case TT_MP4_LATM_MCP1: + case TT_MP4_LATM_MCP0: + if (hTp->numberOfRawDataBlocks <= 0) { + hTp->globalFramePos = FDKgetValidBits(hBs); + + err = CLatmDemux_Read(hBs, &hTp->parser.latm, hTp->transportFmt, + &hTp->callbacks, hTp->asc, &fConfigFound, + ignoreBufferFullness); + + if (err != TRANSPORTDEC_OK) { + if ((err != TRANSPORTDEC_NOT_ENOUGH_BITS) && + !TPDEC_IS_FATAL_ERROR(err)) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } else { + hTp->numberOfRawDataBlocks = + CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + if (hTp->transportFmt == TT_MP4_LOAS) { + syncLayerFrameBits -= startPos - (INT)FDKgetValidBits(hBs) - (13); + } + } + } else { + err = CLatmDemux_ReadPayloadLengthInfo(hBs, &hTp->parser.latm); + if (err != TRANSPORTDEC_OK) { + err = TRANSPORTDEC_SYNC_ERROR; + } + } + if (err == TRANSPORTDEC_OK) { + int layer; + rawDataBlockLength = 0; + for (layer = 0; + layer < (int)CLatmDemux_GetNrOfLayers(&hTp->parser.latm, 0); + layer += 1) { + rawDataBlockLength += + CLatmDemux_GetFrameLengthInBits(&hTp->parser.latm, 0, layer); + } + hTp->numberOfRawDataBlocks--; + } else { + hTp->numberOfRawDataBlocks = 0; + } + break; + default: { syncLayerFrameBits = 0; } break; + } + +bail: + + *pRawDataBlockLength = rawDataBlockLength; + + if (pHeaderBits != NULL) { + *pHeaderBits += startPos - (INT)FDKgetValidBits(hBs); + } + + for (int i = 0; i < (1 * 1); i++) { + /* If parsing error while config found, clear ctrlCFGChange-struct */ + if (hTp->ctrlCFGChange[i].cfgChanged && err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = 0; + hTp->ctrlCFGChange[i].flushCnt = 0; + hTp->ctrlCFGChange[i].flushStatus = TPDEC_FLUSH_OFF; + hTp->ctrlCFGChange[i].buildUpCnt = 0; + hTp->ctrlCFGChange[i].buildUpStatus = TPDEC_BUILD_UP_OFF; + hTp->ctrlCFGChange[i].cfgChanged = 0; + hTp->ctrlCFGChange[i].contentChanged = 0; + hTp->ctrlCFGChange[i].forceCfgChange = 0; + + hTp->callbacks.cbCtrlCFGChange(hTp->callbacks.cbCtrlCFGChangeData, + &hTp->ctrlCFGChange[i]); + } + } + + if (pfConfigFound != NULL) { + *pfConfigFound = fConfigFound; + } + + if (pfTraverseMoreFrames != NULL) { + *pfTraverseMoreFrames = fTraverseMoreFrames; + } + if (pSyncLayerFrameBits != NULL) { + *pSyncLayerFrameBits = syncLayerFrameBits; + } + + return err; +} + +/* How many bits to advance for synchronization search. */ +#define TPDEC_SYNCSKIP 8 + +static TRANSPORTDEC_ERROR synchronization(HANDLE_TRANSPORTDEC hTp, + INT *pHeaderBits) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK, errFirstFrame = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + + INT syncLayerFrameBits = 0; /* Length of sync layer frame (i.e. LOAS) */ + INT rawDataBlockLength = 0, rawDataBlockLengthPrevious; + INT totalBits; + INT headerBits = 0, headerBitsFirstFrame = 0, headerBitsPrevious; + INT numFramesTraversed = 0, fTraverseMoreFrames, + fConfigFound = (hTp->flags & TPDEC_CONFIG_FOUND), startPosFirstFrame = -1; + INT numRawDataBlocksFirstFrame = 0, numRawDataBlocksPrevious, + globalFramePosFirstFrame = 0, rawDataBlockLengthFirstFrame = 0; + INT ignoreBufferFullness = + hTp->flags & + (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | TPDEC_SYNCOK); + UINT endTpFrameBitsPrevious = 0; + + /* Synch parameters */ + INT syncLength; /* Length of sync word in bits */ + UINT syncWord; /* Sync word to be found */ + UINT syncMask; /* Mask for sync word (for adding one bit, so comprising one + bit less) */ + C_ALLOC_SCRATCH_START(contextFirstFrame, transportdec_parser_t, 1); + + totalBits = (INT)FDKgetValidBits(hBs); + + if (totalBits <= 0) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + goto bail; + } + + fTraverseMoreFrames = + (hTp->flags & (TPDEC_MINIMIZE_DELAY | TPDEC_EARLY_CONFIG)) && + !(hTp->flags & TPDEC_SYNCOK); + + /* Set transport specific sync parameters */ + switch (hTp->transportFmt) { + case TT_MP4_ADTS: + syncWord = ADTS_SYNCWORD; + syncLength = ADTS_SYNCLENGTH; + break; + case TT_MP4_LOAS: + syncWord = 0x2B7; + syncLength = 11; + break; + default: + syncWord = 0; + syncLength = 0; + break; + } + + syncMask = (1 << syncLength) - 1; + + do { + INT bitsAvail = 0; /* Bits available in bitstream buffer */ + INT checkLengthBits; /* Helper to check remaining bits and buffer boundaries + */ + UINT synch; /* Current sync word read from bitstream */ + + headerBitsPrevious = headerBits; + + bitsAvail = (INT)FDKgetValidBits(hBs); + + if (hTp->numberOfRawDataBlocks == 0) { + /* search synchword */ + + FDK_ASSERT((bitsAvail % TPDEC_SYNCSKIP) == 0); + + if ((bitsAvail - syncLength) < TPDEC_SYNCSKIP) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + headerBits = 0; + } else { + synch = FDKreadBits(hBs, syncLength); + + if (!(hTp->flags & TPDEC_SYNCOK)) { + for (; (bitsAvail - syncLength) >= TPDEC_SYNCSKIP; + bitsAvail -= TPDEC_SYNCSKIP) { + if (synch == syncWord) { + break; + } + synch = ((synch << TPDEC_SYNCSKIP) & syncMask) | + FDKreadBits(hBs, TPDEC_SYNCSKIP); + } + } + if (synch != syncWord) { + /* No correct syncword found. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + err = TRANSPORTDEC_OK; + } + headerBits = syncLength; + } + } else { + headerBits = 0; + } + + /* Save previous raw data block data */ + rawDataBlockLengthPrevious = rawDataBlockLength; + numRawDataBlocksPrevious = hTp->numberOfRawDataBlocks; + + /* Parse transport header (raw data block granularity) */ + + if (err == TRANSPORTDEC_OK) { + err = transportDec_readHeader(hTp, hBs, syncLength, ignoreBufferFullness, + &rawDataBlockLength, &fTraverseMoreFrames, + &syncLayerFrameBits, &fConfigFound, + &headerBits); + if (TPDEC_IS_FATAL_ERROR(err)) { + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. Ensure that the bit amount lands at a multiple of + * TPDEC_SYNCSKIP. */ + FDKpushBiDirectional( + hBs, -headerBits + TPDEC_SYNCSKIP + (bitsAvail % TPDEC_SYNCSKIP)); + + goto bail; + } + } + + bitsAvail -= headerBits; + + checkLengthBits = syncLayerFrameBits; + + /* Check if the whole frame would fit the bitstream buffer */ + if (err == TRANSPORTDEC_OK) { + if ((checkLengthBits + headerBits) > (((8192 * 4) << 3) - 7)) { + /* We assume that the size of the transport bit buffer has been + chosen to meet all system requirements, thus this condition + is considered a synchronisation error. */ + err = TRANSPORTDEC_SYNC_ERROR; + } else { + if (bitsAvail < checkLengthBits) { + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } + + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + /* Enforce reading of new data */ + hTp->numberOfRawDataBlocks = 0; + break; + } + + if (err == TRANSPORTDEC_SYNC_ERROR) { + int bits; + + /* Enforce re-sync of transport headers. */ + hTp->numberOfRawDataBlocks = 0; + + /* Ensure that the bit amount lands at a multiple of TPDEC_SYNCSKIP */ + bits = (bitsAvail + headerBits) % TPDEC_SYNCSKIP; + /* Rewind - TPDEC_SYNCSKIP, in order to look for a synch one bit ahead + * next time. */ + FDKpushBiDirectional(hBs, -(headerBits - TPDEC_SYNCSKIP) + bits); + headerBits = 0; + } + + /* Frame traversal */ + if (fTraverseMoreFrames) { + /* Save parser context for early config discovery "rewind all frames" */ + if ((hTp->flags & TPDEC_EARLY_CONFIG) && + !(hTp->flags & TPDEC_MINIMIZE_DELAY)) { + /* ignore buffer fullness if just traversing additional frames for ECD + */ + ignoreBufferFullness = 1; + + /* Save context in order to return later */ + if (err == TRANSPORTDEC_OK && startPosFirstFrame == -1) { + startPosFirstFrame = FDKgetValidBits(hBs); + numRawDataBlocksFirstFrame = hTp->numberOfRawDataBlocks; + globalFramePosFirstFrame = hTp->globalFramePos; + rawDataBlockLengthFirstFrame = rawDataBlockLength; + headerBitsFirstFrame = headerBits; + errFirstFrame = err; + FDKmemcpy(contextFirstFrame, &hTp->parser, + sizeof(transportdec_parser_t)); + } + + /* Break when config was found or it is not possible anymore to find a + * config */ + if (startPosFirstFrame != -1 && + (fConfigFound || err != TRANSPORTDEC_OK)) { + /* In case of ECD and sync error, do not rewind anywhere. */ + if (err == TRANSPORTDEC_SYNC_ERROR) { + startPosFirstFrame = -1; + fConfigFound = 0; + numFramesTraversed = 0; + } + break; + } + } + + if (err == TRANSPORTDEC_OK) { + FDKpushFor(hBs, rawDataBlockLength); + numFramesTraversed++; + endTpFrameBitsPrevious = (INT)FDKgetValidBits(hBs); + /* Ignore error here itentionally. */ + transportDec_AdjustEndOfAccessUnit(hTp); + endTpFrameBitsPrevious -= FDKgetValidBits(hBs); + } + } + } while (fTraverseMoreFrames || + (err == TRANSPORTDEC_SYNC_ERROR && !(hTp->flags & TPDEC_SYNCOK))); + + /* Restore context in case of ECD frame traversal */ + if (startPosFirstFrame != -1 && (fConfigFound || err != TRANSPORTDEC_OK)) { + FDKpushBiDirectional(hBs, FDKgetValidBits(hBs) - startPosFirstFrame); + FDKmemcpy(&hTp->parser, contextFirstFrame, sizeof(transportdec_parser_t)); + hTp->numberOfRawDataBlocks = numRawDataBlocksFirstFrame; + hTp->globalFramePos = globalFramePosFirstFrame; + rawDataBlockLength = rawDataBlockLengthFirstFrame; + headerBits = headerBitsFirstFrame; + err = errFirstFrame; + numFramesTraversed = 0; + } + + /* Additional burst data mode buffer fullness check. */ + if (!(hTp->flags & (TPDEC_LOST_FRAMES_PENDING | TPDEC_IGNORE_BUFFERFULLNESS | + TPDEC_SYNCOK)) && + err == TRANSPORTDEC_OK) { + err = additionalHoldOffNeeded(hTp, transportDec_GetBufferFullness(hTp), + FDKgetValidBits(hBs) - syncLayerFrameBits); + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + hTp->holdOffFrames++; + } + } + + /* Rewind for retry because of not enough bits */ + if (err == TRANSPORTDEC_NOT_ENOUGH_BITS) { + FDKpushBack(hBs, headerBits); + headerBits = 0; + } else { + /* reset hold off frame counter */ + hTp->holdOffFrames = 0; + } + + /* Return to last good frame in case of frame traversal but not ECD. */ + if (numFramesTraversed > 0) { + FDKpushBack(hBs, rawDataBlockLengthPrevious + endTpFrameBitsPrevious); + if (err != TRANSPORTDEC_OK) { + hTp->numberOfRawDataBlocks = numRawDataBlocksPrevious; + headerBits = headerBitsPrevious; + rawDataBlockLength = rawDataBlockLengthPrevious; + } + err = TRANSPORTDEC_OK; + } + +bail: + hTp->auLength[0] = rawDataBlockLength; + + /* Detect pointless TRANSPORTDEC_NOT_ENOUGH_BITS error case, where the bit + buffer is already full, or no new burst packet fits. Recover by advancing + the bit buffer. */ + if ((totalBits > 0) && (TRANSPORTDEC_NOT_ENOUGH_BITS == err) && + (FDKgetValidBits(hBs) >= + (((8192 * 4) * 8 - ((hTp->avgBitRate * hTp->burstPeriod) / 1000)) - + 7))) { + FDKpushFor(hBs, TPDEC_SYNCSKIP); + err = TRANSPORTDEC_SYNC_ERROR; + } + + if (err == TRANSPORTDEC_OK) { + hTp->flags |= TPDEC_SYNCOK; + } + + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + + if (pHeaderBits != NULL) { + *pHeaderBits = headerBits; + } + + if (err == TRANSPORTDEC_SYNC_ERROR) { + hTp->flags &= ~TPDEC_SYNCOK; + } + + C_ALLOC_SCRATCH_END(contextFirstFrame, transportdec_parser_t, 1); + + return err; +} + +/** + * \brief Synchronize to stream and estimate the amount of missing access units + * due to a current synchronization error in case of constant average bit rate. + */ +static TRANSPORTDEC_ERROR transportDec_readStream(HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[layer]; + + INT headerBits; + INT bitDistance, bfDelta; + + /* Obtain distance to next synch word */ + bitDistance = (INT)FDKgetValidBits(hBs); + error = synchronization(hTp, &headerBits); + bitDistance -= (INT)FDKgetValidBits(hBs); + + FDK_ASSERT(bitDistance >= 0); + + INT nAU = -1; + + if (error == TRANSPORTDEC_SYNC_ERROR || + (hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { + /* Check if estimating lost access units is feasible. */ + if (hTp->avgBitRate > 0 && hTp->asc[0].m_samplesPerFrame > 0 && + hTp->asc[0].m_samplingFrequency > 0) { + if (error == TRANSPORTDEC_OK) { + int aj; + + aj = transportDec_GetBufferFullness(hTp); + if (aj > 0) { + bfDelta = aj; + } else { + bfDelta = 0; + } + /* sync was ok: last of a series of bad access units. */ + hTp->flags &= ~TPDEC_LOST_FRAMES_PENDING; + /* Add up bitDistance until end of the current frame. Later we substract + this frame from the grand total, since this current successfully + synchronized frame should not be skipped of course; but it must be + accounted into the bufferfulness math. */ + bitDistance += hTp->auLength[0]; + } else { + if (!(hTp->flags & TPDEC_LOST_FRAMES_PENDING)) { + /* sync not ok: one of many bad access units. */ + hTp->flags |= TPDEC_LOST_FRAMES_PENDING; + bfDelta = -(INT)hTp->lastValidBufferFullness; + } else { + bfDelta = 0; + } + } + + { + int num, denom; + + /* Obtain estimate of number of lost frames */ + num = (INT)hTp->asc[0].m_samplingFrequency * (bfDelta + bitDistance) + + hTp->remainder; + denom = hTp->avgBitRate * hTp->asc[0].m_samplesPerFrame; + if (num > 0) { + nAU = num / denom; + hTp->remainder = num % denom; + } else { + hTp->remainder = num; + } + + if (error == TRANSPORTDEC_OK) { + /* Final adjustment of remainder, taken -1 into account because + current frame should not be skipped, thus substract -1 or do + nothing instead of +1-1 accordingly. */ + if ((denom - hTp->remainder) >= hTp->remainder) { + nAU--; + } + + if (nAU < 0) { + /* There was one frame too much concealed, so unfortunately we will + * have to skip one good frame. */ + transportDec_EndAccessUnit(hTp); + error = synchronization(hTp, &headerBits); + nAU = -1; + } + hTp->remainder = 0; + /* Enforce last missed frames to be concealed. */ + if (nAU > 0) { + FDKpushBack(hBs, headerBits); + } + } + } + } + } + + /* Be sure that lost frames are handled correctly. This is necessary due to + some sync error sequences where later it turns out that there is not enough + data, but the bits upto the sync word are discarded, thus causing a value + of nAU > 0 */ + if (nAU > 0) { + error = TRANSPORTDEC_SYNC_ERROR; + } + + hTp->missingAccessUnits = nAU; + + return error; +} + +/* returns error code */ +TRANSPORTDEC_ERROR transportDec_ReadAccessUnit(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + HANDLE_FDK_BITSTREAM hBs; + + if (!hTp) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + hBs = &hTp->bitStream[layer]; + + if ((INT)FDKgetValidBits(hBs) <= 0) { + /* This is only relevant for RAW and ADIF cases. + * For streaming formats err will get overwritten. */ + err = TRANSPORTDEC_NOT_ENOUGH_BITS; + hTp->numberOfRawDataBlocks = 0; + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + /* Read header if not already done */ + if (!(hTp->flags & TPDEC_CONFIG_FOUND)) { + int i; + CProgramConfig *pce; + INT bsStart = FDKgetValidBits(hBs); + UCHAR configChanged = 0; + UCHAR configMode = AC_CM_DET_CFG_CHANGE; + + for (i = 0; i < 2; i++) { + if (i > 0) { + FDKpushBack(hBs, bsStart - FDKgetValidBits(hBs)); + configMode = AC_CM_ALLOC_MEM; + } + + AudioSpecificConfig_Init(&hTp->asc[0]); + pce = &hTp->asc[0].m_progrConfigElement; + err = adifRead_DecodeHeader(&hTp->parser.adif, pce, hBs); + if (err) goto bail; + + /* Map adif header to ASC */ + hTp->asc[0].m_aot = (AUDIO_OBJECT_TYPE)(pce->Profile + 1); + hTp->asc[0].m_samplingFrequencyIndex = pce->SamplingFrequencyIndex; + hTp->asc[0].m_samplingFrequency = + SamplingRateTable[pce->SamplingFrequencyIndex]; + hTp->asc[0].m_channelConfiguration = 0; + hTp->asc[0].m_samplesPerFrame = 1024; + hTp->avgBitRate = hTp->parser.adif.BitRate; + + /* Call callback to decoder. */ + { + int errC; + + errC = hTp->callbacks.cbUpdateConfig( + hTp->callbacks.cbUpdateConfigData, &hTp->asc[0], configMode, + &configChanged); + if (errC == 0) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } else { + err = TRANSPORTDEC_PARSE_ERROR; + goto bail; + } + } + + if (err == TRANSPORTDEC_OK) { + if ((i == 0) && configChanged) { + int errC; + errC = hTp->callbacks.cbFreeMem(hTp->callbacks.cbFreeMemData, + &hTp->asc[0]); + if (errC != 0) { + err = TRANSPORTDEC_PARSE_ERROR; + } + } + } + } + } + hTp->auLength[layer] = -1; /* Access Unit data length is unknown. */ + break; + + case TT_MP4_RAW: + case TT_DRM: + /* One Access Unit was filled into buffer. + So get the length out of the buffer. */ + hTp->auLength[layer] = FDKgetValidBits(hBs); + hTp->flags |= TPDEC_SYNCOK; + break; + + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (err == TRANSPORTDEC_OK) { + int fConfigFound = hTp->flags & TPDEC_CONFIG_FOUND; + err = transportDec_readHeader(hTp, hBs, 0, 1, &hTp->auLength[layer], + NULL, NULL, &fConfigFound, NULL); + if (fConfigFound) { + hTp->flags |= TPDEC_CONFIG_FOUND; + } + } + break; + + case TT_MP4_ADTS: + case TT_MP4_LOAS: + err = transportDec_readStream(hTp, layer); + break; + + default: + err = TRANSPORTDEC_UNSUPPORTED_FORMAT; + break; + } + + if (err == TRANSPORTDEC_OK) { + hTp->accessUnitAnchor[layer] = FDKgetValidBits(hBs); + } else { + hTp->accessUnitAnchor[layer] = 0; + } + +bail: + return err; +} + +TRANSPORTDEC_ERROR transportDec_GetAsc(const HANDLE_TRANSPORTDEC hTp, + const UINT layer, + CSAudioSpecificConfig *asc) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + if (hTp != NULL) { + *asc = hTp->asc[layer]; + err = TRANSPORTDEC_OK; + } else { + err = TRANSPORTDEC_INVALID_PARAMETER; + } + return err; +} + +INT transportDec_GetAuBitsRemaining(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + INT bits; + + if (hTp->accessUnitAnchor[layer] > 0 && hTp->auLength[layer] > 0) { + bits = (INT)FDKgetValidBits(&hTp->bitStream[layer]); + if (bits >= 0) { + bits = hTp->auLength[layer] - ((INT)hTp->accessUnitAnchor[layer] - bits); + } + } else { + bits = FDKgetValidBits(&hTp->bitStream[layer]); + } + + return bits; +} + +INT transportDec_GetAuBitsTotal(const HANDLE_TRANSPORTDEC hTp, + const UINT layer) { + return hTp->auLength[layer]; +} + +TRANSPORTDEC_ERROR transportDec_GetMissingAccessUnitCount( + INT *pNAccessUnits, HANDLE_TRANSPORTDEC hTp) { + *pNAccessUnits = hTp->missingAccessUnits; + + return TRANSPORTDEC_OK; +} + +/* Inform the transportDec layer that reading of access unit has finished. */ +TRANSPORTDEC_ERROR transportDec_EndAccessUnit(HANDLE_TRANSPORTDEC hTp) { + TRANSPORTDEC_ERROR err = TRANSPORTDEC_OK; + + switch (hTp->transportFmt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: { + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream[0]; + if (hTp->numberOfRawDataBlocks == 0) { + /* Read other data if available. */ + if (CLatmDemux_GetOtherDataPresentFlag(&hTp->parser.latm)) { + int otherDataLen = CLatmDemux_GetOtherDataLength(&hTp->parser.latm); + + if ((INT)FDKgetValidBits(hBs) >= otherDataLen) { + FDKpushFor(hBs, otherDataLen); + } else { + /* Do byte align at the end of AudioMuxElement. */ + if (hTp->numberOfRawDataBlocks == 0) { + FDKbyteAlign(hBs, hTp->globalFramePos); + } + return TRANSPORTDEC_NOT_ENOUGH_BITS; + } + } + } else { + /* If bit buffer has not more bits but hTp->numberOfRawDataBlocks > 0 + then too many bits were read and obviously no more RawDataBlocks can + be read. Set numberOfRawDataBlocks to zero to attempt a new sync + attempt. */ + if ((INT)FDKgetValidBits(hBs) <= 0) { + hTp->numberOfRawDataBlocks = 0; + } + } + } break; + default: + break; + } + + err = transportDec_AdjustEndOfAccessUnit(hTp); + + switch (hTp->transportFmt) { + default: + break; + } + + return err; +} + +TRANSPORTDEC_ERROR transportDec_SetParam(const HANDLE_TRANSPORTDEC hTp, + const TPDEC_PARAM param, + const INT value) { + TRANSPORTDEC_ERROR error = TRANSPORTDEC_OK; + + if (hTp == NULL) { + return TRANSPORTDEC_INVALID_PARAMETER; + } + + switch (param) { + case TPDEC_PARAM_MINIMIZE_DELAY: + if (value) { + hTp->flags |= TPDEC_MINIMIZE_DELAY; + } else { + hTp->flags &= ~TPDEC_MINIMIZE_DELAY; + } + break; + case TPDEC_PARAM_EARLY_CONFIG: + if (value) { + hTp->flags |= TPDEC_EARLY_CONFIG; + } else { + hTp->flags &= ~TPDEC_EARLY_CONFIG; + } + break; + case TPDEC_PARAM_IGNORE_BUFFERFULLNESS: + if (value) { + hTp->flags |= TPDEC_IGNORE_BUFFERFULLNESS; + } else { + hTp->flags &= ~TPDEC_IGNORE_BUFFERFULLNESS; + } + break; + case TPDEC_PARAM_SET_BITRATE: + hTp->avgBitRate = value; + break; + case TPDEC_PARAM_BURST_PERIOD: + hTp->burstPeriod = value; + break; + case TPDEC_PARAM_RESET: { + int i; + + for (i = 0; i < (1 * 1); i++) { + FDKresetBitbuffer(&hTp->bitStream[i]); + hTp->auLength[i] = 0; + hTp->accessUnitAnchor[i] = 0; + } + hTp->flags &= ~(TPDEC_SYNCOK | TPDEC_LOST_FRAMES_PENDING); + if (hTp->transportFmt != TT_MP4_ADIF) { + hTp->flags &= ~TPDEC_CONFIG_FOUND; + } + hTp->remainder = 0; + hTp->avgBitRate = 0; + hTp->missingAccessUnits = 0; + hTp->numberOfRawDataBlocks = 0; + hTp->globalFramePos = 0; + hTp->holdOffFrames = 0; + } break; + case TPDEC_PARAM_TARGETLAYOUT: + hTp->targetLayout = value; + break; + case TPDEC_PARAM_FORCE_CONFIG_CHANGE: + hTp->ctrlCFGChange[value].forceCfgChange = TPDEC_FORCE_CONFIG_CHANGE; + break; + case TPDEC_PARAM_USE_ELEM_SKIPPING: + if (value) { + hTp->flags |= TPDEC_USE_ELEM_SKIPPING; + } else { + hTp->flags &= ~TPDEC_USE_ELEM_SKIPPING; + } + break; + } + + return error; +} + +UINT transportDec_GetNrOfSubFrames(HANDLE_TRANSPORTDEC hTp) { + UINT nSubFrames = 0; + + if (hTp == NULL) return 0; + + if (hTp->transportFmt == TT_MP4_LATM_MCP1 || + hTp->transportFmt == TT_MP4_LATM_MCP0 || hTp->transportFmt == TT_MP4_LOAS) + nSubFrames = CLatmDemux_GetNrOfSubFrames(&hTp->parser.latm); + else if (hTp->transportFmt == TT_MP4_ADTS) + nSubFrames = hTp->parser.adts.bs.num_raw_blocks; + + return nSubFrames; +} + +void transportDec_Close(HANDLE_TRANSPORTDEC *phTp) { + if (phTp != NULL) { + if (*phTp != NULL) { + FreeRam_TransportDecoderBuffer(&(*phTp)->bsBuffer); + FreeRam_TransportDecoder(phTp); + } + } +} + +TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return TRANSPORTDEC_UNKOWN_ERROR; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return TRANSPORTDEC_UNKOWN_ERROR; + info += i; + + info->module_id = FDK_TPDEC; +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); + info->flags = 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | + CAPF_RAWPACKETS | CAPF_DRM; + + return TRANSPORTDEC_OK; /* FDKERR_NOERROR; */ +} + +int transportDec_CrcStartReg(HANDLE_TRANSPORTDEC pTp, INT mBits) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + return adtsRead_CrcStartReg(&pTp->parser.adts, &pTp->bitStream[0], mBits); + case TT_DRM: + return drmRead_CrcStartReg(&pTp->parser.drm, &pTp->bitStream[0], mBits); + default: + return -1; + } +} + +void transportDec_CrcEndReg(HANDLE_TRANSPORTDEC pTp, INT reg) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + adtsRead_CrcEndReg(&pTp->parser.adts, &pTp->bitStream[0], reg); + break; + case TT_DRM: + drmRead_CrcEndReg(&pTp->parser.drm, &pTp->bitStream[0], reg); + break; + default: + break; + } +} + +TRANSPORTDEC_ERROR transportDec_CrcCheck(HANDLE_TRANSPORTDEC pTp) { + switch (pTp->transportFmt) { + case TT_MP4_ADTS: + if ((pTp->parser.adts.bs.num_raw_blocks > 0) && + (pTp->parser.adts.bs.protection_absent == 0)) { + transportDec_AdjustEndOfAccessUnit(pTp); + } + return adtsRead_CrcCheck(&pTp->parser.adts); + case TT_DRM: + return drmRead_CrcCheck(&pTp->parser.drm); + default: + return TRANSPORTDEC_OK; + } +} + +TRANSPORTDEC_ERROR transportDec_DrmRawSdcAudioConfig_Check(UCHAR *conf, + const UINT length) { + CSAudioSpecificConfig asc; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + FDKinitBitStream(hBs, conf, BUFSIZE_DUMMY_VALUE, length << 3, BS_READER); + + TRANSPORTDEC_ERROR err = + DrmRawSdcAudioConfig_Parse(&asc, hBs, NULL, (UCHAR)AC_CM_ALLOC_MEM, 0); + + return err; +} diff --git a/fdk-aac/libMpegTPEnc/include/tp_data.h b/fdk-aac/libMpegTPEnc/include/tp_data.h new file mode 100644 index 0000000..00de356 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/include/tp_data.h @@ -0,0 +1,466 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport data tables + +*******************************************************************************/ + +#ifndef TP_DATA_H +#define TP_DATA_H + +#include "machine_type.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/* + * Configuration + */ + +#define TP_USAC_MAX_SPEAKERS (24) + +#define TP_USAC_MAX_EXT_ELEMENTS ((24)) + +#define TP_USAC_MAX_ELEMENTS ((24) + TP_USAC_MAX_EXT_ELEMENTS) + +#define TP_USAC_MAX_CONFIG_LEN \ + 512 /* next power of two of maximum of escapedValue(hBs, 4, 4, 8) in \ + AudioPreRoll() (285) */ + +#define TPDEC_USAC_NUM_CONFIG_CHANGE_FRAMES \ + (1) /* Number of frames for config change in USAC */ + +enum { + TPDEC_FLUSH_OFF = 0, + TPDEC_RSV60_CFG_CHANGE_ATSC_FLUSH_ON = 1, + TPDEC_RSV60_DASH_IPF_ATSC_FLUSH_ON = 2, + TPDEC_USAC_DASH_IPF_FLUSH_ON = 3 +}; + +enum { + TPDEC_BUILD_UP_OFF = 0, + TPDEC_RSV60_BUILD_UP_ON = 1, + TPDEC_RSV60_BUILD_UP_ON_IN_BAND = 2, + TPDEC_USAC_BUILD_UP_ON = 3, + TPDEC_RSV60_BUILD_UP_IDLE = 4, + TPDEC_RSV60_BUILD_UP_IDLE_IN_BAND = 5 +}; + +/** + * ProgramConfig struct. + */ +/* ISO/IEC 14496-3 4.4.1.1 Table 4.2 Program config element */ +#define PC_FSB_CHANNELS_MAX 16 /* Front/Side/Back channels */ +#define PC_LFE_CHANNELS_MAX 4 +#define PC_ASSOCDATA_MAX 8 +#define PC_CCEL_MAX 16 /* CC elements */ +#define PC_COMMENTLENGTH 256 +#define PC_NUM_HEIGHT_LAYER 3 + +typedef struct { + /* PCE bitstream elements: */ + UCHAR ElementInstanceTag; + UCHAR Profile; + UCHAR SamplingFrequencyIndex; + UCHAR NumFrontChannelElements; + UCHAR NumSideChannelElements; + UCHAR NumBackChannelElements; + UCHAR NumLfeChannelElements; + UCHAR NumAssocDataElements; + UCHAR NumValidCcElements; + + UCHAR MonoMixdownPresent; + UCHAR MonoMixdownElementNumber; + + UCHAR StereoMixdownPresent; + UCHAR StereoMixdownElementNumber; + + UCHAR MatrixMixdownIndexPresent; + UCHAR MatrixMixdownIndex; + UCHAR PseudoSurroundEnable; + + UCHAR FrontElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR FrontElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR SideElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR SideElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR BackElementIsCpe[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementTagSelect[PC_FSB_CHANNELS_MAX]; + UCHAR BackElementHeightInfo[PC_FSB_CHANNELS_MAX]; + + UCHAR LfeElementTagSelect[PC_LFE_CHANNELS_MAX]; + + UCHAR AssocDataElementTagSelect[PC_ASSOCDATA_MAX]; + + UCHAR CcElementIsIndSw[PC_CCEL_MAX]; + UCHAR ValidCcElementTagSelect[PC_CCEL_MAX]; + + UCHAR CommentFieldBytes; + UCHAR Comment[PC_COMMENTLENGTH]; + + /* Helper variables for administration: */ + UCHAR isValid; /*!< Flag showing if PCE has been read successfully. */ + UCHAR + NumChannels; /*!< Amount of audio channels summing all channel elements + including LFEs */ + UCHAR NumEffectiveChannels; /*!< Amount of audio channels summing only SCEs + and CPEs */ + UCHAR elCounter; + +} CProgramConfig; + +typedef enum { + ASCEXT_UNKOWN = -1, + ASCEXT_SBR = 0x2b7, + ASCEXT_PS = 0x548, + ASCEXT_MPS = 0x76a, + ASCEXT_SAOC = 0x7cb, + ASCEXT_LDMPS = 0x7cc + +} TP_ASC_EXTENSION_ID; + +/** + * GaSpecificConfig struct + */ +typedef struct { + UINT m_frameLengthFlag; + UINT m_dependsOnCoreCoder; + UINT m_coreCoderDelay; + + UINT m_extensionFlag; + UINT m_extensionFlag3; + + UINT m_layer; + UINT m_numOfSubFrame; + UINT m_layerLength; + +} CSGaSpecificConfig; + +typedef enum { + ELDEXT_TERM = 0x0, /* Termination tag */ + ELDEXT_SAOC = 0x1, /* SAOC config */ + ELDEXT_LDSAC = 0x2, /* LD MPEG Surround config */ + ELDEXT_DOWNSCALEINFO = 0x3 /* ELD sample rate adaptation */ + /* reserved */ +} ASC_ELD_EXT_TYPE; + +typedef struct { + UCHAR m_frameLengthFlag; + + UCHAR m_sbrPresentFlag; + UCHAR + m_useLdQmfTimeAlign; /* Use LD-MPS QMF in SBR to achive time alignment */ + UCHAR m_sbrSamplingRate; + UCHAR m_sbrCrcFlag; + UINT m_downscaledSamplingFrequency; + +} CSEldSpecificConfig; + +typedef struct { + USAC_EXT_ELEMENT_TYPE usacExtElementType; + USHORT usacExtElementConfigLength; + USHORT usacExtElementDefaultLength; + UCHAR usacExtElementPayloadFrag; + UCHAR usacExtElementHasAudioPreRoll; +} CSUsacExtElementConfig; + +typedef struct { + MP4_ELEMENT_ID usacElementType; + UCHAR m_noiseFilling; + UCHAR m_harmonicSBR; + UCHAR m_interTes; + UCHAR m_pvc; + UCHAR m_stereoConfigIndex; + CSUsacExtElementConfig extElement; +} CSUsacElementConfig; + +typedef struct { + UCHAR m_frameLengthFlag; + UCHAR m_coreSbrFrameLengthIndex; + UCHAR m_sbrRatioIndex; + UCHAR m_nUsacChannels; /* number of audio channels signaled in + UsacDecoderConfig() / rsv603daDecoderConfig() via + numElements and usacElementType */ + UCHAR m_channelConfigurationIndex; + UINT m_usacNumElements; + CSUsacElementConfig element[TP_USAC_MAX_ELEMENTS]; + + UCHAR numAudioChannels; + UCHAR m_usacConfigExtensionPresent; + UCHAR elementLengthPresent; + UCHAR UsacConfig[TP_USAC_MAX_CONFIG_LEN]; + USHORT UsacConfigBits; +} CSUsacConfig; + +/** + * Audio configuration struct, suitable for encoder and decoder configuration. + */ +typedef struct { + /* XYZ Specific Data */ + union { + CSGaSpecificConfig + m_gaSpecificConfig; /**< General audio specific configuration. */ + CSEldSpecificConfig m_eldSpecificConfig; /**< ELD specific configuration. */ + CSUsacConfig m_usacConfig; /**< USAC specific configuration */ + } m_sc; + + /* Common ASC parameters */ + CProgramConfig m_progrConfigElement; /**< Program configuration. */ + + AUDIO_OBJECT_TYPE m_aot; /**< Audio Object Type. */ + UINT m_samplingFrequency; /**< Samplerate. */ + UINT m_samplesPerFrame; /**< Amount of samples per frame. */ + UINT m_directMapping; /**< Document this please !! */ + + AUDIO_OBJECT_TYPE m_extensionAudioObjectType; /**< Audio object type */ + UINT m_extensionSamplingFrequency; /**< Samplerate */ + + SCHAR m_channelConfiguration; /**< Channel configuration index */ + + SCHAR m_epConfig; /**< Error protection index */ + SCHAR m_vcb11Flag; /**< aacSectionDataResilienceFlag */ + SCHAR m_rvlcFlag; /**< aacScalefactorDataResilienceFlag */ + SCHAR m_hcrFlag; /**< aacSpectralDataResilienceFlag */ + + SCHAR m_sbrPresentFlag; /**< Flag indicating the presence of SBR data in the + bitstream */ + SCHAR + m_psPresentFlag; /**< Flag indicating the presence of parametric stereo + data in the bitstream */ + UCHAR m_samplingFrequencyIndex; /**< Samplerate index */ + UCHAR m_extensionSamplingFrequencyIndex; /**< Samplerate index */ + SCHAR m_extensionChannelConfiguration; /**< Channel configuration index */ + + UCHAR + configMode; /**< The flag indicates if the callback shall work in memory + allocation mode or in config change detection mode */ + UCHAR AacConfigChanged; /**< The flag will be set if at least one aac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SbrConfigChanged; /**< The flag will be set if at least one sbr config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + UCHAR SacConfigChanged; /**< The flag will be set if at least one sac config + parameter has changed that requires a memory + reconfiguration, otherwise it will be cleared */ + + UCHAR + config[TP_USAC_MAX_CONFIG_LEN]; /**< Configuration stored as bitstream */ + UINT configBits; /**< Configuration length in bits */ + +} CSAudioSpecificConfig; + +typedef struct { + SCHAR flushCnt; /**< Flush frame counter */ + UCHAR flushStatus; /**< Flag indicates flush mode: on|off */ + SCHAR buildUpCnt; /**< Build up frame counter */ + UCHAR buildUpStatus; /**< Flag indicates build up mode: on|off */ + UCHAR cfgChanged; /**< Flag indicates that the config changed and the decoder + needs to be initialized again via callback. Make sure + that memory is freed before initialization. */ + UCHAR contentChanged; /**< Flag indicates that the content changed i.e. a + right truncation occured before */ + UCHAR forceCfgChange; /**< Flag indicates if config change has to be forced + even if new config is the same */ +} CCtrlCFGChange; + +typedef INT (*cbUpdateConfig_t)(void *, const CSAudioSpecificConfig *, + const UCHAR configMode, UCHAR *configChanged); +typedef INT (*cbFreeMem_t)(void *, const CSAudioSpecificConfig *); +typedef INT (*cbCtrlCFGChange_t)(void *, const CCtrlCFGChange *); +typedef INT (*cbSsc_t)(void *, HANDLE_FDK_BITSTREAM, + const AUDIO_OBJECT_TYPE coreCodec, + const INT samplingRate, const INT frameSize, + const INT stereoConfigIndex, + const INT coreSbrFrameLengthIndex, const INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +typedef INT (*cbSbr_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSbr, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +typedef INT (*cbUsac_t)(void *self, HANDLE_FDK_BITSTREAM hBs); + +typedef INT (*cbUniDrc_t)(void *self, HANDLE_FDK_BITSTREAM hBs, + const INT fullPayloadLength, const INT payloadType, + const INT subStreamIndex, const INT payloadStart, + const AUDIO_OBJECT_TYPE); + +typedef struct { + cbUpdateConfig_t cbUpdateConfig; /*!< Function pointer for Config change + notify callback. */ + void *cbUpdateConfigData; /*!< User data pointer for Config change notify + callback. */ + cbFreeMem_t cbFreeMem; /*!< Function pointer for free memory callback. */ + void *cbFreeMemData; /*!< User data pointer for free memory callback. */ + cbCtrlCFGChange_t cbCtrlCFGChange; /*!< Function pointer for config change + control callback. */ + void *cbCtrlCFGChangeData; /*!< User data pointer for config change control + callback. */ + cbSsc_t cbSsc; /*!< Function pointer for SSC parser callback. */ + void *cbSscData; /*!< User data pointer for SSC parser callback. */ + cbSbr_t cbSbr; /*!< Function pointer for SBR header parser callback. */ + void *cbSbrData; /*!< User data pointer for SBR header parser callback. */ + cbUsac_t cbUsac; + void *cbUsacData; + cbUniDrc_t cbUniDrc; /*!< Function pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ + void *cbUniDrcData; /*!< User data pointer for uniDrcConfig and + loudnessInfoSet parser callback. */ +} CSTpCallBacks; + +static const UINT SamplingRateTable[] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, + 8000, 7350, 0, 0, 57600, 51200, 40000, 38400, 34150, 28800, 25600, + 20000, 19200, 17075, 14400, 12800, 9600, 0, 0, 0, 0}; + +static inline int getSamplingRateIndex(UINT samplingRate, UINT nBits) { + UINT sf_index; + UINT tableSize = (1 << nBits) - 1; + + for (sf_index = 0; sf_index < tableSize; sf_index++) { + if (SamplingRateTable[sf_index] == samplingRate) break; + } + + if (sf_index > tableSize) { + return tableSize - 1; + } + + return sf_index; +} + +/* + * Get Channel count from channel configuration + */ +static inline int getNumberOfTotalChannels(int channelConfig) { + switch (channelConfig) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + return channelConfig; + case 7: + case 12: + case 14: + return 8; + case 11: + return 7; + case 13: + return 24; + default: + return 0; + } +} + +static inline int getNumberOfEffectiveChannels( + const int + channelConfig) { /* index: 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 */ + const int n[] = {0, 1, 2, 3, 4, 5, 5, 7, 0, 0, 0, 6, 7, 22, 7, 0}; + return n[channelConfig]; +} + +#endif /* TP_DATA_H */ diff --git a/fdk-aac/libMpegTPEnc/include/tpenc_lib.h b/fdk-aac/libMpegTPEnc/include/tpenc_lib.h new file mode 100644 index 0000000..4eb89a7 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/include/tpenc_lib.h @@ -0,0 +1,339 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport encode + +*******************************************************************************/ + +#ifndef TPENC_LIB_H +#define TPENC_LIB_H + +#include "tp_data.h" +#include "FDK_bitstream.h" + +#define TRANSPORTENC_INBUF_SIZE 8192 + +typedef enum { + TRANSPORTENC_OK = 0, /*!< All fine. */ + TRANSPORTENC_NO_MEM, /*!< Out of memory. */ + TRANSPORTENC_UNKOWN_ERROR = 1, /*!< Unknown error (embarrasing). */ + TRANSPORTENC_INVALID_PARAMETER, /*!< An invalid parameter was passed to a + function . */ + TRANSPORTENC_UNSUPPORTED_FORMAT, /*!< Unsupported transport format. */ + TRANSPORTENC_NOT_ENOUGH_BITS, /*!< Out of bits. Provide more bits and try + again. */ + + TRANSPORTENC_INVALID_CONFIG, /*!< Error in configuration. */ + TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES, /*!< LATM: number of subframes out + of range. */ + TRANSPORTENC_LOAS_NOT_AVAILABLE, /*!< LOAS format not supported. */ + TRANSPORTENC_INVALID_LATM_ALIGNMENT, /*!< AudioMuxElement length not aligned + to 1 byte. */ + + TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH, /*!< Invalid transmission + frame length (< 0). */ + TRANSPORTENC_INVALID_CELP_FRAME_LENGTH, /*!< Invalid CELP frame length found + (>= 62). */ + TRANSPORTENC_INVALID_FRAME_BITS, /*!< Frame bits is not 40 and not 80. */ + TRANSPORTENC_INVALID_AOT, /*!< Unknown AOT found. */ + TRANSPORTENC_INVALID_AU_LENGTH /*!< Invalid Access Unit length (not + byte-aligned). */ + +} TRANSPORTENC_ERROR; + +typedef struct TRANSPORTENC *HANDLE_TRANSPORTENC; + +/** + * \brief Determine a reasonable channel configuration on the basis + * of channel_mode. + * \param noChannels Number of audio channels. + * \return CHANNEL_MODE value that matches the given amount of audio + * channels. + */ +CHANNEL_MODE transportEnc_GetChannelMode(int noChannels); + +/** + * \brief Register SBR heaqder writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SBR header + * writing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSbrCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSbr_t cbSbr, void *user_data); + +/** + * \brief Register USAC SC writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle USAC + * SCwriting. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterUsacCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbUsac_t cbUsac, void *user_data); + +/** + * \brief Register SSC writer callback. + * \param hTp Handle of transport decoder. + * \param cbUpdateConfig Pointer to a callback function to handle SSC writing. + * \param user_data void pointer for user data passed to the callback as + * first parameter. + * \return 0 on success. + */ +int transportEnc_RegisterSscCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSsc_t cbSsc, void *user_data); + +/** + * \brief Write ASC from given parameters. + * \param asc A HANDLE_FDK_BITSTREAM where the ASC is written to. + * \param config Structure containing the codec configuration settings. + * \param cb callback information structure. + * \return 0 on success. + */ +int transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, + CSTpCallBacks *cb); + +/* Defintion of flags that can be passed to transportEnc_Open() */ +#define TP_FLAG_MPEG4 1 /** MPEG4 (instead of MPEG2) */ +#define TP_FLAG_LATM_AMV 2 /** LATM AudioMuxVersion */ +#define TP_FLAG_LATM_AMVA 4 /** LATM AudioMuxVersionA */ + +/** + * \brief Allocate transport encoder. + * \param phTpEnc Pointer to transport encoder handle. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Open(HANDLE_TRANSPORTENC *phTpEnc); + +/** + * \brief Init transport encoder. + * \param bsBuffer Pointer to transport encoder. + * \param bsBuffer Pointer to bitstream buffer. + * \param bsBufferSize Size in bytes of bsBuffer. + * \param transportFmt Format of the transport to be written. + * \param config Pointer to a valid CODER_CONFIG struct. + * \param flags Transport encoder flags. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *config, UINT flags); + +/** + * \brief Write additional bits in transport encoder. + * \param config Pointer to a valid CODER_CONFIG struct. + * \param nBits Number of additional bits. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_AddOtherDataBits(HANDLE_TRANSPORTENC hTpEnc, + const int nBits); + +/** + * \brief Get transport encoder bitstream. + * \param hTp Pointer to a transport encoder handle. + * \return The handle to the requested FDK bitstream. + */ +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream(HANDLE_TRANSPORTENC hTp); + +/** + * \brief Get amount of bits required by the transport headers. + * \param hTp Handle of transport encoder. + * \param auBits Amount of payload bits required for the current subframe. + * \return Error code. + */ +INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits); + +/** + * \brief Close transport encoder. This function assures that all + * allocated memory is freed. + * \param phTp Pointer to a previously allocated transport encoder handle. + */ +void transportEnc_Close(HANDLE_TRANSPORTENC *phTp); + +/** + * \brief Write one access unit. + * \param hTp Handle of transport encoder. + * \param total_bits Amount of total access unit bits. + * \param bufferFullness Value of current buffer fullness in bits. + * \param noConsideredChannels Number of bitrate wise considered channels (all + * minus LFE channels). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp, + INT total_bits, + int bufferFullness, + int noConsideredChannels); + +/** + * \brief Inform the transportEnc layer that writing of access unit has + * finished. This function is required to be called when the encoder has + * finished writing one Access one Access Unit for bitstream + * housekeeping. + * \param hTp Transport handle. + * \param pBits Pointer to an int, where the current amount of frame bits is + * passed and where the current amount of subframe bits is returned. + * + * OR: This integer is modified by the amount of extra bit alignment that may + * occurr. + * + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, + int *pBits); + +/* + * \brief Get a payload frame. + * \param hTpEnc Transport encoder handle. + * \param nBytes Pointer to an int to hold the frame size in bytes. Returns + * zero if currently there is no complete frame for output (number of sub frames + * > 1). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, + int *nbytes); + +/* ADTS CRC support */ + +/** + * \brief Set current bitstream position as start of a new data region. + * \param hTpEnc Transport encoder handle. + * \param mBits Size in bits of the data region. Set to 0 if it should not be + * of a fixed size. + * \return Data region ID, which should be used when calling + * transportEnc_CrcEndReg(). + */ +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits); + +/** + * \brief Set end of data region. + * \param hTpEnc Transport encoder handle. + * \param reg Data region ID, opbtained from transportEnc_CrcStartReg(). + * \return void + */ +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg); + +/** + * \brief Get AudioSpecificConfig or StreamMuxConfig from transport + * encoder handle and write it to dataBuffer. + * \param hTpEnc Transport encoder handle. + * \param cc Pointer to the current and valid configuration contained + * in a CODER_CONFIG struct. + * \param dataBuffer Bitbuffer holding binary configuration. + * \param confType Pointer to an UINT where the configuration type is + * returned (0:ASC, 1:SMC). + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType); + +/** + * \brief Get information (version among other things) of the transport + * encoder library. + * \param info Pointer to an allocated LIB_INFO struct. + * \return Error code. + */ +TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info); + +#endif /* #ifndef TPENC_LIB_H */ diff --git a/fdk-aac/libMpegTPEnc/src/tp_version.h b/fdk-aac/libMpegTPEnc/src/tp_version.h new file mode 100644 index 0000000..9f1aa22 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tp_version.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(TP_VERSION_H) +#define TP_VERSION_H + +/* library info */ +#define TP_LIB_VL0 3 +#define TP_LIB_VL1 0 +#define TP_LIB_VL2 0 +#define TP_LIB_TITLE "MPEG Transport" +#ifdef __ANDROID__ +#define TP_LIB_BUILD_DATE "" +#define TP_LIB_BUILD_TIME "" +#else +#define TP_LIB_BUILD_DATE __DATE__ +#define TP_LIB_BUILD_TIME __TIME__ +#endif +#endif /* !defined(TP_VERSION_H) */ diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_adif.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_adif.cpp new file mode 100644 index 0000000..b281eff --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_adif.cpp @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: ADIF Transport Headers writing + +*******************************************************************************/ + +#include "tpenc_adif.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +int adifWrite_EncodeHeader(ADIF_INFO *adif, HANDLE_FDK_BITSTREAM hBs, + INT adif_buffer_fullness) { + /* ADIF/PCE/ADTS definitions */ + const char adifId[5] = "ADIF"; + const int copyRightIdPresent = 0; + const int originalCopy = 0; + const int home = 0; + int err = 0; + + int i; + + INT totalBitRate = adif->bitRate; + + if (adif->headerWritten) return 0; + + /* Align inside PCE with respect to the first bit of the header */ + UINT alignAnchor = FDKgetValidBits(hBs); + + /* Signal variable bitrate if buffer fullnes exceeds 20 bit */ + adif->bVariableRate = (adif_buffer_fullness >= (INT)(0x1 << 20)) ? 1 : 0; + + FDKwriteBits(hBs, adifId[0], 8); + FDKwriteBits(hBs, adifId[1], 8); + FDKwriteBits(hBs, adifId[2], 8); + FDKwriteBits(hBs, adifId[3], 8); + + FDKwriteBits(hBs, copyRightIdPresent ? 1 : 0, 1); + + if (copyRightIdPresent) { + for (i = 0; i < 72; i++) { + FDKwriteBits(hBs, 0, 1); + } + } + FDKwriteBits(hBs, originalCopy ? 1 : 0, 1); + FDKwriteBits(hBs, home ? 1 : 0, 1); + FDKwriteBits(hBs, adif->bVariableRate ? 1 : 0, 1); + FDKwriteBits(hBs, totalBitRate, 23); + + /* we write only one PCE at the moment */ + FDKwriteBits(hBs, 0, 4); + + if (!adif->bVariableRate) { + FDKwriteBits(hBs, adif_buffer_fullness, 20); + } + /* Write PCE */ + transportEnc_writePCE(hBs, adif->cm, adif->samplingRate, adif->instanceTag, + adif->profile, adif->matrixMixdownA, + (adif->pseudoSurroundEnable) ? 1 : 0, alignAnchor); + + return err; +} + +int adifWrite_GetHeaderBits(ADIF_INFO *adif) { + /* ADIF definitions */ + const int copyRightIdPresent = 0; + + if (adif->headerWritten) return 0; + + int bits = 0; + + bits += 8 * 4; /* ADIF ID */ + + bits += 1; /* Copyright present */ + + if (copyRightIdPresent) bits += 72; /* Copyright ID */ + + bits += 26; + + bits += 4; /* Number of PCE's */ + + if (!adif->bVariableRate) { + bits += 20; + } + + /* write PCE */ + bits = transportEnc_GetPCEBits(adif->cm, adif->matrixMixdownA, bits); + + return bits; +} diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_adif.h b/fdk-aac/libMpegTPEnc/src/tpenc_adif.h new file mode 100644 index 0000000..e001afc --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_adif.h @@ -0,0 +1,146 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Goeschel + + Description: Transport Headers support + +*******************************************************************************/ + +#ifndef TPENC_ADIF_H +#define TPENC_ADIF_H + +#include "machine_type.h" +#include "FDK_bitstream.h" + +#include "tp_data.h" + +typedef struct { + CHANNEL_MODE cm; + INT samplingRate; + INT bitRate; + int profile; + int bVariableRate; + int instanceTag; + int headerWritten; + int matrixMixdownA; + int pseudoSurroundEnable; + +} ADIF_INFO; + +/** + * \brief encodes ADIF Header + * + * \param adif pointer to ADIF_INFO structure + * \param hBitStream handle of bitstream, where the ADIF header is written into + * \param adif_buffer_fullness buffer fullness value for the ADIF header + * + * \return 0 on success + */ +int adifWrite_EncodeHeader(ADIF_INFO *adif, HANDLE_FDK_BITSTREAM hBitStream, + INT adif_buffer_fullness); + +/** + * \brief Get bit demand of a ADIF header + * + * \param adif pointer to ADIF_INFO structure + * + * \return amount of bits required to write the ADIF header according to the + * data contained in the adif parameter + */ +int adifWrite_GetHeaderBits(ADIF_INFO *adif); + +#endif /* TPENC_ADIF_H */ diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_adts.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_adts.cpp new file mode 100644 index 0000000..3f7e62c --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_adts.cpp @@ -0,0 +1,319 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Groeschel + + Description: ADTS Transport Headers support + +*******************************************************************************/ + +#include "tpenc_adts.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +int adtsWrite_CrcStartReg( + HANDLE_ADTS pAdts, /*!< pointer to adts stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ +) { + if (pAdts->protection_absent) { + return 0; + } + return (FDKcrcStartReg(&pAdts->crcInfo, hBs, mBits)); +} + +void adtsWrite_CrcEndReg( + HANDLE_ADTS pAdts, /*!< pointer to adts crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ +) { + if (pAdts->protection_absent == 0) { + FDKcrcEndReg(&pAdts->crcInfo, hBs, reg); + } +} + +int adtsWrite_GetHeaderBits(HANDLE_ADTS hAdts) { + int bits = 0; + + if (hAdts->currentBlock == 0) { + /* Static and variable header bits */ + bits = 56; + if (!hAdts->protection_absent) { + /* Add header/ single raw data block CRC bits */ + bits += 16; + if (hAdts->num_raw_blocks > 0) { + /* Add bits of raw data block position markers */ + bits += (hAdts->num_raw_blocks) * 16; + } + } + } + if (!hAdts->protection_absent && hAdts->num_raw_blocks > 0) { + /* Add raw data block CRC bits. Not really part of the header, put they + * cause bit overhead to be accounted. */ + bits += 16; + } + + hAdts->headerBits = bits; + + return bits; +} + +INT adtsWrite_Init(HANDLE_ADTS hAdts, CODER_CONFIG *config) { + /* Sanity checks */ + if (config->nSubFrames < 1 || config->nSubFrames > 4 || + (int)config->aot > 4 || (int)config->aot < 1) { + return -1; + } + + /* fixed header */ + if (config->flags & CC_MPEG_ID) { + hAdts->mpeg_id = 0; /* MPEG 4 */ + } else { + hAdts->mpeg_id = 1; /* MPEG 2 */ + } + hAdts->layer = 0; + hAdts->protection_absent = !(config->flags & CC_PROTECTION); + hAdts->profile = ((int)config->aot) - 1; + hAdts->sample_freq_index = getSamplingRateIndex(config->samplingRate, 4); + hAdts->sample_freq = config->samplingRate; + hAdts->private_bit = 0; + hAdts->channel_mode = config->channelMode; + hAdts->original = 0; + hAdts->home = 0; + /* variable header */ + hAdts->copyright_id = 0; + hAdts->copyright_start = 0; + + hAdts->num_raw_blocks = config->nSubFrames - 1; /* 0 means 1 raw data block */ + + hAdts->channel_config_zero = config->channelConfigZero; + + FDKcrcInit(&hAdts->crcInfo, 0x8005, 0xFFFF, 16); + + hAdts->currentBlock = 0; + + return 0; +} + +int adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, int frame_length) { + INT crcIndex = 0; + + hAdts->headerBits = adtsWrite_GetHeaderBits(hAdts); + + FDK_ASSERT(((frame_length + hAdts->headerBits) / 8) < 0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness < 0x800); /* 11 bit */ + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + } + + if (hAdts->currentBlock == 0) { + FDKresetBitbuffer(hBitStream, BS_WRITER); + } + + hAdts->subFrameStartBit = FDKgetValidBits(hBitStream); + + /* Skip new header if this is raw data block 1..n */ + if (hAdts->currentBlock == 0) { + FDKresetBitbuffer(hBitStream, BS_WRITER); + + if (hAdts->num_raw_blocks == 0) { + crcIndex = adtsWrite_CrcStartReg(hAdts, hBitStream, 0); + } + + /* fixed header */ + FDKwriteBits(hBitStream, 0xFFF, 12); + FDKwriteBits(hBitStream, hAdts->mpeg_id, 1); + FDKwriteBits(hBitStream, hAdts->layer, 2); + FDKwriteBits(hBitStream, hAdts->protection_absent, 1); + FDKwriteBits(hBitStream, hAdts->profile, 2); + FDKwriteBits(hBitStream, hAdts->sample_freq_index, 4); + FDKwriteBits(hBitStream, hAdts->private_bit, 1); + FDKwriteBits( + hBitStream, + getChannelConfig(hAdts->channel_mode, hAdts->channel_config_zero), 3); + FDKwriteBits(hBitStream, hAdts->original, 1); + FDKwriteBits(hBitStream, hAdts->home, 1); + /* variable header */ + FDKwriteBits(hBitStream, hAdts->copyright_id, 1); + FDKwriteBits(hBitStream, hAdts->copyright_start, 1); + FDKwriteBits(hBitStream, (frame_length + hAdts->headerBits) >> 3, 13); + FDKwriteBits(hBitStream, buffer_fullness, 11); + FDKwriteBits(hBitStream, hAdts->num_raw_blocks, 2); + + if (!hAdts->protection_absent) { + int i; + + /* End header CRC portion for single raw data block and write dummy zero + * values for unknown fields. */ + if (hAdts->num_raw_blocks == 0) { + adtsWrite_CrcEndReg(hAdts, hBitStream, crcIndex); + } else { + for (i = 0; i < hAdts->num_raw_blocks; i++) { + FDKwriteBits(hBitStream, 0, 16); + } + } + FDKwriteBits(hBitStream, 0, 16); + } + } /* End of ADTS header */ + + return 0; +} + +void adtsWrite_EndRawDataBlock(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBs, + int *pBits) { + if (!hAdts->protection_absent) { + FDK_BITSTREAM bsWriter; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + FDKpushFor(&bsWriter, 56); + + if (hAdts->num_raw_blocks == 0) { + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } else { + int distance; + + /* Write CRC of current raw data block */ + FDKwriteBits(hBs, FDKcrcGetCRC(&hAdts->crcInfo), 16); + + /* Write distance to current data block */ + if (hAdts->currentBlock < hAdts->num_raw_blocks) { + FDKpushFor(&bsWriter, hAdts->currentBlock * 16); + distance = + FDKgetValidBits(hBs) - (56 + (hAdts->num_raw_blocks) * 16 + 16); + FDKwriteBits(&bsWriter, distance >> 3, 16); + } + } + FDKsyncCache(&bsWriter); + } + + /* Write total frame lenth for multiple raw data blocks and header CRC */ + if (hAdts->num_raw_blocks > 0 && + hAdts->currentBlock == hAdts->num_raw_blocks) { + FDK_BITSTREAM bsWriter; + int crcIndex = 0; + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + + if (!hAdts->protection_absent) { + FDKcrcReset(&hAdts->crcInfo); + crcIndex = FDKcrcStartReg(&hAdts->crcInfo, &bsWriter, 0); + } + /* Write total frame length */ + FDKpushFor(&bsWriter, 56 - 28 + 2); + FDKwriteBits(&bsWriter, FDKgetValidBits(hBs) >> 3, 13); + + /* Write header CRC */ + if (!hAdts->protection_absent) { + FDKpushFor(&bsWriter, 11 + 2 + (hAdts->num_raw_blocks) * 16); + FDKcrcEndReg(&hAdts->crcInfo, &bsWriter, crcIndex); + FDKwriteBits(&bsWriter, FDKcrcGetCRC(&hAdts->crcInfo), 16); + } + FDKsyncCache(&bsWriter); + } + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hAdts->subFrameStartBit; + if (!hAdts->protection_absent && hAdts->num_raw_blocks > 0) { + /* Fixup CRC bits, since they come after each raw data block */ + *pBits += 16; + } + hAdts->currentBlock++; +} diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_adts.h b/fdk-aac/libMpegTPEnc/src/tpenc_adts.h new file mode 100644 index 0000000..fe86306 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_adts.h @@ -0,0 +1,208 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Alex Groeschel + + Description: ADTS Transport writer + +*******************************************************************************/ + +#ifndef TPENC_ADTS_H +#define TPENC_ADTS_H + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + INT sample_freq; + CHANNEL_MODE channel_mode; + UCHAR decoderCanDoMpeg4; + UCHAR mpeg_id; + UCHAR layer; + UCHAR protection_absent; + UCHAR profile; + UCHAR sample_freq_index; + UCHAR private_bit; + UCHAR original; + UCHAR home; + UCHAR copyright_id; + UCHAR copyright_start; + USHORT frame_length; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + UCHAR channel_config_zero; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block + begins */ + FDK_CRCINFO crcInfo; +} STRUCT_ADTS; + +typedef STRUCT_ADTS *HANDLE_ADTS; + +/** + * \brief Initialize ADTS data structure + * + * \param hAdts ADTS data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the ADTS header is extrated from + * + * \return 0 in case of success. + */ +INT adtsWrite_Init(HANDLE_ADTS hAdts, CODER_CONFIG *config); + +/** + * \brief Get the total bit overhead caused by ADTS + * + * \hAdts handle to ADTS data + * + * \return Amount of additional bits required for the current raw data block + */ +int adtsWrite_GetHeaderBits(HANDLE_ADTS hAdts); + +/** + * \brief Write an ADTS header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hAdts ADTS data handle + * \param hBitStream bitstream handle into which the ADTS may be written into + * \param buffer_fullness the buffer fullness value for the ADTS header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT adtsWrite_EncodeHeader(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, int frame_length); +/** + * \brief Finish a ADTS raw data block + * + * \param hAdts ADTS data handle + * \param hBs bitstream handle into which the ADTS may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit + * count, which is corrected to the current raw data block boundary. + * + */ +void adtsWrite_EndRawDataBlock(HANDLE_ADTS hAdts, HANDLE_FDK_BITSTREAM hBs, + int *bits); + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if + * there are less than mBits bits available. If mBits is negative no zero + * padding is done. If mBits is zero the memory for the buffer is + * allocated dynamically, the number of bits is not limited. + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC + * region + * + * \return ID for the created region, -1 in case of an error + */ +int adtsWrite_CrcStartReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, + int mBits); + +/** + * \brief Ends CRC region identified by reg + * + * \param pAdts ADTS data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by adtsWrite_CrcStartReg() + */ +void adtsWrite_CrcEndReg(HANDLE_ADTS pAdts, HANDLE_FDK_BITSTREAM hBs, int reg); + +#endif /* TPENC_ADTS_H */ diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_asc.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_asc.cpp new file mode 100644 index 0000000..0b484a0 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_asc.cpp @@ -0,0 +1,996 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#include "tp_data.h" + +#include "tpenc_lib.h" +#include "tpenc_asc.h" +#include "FDK_bitstream.h" +#include "genericStds.h" + +#include "FDK_crc.h" + +#define PCE_HEIGHT_EXT_SYNC (0xAC) +#define HEIGHT_NORMAL 0 +#define HEIGHT_TOP 1 +#define HEIGHT_BOTTOM 2 +#define MAX_FRONT_ELEMENTS 8 +#define MAX_SIDE_ELEMENTS 3 +#define MAX_BACK_ELEMENTS 4 + +/** + * Describe additional PCE height information for front, side and back channel + * elements. + */ +typedef struct { + UCHAR + num_front_height_channel_elements[2]; /*!< Number of front channel + elements in top [0] and bottom + [1] plane. */ + UCHAR num_side_height_channel_elements[2]; /*!< Number of side channel + elements in top [0] and bottom + [1] plane. */ + UCHAR num_back_height_channel_elements[2]; /*!< Number of back channel + elements in top [0] and bottom + [1] plane. */ +} PCE_HEIGHT_NUM; + +/** + * Describe a PCE based on placed channel elements and element type sequence. + */ +typedef struct { + UCHAR num_front_channel_elements; /*!< Number of front channel elements. */ + UCHAR num_side_channel_elements; /*!< Number of side channel elements. */ + UCHAR num_back_channel_elements; /*!< Number of back channel elements. */ + UCHAR num_lfe_channel_elements; /*!< Number of lfe channel elements. */ + const MP4_ELEMENT_ID + *pEl_type; /*!< List contains sequence describing the elements + in present channel mode. (MPEG order) */ + const PCE_HEIGHT_NUM *pHeight_num; +} PCE_CONFIGURATION; + +/** + * Map an incoming channel mode to a existing PCE configuration entry. + */ +typedef struct { + CHANNEL_MODE channel_mode; /*!< Present channel mode. */ + PCE_CONFIGURATION + pce_configuration; /*!< Program config element description. */ + +} CHANNEL_CONFIGURATION; + +/** + * The following arrays provide the IDs of the consecutive elements for each + * mode. + */ +static const MP4_ELEMENT_ID elType_1[] = {ID_SCE}; +static const MP4_ELEMENT_ID elType_2[] = {ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2[] = {ID_SCE, ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2_1[] = {ID_SCE, ID_CPE, ID_SCE}; +static const MP4_ELEMENT_ID elType_1_2_2[] = {ID_SCE, ID_CPE, ID_CPE}; +static const MP4_ELEMENT_ID elType_1_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_1_2_2_2_1[] = {ID_SCE, ID_CPE, ID_CPE, + ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_6_1[] = {ID_SCE, ID_CPE, ID_CPE, ID_SCE, + ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_back[] = {ID_SCE, ID_CPE, ID_CPE, ID_CPE, + ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_top_front[] = {ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_CPE}; +static const MP4_ELEMENT_ID elType_7_1_rear_surround[] = { + ID_SCE, ID_CPE, ID_CPE, ID_CPE, ID_LFE}; +static const MP4_ELEMENT_ID elType_7_1_front_center[] = {ID_SCE, ID_CPE, ID_CPE, + ID_CPE, ID_LFE}; + +/** + * The following arrays provide information on how many front, side and back + * elements are assigned to the top or bottom plane for each mode that comprises + * height information. + */ +static const PCE_HEIGHT_NUM heightNum_7_1_top_front = {{1, 0}, {0, 0}, {0, 0}}; + +/** + * \brief Table contains all supported channel modes and according PCE + configuration description. + * + * The mode identifier is followed by the number of front, side, back, and LFE + elements. + * These are followed by a pointer to the IDs of the consecutive elements + (ID_SCE, ID_CPE, ID_LFE). + * + * For some modes (MODE_7_1_TOP_FRONT and MODE_22_2) additional height + information is transmitted. + * In this case the additional pointer provides information on how many front, + side and back elements + * are assigned to the top or bottom plane.The elements are arranged in the + following order: normal height (front, side, back, LFE), top height (front, + side, back), bottom height (front, side, back). + * + * + * E.g. MODE_7_1_TOP_FRONT means: + * - 3 elements are front channel elements. + * - 0 elements are side channel elements. + * - 1 element is back channel element. + * - 1 element is an LFE channel element. + * - the element order is ID_SCE, ID_CPE, ID_CPE, + ID_LFE, ID_CPE. + * - 1 of the front elements is in the top plane. + * + * This leads to the following mapping for the cconsecutive elements in the + MODE_7_1_TOP_FRONT bitstream: + * - ID_SCE -> normal height front, + - ID_CPE -> normal height front, + - ID_CPE -> normal height back, + - ID_LFE -> normal height LFE, + - ID_CPE -> top height front. + */ +static const CHANNEL_CONFIGURATION pceConfigTab[] = { + {MODE_1, + {1, 0, 0, 0, elType_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_2, + {1, 0, 0, 0, elType_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2, + {2, 0, 0, 0, elType_1_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_1, + {2, 0, 1, 0, elType_1_2_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2, + {2, 0, 1, 0, elType_1_2_2, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2_1, + {2, 0, 1, 1, elType_1_2_2_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_1_2_2_2_1, + {3, 0, 1, 1, elType_1_2_2_2_1, + NULL}}, /* don't transmit height information in this mode */ + + {MODE_6_1, + {2, 0, 2, 1, elType_6_1, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_BACK, + {2, 0, 2, 1, elType_7_1_back, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_TOP_FRONT, + {3, 0, 1, 1, elType_7_1_top_front, &heightNum_7_1_top_front}}, + + {MODE_7_1_REAR_SURROUND, + {2, 0, 2, 1, elType_7_1_rear_surround, + NULL}}, /* don't transmit height information in this mode */ + {MODE_7_1_FRONT_CENTER, + {3, 0, 1, 1, elType_7_1_front_center, + NULL}} /* don't transmit height information in this mode */ +}; + +/** + * \brief Get program config element description for existing channel mode. + * + * \param channel_mode Current channel mode. + * + * \return + * - Pointer to PCE_CONFIGURATION entry, on success. + * - NULL, on failure. + */ +static const PCE_CONFIGURATION *getPceEntry(const CHANNEL_MODE channel_mode) { + UINT i; + const PCE_CONFIGURATION *pce_config = NULL; + + for (i = 0; i < (sizeof(pceConfigTab) / sizeof(CHANNEL_CONFIGURATION)); i++) { + if (pceConfigTab[i].channel_mode == channel_mode) { + pce_config = &pceConfigTab[i].pce_configuration; + break; + } + } + + return pce_config; +} + +int getChannelConfig(const CHANNEL_MODE channel_mode, + const UCHAR channel_config_zero) { + INT chan_config = 0; + + if (channel_config_zero != 0) { + chan_config = 0; + } else { + switch (channel_mode) { + case MODE_1: + chan_config = 1; + break; + case MODE_2: + chan_config = 2; + break; + case MODE_1_2: + chan_config = 3; + break; + case MODE_1_2_1: + chan_config = 4; + break; + case MODE_1_2_2: + chan_config = 5; + break; + case MODE_1_2_2_1: + chan_config = 6; + break; + case MODE_1_2_2_2_1: + chan_config = 7; + break; + case MODE_6_1: + chan_config = 11; + break; + case MODE_7_1_BACK: + chan_config = 12; + break; + case MODE_7_1_TOP_FRONT: + chan_config = 14; + break; + default: + chan_config = 0; + } + } + + return chan_config; +} + +CHANNEL_MODE transportEnc_GetChannelMode(int noChannels) { + CHANNEL_MODE chMode; + + if (noChannels <= 8 && noChannels > 0) + chMode = (CHANNEL_MODE)( + (noChannels == 8) ? 7 + : noChannels); /* see : iso/mpeg4 v1 audio subpart1*/ + else + chMode = MODE_UNKNOWN; + + return chMode; +} + +int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, CHANNEL_MODE channelMode, + INT sampleRate, int instanceTagPCE, int profile, + int matrixMixdownA, int pseudoSurroundEnable, + UINT alignAnchor) { + int sampleRateIndex, i; + const PCE_CONFIGURATION *config = NULL; + const MP4_ELEMENT_ID *pEl_list = NULL; + UCHAR cpeCnt = 0, sceCnt = 0, lfeCnt = 0, frntCnt = 0, sdCnt = 0, bckCnt = 0, + isCpe = 0, tag = 0, normalFrontEnd = 0, normalSideEnd = 0, + normalBackEnd = 0, topFrontEnd = 0, topSideEnd = 0, topBackEnd = 0, + bottomFrontEnd = 0, bottomSideEnd = 0; +#ifdef FDK_ASSERT_ENABLE + UCHAR bottomBackEnd = 0; +#endif + enum elementDepth { FRONT, SIDE, BACK } elDepth; + + sampleRateIndex = getSamplingRateIndex(sampleRate, 4); + if (sampleRateIndex == 15) { + return -1; + } + + if ((config = getPceEntry(channelMode)) == NULL) { + return -1; + } + + FDK_ASSERT(config->num_front_channel_elements <= MAX_FRONT_ELEMENTS); + FDK_ASSERT(config->num_side_channel_elements <= MAX_SIDE_ELEMENTS); + FDK_ASSERT(config->num_back_channel_elements <= MAX_BACK_ELEMENTS); + + UCHAR frontIsCpe[MAX_FRONT_ELEMENTS] = {0}, + frontTag[MAX_FRONT_ELEMENTS] = {0}, sideIsCpe[MAX_SIDE_ELEMENTS] = {0}, + sideTag[MAX_SIDE_ELEMENTS] = {0}, backIsCpe[MAX_BACK_ELEMENTS] = {0}, + backTag[MAX_BACK_ELEMENTS] = {0}; + + /* Write general information */ + + FDKwriteBits(hBs, instanceTagPCE, 4); /* Element instance tag */ + FDKwriteBits(hBs, profile, 2); /* Object type */ + FDKwriteBits(hBs, sampleRateIndex, 4); /* Sample rate index*/ + + FDKwriteBits(hBs, config->num_front_channel_elements, + 4); /* Front channel Elements */ + FDKwriteBits(hBs, config->num_side_channel_elements, + 4); /* No Side Channel Elements */ + FDKwriteBits(hBs, config->num_back_channel_elements, + 4); /* No Back channel Elements */ + FDKwriteBits(hBs, config->num_lfe_channel_elements, + 2); /* No Lfe channel elements */ + + FDKwriteBits(hBs, 0, 3); /* No assoc data elements */ + FDKwriteBits(hBs, 0, 4); /* No valid cc elements */ + FDKwriteBits(hBs, 0, 1); /* Mono mixdown present */ + FDKwriteBits(hBs, 0, 1); /* Stereo mixdown present */ + + if (matrixMixdownA != 0 && + ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { + FDKwriteBits(hBs, 1, 1); /* Matrix mixdown present */ + FDKwriteBits(hBs, (matrixMixdownA - 1) & 0x3, 2); /* matrix_mixdown_idx */ + FDKwriteBits(hBs, (pseudoSurroundEnable) ? 1 : 0, + 1); /* pseudo_surround_enable */ + } else { + FDKwriteBits(hBs, 0, 1); /* Matrix mixdown not present */ + } + + if (config->pHeight_num != NULL) { + /* we have up to three different height levels, and in each height level we + * may have front, side and back channels. We need to know where each + * section ends to correctly count the tags */ + normalFrontEnd = config->num_front_channel_elements - + config->pHeight_num->num_front_height_channel_elements[0] - + config->pHeight_num->num_front_height_channel_elements[1]; + normalSideEnd = normalFrontEnd + config->num_side_channel_elements - + config->pHeight_num->num_side_height_channel_elements[0] - + config->pHeight_num->num_side_height_channel_elements[1]; + normalBackEnd = normalSideEnd + config->num_back_channel_elements - + config->pHeight_num->num_back_height_channel_elements[0] - + config->pHeight_num->num_back_height_channel_elements[1]; + + topFrontEnd = + normalBackEnd + config->num_lfe_channel_elements + + config->pHeight_num->num_front_height_channel_elements[0]; /* only + normal + height + LFEs + assumed */ + topSideEnd = + topFrontEnd + config->pHeight_num->num_side_height_channel_elements[0]; + topBackEnd = + topSideEnd + config->pHeight_num->num_back_height_channel_elements[0]; + + bottomFrontEnd = + topBackEnd + config->pHeight_num->num_front_height_channel_elements[1]; + bottomSideEnd = bottomFrontEnd + + config->pHeight_num->num_side_height_channel_elements[1]; +#ifdef FDK_ASSERT_ENABLE + bottomBackEnd = bottomSideEnd + + config->pHeight_num->num_back_height_channel_elements[1]; +#endif + + } else { + /* we have only one height level, so we don't care about top or bottom */ + normalFrontEnd = config->num_front_channel_elements; + normalSideEnd = normalFrontEnd + config->num_side_channel_elements; + normalBackEnd = normalSideEnd + config->num_back_channel_elements; + } + + /* assign cpe and tag information to either front, side or back channels */ + + pEl_list = config->pEl_type; + + for (i = 0; i < config->num_front_channel_elements + + config->num_side_channel_elements + + config->num_back_channel_elements + + config->num_lfe_channel_elements; + i++) { + if (*pEl_list == ID_LFE) { + pEl_list++; + continue; + } + isCpe = (*pEl_list++ == ID_CPE) ? 1 : 0; + tag = (isCpe) ? cpeCnt++ : sceCnt++; + + if (i < normalFrontEnd) + elDepth = FRONT; + else if (i < normalSideEnd) + elDepth = SIDE; + else if (i < normalBackEnd) + elDepth = BACK; + else if (i < topFrontEnd) + elDepth = FRONT; + else if (i < topSideEnd) + elDepth = SIDE; + else if (i < topBackEnd) + elDepth = BACK; + else if (i < bottomFrontEnd) + elDepth = FRONT; + else if (i < bottomSideEnd) + elDepth = SIDE; + else { + elDepth = BACK; + FDK_ASSERT(i < bottomBackEnd); /* won't fail if implementation of pce + configuration table is correct */ + } + + switch (elDepth) { + case FRONT: + FDK_ASSERT(frntCnt < config->num_front_channel_elements); + frontIsCpe[frntCnt] = isCpe; + frontTag[frntCnt++] = tag; + break; + case SIDE: + FDK_ASSERT(sdCnt < config->num_side_channel_elements); + sideIsCpe[sdCnt] = isCpe; + sideTag[sdCnt++] = tag; + break; + case BACK: + FDK_ASSERT(bckCnt < config->num_back_channel_elements); + backIsCpe[bckCnt] = isCpe; + backTag[bckCnt++] = tag; + break; + } + } + + /* Write front channel isCpe and tags */ + for (i = 0; i < config->num_front_channel_elements; i++) { + FDKwriteBits(hBs, frontIsCpe[i], 1); + FDKwriteBits(hBs, frontTag[i], 4); + } + /* Write side channel isCpe and tags */ + for (i = 0; i < config->num_side_channel_elements; i++) { + FDKwriteBits(hBs, sideIsCpe[i], 1); + FDKwriteBits(hBs, sideTag[i], 4); + } + /* Write back channel isCpe and tags */ + for (i = 0; i < config->num_back_channel_elements; i++) { + FDKwriteBits(hBs, backIsCpe[i], 1); + FDKwriteBits(hBs, backTag[i], 4); + } + /* Write LFE information */ + for (i = 0; i < config->num_lfe_channel_elements; i++) { + FDKwriteBits(hBs, lfeCnt++, 4); /* LFE channel Instance Tag. */ + } + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + /* Byte alignment: relative to alignAnchor + ADTS: align with respect to the first bit of the raw_data_block() + ADIF: align with respect to the first bit of the header + LATM: align with respect to the first bit of the ASC */ + FDKbyteAlign(hBs, alignAnchor); /* Alignment */ + + /* Write comment information */ + + if (config->pHeight_num != NULL) { + /* embed height information in comment field */ + + INT commentBytes = + 1 /* PCE_HEIGHT_EXT_SYNC */ + + ((((config->num_front_channel_elements + + config->num_side_channel_elements + + config->num_back_channel_elements) + << 1) + + 7) >> + 3) /* 2 bit height info per element, round up to full bytes */ + + 1; /* CRC */ + + FDKwriteBits(hBs, commentBytes, 8); /* comment size. */ + + FDK_CRCINFO crcInfo; /* CRC state info */ + INT crcReg; + + FDKcrcInit(&crcInfo, 0x07, 0xFF, 8); + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + + FDKwriteBits(hBs, PCE_HEIGHT_EXT_SYNC, 8); /* indicate height extension */ + + /* front channel height information */ + for (i = 0; + i < config->num_front_channel_elements - + config->pHeight_num->num_front_height_channel_elements[0] - + config->pHeight_num->num_front_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_front_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + /* side channel height information */ + for (i = 0; + i < config->num_side_channel_elements - + config->pHeight_num->num_side_height_channel_elements[0] - + config->pHeight_num->num_side_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_side_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + /* back channel height information */ + for (i = 0; + i < config->num_back_channel_elements - + config->pHeight_num->num_back_height_channel_elements[0] - + config->pHeight_num->num_back_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_NORMAL, 2); + for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[0]; + i++) + FDKwriteBits(hBs, HEIGHT_TOP, 2); + for (i = 0; i < config->pHeight_num->num_back_height_channel_elements[1]; + i++) + FDKwriteBits(hBs, HEIGHT_BOTTOM, 2); + + FDKbyteAlign(hBs, alignAnchor); /* Alignment */ + + FDKcrcEndReg(&crcInfo, hBs, crcReg); + FDKwriteBits(hBs, FDKcrcGetCRC(&crcInfo), 8); + + } else { + FDKwriteBits(hBs, 0, + 8); /* Do no write any comment or height information. */ + } + + return 0; +} + +int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, int matrixMixdownA, + int bits) { + const PCE_CONFIGURATION *config = NULL; + + if ((config = getPceEntry(channelMode)) == NULL) { + return -1; /* unsupported channelmapping */ + } + + bits += + 4 + 2 + 4; /* Element instance tag + Object type + Sample rate index */ + bits += 4 + 4 + 4 + 2; /* No (front + side + back + lfe channel) elements */ + bits += 3 + 4; /* No (assoc data + valid cc) elements */ + bits += 1 + 1 + 1; /* Mono + Stereo + Matrix mixdown present */ + + if (matrixMixdownA != 0 && + ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1))) { + bits += 3; /* matrix_mixdown_idx + pseudo_surround_enable */ + } + + bits += (1 + 4) * (INT)config->num_front_channel_elements; + bits += (1 + 4) * (INT)config->num_side_channel_elements; + bits += (1 + 4) * (INT)config->num_back_channel_elements; + bits += (4) * (INT)config->num_lfe_channel_elements; + + /* - num_valid_cc_elements always 0. + - num_assoc_data_elements always 0. */ + + if ((bits % 8) != 0) { + bits += (8 - (bits % 8)); /* Alignment */ + } + + bits += 8; /* Comment field bytes */ + + if (config->pHeight_num != NULL) { + /* Comment field (height extension) */ + + bits += + 8 /* PCE_HEIGHT_EXT_SYNC */ + + + ((config->num_front_channel_elements + + config->num_side_channel_elements + config->num_back_channel_elements) + << 1) /* 2 bit height info per element */ + + 8; /* CRC */ + + if ((bits % 8) != 0) { + bits += (8 - (bits % 8)); /* Alignment */ + } + } + + return bits; +} + +static void writeAot(HANDLE_FDK_BITSTREAM hBitstreamBuffer, + AUDIO_OBJECT_TYPE aot) { + int tmp = (int)aot; + + if (tmp > 31) { + FDKwriteBits(hBitstreamBuffer, AOT_ESCAPE, 5); + FDKwriteBits(hBitstreamBuffer, tmp - 32, 6); /* AudioObjectType */ + } else { + FDKwriteBits(hBitstreamBuffer, tmp, 5); + } +} + +static void writeSampleRate(HANDLE_FDK_BITSTREAM hBs, int sampleRate, + int nBits) { + int srIdx = getSamplingRateIndex(sampleRate, nBits); + + FDKwriteBits(hBs, srIdx, nBits); + if (srIdx == (1 << nBits) - 1) { + FDKwriteBits(hBs, sampleRate, 24); + } +} + +static int transportEnc_writeGASpecificConfig(HANDLE_FDK_BITSTREAM asc, + CODER_CONFIG *config, int extFlg, + UINT alignAnchor) { + int aot = config->aot; + int samplesPerFrame = config->samplesPerFrame; + + /* start of GASpecificConfig according to ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits(asc, + ((samplesPerFrame == 960 || samplesPerFrame == 480) ? 1 : 0), + 1); /* frameLengthFlag: 1 for a 960/480 (I)MDCT, 0 for a 1024/512 + (I)MDCT*/ + FDKwriteBits(asc, 0, + 1); /* dependsOnCoreCoder: Sampling Rate Coder Specific, see in + ISO/IEC 14496-3 Subpart 4, 4.4.1 */ + FDKwriteBits(asc, extFlg, + 1); /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23 */ + + /* Write PCE if channel config is not 1-7 */ + if (getChannelConfig(config->channelMode, config->channelConfigZero) == 0) { + transportEnc_writePCE(asc, config->channelMode, config->samplingRate, 0, 1, + config->matrixMixdownA, + (config->flags & CC_PSEUDO_SURROUND) ? 1 : 0, + alignAnchor); + } + if ((aot == AOT_AAC_SCAL) || (aot == AOT_ER_AAC_SCAL)) { + FDKwriteBits(asc, 0, 3); /* layerNr */ + } + if (extFlg) { + if (aot == AOT_ER_BSAC) { + FDKwriteBits(asc, config->BSACnumOfSubFrame, 5); /* numOfSubFrame */ + FDKwriteBits(asc, config->BSAClayerLength, 11); /* layer_length */ + } + if ((aot == AOT_ER_AAC_LC) || (aot == AOT_ER_AAC_LTP) || + (aot == AOT_ER_AAC_SCAL) || (aot == AOT_ER_AAC_LD)) { + FDKwriteBits(asc, (config->flags & CC_VCB11) ? 1 : 0, + 1); /* aacSectionDataResillienceFlag */ + FDKwriteBits(asc, (config->flags & CC_RVLC) ? 1 : 0, + 1); /* aacScaleFactorDataResillienceFlag */ + FDKwriteBits(asc, (config->flags & CC_HCR) ? 1 : 0, + 1); /* aacSpectralDataResillienceFlag */ + } + FDKwriteBits(asc, 0, 1); /* extensionFlag3: reserved. Shall be '0' */ + } + return 0; +} + +static int transportEnc_writeELDSpecificConfig(HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *config, + int epConfig, + CSTpCallBacks *cb) { + UINT frameLengthFlag = 0; + switch (config->samplesPerFrame) { + case 512: + case 256: + case 128: + case 64: + frameLengthFlag = 0; + break; + case 480: + case 240: + case 160: + case 120: + case 60: + frameLengthFlag = 1; + break; + } + + FDKwriteBits(hBs, frameLengthFlag, 1); + + FDKwriteBits(hBs, (config->flags & CC_VCB11) ? 1 : 0, 1); + FDKwriteBits(hBs, (config->flags & CC_RVLC) ? 1 : 0, 1); + FDKwriteBits(hBs, (config->flags & CC_HCR) ? 1 : 0, 1); + + FDKwriteBits(hBs, (config->flags & CC_SBR) ? 1 : 0, 1); /* SBR header flag */ + if ((config->flags & CC_SBR)) { + FDKwriteBits(hBs, (config->samplingRate == config->extSamplingRate) ? 0 : 1, + 1); /* Samplerate Flag */ + FDKwriteBits(hBs, (config->flags & CC_SBRCRC) ? 1 : 0, 1); /* SBR CRC flag*/ + + if (cb->cbSbr != NULL) { + const PCE_CONFIGURATION *pPce; + int e, sbrElementIndex = 0; + + pPce = getPceEntry(config->channelMode); + + for (e = 0; e < pPce->num_front_channel_elements + + pPce->num_side_channel_elements + + pPce->num_back_channel_elements + + pPce->num_lfe_channel_elements; + e++) { + if ((pPce->pEl_type[e] == ID_SCE) || (pPce->pEl_type[e] == ID_CPE)) { + cb->cbSbr(cb->cbSbrData, hBs, 0, 0, 0, config->aot, pPce->pEl_type[e], + sbrElementIndex, 0, 0, 0, NULL, 1); + sbrElementIndex++; + } + } + } + } + + if ((config->flags & CC_SAC) && (cb->cbSsc != NULL)) { + FDKwriteBits(hBs, ELDEXT_LDSAC, 4); + + const INT eldExtLen = + (cb->cbSsc(cb->cbSscData, NULL, config->aot, config->extSamplingRate, 0, + 0, 0, 0, 0, NULL) + + 7) >> + 3; + INT cnt = eldExtLen; + + if (cnt < 0xF) { + FDKwriteBits(hBs, cnt, 4); + } else { + FDKwriteBits(hBs, 0xF, 4); + cnt -= 0xF; + + if (cnt < 0xFF) { + FDKwriteBits(hBs, cnt, 8); + } else { + FDKwriteBits(hBs, 0xFF, 8); + cnt -= 0xFF; + + FDK_ASSERT(cnt <= 0xFFFF); + FDKwriteBits(hBs, cnt, 16); + } + } + + cb->cbSsc(cb->cbSscData, hBs, config->aot, config->extSamplingRate, 0, 0, 0, + 0, 0, NULL); + } + + if (config->downscaleSamplingRate != 0 && + config->downscaleSamplingRate != config->extSamplingRate) { + /* downscale active */ + + /* eldExtLenDsc: Number of bytes for the ELD downscale extension (srIdx + needs 1 byte + + downscaleSamplingRate needs additional 3 bytes) */ + int eldExtLenDsc = 1; + int downscaleSamplingRate = config->downscaleSamplingRate; + FDKwriteBits(hBs, ELDEXT_DOWNSCALEINFO, 4); /* ELDEXT_DOWNSCALEINFO */ + + if ((downscaleSamplingRate != 96000) && (downscaleSamplingRate != 88200) && + (downscaleSamplingRate != 64000) && (downscaleSamplingRate != 48000) && + (downscaleSamplingRate != 44100) && (downscaleSamplingRate != 32000) && + (downscaleSamplingRate != 24000) && (downscaleSamplingRate != 22050) && + (downscaleSamplingRate != 16000) && (downscaleSamplingRate != 12000) && + (downscaleSamplingRate != 11025) && (downscaleSamplingRate != 8000) && + (downscaleSamplingRate != 7350)) { + eldExtLenDsc = 4; /* length extends to 4 if downscaleSamplingRate's value + is not one of the listed values */ + } + + FDKwriteBits(hBs, eldExtLenDsc, 4); + writeSampleRate(hBs, downscaleSamplingRate, 4); + FDKwriteBits(hBs, 0x0, 4); /* fill_nibble */ + } + + FDKwriteBits(hBs, ELDEXT_TERM, 4); /* ELDEXT_TERM */ + + return 0; +} + +static int transportEnc_writeUsacSpecificConfig(HANDLE_FDK_BITSTREAM hBs, + int extFlag, CODER_CONFIG *cc, + CSTpCallBacks *cb) { + FDK_BITSTREAM usacConf; + int usacConfigBits = cc->rawConfigBits; + + if ((usacConfigBits <= 0) || + ((usacConfigBits + 7) / 8 > (int)sizeof(cc->rawConfig))) { + return TRANSPORTENC_UNSUPPORTED_FORMAT; + } + FDKinitBitStream(&usacConf, cc->rawConfig, BUFSIZE_DUMMY_VALUE, + usacConfigBits, BS_READER); + + for (; usacConfigBits > 0; usacConfigBits--) { + UINT tmp = FDKreadBit(&usacConf); + FDKwriteBits(hBs, tmp, 1); + } + FDKsyncCache(hBs); + + return TRANSPORTENC_OK; +} + +int transportEnc_writeASC(HANDLE_FDK_BITSTREAM asc, CODER_CONFIG *config, + CSTpCallBacks *cb) { + UINT extFlag = 0; + int err; + int epConfig = 0; + + /* Required for the PCE. */ + UINT alignAnchor = FDKgetValidBits(asc); + + /* Extension Flag: Shall be 1 for aot = 17,19,20,21,22,23,39 */ + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_USAC: + extFlag = 1; + break; + default: + break; + } + + if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) + writeAot(asc, config->extAOT); + else + writeAot(asc, config->aot); + + /* In case of USAC it is the output not the core sampling rate */ + writeSampleRate(asc, config->samplingRate, 4); + + /* Try to guess a reasonable channel mode if not given */ + if (config->channelMode == MODE_INVALID) { + config->channelMode = transportEnc_GetChannelMode(config->noChannels); + if (config->channelMode == MODE_INVALID) return -1; + } + + FDKwriteBits( + asc, getChannelConfig(config->channelMode, config->channelConfigZero), 4); + + if (config->sbrSignaling == SIG_EXPLICIT_HIERARCHICAL && config->sbrPresent) { + writeSampleRate(asc, config->extSamplingRate, 4); + writeAot(asc, config->aot); + } + + switch (config->aot) { + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_SSR: + case AOT_AAC_LTP: + case AOT_AAC_SCAL: + case AOT_TWIN_VQ: + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + err = + transportEnc_writeGASpecificConfig(asc, config, extFlag, alignAnchor); + if (err) return err; + break; + case AOT_ER_AAC_ELD: + err = transportEnc_writeELDSpecificConfig(asc, config, epConfig, cb); + if (err) return err; + break; + case AOT_USAC: + err = transportEnc_writeUsacSpecificConfig(asc, extFlag, config, cb); + if (err) { + return err; + } + break; + default: + return -1; + } + + switch (config->aot) { + case AOT_ER_AAC_LC: + case AOT_ER_AAC_LTP: + case AOT_ER_AAC_SCAL: + case AOT_ER_TWIN_VQ: + case AOT_ER_BSAC: + case AOT_ER_AAC_LD: + case AOT_ER_CELP: + case AOT_ER_HVXC: + case AOT_ER_HILN: + case AOT_ER_PARA: + case AOT_ER_AAC_ELD: + FDKwriteBits(asc, 0, 2); /* epconfig 0 */ + break; + default: + break; + } + + /* backward compatible explicit signaling of extension AOT */ + if (config->sbrSignaling == SIG_EXPLICIT_BW_COMPATIBLE) { + TP_ASC_EXTENSION_ID ascExtId = ASCEXT_UNKOWN; + + if (config->sbrPresent) { + ascExtId = ASCEXT_SBR; + FDKwriteBits(asc, ascExtId, 11); + writeAot(asc, config->extAOT); + FDKwriteBits(asc, 1, 1); /* sbrPresentFlag=1 */ + writeSampleRate(asc, config->extSamplingRate, 4); + if (config->psPresent) { + ascExtId = ASCEXT_PS; + FDKwriteBits(asc, ascExtId, 11); + FDKwriteBits(asc, 1, 1); /* psPresentFlag=1 */ + } + } + } + + /* Make sure all bits are sync'ed */ + FDKsyncCache(asc); + + return 0; +} diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_asc.h b/fdk-aac/libMpegTPEnc/src/tpenc_asc.h new file mode 100644 index 0000000..5f5621e --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_asc.h @@ -0,0 +1,147 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: Audio Specific Config writer + +*******************************************************************************/ + +#ifndef TPENC_ASC_H +#define TPENC_ASC_H + +/** + * \brief Get channel config from channel mode. + * + * \param channel_mode channel mode + * \param channel_config_zero no standard channel configuration + * + * \return chanel config + */ +int getChannelConfig(const CHANNEL_MODE channel_mode, + const UCHAR channel_config_zero); + +/** + * \brief Write a Program Config Element. + * + * \param hBs bitstream handle into which the PCE is appended + * \param channelMode the channel mode to be used + * \param sampleRate the sample rate + * \param instanceTagPCE the instance tag of the Program Config Element + * \param profile the MPEG Audio profile to be used + * \param matrix mixdown gain + * \param pseudo surround indication + * \param reference bitstream position for alignment + * \return zero on success, non-zero on failure. + */ +int transportEnc_writePCE(HANDLE_FDK_BITSTREAM hBs, CHANNEL_MODE channelMode, + INT sampleRate, int instanceTagPCE, int profile, + int matrixMixdownA, int pseudoSurroundEnable, + UINT alignAnchor); + +/** + * \brief Get the bit count required by a Program Config Element + * + * \param channelMode the channel mode to be used + * \param matrix mixdown gain + * \param bit offset at which the PCE would start + * \return the amount of bits required for the PCE including the given bit + * offset. + */ +int transportEnc_GetPCEBits(CHANNEL_MODE channelMode, int matrixMixdownA, + int bits); + +#endif /* TPENC_ASC_H */ diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_dab.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_dab.cpp new file mode 100644 index 0000000..202fecf --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_dab.cpp @@ -0,0 +1,467 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport Headers support + +******************************************************************************/ +#include +#include "FDK_audio.h" +#include "tpenc_dab.h" + + +#include "tpenc_lib.h" +#include "tpenc_asc.h" + +#include "common_fix.h" + +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, /*!< pointer to dab stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int mBits /*!< number of bits in crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcStartReg(%p): bits in crc region=%d\n", hBs, mBits); + return ( FDKcrcStartReg(&pDab->crcInfo2, hBs, mBits) ); +} + +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, /*!< pointer to dab crc info stucture */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to current bit buffer structure */ + int reg /*!< crc region */ + ) +{ + //fprintf(stderr, "dabWrite_CrcEndReg(%p): crc region=%d\n", hBs, reg); + FDKcrcEndReg(&pDab->crcInfo2, hBs, reg); +} + +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ) +{ + int bits = 0; + + if (hDab->currentBlock == 0) { + /* Static and variable header bits */ + bits += 16; //header_firecode 16 + bits += 8; //rfa=1, dac_rate=1, sbr_flag=1, aac_channel_mode=1, ps_flag=1, mpeg_surround_config=3 + bits += 12 * hDab->num_raw_blocks; //au_start[1...num_aus] 12 bit AU start position markers + + //4 byte alignment + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) + bits+=4; + //16sbr => 16 + 5 + 3 + 12*(2-1) => 36 => 40 bits 5 + //24sbr => 16 + 5 + 3 + 12*(3-1) => 48 ok 6 + //32sbr => 16 + 5 + 3 + 12*(4-1) => 60 => 64 bits 8 + //48sbr => 16 + 5 + 3 + 12*(6-1) => 84 => 88 bits 11 + } + + /* Add raw data block CRC bits. Not really part of the header, put they cause bit overhead to be accounted. */ + bits += 16; + + + return bits; +} + + +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ) +{ + //fprintf(stderr, "streamDataLength=%d (%d bytes)\n", streamDataLength, streamDataLength >> 3); + return dabWrite_GetHeaderBits(hDab); +} + + +INT dabWrite_Init(HANDLE_DAB hDab, CODER_CONFIG *config) +{ + /* Sanity checks */ + if((int)config->aot > 4 + || (int)config->aot < 1 ) { + return -1; + } + + /* Sanity checks DAB-specific */ + if ( !(config->nSubFrames == 2 && config->samplingRate == 16000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 3 && config->samplingRate == 24000 && (config->flags & CC_SBR)) && + !(config->nSubFrames == 4 && config->samplingRate == 32000) && + !(config->nSubFrames == 6 && config->samplingRate == 48000)) { + return -1; + } + + hDab->dac_rate = 0; + hDab->aac_channel_mode=0; + hDab->sbr_flag = 0; + hDab->ps_flag = 0; + hDab->mpeg_surround_config=0; + hDab->subchannels_num=config->bitRate/8000; + + + if(config->samplingRate == 24000 || config->samplingRate == 48000) + hDab->dac_rate = 1; + + if (config->extAOT==AOT_SBR || config->extAOT == AOT_PS) + hDab->sbr_flag = 1; + + if(config->extAOT == AOT_PS) + hDab->ps_flag = 1; + + + if(config->channelMode == MODE_2) + hDab->aac_channel_mode = 1; + + //fprintf(stderr, "hDab->dac_rate=%d\n", hDab->dac_rate); + //fprintf(stderr, "hDab->sbr_flag=%d\n", hDab->sbr_flag); + //fprintf(stderr, "hDab->ps_flag=%d\n", hDab->ps_flag); + //fprintf(stderr, "hDab->aac_channel_mode=%d\n", hDab->aac_channel_mode); + //fprintf(stderr, "hDab->subchannels_num=%d\n", hDab->subchannels_num); + //fprintf(stderr, "cc->nSubFrames=%d\n", config->nSubFrames); + + hDab->num_raw_blocks=config->nSubFrames-1; /* 0 means 1 raw data block */ + + FDKcrcInit(&hDab->crcInfo, 0x1021, 0xFFFF, 16); + FDKcrcInit(&hDab->crcFire, 0x782d, 0, 16); + FDKcrcInit(&hDab->crcInfo2, 0x8005, 0xFFFF, 16); + + hDab->currentBlock = 0; + hDab->headerBits = dabWrite_GetHeaderBits(hDab); + + return 0; +} + +int dabWrite_EncodeHeader(HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int buffer_fullness, + int frame_length) +{ + INT crcIndex = 0; + + + FDK_ASSERT(((frame_length+hDab->headerBits)/8)<0x2000); /*13 bit*/ + FDK_ASSERT(buffer_fullness<0x800); /* 11 bit */ + + FDKcrcReset(&hDab->crcInfo); + + +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->currentBlock=%d, frame_length=%d, buffer_fullness=%d\n", +// hDab->currentBlock, frame_length, buffer_fullness); + +// if (hDab->currentBlock == 0) { +// //hDab->subFrameStartPrev=dabWrite_GetHeaderBits(hDab); +// fprintf(stderr, "header bits[%d] [%d]\n", hDab->subFrameStartPrev, hDab->subFrameStartPrev >> 3); +// FDKresetBitbuffer(hBitStream, BS_WRITER); +// } + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); +// fprintf(stderr, "dabWrite_EncodeHeader() hDab->subFrameStartBit=%d [%d]\n", hDab->subFrameStartBit, hDab->subFrameStartBit >> 3); + + //hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + /* Skip new header if this is raw data block 1..n */ + if (hDab->currentBlock == 0) + { + FDKresetBitbuffer(hBitStream, BS_WRITER); +// fprintf(stderr, "dabWrite_EncodeHeader() after FDKresetBitbuffer=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + + /* fixed header */ + FDKwriteBits(hBitStream, 0, 16); //header_firecode + FDKwriteBits(hBitStream, 0, 1); //rfa + FDKwriteBits(hBitStream, hDab->dac_rate, 1); + FDKwriteBits(hBitStream, hDab->sbr_flag, 1); + FDKwriteBits(hBitStream, hDab->aac_channel_mode, 1); + FDKwriteBits(hBitStream, hDab->ps_flag, 1); + FDKwriteBits(hBitStream, hDab->mpeg_surround_config, 3); + /* variable header */ + int i; + for(i=0; inum_raw_blocks; i++) + FDKwriteBits(hBitStream, 0, 12); + /* padding */ + if (hDab->dac_rate == 0 || hDab->sbr_flag == 0) { + FDKwriteBits(hBitStream, 0, 4); + } + } /* End of DAB header */ + + hDab->subFrameStartBit = FDKgetValidBits(hBitStream); + FDK_ASSERT(FDKgetValidBits(hBitStream) % 8 == 0); //only aligned header + +// fprintf(stderr, "dabWrite_EncodeHeader() FDKgetValidBits(hBitStream)=%d [%d]\n", FDKgetValidBits(hBitStream), FDKgetValidBits(hBitStream) >> 3); + return 0; +} + +int dabWrite_writeExtensionFillPayload(HANDLE_FDK_BITSTREAM hBitStream, int extPayloadBits) +{ +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + +#define EXT_TYPE_BITS ( 4 ) +#define DATA_EL_VERSION_BITS ( 4 ) +#define FILL_NIBBLE_BITS ( 4 ) + + INT extBitsUsed = 0; + INT extPayloadType = EXT_FIL; + //fprintf(stderr, "FDKaacEnc_writeExtensionPayload() extPayloadType=%d\n", extPayloadType); + if (extPayloadBits >= EXT_TYPE_BITS) + { + UCHAR fillByte = 0x00; /* for EXT_FIL and EXT_FILL_DATA */ + + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, extPayloadType, EXT_TYPE_BITS); + } + extBitsUsed += EXT_TYPE_BITS; + + switch (extPayloadType) { + case EXT_FILL_DATA: + fillByte = 0xA5; + case EXT_FIL: + default: + if (hBitStream != NULL) { + int writeBits = extPayloadBits; + FDKwriteBits(hBitStream, 0x00, FILL_NIBBLE_BITS); + writeBits -= 8; /* acount for the extension type and the fill nibble */ + while (writeBits >= 8) { + FDKwriteBits(hBitStream, fillByte, 8); + writeBits -= 8; + } + } + extBitsUsed += FILL_NIBBLE_BITS + (extPayloadBits & ~0x7) - 8; + break; + } + } + + return (extBitsUsed); +} + +void dabWrite_FillRawDataBlock(HANDLE_FDK_BITSTREAM hBitStream, int payloadBits) +{ + INT extBitsUsed = 0; +#define EL_ID_BITS ( 3 ) +#define FILL_EL_COUNT_BITS ( 4 ) +#define FILL_EL_ESC_COUNT_BITS ( 8 ) +#define MAX_FILL_DATA_BYTES ( 269 ) + while (payloadBits >= (EL_ID_BITS + FILL_EL_COUNT_BITS)) { + INT cnt, esc_count=-1, alignBits=7; + + payloadBits -= EL_ID_BITS + FILL_EL_COUNT_BITS; + if (payloadBits >= 15*8) { + payloadBits -= FILL_EL_ESC_COUNT_BITS; + esc_count = 0; /* write esc_count even if cnt becomes smaller 15 */ + } + alignBits = 0; + + cnt = fixMin(MAX_FILL_DATA_BYTES, (payloadBits+alignBits)>>3); + + if (cnt >= 15) { + esc_count = cnt - 15 + 1; + } + + if (hBitStream != NULL) { + /* write bitstream */ + FDKwriteBits(hBitStream, ID_FIL, EL_ID_BITS); + if (esc_count >= 0) { + FDKwriteBits(hBitStream, 15, FILL_EL_COUNT_BITS); + FDKwriteBits(hBitStream, esc_count, FILL_EL_ESC_COUNT_BITS); + } else { + FDKwriteBits(hBitStream, cnt, FILL_EL_COUNT_BITS); + } + } + + extBitsUsed += EL_ID_BITS + FILL_EL_COUNT_BITS + ((esc_count>=0) ? FILL_EL_ESC_COUNT_BITS : 0); + + cnt = fixMin(cnt*8, payloadBits); /* convert back to bits */ +#if 0 + extBitsUsed += FDKaacEnc_writeExtensionPayload( hBitStream, + pExtension->type, + pExtension->pPayload, + cnt ); +#else + extBitsUsed += dabWrite_writeExtensionFillPayload(hBitStream, cnt); +#endif + payloadBits -= cnt; + } +} + +void dabWrite_EndRawDataBlock(HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBs, + int *pBits) +{ + FDK_BITSTREAM bsWriter; + INT crcIndex = 0; + USHORT crcData; + INT writeBits=0; + INT writeBitsNonLastBlock=0; + INT writeBitsLastBlock=0; +#if 1 + if (hDab->currentBlock == hDab->num_raw_blocks) { + //calculate byte-alignment before writing ID_FIL + if((FDKgetValidBits(hBs)+3) % 8){ + writeBits = 8 - ((FDKgetValidBits(hBs)+3) % 8); + } + + INT offset_end = hDab->subchannels_num*110*8 - 2*8 - 3; + writeBitsLastBlock = offset_end - FDKgetValidBits(hBs); + dabWrite_FillRawDataBlock(hBs, writeBitsLastBlock); + FDKsyncCache(hBs); + //fprintf(stderr, "FIL-element written=%d\n", writeBitsLastBlock); + writeBitsLastBlock=writeBits; + } +#endif + FDKwriteBits(hBs, 7, 3); //finalize AU: ID_END + FDKsyncCache(hBs); + //byte-align (if ID_FIL doesn't align it). + if(FDKgetValidBits(hBs) % 8){ + writeBits = 8 - (FDKgetValidBits(hBs) % 8); + FDKwriteBits(hBs, 0x00, writeBits); + FDKsyncCache(hBs); + } + + //fake-written bits alignment for last AU + if (hDab->currentBlock == hDab->num_raw_blocks) + writeBits=writeBitsLastBlock; + + INT frameLen = (FDKgetValidBits(hBs) - hDab->subFrameStartBit) >> 3; + //fprintf(stderr, "frame=%d, offset writeBits=%d\n", frameLen, writeBits); + + FDK_ASSERT(FDKgetValidBits(hBs) % 8 == 0); //only aligned au's + FDK_ASSERT(hDab->subchannels_num*110*8 >= FDKgetValidBits(hBs)+2*8); //don't overlap superframe + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, hDab->subFrameStartBit); + FDKcrcReset(&hDab->crcInfo); + hDab->crcIndex = FDKcrcStartReg(&hDab->crcInfo, &bsWriter, 0); +#if 0 + if (hDab->currentBlock == hDab->num_raw_blocks) { + INT offset_size = hDab->subchannels_num*110*8 - 2*8 - FDKgetValidBits(hBs); + //fprintf(stderr, "offset_size=%d\n", offset_size >> 3); + FDKpushFor(hBs, offset_size); + } +#endif + + FDKpushFor(&bsWriter, FDKgetValidBits(hBs) - hDab->subFrameStartBit); + FDKcrcEndReg(&hDab->crcInfo, &bsWriter, hDab->crcIndex); + crcData = FDKcrcGetCRC(&hDab->crcInfo); + //fprintf(stderr, "crcData = %04x\n", crcData); + /* Write inverted CRC of current raw data block */ + FDKwriteBits(hBs, crcData ^ 0xffff, 16); + FDKsyncCache(hBs); + + + /* Write distance to current data block */ + if(hDab->currentBlock) { + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 24 + (hDab->currentBlock-1)*12); + //fprintf(stderr, "FDKwriteBits() = %d\n", hDab->subFrameStartBit>>3); + FDKwriteBits(&bsWriter, (hDab->subFrameStartBit>>3), 12); + FDKsyncCache(&bsWriter); + } + + /* Write FireCode */ + if (hDab->currentBlock == hDab->num_raw_blocks) { + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKpushFor(&bsWriter, 16); + + FDKcrcReset(&hDab->crcFire); + crcIndex = FDKcrcStartReg(&hDab->crcFire, &bsWriter, 72); + FDKpushFor(&bsWriter, 9*8); //9bytes + FDKcrcEndReg(&hDab->crcFire, &bsWriter, crcIndex); + + crcData = FDKcrcGetCRC(&hDab->crcFire); + //fprintf(stderr, "Firecode: %04x\n", crcData); + + FDKinitBitStream(&bsWriter, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, BS_WRITER); + FDKwriteBits(&bsWriter, crcData, 16); + FDKsyncCache(&bsWriter); + } + + if (hDab->currentBlock == 0) + *pBits += hDab->headerBits; + else + *pBits += 16; + + *pBits += writeBits + 3; //size: ID_END + alignment + + /* Correct *pBits to reflect the amount of bits of the current subframe */ + *pBits -= hDab->subFrameStartBit; + /* Fixup CRC bits, since they come after each raw data block */ + + hDab->currentBlock++; + //fprintf(stderr, "dabWrite_EndRawDataBlock() *pBits=%d (%d)\n", *pBits, *pBits >> 3); +} + diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_dab.h b/fdk-aac/libMpegTPEnc/src/tpenc_dab.h new file mode 100644 index 0000000..17b83c6 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_dab.h @@ -0,0 +1,217 @@ + +/* ----------------------------------------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +� Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V. + All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements +the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio. +This FDK AAC Codec software is intended to be used on a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual +audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by +independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part +of the MPEG specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer) +may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners +individually for the purpose of encoding or decoding bit streams in products that are compliant with +the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license +these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec +software may already be covered under those patent licenses when it is used for those licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality, +are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional +applications information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, are permitted without +payment of copyright license fees provided that you satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of the FDK AAC Codec or +your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation and/or other materials +provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form. +You must make available free of charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived from this library without +prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec +software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software +and the date of any change. For modified versions of the FDK AAC Codec, the term +"Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term +"Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer, +ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with +respect to this software. + +You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized +by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors +"AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties +of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages, +including but not limited to procurement of substitute goods or services; loss of use, data, or profits, +or business interruption, however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of this software, even if +advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------------------------------------- */ + +/******************************** MPEG Audio Encoder ************************** + + Initial author: serge + contents/description: DAB Transport writer + +******************************************************************************/ + +#ifndef TPENC_DAB_H +#define TPENC_DAB_H + + + +#include "tp_data.h" + +#include "FDK_crc.h" + +typedef struct { + USHORT frame_length; + UCHAR dac_rate; + UCHAR aac_channel_mode; + UCHAR sbr_flag; + UCHAR ps_flag; + UCHAR mpeg_surround_config; + UCHAR num_raw_blocks; + UCHAR BufferFullnesStartFlag; + int subchannels_num; + int headerBits; /*!< Header bit demand for the current raw data block */ + int currentBlock; /*!< Index of current raw data block */ + int subFrameStartBit; /*!< Bit position where the current raw data block begins */ + //int subFrameStartPrev; /*!< Bit position where the previous raw data block begins */ + int crcIndex; + FDK_CRCINFO crcInfo; + FDK_CRCINFO crcFire; + FDK_CRCINFO crcInfo2; + USHORT tab[256]; +} STRUCT_DAB; + +typedef STRUCT_DAB *HANDLE_DAB; + +/** + * \brief Initialize DAB data structure + * + * \param hDab DAB data handle + * \param config a valid CODER_CONFIG struct from where the required + * information for the DAB header is extrated from + * + * \return 0 in case of success. + */ +INT dabWrite_Init( + HANDLE_DAB hDab, + CODER_CONFIG *config + ); + +/** + * \brief Get the total bit overhead caused by DAB + * + * \hDab handle to DAB data + * + * \return Amount of additional bits required for the current raw data block + */ +int dabWrite_GetHeaderBits( HANDLE_DAB hDab ); +int dabWrite_CountTotalBitDemandHeader( HANDLE_DAB hDab, unsigned int streamDataLength ); + +/** + * \brief Write an DAB header into the given bitstream. May not write a header + * in case of multiple raw data blocks. + * + * \param hDab DAB data handle + * \param hBitStream bitstream handle into which the DAB may be written into + * \param buffer_fullness the buffer fullness value for the DAB header + * \param the current raw data block length + * + * \return 0 in case of success. + */ +INT dabWrite_EncodeHeader( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBitStream, + int bufferFullness, + int frame_length + ); +/** + * \brief Finish a DAB raw data block + * + * \param hDab DAB data handle + * \param hBs bitstream handle into which the DAB may be written into + * \param pBits a pointer to a integer holding the current bitstream buffer bit count, + * which is corrected to the current raw data block boundary. + * + */ +void dabWrite_EndRawDataBlock( + HANDLE_DAB hDab, + HANDLE_FDK_BITSTREAM hBs, + int *bits + ); + + +/** + * \brief Start CRC region with a maximum number of bits + * If mBits is positive zero padding will be used for CRC calculation, if there + * are less than mBits bits available. + * If mBits is negative no zero padding is done. + * If mBits is zero the memory for the buffer is allocated dynamically, the + * number of bits is not limited. + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param mBits limit of number of bits to be considered for the requested CRC region + * + * \return ID for the created region, -1 in case of an error + */ +int dabWrite_CrcStartReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int mBits + ); + +/** + * \brief Ends CRC region identified by reg + * + * \param pDab DAB data handle + * \param hBs bitstream handle of which the CRC region ends + * \param reg a CRC region ID returned previously by dabWrite_CrcStartReg() + */ +void dabWrite_CrcEndReg( + HANDLE_DAB pDab, + HANDLE_FDK_BITSTREAM hBs, + int reg + ); + + + + +#endif /* TPENC_DAB_H */ + diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_latm.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_latm.cpp new file mode 100644 index 0000000..2d35d48 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_latm.cpp @@ -0,0 +1,850 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#include "tpenc_latm.h" + +#include "genericStds.h" + +static const short celpFrameLengthTable[64] = { + 154, 170, 186, 147, 156, 165, 114, 120, 186, 126, 132, 138, 142, + 146, 154, 166, 174, 182, 190, 198, 206, 210, 214, 110, 114, 118, + 120, 122, 218, 230, 242, 254, 266, 278, 286, 294, 318, 342, 358, + 374, 390, 406, 422, 136, 142, 148, 154, 160, 166, 170, 174, 186, + 198, 206, 214, 222, 230, 238, 216, 160, 280, 338, 0, 0}; + +/******* + write value to transport stream + first two bits define the size of the value itself + then the value itself, with a size of 0-3 bytes +*******/ +static UINT transportEnc_LatmWriteValue(HANDLE_FDK_BITSTREAM hBs, int value) { + UCHAR valueBytes = 4; + unsigned int bitsWritten = 0; + int i; + + if (value < (1 << 8)) { + valueBytes = 1; + } else if (value < (1 << 16)) { + valueBytes = 2; + } else if (value < (1 << 24)) { + valueBytes = 3; + } else { + valueBytes = 4; + } + + FDKwriteBits(hBs, valueBytes - 1, 2); /* size of value in Bytes */ + for (i = 0; i < valueBytes; i++) { + /* write most significant Byte first */ + FDKwriteBits(hBs, (UCHAR)(value >> ((valueBytes - 1 - i) << 3)), 8); + } + + bitsWritten = (valueBytes << 3) + 2; + + return bitsWritten; +} + +static UINT transportEnc_LatmCountFixBitDemandHeader(HANDLE_LATM_STREAM hAss) { + int bitDemand = 0; + int insertSetupData = 0; + + /* only if start of new latm frame */ + if (hAss->subFrameCnt == 0) { + /* AudioSyncStream */ + + if (hAss->tt == TT_MP4_LOAS) { + bitDemand += 11; /* syncword */ + bitDemand += 13; /* audioMuxLengthBytes */ + } + + /* AudioMuxElement*/ + + /* AudioMuxElement::Stream Mux Config */ + if (hAss->muxConfigPeriod > 0) { + insertSetupData = (hAss->latmFrameCounter == 0); + } else { + insertSetupData = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + /* AudioMuxElement::useSameStreamMux Flag */ + bitDemand += 1; + + if (insertSetupData) { + bitDemand += hAss->streamMuxConfigBits; + } + } + + /* AudioMuxElement::otherDataBits */ + bitDemand += hAss->otherDataLenBits; + + /* AudioMuxElement::ByteAlign */ + if (bitDemand % 8) { + hAss->fillBits = 8 - (bitDemand % 8); + bitDemand += hAss->fillBits; + } else { + hAss->fillBits = 0; + } + } + + return bitDemand; +} + +static UINT transportEnc_LatmCountVarBitDemandHeader( + HANDLE_LATM_STREAM hAss, unsigned int streamDataLength) { + int bitDemand = 0; + int prog, layer; + + /* Payload Length Info*/ + if (hAss->allStreamsSameTimeFraming) { + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + + if (p_linfo->streamID >= 0) { + switch (p_linfo->frameLengthType) { + case 0: + if (streamDataLength > 0) { + streamDataLength -= bitDemand; + while (streamDataLength >= (255 << 3)) { + bitDemand += 8; + streamDataLength -= (255 << 3); + } + bitDemand += 8; + } + break; + + case 1: + case 4: + case 6: + bitDemand += 2; + break; + + default: + return 0; + } + } + } + } + } else { + /* there are many possibilities to use this mechanism. */ + switch (hAss->varMode) { + case LATMVAR_SIMPLE_SEQUENCE: { + /* Use the sequence generated by the encoder */ + // int streamCntPosition = transportEnc_SetWritePointer( + // hAss->hAssemble, 0 ); int streamCntPosition = FDKgetValidBits( + // hAss->hAssemble ); + bitDemand += 4; + + hAss->varStreamCnt = 0; + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + + if (p_linfo->streamID >= 0) { + bitDemand += 4; /* streamID */ + switch (p_linfo->frameLengthType) { + case 0: + streamDataLength -= bitDemand; + while (streamDataLength >= (255 << 3)) { + bitDemand += 8; + streamDataLength -= (255 << 3); + } + + bitDemand += 8; + break; + /*bitDemand += 1; endFlag + break;*/ + + case 1: + case 4: + case 6: + + break; + + default: + return 0; + } + hAss->varStreamCnt++; + } + } + } + bitDemand += 4; + // transportEnc_UpdateBitstreamField( hAss->hAssemble, + // streamCntPosition, hAss->varStreamCnt-1, 4 ); UINT pos = + // streamCntPosition-FDKgetValidBits(hAss->hAssemble); FDKpushBack( + // hAss->hAssemble, pos); FDKwriteBits( hAss->hAssemble, + // hAss->varStreamCnt-1, 4); FDKpushFor( hAss->hAssemble, pos-4); + } break; + + default: + return 0; + } + } + + return bitDemand; +} + +TRANSPORTENC_ERROR +CreateStreamMuxConfig(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, CSTpCallBacks *cb) { + INT streamIDcnt, tmp; + int layer, prog; + + USHORT coreFrameOffset = 0; + + hAss->taraBufferFullness = 0xFF; + hAss->audioMuxVersionA = 0; /* for future extensions */ + hAss->streamMuxConfigBits = 0; + + FDKwriteBits(hBs, hAss->audioMuxVersion, 1); /* audioMuxVersion */ + hAss->streamMuxConfigBits += 1; + + if (hAss->audioMuxVersion == 1) { + FDKwriteBits(hBs, hAss->audioMuxVersionA, 1); /* audioMuxVersionA */ + hAss->streamMuxConfigBits += 1; + } + + if (hAss->audioMuxVersionA == 0) { + if (hAss->audioMuxVersion == 1) { + hAss->streamMuxConfigBits += transportEnc_LatmWriteValue( + hBs, hAss->taraBufferFullness); /* taraBufferFullness */ + } + FDKwriteBits(hBs, hAss->allStreamsSameTimeFraming ? 1 : 0, + 1); /* allStreamsSameTimeFraming */ + FDKwriteBits(hBs, hAss->noSubframes - 1, 6); /* Number of Subframes */ + FDKwriteBits(hBs, hAss->noProgram - 1, 4); /* Number of Programs */ + + hAss->streamMuxConfigBits += 11; + + streamIDcnt = 0; + for (prog = 0; prog < hAss->noProgram; prog++) { + int transLayer = 0; + + FDKwriteBits(hBs, hAss->noLayer[prog] - 1, 3); + hAss->streamMuxConfigBits += 3; + + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + LATM_LAYER_INFO *p_linfo = &(hAss->m_linfo[prog][layer]); + CODER_CONFIG *p_lci = hAss->config[prog][layer]; + + p_linfo->streamID = -1; + + if (hAss->config[prog][layer] != NULL) { + int useSameConfig = 0; + + if (transLayer > 0) { + FDKwriteBits(hBs, useSameConfig ? 1 : 0, 1); + hAss->streamMuxConfigBits += 1; + } + if ((useSameConfig == 0) || (transLayer == 0)) { + const UINT alignAnchor = FDKgetValidBits(hBs); + + if (0 != + (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) { + return TRANSPORTENC_UNKOWN_ERROR; + } + + if (hAss->audioMuxVersion == 1) { + UINT ascLen = transportEnc_LatmWriteValue(hBs, 0); + FDKbyteAlign(hBs, alignAnchor); + ascLen = FDKgetValidBits(hBs) - alignAnchor - ascLen; + FDKpushBack(hBs, FDKgetValidBits(hBs) - alignAnchor); + + transportEnc_LatmWriteValue(hBs, ascLen); + + if (0 != + (transportEnc_writeASC(hBs, hAss->config[prog][layer], cb))) { + return TRANSPORTENC_UNKOWN_ERROR; + } + + FDKbyteAlign(hBs, alignAnchor); /* asc length fillbits */ + } + + hAss->streamMuxConfigBits += + FDKgetValidBits(hBs) - + alignAnchor; /* add asc length to smc summary */ + } + transLayer++; + + if (!hAss->allStreamsSameTimeFraming) { + if (streamIDcnt >= LATM_MAX_STREAM_ID) + return TRANSPORTENC_INVALID_CONFIG; + } + p_linfo->streamID = streamIDcnt++; + + switch (p_lci->aot) { + case AOT_AAC_MAIN: + case AOT_AAC_LC: + case AOT_AAC_SSR: + case AOT_AAC_LTP: + case AOT_AAC_SCAL: + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + case AOT_USAC: + p_linfo->frameLengthType = 0; + + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + FDKwriteBits(hBs, bufferFullness, 8); /* bufferFullness */ + hAss->streamMuxConfigBits += 11; + + if (!hAss->allStreamsSameTimeFraming) { + CODER_CONFIG *p_lci_prev = hAss->config[prog][layer - 1]; + if (((p_lci->aot == AOT_AAC_SCAL) || + (p_lci->aot == AOT_ER_AAC_SCAL)) && + ((p_lci_prev->aot == AOT_CELP) || + (p_lci_prev->aot == AOT_ER_CELP))) { + FDKwriteBits(hBs, coreFrameOffset, 6); /* coreFrameOffset */ + hAss->streamMuxConfigBits += 6; + } + } + break; + + case AOT_TWIN_VQ: + p_linfo->frameLengthType = 1; + tmp = ((p_lci->bitsFrame + 7) >> 3) - + 20; /* transmission frame length in bytes */ + if ((tmp < 0)) { + return TRANSPORTENC_INVALID_TRANSMISSION_FRAME_LENGTH; + } + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + FDKwriteBits(hBs, tmp, 9); + hAss->streamMuxConfigBits += 12; + + p_linfo->frameLengthBits = (tmp + 20) << 3; + break; + + case AOT_CELP: + p_linfo->frameLengthType = 4; + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + hAss->streamMuxConfigBits += 3; + { + int i; + for (i = 0; i < 62; i++) { + if (celpFrameLengthTable[i] == p_lci->bitsFrame) break; + } + if (i >= 62) { + return TRANSPORTENC_INVALID_CELP_FRAME_LENGTH; + } + + FDKwriteBits(hBs, i, 6); /* CELPframeLengthTabelIndex */ + hAss->streamMuxConfigBits += 6; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_HVXC: + p_linfo->frameLengthType = 6; + FDKwriteBits(hBs, p_linfo->frameLengthType, + 3); /* frameLengthType */ + hAss->streamMuxConfigBits += 3; + { + int i; + + if (p_lci->bitsFrame == 40) { + i = 0; + } else if (p_lci->bitsFrame == 80) { + i = 1; + } else { + return TRANSPORTENC_INVALID_FRAME_BITS; + } + FDKwriteBits(hBs, i, 1); /* HVXCframeLengthTableIndex */ + hAss->streamMuxConfigBits += 1; + } + p_linfo->frameLengthBits = p_lci->bitsFrame; + break; + + case AOT_NULL_OBJECT: + default: + return TRANSPORTENC_INVALID_AOT; + } + } + } + } + + FDKwriteBits(hBs, (hAss->otherDataLenBits > 0) ? 1 : 0, + 1); /* otherDataPresent */ + hAss->streamMuxConfigBits += 1; + + if (hAss->otherDataLenBits > 0) { + FDKwriteBits(hBs, 0, 1); + FDKwriteBits(hBs, hAss->otherDataLenBits, 8); + hAss->streamMuxConfigBits += 9; + } + + FDKwriteBits(hBs, 0, 1); /* crcCheckPresent=0 */ + hAss->streamMuxConfigBits += 1; + + } else { /* if ( audioMuxVersionA == 0 ) */ + + /* for future extensions */ + } + + return TRANSPORTENC_OK; +} + +static TRANSPORTENC_ERROR WriteAuPayloadLengthInfo( + HANDLE_FDK_BITSTREAM hBitStream, int AuLengthBits) { + int restBytes; + + if (AuLengthBits % 8) return TRANSPORTENC_INVALID_AU_LENGTH; + + while (AuLengthBits >= 255 * 8) { + FDKwriteBits(hBitStream, 255, 8); /* 255 shows incomplete AU */ + AuLengthBits -= (255 * 8); + } + + restBytes = (AuLengthBits) >> 3; + FDKwriteBits(hBitStream, restBytes, 8); + + return TRANSPORTENC_OK; +} + +static TRANSPORTENC_ERROR transportEnc_LatmSetNrOfSubframes( + HANDLE_LATM_STREAM hAss, INT noSubframes_next) /* nr of access units / + payloads within a latm + frame */ +{ + /* sanity chk */ + if (noSubframes_next < 1 || noSubframes_next > MAX_NR_OF_SUBFRAMES) { + return TRANSPORTENC_LATM_INVALID_NR_OF_SUBFRAMES; + } + + hAss->noSubframes_next = noSubframes_next; + + /* if at start then we can take over the value immediately, otherwise we have + * to wait for the next SMC */ + if ((hAss->subFrameCnt == 0) && (hAss->latmFrameCounter == 0)) { + hAss->noSubframes = noSubframes_next; + } + + return TRANSPORTENC_OK; +} + +static int allStreamsSameTimeFraming(HANDLE_LATM_STREAM hAss, UCHAR noProgram, + UCHAR noLayer[] /* return */) { + int prog, layer; + + signed int lastNoSamples = -1; + signed int minFrameSamples = FDK_INT_MAX; + signed int maxFrameSamples = 0; + + signed int highestSamplingRate = -1; + + for (prog = 0; prog < noProgram; prog++) { + noLayer[prog] = 0; + + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + if (hAss->config[prog][layer] != NULL) { + INT hsfSamplesFrame; + + noLayer[prog]++; + + if (highestSamplingRate < 0) + highestSamplingRate = hAss->config[prog][layer]->samplingRate; + + hsfSamplesFrame = hAss->config[prog][layer]->samplesPerFrame * + highestSamplingRate / + hAss->config[prog][layer]->samplingRate; + + if (hsfSamplesFrame <= minFrameSamples) + minFrameSamples = hsfSamplesFrame; + if (hsfSamplesFrame >= maxFrameSamples) + maxFrameSamples = hsfSamplesFrame; + + if (lastNoSamples == -1) { + lastNoSamples = hsfSamplesFrame; + } else { + if (hsfSamplesFrame != lastNoSamples) { + return 0; + } + } + } + } + } + + return 1; +} + +/** + * Initialize LATM/LOAS Stream and add layer 0 at program 0. + */ +static TRANSPORTENC_ERROR transportEnc_InitLatmStream( + HANDLE_LATM_STREAM hAss, int fractDelayPresent, + signed int + muxConfigPeriod, /* insert setup data every muxConfigPeriod frames */ + UINT audioMuxVersion, TRANSPORT_TYPE tt) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + if (hAss == NULL) return TRANSPORTENC_INVALID_PARAMETER; + + hAss->tt = tt; + + hAss->noProgram = 1; + + hAss->audioMuxVersion = audioMuxVersion; + + /* Fill noLayer array using hAss->config */ + hAss->allStreamsSameTimeFraming = + allStreamsSameTimeFraming(hAss, hAss->noProgram, hAss->noLayer); + /* Only allStreamsSameTimeFraming==1 is supported */ + FDK_ASSERT(hAss->allStreamsSameTimeFraming); + + hAss->fractDelayPresent = fractDelayPresent; + hAss->otherDataLenBits = 0; + + hAss->varMode = LATMVAR_SIMPLE_SEQUENCE; + + /* initialize counters */ + hAss->subFrameCnt = 0; + hAss->noSubframes = DEFAULT_LATM_NR_OF_SUBFRAMES; + hAss->noSubframes_next = DEFAULT_LATM_NR_OF_SUBFRAMES; + + /* sync layer related */ + hAss->audioMuxLengthBytes = 0; + + hAss->latmFrameCounter = 0; + hAss->muxConfigPeriod = muxConfigPeriod; + + return ErrorStatus; +} + +/** + * + */ +UINT transportEnc_LatmCountTotalBitDemandHeader(HANDLE_LATM_STREAM hAss, + unsigned int streamDataLength) { + UINT bitDemand = 0; + + switch (hAss->tt) { + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + if (hAss->subFrameCnt == 0) { + bitDemand = transportEnc_LatmCountFixBitDemandHeader(hAss); + } + bitDemand += transportEnc_LatmCountVarBitDemandHeader( + hAss, streamDataLength /*- bitDemand*/); + break; + default: + break; + } + + return bitDemand; +} + +static TRANSPORTENC_ERROR AdvanceAudioMuxElement(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int auBits, int bufferFullness, + CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + int insertMuxSetup; + + /* Insert setup data to assemble Buffer */ + if (hAss->subFrameCnt == 0) { + if (hAss->muxConfigPeriod > 0) { + insertMuxSetup = (hAss->latmFrameCounter == 0); + } else { + insertMuxSetup = 0; + } + + if (hAss->tt != TT_MP4_LATM_MCP0) { + if (insertMuxSetup) { + FDKwriteBits(hBs, 0, 1); /* useSameStreamMux useNewStreamMux */ + if (TRANSPORTENC_OK != (ErrorStatus = CreateStreamMuxConfig( + hAss, hBs, bufferFullness, cb))) { + return ErrorStatus; + } + } else { + FDKwriteBits(hBs, 1, 1); /* useSameStreamMux */ + } + } + } + + /* PayloadLengthInfo */ + { + int prog, layer; + + for (prog = 0; prog < hAss->noProgram; prog++) { + for (layer = 0; layer < hAss->noLayer[prog]; layer++) { + ErrorStatus = WriteAuPayloadLengthInfo(hBs, auBits); + if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus; + } + } + } + /* At this point comes the access unit. */ + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR +transportEnc_LatmWrite(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int auBits, int bufferFullness, CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus; + + if (hAss->subFrameCnt == 0) { + /* Start new frame */ + FDKresetBitbuffer(hBs, BS_WRITER); + } + + hAss->latmSubframeStart = FDKgetValidBits(hBs); + + /* Insert syncword and syncword distance + - only if loas + - we must update the syncword distance (=audiomuxlengthbytes) later + */ + if (hAss->tt == TT_MP4_LOAS && hAss->subFrameCnt == 0) { + /* Start new LOAS frame */ + FDKwriteBits(hBs, 0x2B7, 11); + hAss->audioMuxLengthBytes = 0; + hAss->audioMuxLengthBytesPos = + FDKgetValidBits(hBs); /* store read pointer position */ + FDKwriteBits(hBs, hAss->audioMuxLengthBytes, 13); + } + + ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, auBits, bufferFullness, cb); + + if (ErrorStatus != TRANSPORTENC_OK) return ErrorStatus; + + return ErrorStatus; +} + +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, int *bits) { + /* Substract bits from possible previous subframe */ + *bits -= hAss->latmSubframeStart; + /* Add fill bits */ + if (hAss->subFrameCnt == 0) { + *bits += hAss->otherDataLenBits; + *bits += hAss->fillBits; + } +} + +TRANSPORTENC_ERROR transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *pBytes) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + hAss->subFrameCnt++; + if (hAss->subFrameCnt >= hAss->noSubframes) { + /* Add LOAS frame length if required. */ + if (hAss->tt == TT_MP4_LOAS) { + FDK_BITSTREAM tmpBuf; + + /* Determine frame length info */ + hAss->audioMuxLengthBytes = + ((FDKgetValidBits(hBs) + hAss->otherDataLenBits + 7) >> 3) - + 3; /* 3=Syncword + length */ + + /* Check frame length info */ + if (hAss->audioMuxLengthBytes >= (1 << 13)) { + ErrorStatus = TRANSPORTENC_INVALID_AU_LENGTH; + goto bail; + } + + /* Write length info into assembler buffer */ + FDKinitBitStream(&tmpBuf, hBs->hBitBuf.Buffer, hBs->hBitBuf.bufSize, 0, + BS_WRITER); + FDKpushFor(&tmpBuf, hAss->audioMuxLengthBytesPos); + FDKwriteBits(&tmpBuf, hAss->audioMuxLengthBytes, 13); + FDKsyncCache(&tmpBuf); + } + + /* Write AudioMuxElement other data bits */ + FDKwriteBits(hBs, 0, hAss->otherDataLenBits); + + /* Write AudioMuxElement byte alignment fill bits */ + FDKwriteBits(hBs, 0, hAss->fillBits); + + FDK_ASSERT((FDKgetValidBits(hBs) % 8) == 0); + + hAss->subFrameCnt = 0; + + FDKsyncCache(hBs); + *pBytes = (FDKgetValidBits(hBs) + 7) >> 3; + + if (hAss->muxConfigPeriod > 0) { + hAss->latmFrameCounter++; + + if (hAss->latmFrameCounter >= hAss->muxConfigPeriod) { + hAss->latmFrameCounter = 0; + hAss->noSubframes = hAss->noSubframes_next; + } + } + } else { + /* No data this time */ + *pBytes = 0; + } + +bail: + return ErrorStatus; +} + +/** + * Init LATM/LOAS + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, + CSTpCallBacks *cb) { + TRANSPORTENC_ERROR ErrorStatus; + int fractDelayPresent = 0; + int prog, layer; + + int setupDataDistanceFrames = layerConfig->headerPeriod; + + FDK_ASSERT(setupDataDistanceFrames >= 0); + + for (prog = 0; prog < LATM_MAX_PROGRAMS; prog++) { + for (layer = 0; layer < LATM_MAX_LAYERS; layer++) { + hAss->config[prog][layer] = NULL; + hAss->m_linfo[prog][layer].streamID = -1; + } + } + + hAss->config[0][0] = layerConfig; + hAss->m_linfo[0][0].streamID = 0; + + ErrorStatus = transportEnc_InitLatmStream(hAss, fractDelayPresent, + setupDataDistanceFrames, + (audioMuxVersion) ? 1 : 0, tt); + if (ErrorStatus != TRANSPORTENC_OK) goto bail; + + ErrorStatus = + transportEnc_LatmSetNrOfSubframes(hAss, layerConfig->nSubFrames); + if (ErrorStatus != TRANSPORTENC_OK) goto bail; + + /* Get the size of the StreamMuxConfig somehow */ + if (TRANSPORTENC_OK != + (ErrorStatus = AdvanceAudioMuxElement(hAss, hBs, 0, 0, cb))) { + goto bail; + } + + // CreateStreamMuxConfig(hAss, hBs, 0); + +bail: + return ErrorStatus; +} + +TRANSPORTENC_ERROR transportEnc_LatmAddOtherDataBits(HANDLE_LATM_STREAM hAss, + const int otherDataBits) { + TRANSPORTENC_ERROR ErrorStatus = TRANSPORTENC_OK; + + if ((hAss->otherDataLenBits != 0) || (otherDataBits % 8 != 0)) { + /* This implementation allows to add other data bits only once. + To keep existing alignment only whole bytes are allowed. */ + ErrorStatus = TRANSPORTENC_UNKOWN_ERROR; + } else { + /* Ensure correct addional bits in payload. */ + if (hAss->tt == TT_MP4_LATM_MCP0) { + hAss->otherDataLenBits = otherDataBits; + } else { + hAss->otherDataLenBits = otherDataBits - 9; + hAss->streamMuxConfigBits += 9; + } + } + + return ErrorStatus; +} diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_latm.h b/fdk-aac/libMpegTPEnc/src/tpenc_latm.h new file mode 100644 index 0000000..d650357 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_latm.h @@ -0,0 +1,274 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef TPENC_LATM_H +#define TPENC_LATM_H + +#include "tpenc_lib.h" +#include "FDK_bitstream.h" + +#define DEFAULT_LATM_NR_OF_SUBFRAMES 1 +#define DEFAULT_LATM_SMC_REPEAT 8 + +#define MAX_AAC_LAYERS 9 + +#define LATM_MAX_PROGRAMS 1 +#define LATM_MAX_STREAM_ID 16 + +#define LATM_MAX_LAYERS 1 /*MAX_AAC_LAYERS*/ + +#define MAX_NR_OF_SUBFRAMES \ + 2 /* set this carefully to avoid buffer overflows \ + */ + +typedef enum { LATMVAR_SIMPLE_SEQUENCE } LATM_VAR_MODE; + +typedef struct { + signed int frameLengthType; + signed int frameLengthBits; + signed int varFrameLengthTable[4]; + signed int streamID; +} LATM_LAYER_INFO; + +typedef struct { + LATM_LAYER_INFO m_linfo[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + CODER_CONFIG *config[LATM_MAX_PROGRAMS][LATM_MAX_LAYERS]; + + LATM_VAR_MODE varMode; + TRANSPORT_TYPE tt; + + int audioMuxLengthBytes; + + int audioMuxLengthBytesPos; + int taraBufferFullness; /* state of the bit reservoir */ + int varStreamCnt; + + UCHAR + latmFrameCounter; /* Current frame number. Counts modulo muxConfigPeriod + */ + UCHAR muxConfigPeriod; /* Distance in frames between MuxConfig */ + + UCHAR + audioMuxVersion; /* AMV1 supports transmission of taraBufferFullness and + ASC lengths */ + UCHAR audioMuxVersionA; /* for future extensions */ + + UCHAR noProgram; + UCHAR noLayer[LATM_MAX_PROGRAMS]; + UCHAR fractDelayPresent; + + UCHAR allStreamsSameTimeFraming; + UCHAR subFrameCnt; /* Current Subframe frame */ + UCHAR noSubframes; /* Number of subframes */ + UINT latmSubframeStart; /* Position of current subframe start */ + UCHAR noSubframes_next; + + UCHAR otherDataLenBits; /* AudioMuxElement other data bits */ + UCHAR fillBits; /* AudioMuxElement fill bits */ + UINT streamMuxConfigBits; + +} LATM_STREAM; + +typedef LATM_STREAM *HANDLE_LATM_STREAM; + +/** + * \brief Initialize LATM_STREAM Handle. Creates automatically one program with + * one layer with the given layerConfig. The layerConfig must be persisten + * because references to this pointer are made at any time again. Use + * transportEnc_Latm_AddLayer() to add more programs/layers. + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param layerConfig a valid CODER_CONFIG struct containing the current audio + * configuration parameters + * \param audioMuxVersion the LATM audioMuxVersion to be used + * \param tt the specific TRANSPORT_TYPE to be used, either TT_MP4_LOAS, + * TT_MP4_LATM_MCP1 or TT_MP4_LATM_MCP0 LOAS + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_Latm_Init(HANDLE_LATM_STREAM hLatmStreamInfo, + HANDLE_FDK_BITSTREAM hBs, + CODER_CONFIG *layerConfig, + UINT audioMuxVersion, + TRANSPORT_TYPE tt, CSTpCallBacks *cb); + +/** + * \brief Write addional other data bits in AudioMuxElement + * + * \param hAss HANDLE_LATM_STREAM handle + * \param otherDataBits number of other data bits to be written + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_LatmAddOtherDataBits(HANDLE_LATM_STREAM hAss, + const int otherDataBits); + +/** + * \brief Get bit demand of next LATM/LOAS header + * + * \param hAss HANDLE_LATM_STREAM handle + * \param streamDataLength the length of the payload + * + * \return the number of bits required by the LATM/LOAS headers + */ +unsigned int transportEnc_LatmCountTotalBitDemandHeader( + HANDLE_LATM_STREAM hAss, unsigned int streamDataLength); + +/** + * \brief Write LATM/LOAS header into given bitstream handle + * + * \param hLatmStreamInfo HANDLE_LATM_STREAM handle + * \param hBitstream Bitstream handle + * \param auBits amount of current payload bits + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR +transportEnc_LatmWrite(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBitstream, + int auBits, int bufferFullness, CSTpCallBacks *cb); + +/** + * \brief Adjust bit count relative to current subframe + * + * \param hAss HANDLE_LATM_STREAM handle + * \param pBits pointer to an int, where the current frame bit count is + * contained, and where the subframe relative bit count will be returned into + * + * \return void + */ +void transportEnc_LatmAdjustSubframeBits(HANDLE_LATM_STREAM hAss, int *pBits); + +/** + * \brief Request an LATM frame, which may, or may not be available + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param pBytes pointer to an int, where the current frame byte count stored + * into. A return value of zero means that currently no LATM/LOAS frame can be + * returned. The latter is expected in case of multiple subframes being + * used. + * + * \return an TRANSPORTENC_ERROR error code + */ +TRANSPORTENC_ERROR transportEnc_LatmGetFrame(HANDLE_LATM_STREAM hAss, + HANDLE_FDK_BITSTREAM hBs, + int *pBytes); + +/** + * \brief Write a StreamMuxConfig into the given bitstream handle + * + * \param hAss HANDLE_LATM_STREAM handle + * \param hBs Bitstream handle + * \param bufferFullness LATM buffer fullness value + * \param cb callback information structure. + * + * \return void + */ +TRANSPORTENC_ERROR +CreateStreamMuxConfig(HANDLE_LATM_STREAM hAss, HANDLE_FDK_BITSTREAM hBs, + int bufferFullness, CSTpCallBacks *cb); + +#endif /* TPENC_LATM_H */ diff --git a/fdk-aac/libMpegTPEnc/src/tpenc_lib.cpp b/fdk-aac/libMpegTPEnc/src/tpenc_lib.cpp new file mode 100644 index 0000000..316c6e0 --- /dev/null +++ b/fdk-aac/libMpegTPEnc/src/tpenc_lib.cpp @@ -0,0 +1,713 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/******************* MPEG transport format encoder library ********************* + + Author(s): Manuel Jander + + Description: MPEG Transport encode + +*******************************************************************************/ + +#include "tpenc_lib.h" + +/* library info */ +#include "tp_version.h" + +#define MODULE_NAME "transportEnc" + +#include "tpenc_asc.h" + +#include "tpenc_adts.h" + +#include "tpenc_adif.h" + +#include "tpenc_dab.h" + +#include "tpenc_latm.h" + +typedef struct { + int curSubFrame; + int nSubFrames; + int prevBits; +} RAWPACKETS_INFO; + +struct TRANSPORTENC { + CODER_CONFIG config; + TRANSPORT_TYPE transportFmt; /*!< MPEG4 transport type. */ + + FDK_BITSTREAM bitStream; + UCHAR *bsBuffer; + INT bsBufferSize; + + INT pceFrameCounter; /*!< Indicates frame period when PCE must be written in + raw_data_block. -1 means not to write a PCE in + raw_dat_block. */ + union { + STRUCT_ADTS adts; + + ADIF_INFO adif; + + STRUCT_DAB dab; + + LATM_STREAM latm; + + RAWPACKETS_INFO raw; + + } writer; + + CSTpCallBacks callbacks; +}; + +typedef struct _TRANSPORTENC_STRUCT TRANSPORTENC_STRUCT; + +/* + * MEMORY Declaration + */ + +C_ALLOC_MEM(Ram_TransportEncoder, struct TRANSPORTENC, 1) + +TRANSPORTENC_ERROR transportEnc_Open(HANDLE_TRANSPORTENC *phTpEnc) { + HANDLE_TRANSPORTENC hTpEnc; + + if (phTpEnc == NULL) { + return TRANSPORTENC_INVALID_PARAMETER; + } + + hTpEnc = GetRam_TransportEncoder(0); + + if (hTpEnc == NULL) { + return TRANSPORTENC_NO_MEM; + } + + *phTpEnc = hTpEnc; + return TRANSPORTENC_OK; +} + +/** + * \brief Get frame period of PCE in raw_data_block. + * + * - Write PCE only if necessary. PCE can be part of the ASC if chConfig==0 + * whererfore no additonal PCE will be written in raw_data_block. + * - A matrixMixdown coefficient can only be written if chConfig is 5.0 or 5.1. + * - The PCE repetition rate in raw_data_block can be controlled via + * headerPeriod parameter. + * + * \param channelMode Encoder Channel Mode. + * \param channelConfigZero No standard channel configuration. + * \param transportFmt Format of the transport to be written. + * \param headerPeriod Chosen PCE frame repetition rate. + * \param matrixMixdownA Indicates if a valid Matrix Mixdown coefficient + * is available. + * + * \return PCE frame repetition rate. -1 means no PCE present in + * raw_data_block. + */ +static INT getPceRepetitionRate(const CHANNEL_MODE channelMode, + const int channelConfigZero, + const TRANSPORT_TYPE transportFmt, + const int headerPeriod, + const int matrixMixdownA) { + INT pceFrameCounter = -1; /* variable to be returned */ + + if (headerPeriod > 0) { + switch (getChannelConfig(channelMode, channelConfigZero)) { + case 0: + switch (transportFmt) { + case TT_MP4_ADTS: + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + if ((channelMode == MODE_1_2_2) || (channelMode == MODE_1_2_2_1)) { + pceFrameCounter = headerPeriod; /* repeating pce only meaningful + for potential matrix mixdown */ + break; + } + FDK_FALLTHROUGH; + case TT_MP4_LOAS: /* PCE in ASC if chChonfig==0 */ + case TT_MP4_LATM_MCP1: /* PCE in ASC if chChonfig==0 */ + case TT_DABPLUS: + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + break; + case 5: /* MODE_1_2_2 */ + case 6: /* MODE_1_2_2_1 */ + /* matrixMixdownCoefficient can only be written if 5.0 and 5.1 config + * present. */ + if (matrixMixdownA != 0) { + switch (transportFmt) { + case TT_MP4_ADIF: /* ADIF header comprises PCE */ + case TT_MP4_ADTS: + case TT_MP4_LOAS: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP1: /* no PCE in ASC because chConfig!=0 */ + case TT_MP4_LATM_MCP0: + case TT_MP4_RAW: + pceFrameCounter = headerPeriod; + break; + case TT_DABPLUS: + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch transportFmt */ + } /* if matrixMixdownA!=0 */ + break; + default: + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } /* switch getChannelConfig() */ + } /* if headerPeriod>0 */ + else { + pceFrameCounter = -1; /* no PCE in raw_data_block */ + } + + return pceFrameCounter; +} + +TRANSPORTENC_ERROR transportEnc_Init(HANDLE_TRANSPORTENC hTpEnc, + UCHAR *bsBuffer, INT bsBufferSize, + TRANSPORT_TYPE transportFmt, + CODER_CONFIG *cconfig, UINT flags) { + /* Copy configuration structure */ + FDKmemcpy(&hTpEnc->config, cconfig, sizeof(CODER_CONFIG)); + + /* Init transportEnc struct. */ + hTpEnc->transportFmt = transportFmt; + + hTpEnc->bsBuffer = bsBuffer; + hTpEnc->bsBufferSize = bsBufferSize; + + FDKinitBitStream(&hTpEnc->bitStream, hTpEnc->bsBuffer, hTpEnc->bsBufferSize, + 0, BS_WRITER); + + switch (transportFmt) { + case TT_MP4_ADIF: + /* Sanity checks */ + if ((hTpEnc->config.aot != AOT_AAC_LC) || + (hTpEnc->config.samplesPerFrame != 1024)) { + return TRANSPORTENC_INVALID_PARAMETER; + } + hTpEnc->writer.adif.headerWritten = 0; + hTpEnc->writer.adif.samplingRate = hTpEnc->config.samplingRate; + hTpEnc->writer.adif.bitRate = hTpEnc->config.bitRate; + hTpEnc->writer.adif.profile = ((int)hTpEnc->config.aot) - 1; + hTpEnc->writer.adif.cm = hTpEnc->config.channelMode; + hTpEnc->writer.adif.bVariableRate = 0; + hTpEnc->writer.adif.instanceTag = 0; + hTpEnc->writer.adif.matrixMixdownA = hTpEnc->config.matrixMixdownA; + hTpEnc->writer.adif.pseudoSurroundEnable = + (hTpEnc->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0; + break; + + case TT_MP4_ADTS: + /* Sanity checks */ + if ((hTpEnc->config.aot != AOT_AAC_LC) || + (hTpEnc->config.samplesPerFrame != 1024)) { + return TRANSPORTENC_INVALID_PARAMETER; + } + if (adtsWrite_Init(&hTpEnc->writer.adts, &hTpEnc->config) != 0) { + return TRANSPORTENC_INVALID_PARAMETER; + } + break; + + case TT_DABPLUS: + /* Sanity checks */ + if ( ( hTpEnc->config.aot != AOT_AAC_LC) + ||(hTpEnc->config.samplesPerFrame != 960) ) + { + return TRANSPORTENC_INVALID_PARAMETER; + } + if ( dabWrite_Init(&hTpEnc->writer.dab, &hTpEnc->config) != 0) { + return TRANSPORTENC_INVALID_PARAMETER; + } + break; + + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: { + TRANSPORTENC_ERROR error; + + error = transportEnc_Latm_Init(&hTpEnc->writer.latm, &hTpEnc->bitStream, + &hTpEnc->config, flags & TP_FLAG_LATM_AMV, + transportFmt, &hTpEnc->callbacks); + if (error != TRANSPORTENC_OK) { + return error; + } + } break; + + case TT_MP4_RAW: + hTpEnc->writer.raw.curSubFrame = 0; + hTpEnc->writer.raw.nSubFrames = hTpEnc->config.nSubFrames; + break; + + default: + return TRANSPORTENC_INVALID_PARAMETER; + } + + /* pceFrameCounter indicates if PCE must be written in raw_data_block. */ + hTpEnc->pceFrameCounter = getPceRepetitionRate( + hTpEnc->config.channelMode, hTpEnc->config.channelConfigZero, + transportFmt, hTpEnc->config.headerPeriod, hTpEnc->config.matrixMixdownA); + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR transportEnc_AddOtherDataBits(HANDLE_TRANSPORTENC hTpEnc, + const int nBits) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + tpErr = transportEnc_LatmAddOtherDataBits(&hTpEnc->writer.latm, nBits); + break; + case TT_MP4_ADTS: + case TT_MP4_ADIF: + case TT_MP4_RAW: + default: + tpErr = TRANSPORTENC_UNKOWN_ERROR; + } + + return tpErr; +} + +HANDLE_FDK_BITSTREAM transportEnc_GetBitstream(HANDLE_TRANSPORTENC hTp) { + return &hTp->bitStream; +} + +int transportEnc_RegisterSbrCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSbr_t cbSbr, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbSbr = cbSbr; + hTpEnc->callbacks.cbSbrData = user_data; + return 0; +} +int transportEnc_RegisterUsacCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbUsac_t cbUsac, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbUsac = cbUsac; + hTpEnc->callbacks.cbUsacData = user_data; + return 0; +} + +int transportEnc_RegisterSscCallback(HANDLE_TRANSPORTENC hTpEnc, + const cbSsc_t cbSsc, void *user_data) { + if (hTpEnc == NULL) { + return -1; + } + hTpEnc->callbacks.cbSsc = cbSsc; + hTpEnc->callbacks.cbSscData = user_data; + return 0; +} + +TRANSPORTENC_ERROR transportEnc_WriteAccessUnit(HANDLE_TRANSPORTENC hTp, + INT frameUsedBits, + int bufferFullness, int ncc) { + TRANSPORTENC_ERROR err = TRANSPORTENC_OK; + + if (!hTp) { + return TRANSPORTENC_INVALID_PARAMETER; + } + HANDLE_FDK_BITSTREAM hBs = &hTp->bitStream; + + /* In case of writing PCE in raw_data_block frameUsedBits must be adapted. */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + frameUsedBits += transportEnc_GetPCEBits( + hTp->config.channelMode, hTp->config.matrixMixdownA, + 3); /* Consider 3 bits ID signalling in alignment */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, + BS_WRITER); + if (0 != adifWrite_EncodeHeader(&hTp->writer.adif, hBs, bufferFullness)) { + err = TRANSPORTENC_INVALID_CONFIG; + } + break; + case TT_MP4_ADTS: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ + adtsWrite_EncodeHeader(&hTp->writer.adts, &hTp->bitStream, bufferFullness, + frameUsedBits); + break; + case TT_DABPLUS: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0x7FF, bufferFullness); /* Signal variable rate */ + dabWrite_EncodeHeader( + &hTp->writer.dab, + &hTp->bitStream, + bufferFullness, + frameUsedBits + ); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + bufferFullness /= ncc; /* Number of Considered Channels */ + bufferFullness /= 32; + bufferFullness = FDKmin(0xFF, bufferFullness); /* Signal variable rate */ + transportEnc_LatmWrite(&hTp->writer.latm, hBs, frameUsedBits, + bufferFullness, &hTp->callbacks); + break; + case TT_MP4_RAW: + if (hTp->writer.raw.curSubFrame >= hTp->writer.raw.nSubFrames) { + hTp->writer.raw.curSubFrame = 0; + FDKinitBitStream(&hTp->bitStream, hTp->bsBuffer, hTp->bsBufferSize, 0, + BS_WRITER); + } + hTp->writer.raw.prevBits = FDKgetValidBits(hBs); + break; + default: + err = TRANSPORTENC_UNSUPPORTED_FORMAT; + break; + } + + /* Write PCE in raw_data_block if required */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + INT crcIndex = 0; + /* Align inside PCE with repsect to the first bit of the raw_data_block() */ + UINT alignAnchor = FDKgetValidBits(&hTp->bitStream); + + /* Write PCE element ID bits */ + FDKwriteBits(&hTp->bitStream, ID_PCE, 3); + + if ((hTp->transportFmt == TT_MP4_ADTS) && + !hTp->writer.adts.protection_absent) { + crcIndex = adtsWrite_CrcStartReg(&hTp->writer.adts, &hTp->bitStream, 0); + } + + /* Write PCE as first raw_data_block element */ + transportEnc_writePCE( + &hTp->bitStream, hTp->config.channelMode, hTp->config.samplingRate, 0, + 1, hTp->config.matrixMixdownA, + (hTp->config.flags & CC_PSEUDO_SURROUND) ? 1 : 0, alignAnchor); + + if ((hTp->transportFmt == TT_MP4_ADTS) && + !hTp->writer.adts.protection_absent) { + adtsWrite_CrcEndReg(&hTp->writer.adts, &hTp->bitStream, crcIndex); + } + hTp->pceFrameCounter = 0; /* reset pce frame counter */ + } + + if (hTp->pceFrameCounter != -1) { + hTp->pceFrameCounter++; /* Update pceFrameCounter only if PCE writing is + active. */ + } + + return err; +} + +TRANSPORTENC_ERROR transportEnc_EndAccessUnit(HANDLE_TRANSPORTENC hTp, + int *bits) { + switch (hTp->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + transportEnc_LatmAdjustSubframeBits(&hTp->writer.latm, bits); + break; + case TT_MP4_ADTS: + adtsWrite_EndRawDataBlock(&hTp->writer.adts, &hTp->bitStream, bits); + break; + case TT_DABPLUS: + dabWrite_EndRawDataBlock(&hTp->writer.dab, &hTp->bitStream, bits); + break; + case TT_MP4_ADIF: + /* Substract ADIF header from AU bits, not to be considered. */ + *bits -= adifWrite_GetHeaderBits(&hTp->writer.adif); + hTp->writer.adif.headerWritten = 1; + break; + case TT_MP4_RAW: + *bits -= hTp->writer.raw.prevBits; + break; + default: + break; + } + + return TRANSPORTENC_OK; +} + +TRANSPORTENC_ERROR transportEnc_GetFrame(HANDLE_TRANSPORTENC hTpEnc, + int *nbytes) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + HANDLE_FDK_BITSTREAM hBs = &hTpEnc->bitStream; + + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + *nbytes = hTpEnc->bsBufferSize; + tpErr = transportEnc_LatmGetFrame(&hTpEnc->writer.latm, hBs, nbytes); + break; + case TT_MP4_ADTS: + if (hTpEnc->writer.adts.currentBlock >= + hTpEnc->writer.adts.num_raw_blocks + 1) { + *nbytes = (FDKgetValidBits(hBs) + 7) >> 3; + hTpEnc->writer.adts.currentBlock = 0; + } else { + *nbytes = 0; + } + break; + case TT_DABPLUS: + if (hTpEnc->writer.dab.currentBlock >= hTpEnc->writer.dab.num_raw_blocks+1) { + *nbytes = (FDKgetValidBits(hBs) + 7)>>3; + hTpEnc->writer.dab.currentBlock = 0; + } else { + *nbytes = 0; + } + break; + case TT_MP4_ADIF: + FDK_ASSERT((INT)FDKgetValidBits(hBs) >= 0); + *nbytes = (FDKgetValidBits(hBs) + 7) >> 3; + break; + case TT_MP4_RAW: + FDKsyncCache(hBs); + hTpEnc->writer.raw.curSubFrame++; + *nbytes = ((FDKgetValidBits(hBs) - hTpEnc->writer.raw.prevBits) + 7) >> 3; + break; + default: + break; + } + + return tpErr; +} + +INT transportEnc_GetStaticBits(HANDLE_TRANSPORTENC hTp, int auBits) { + INT nbits = 0, nPceBits = 0; + + /* Write PCE within raw_data_block in transport lib. */ + if (hTp->pceFrameCounter >= hTp->config.headerPeriod) { + nPceBits = transportEnc_GetPCEBits( + hTp->config.channelMode, hTp->config.matrixMixdownA, + 3); /* Consider 3 bits ID signalling in alignment */ + auBits += nPceBits; /* Adapt required raw_data_block bit consumtpion for AU + length information e.g. in LATM/LOAS configuration. + */ + } + + switch (hTp->transportFmt) { + case TT_MP4_ADIF: + case TT_MP4_RAW: + nbits = 0; /* Do not consider the ADIF header into the total bitrate */ + break; + case TT_MP4_ADTS: + nbits = adtsWrite_GetHeaderBits(&hTp->writer.adts); + break; + case TT_DABPLUS: + nbits = dabWrite_CountTotalBitDemandHeader(&hTp->writer.dab, auBits); + break; + case TT_MP4_LOAS: + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + nbits = + transportEnc_LatmCountTotalBitDemandHeader(&hTp->writer.latm, auBits); + break; + default: + nbits = 0; + break; + } + + /* PCE is written in the transport library therefore the bit consumption is + * part of the transport static bits. */ + nbits += nPceBits; + + return nbits; +} + +void transportEnc_Close(HANDLE_TRANSPORTENC *phTp) { + if (phTp != NULL) { + if (*phTp != NULL) { + FreeRam_TransportEncoder(phTp); + } + } +} + +int transportEnc_CrcStartReg(HANDLE_TRANSPORTENC hTpEnc, int mBits) { + int crcReg = 0; + + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + crcReg = adtsWrite_CrcStartReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, + mBits); + break; + case TT_DABPLUS: + crcReg = dabWrite_CrcStartReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, mBits); + break; + default: + break; + } + + return crcReg; +} + +void transportEnc_CrcEndReg(HANDLE_TRANSPORTENC hTpEnc, int reg) { + switch (hTpEnc->transportFmt) { + case TT_MP4_ADTS: + adtsWrite_CrcEndReg(&hTpEnc->writer.adts, &hTpEnc->bitStream, reg); + break; + case TT_DABPLUS: + dabWrite_CrcEndReg(&hTpEnc->writer.dab, &hTpEnc->bitStream, reg); + break; + default: + break; + } +} + +TRANSPORTENC_ERROR transportEnc_GetConf(HANDLE_TRANSPORTENC hTpEnc, + CODER_CONFIG *cc, + FDK_BITSTREAM *dataBuffer, + UINT *confType) { + TRANSPORTENC_ERROR tpErr = TRANSPORTENC_OK; + HANDLE_LATM_STREAM hLatmConfig = &hTpEnc->writer.latm; + + *confType = 0; /* set confType variable to default */ + + /* write StreamMuxConfig or AudioSpecificConfig depending on format used */ + switch (hTpEnc->transportFmt) { + case TT_MP4_LATM_MCP0: + case TT_MP4_LATM_MCP1: + case TT_MP4_LOAS: + tpErr = + CreateStreamMuxConfig(hLatmConfig, dataBuffer, 0, &hTpEnc->callbacks); + *confType = 1; /* config is SMC */ + break; + default: + if (transportEnc_writeASC(dataBuffer, cc, &hTpEnc->callbacks) != 0) { + tpErr = TRANSPORTENC_UNKOWN_ERROR; + } + } + + return tpErr; +} + +TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return TRANSPORTENC_INVALID_PARAMETER; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return TRANSPORTENC_UNKOWN_ERROR; + } + info += i; + + info->module_id = FDK_TPENC; + info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = TP_LIB_TITLE; + + /* Set flags */ + info->flags = + 0 | CAPF_ADIF | CAPF_ADTS | CAPF_LATM | CAPF_LOAS | CAPF_RAWPACKETS | CAPF_DAB_AAC; + + return TRANSPORTENC_OK; +} diff --git a/fdk-aac/libPCMutils/include/limiter.h b/fdk-aac/libPCMutils/include/limiter.h new file mode 100644 index 0000000..fab7226 --- /dev/null +++ b/fdk-aac/libPCMutils/include/limiter.h @@ -0,0 +1,281 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Matthias Neusinger + + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#ifndef LIMITER_H +#define LIMITER_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#define TDL_ATTACK_DEFAULT_MS (15) /* default attack time in ms */ +#define TDL_RELEASE_DEFAULT_MS (50) /* default release time in ms */ + +#define TDL_GAIN_SCALING (15) /* scaling of gain value. */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct TDLimiter { + unsigned int attack; + FIXP_DBL attackConst, releaseConst; + unsigned int attackMs, releaseMs, maxAttackMs; + FIXP_DBL threshold; + unsigned int channels, maxChannels; + UINT sampleRate, maxSampleRate; + FIXP_DBL cor, max; + FIXP_DBL* maxBuf; + FIXP_DBL* delayBuf; + unsigned int maxBufIdx, delayBufIdx; + FIXP_DBL smoothState0; + FIXP_DBL minGain; + + FIXP_DBL additionalGainPrev; + FIXP_DBL additionalGainFilterState; + FIXP_DBL additionalGainFilterState1; +}; + +typedef enum { + TDLIMIT_OK = 0, + TDLIMIT_UNKNOWN = -1, + + __error_codes_start = -100, + + TDLIMIT_INVALID_HANDLE, + TDLIMIT_INVALID_PARAMETER, + + __error_codes_end +} TDLIMITER_ERROR; + +struct TDLimiter; +typedef struct TDLimiter* TDLimiterPtr; + +#define PCM_LIM LONG +#define FIXP_DBL2PCM_LIM(x) (x) +#define PCM_LIM2FIXP_DBL(x) (x) +#define PCM_LIM_BITS 32 +#define FIXP_PCM_LIM FIXP_DBL + +#define SAMPLE_BITS_LIM DFRACT_BITS + +/****************************************************************************** + * pcmLimiter_Reset * + * limiter: limiter handle * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_Destroy * + * limiter: limiter handle * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_GetDelay * + * limiter: limiter handle * + * returns: exact delay caused by the limiter in samples per channel * + ******************************************************************************/ +unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_GetMaxGainReduction * + * limiter: limiter handle * + * returns: maximum gain reduction in last processed block in dB * + ******************************************************************************/ +INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter); + +/****************************************************************************** + * pcmLimiter_SetNChannels * + * limiter: limiter handle * + * nChannels: number of channels ( <= maxChannels specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter, + unsigned int nChannels); + +/****************************************************************************** + * pcmLimiter_SetSampleRate * + * limiter: limiter handle * + * sampleRate: sampling rate in Hz ( <= maxSampleRate specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter, UINT sampleRate); + +/****************************************************************************** + * pcmLimiter_SetAttack * + * limiter: limiter handle * + * attackMs: attack time in ms ( <= maxAttackMs specified on create) * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter, + unsigned int attackMs); + +/****************************************************************************** + * pcmLimiter_SetRelease * + * limiter: limiter handle * + * releaseMs: release time in ms * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter, + unsigned int releaseMs); + +/****************************************************************************** + * pcmLimiter_GetLibInfo * + * info: pointer to an allocated and initialized LIB_INFO structure * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info); + +#ifdef __cplusplus +} +#endif + +/****************************************************************************** + * pcmLimiter_Create * + * maxAttackMs: maximum and initial attack/lookahead time in milliseconds * + * releaseMs: release time in milliseconds (90% time constant) * + * threshold: limiting threshold * + * maxChannels: maximum and initial number of channels * + * maxSampleRate: maximum and initial sampling rate in Hz * + * returns: limiter handle * + ******************************************************************************/ +TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, + FIXP_DBL threshold, unsigned int maxChannels, + UINT maxSampleRate); + +/****************************************************************************** + * pcmLimiter_SetThreshold * + * limiter: limiter handle * + * threshold: limiter threshold * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, + FIXP_DBL threshold); + +/****************************************************************************** + * pcmLimiter_Apply * + * limiter: limiter handle * + * pGain : pointer to gains to be applied to the signal before limiting, * + * which are downscaled by TDL_GAIN_SCALING bit. * + * These gains are delayed by gain_delay, and smoothed. * + * Smoothing is done by a butterworth lowpass filter with a cutoff * + * frequency which is fixed with respect to the sampling rate. * + * It is a substitute for the smoothing due to windowing and * + * overlap/add, if a gain is applied in frequency domain. * + * gain_scale: pointer to scaling exponents to be applied to the signal before * + * limiting, without delay and without smoothing * + * gain_size: number of elements in pGain, currently restricted to 1 * + * gain_delay: delay [samples] with which the gains in pGain shall be applied * + * gain_delay <= nSamples * + * samples: input/output buffer containing interleaved samples * + * precision of output will be DFRACT_BITS-TDL_GAIN_SCALING bits * + * nSamples: number of samples per channel * + * returns: error code * + ******************************************************************************/ +TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, + INT_PCM* samplesOut, FIXP_DBL* pGain, + const INT* gain_scale, const UINT gain_size, + const UINT gain_delay, const UINT nSamples); + +#endif /* #ifndef LIMITER_H */ diff --git a/fdk-aac/libPCMutils/include/pcm_utils.h b/fdk-aac/libPCMutils/include/pcm_utils.h new file mode 100644 index 0000000..073bcfc --- /dev/null +++ b/fdk-aac/libPCMutils/include/pcm_utils.h @@ -0,0 +1,131 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Alfonso Pino Garcia + + Description: Functions that perform (de)interleaving combined with format +change + +*******************************************************************************/ + +#if !defined(PCM_UTILS_H) +#define PCM_UTILS_H + +#include "common_fix.h" + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_interleave(const FIXP_SGL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); + +void FDK_deinterleave(const LONG *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const LONG *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const SHORT *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +void FDK_deinterleave(const SHORT *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length); +#endif /* !defined(PCM_UTILS_H) */ diff --git a/fdk-aac/libPCMutils/include/pcmdmx_lib.h b/fdk-aac/libPCMutils/include/pcmdmx_lib.h new file mode 100644 index 0000000..d37a851 --- /dev/null +++ b/fdk-aac/libPCMutils/include/pcmdmx_lib.h @@ -0,0 +1,460 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Christian Griebel + + Description: + +*******************************************************************************/ + +/** + * \file pcmdmx_lib.h + * \brief FDK PCM audio mixdown library interface header file. + + \page INTRO Introduction + + + \section SCOPE Scope + + This document describes the high-level application interface and usage of the + FDK PCM audio mixdown module library developed by the Fraunhofer Institute for + Integrated Circuits (IIS). Depending on the library configuration, the module + can manipulate the number of audio channels of a given PCM signal. It can + create for example a two channel stereo audio signal from a given multi-channel + configuration (e.g. 5.1 channels). + + + \page ABBREV List of abbreviations + + \li \b AAC - Advanced Audio Coding\n + Is an audio coding standard for lossy digital audio compression standardized + by ISO and IEC, as part of the MPEG-2 (ISO/IEC 13818-7:2006) and MPEG-4 + (ISO/IEC 14496-3:2009) specifications. + + \li \b DSE - Data Stream Element\n + A syntactical element of the MPEG-2/4 Advanced Audio Coding bitstream + standardized in ISO/IEC 14496-3:2009. It can convey any kind of data associated + to one program. + + \li \b PCE - Program Config Element\n + A syntactical element of the MPEG-2/4 Advanced Audio Coding bitstream + standardized in ISO/IEC 14496-3:2009 that can define the stream configuration + for a single program. In addition it can comprise simple downmix meta data. + + */ + +#ifndef PCMDMX_LIB_H +#define PCMDMX_LIB_H + +#include "machine_type.h" +#include "common_fix.h" +#include "FDK_audio.h" +#include "FDK_bitstream.h" + +/** + * \enum PCMDMX_ERROR + * + * Error codes that can be returned by module interface functions. + */ +typedef enum { + PCMDMX_OK = 0x0, /*!< No error happened. */ + PCMDMX_UNSUPPORTED = + 0x1, /*!< The requested feature/service is unavailable. This can + occur if the module was built for a wrong configuration. */ + pcm_dmx_fatal_error_start, + PCMDMX_OUT_OF_MEMORY, /*!< Not enough memory to set up an instance of the + module. */ + pcm_dmx_fatal_error_end, + + PCMDMX_INVALID_HANDLE, /*!< The given instance handle is not valid. */ + PCMDMX_INVALID_ARGUMENT, /*!< One of the parameters handed over is invalid. */ + PCMDMX_INVALID_CH_CONFIG, /*!< The given channel configuration is not + supported and thus no processing was performed. + */ + PCMDMX_INVALID_MODE, /*!< The set configuration/mode is not applicable. */ + PCMDMX_UNKNOWN_PARAM, /*!< The handed parameter is not known/supported. */ + PCMDMX_UNABLE_TO_SET_PARAM, /*!< Unable to set the specific parameter. Most + probably the value ist out of range. + */ + PCMDMX_CORRUPT_ANC_DATA, /*!< The read ancillary data was corrupt. */ + PCMDMX_OUTPUT_BUFFER_TOO_SMALL /*!< The size of pcm output buffer is too + small. */ + +} PCMDMX_ERROR; + +/** Macro to identify fatal errors. */ +#define PCMDMX_IS_FATAL_ERROR(err) \ + ((((err) >= pcm_dmx_fatal_error_start) && \ + ((err) <= pcm_dmx_fatal_error_end)) \ + ? 1 \ + : 0) + +/** + * \enum PCMDMX_PARAM + * + * Modules dynamic runtime parameters that can be handed to function + * pcmDmx_SetParam() and pcmDmx_GetParam(). + */ +typedef enum { + DMX_PROFILE_SETTING = + 0x01, /*!< Defines which equations, coefficients and default/ + fallback values used for downmixing. See + ::DMX_PROFILE_TYPE type for details. */ + DMX_BS_DATA_EXPIRY_FRAME = + 0x10, /*!< The number of frames without new metadata that + have to go by before the bitstream data expires. + The value 0 disables expiry. */ + DMX_BS_DATA_DELAY = + 0x11, /*!< The number of delay frames of the output samples + compared to the bitstream data. */ + MIN_NUMBER_OF_OUTPUT_CHANNELS = + 0x20, /*!< The minimum number of output channels. For all + input configurations that have less than the given + channels the module will modify the output + automatically to obtain the given number of output + channels. Mono signals will be duplicated. If more + than two output channels are desired the module + just adds empty channels. The parameter value must + be either -1, 0, 1, 2, 6 or 8. If the value is + greater than zero and exceeds the value of + parameter ::MAX_NUMBER_OF_OUTPUT_CHANNELS the + latter will be set to the same value. Both values + -1 and 0 disable the feature. */ + MAX_NUMBER_OF_OUTPUT_CHANNELS = + 0x21, /*!< The maximum number of output channels. For all + input configurations that have more than the given + channels the module will apply a mixdown + automatically to obtain the given number of output + channels. The value must be either -1, 0, 1, 2, 6 + or 8. If it's greater than zero and lower or equal + than the value of ::MIN_NUMBER_OF_OUTPUT_CHANNELS + parameter the latter will be set to the same value. + The values -1 and 0 disable the feature. */ + DMX_DUAL_CHANNEL_MODE = + 0x30, /*!< Downmix mode for two channel audio data. See type + ::DUAL_CHANNEL_MODE for details. */ + DMX_PSEUDO_SURROUND_MODE = + 0x31 /*!< Defines how module handles pseudo surround + compatible signals. See ::PSEUDO_SURROUND_MODE + type for details. */ +} PCMDMX_PARAM; + +/** + * \enum DMX_PROFILE_TYPE + * + * Valid value list for parameter ::DMX_PROFILE_SETTING. + */ +typedef enum { + DMX_PRFL_STANDARD = + 0x0, /*!< The standard profile creates mixdown signals based on + the advanced downmix metadata (from a DSE), equations + and default values defined in ISO/IEC 14496:3 + Ammendment 4. Any other (legacy) downmix metadata will + be ignored. */ + DMX_PRFL_MATRIX_MIX = + 0x1, /*!< This profile behaves just as the standard profile if + advanced downmix metadata (from a DSE) is available. If + not, the matrix_mixdown information embedded in the + program configuration element (PCE) will be applied. If + neither is the case the module creates a mixdown using + the default coefficients defined in MPEG-4 Ammendment 4. + The profile can be used e.g. to support legacy digital + TV (e.g. DVB) streams. */ + DMX_PRFL_FORCE_MATRIX_MIX = + 0x2, /*!< Similar to the ::DMX_PRFL_MATRIX_MIX profile but if both + the advanced (DSE) and the legacy (PCE) MPEG downmix + metadata are available the latter will be applied. */ + DMX_PRFL_ARIB_JAPAN = + 0x3 /*!< Downmix creation as described in ABNT NBR 15602-2. But + if advanced downmix metadata is available it will be + prefered. */ +} DMX_PROFILE_TYPE; + +/** + * \enum PSEUDO_SURROUND_MODE + * + * Valid value list for parameter ::DMX_PSEUDO_SURROUND_MODE. + */ +typedef enum { + NEVER_DO_PS_DMX = + -1, /*!< Ignore any metadata and do never create a pseudo surround + compatible downmix. (Default) */ + AUTO_PS_DMX = 0, /*!< Create a pseudo surround compatible downmix only if + signalled in bitstreams meta data. */ + FORCE_PS_DMX = + 1 /*!< Always create a pseudo surround compatible downmix. + CAUTION: This can lead to excessive signal cancellations + and signal level differences for non-compatible signals. */ +} PSEUDO_SURROUND_MODE; + +/** + * \enum DUAL_CHANNEL_MODE + * + * Valid value list for parameter ::DMX_DUAL_CHANNEL_MODE. + */ +typedef enum { + STEREO_MODE = 0x0, /*!< Leave stereo signals as they are. */ + CH1_MODE = 0x1, /*!< Create a dual mono output signal from channel 1. */ + CH2_MODE = 0x2, /*!< Create a dual mono output signal from channel 2. */ + MIXED_MODE = 0x3 /*!< Create a dual mono output signal by mixing the two + channels. */ +} DUAL_CHANNEL_MODE; + +#define DMX_PCM FIXP_DBL +#define DMX_PCMF FIXP_DBL +#define DMX_PCM_BITS DFRACT_BITS +#define FX_DMX2FX_PCM(x) FX_DBL2FX_PCM((FIXP_DBL)(x)) + +/* ------------------------ * + * MODULES INTERFACE: * + * ------------------------ */ +typedef struct PCM_DMX_INSTANCE *HANDLE_PCM_DOWNMIX; + +/*! \addtogroup pcmDmxResetFlags Modules reset flags + * Macros that can be used as parameter for function pcmDmx_Reset() to specify + * which parts of the module shall be reset. + * @{ + * + * \def PCMDMX_RESET_PARAMS + * Only reset the user specific parameters that have been modified with + * pcmDmx_SetParam(). + * + * \def PCMDMX_RESET_BS_DATA + * Delete the meta data that has been fed with the appropriate interface + * functions. + * + * \def PCMDMX_RESET_FULL + * Reset the complete module instance to the state after pcmDmx_Open() had been + * called. + */ +#define PCMDMX_RESET_PARAMS (1) +#define PCMDMX_RESET_BS_DATA (2) +#define PCMDMX_RESET_FULL (PCMDMX_RESET_PARAMS | PCMDMX_RESET_BS_DATA) +/*! @} */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Open and initialize an instance of the PCM downmix module + * @param[out] pSelf Pointer to a buffer receiving the handle of the new + *instance. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Open(HANDLE_PCM_DOWNMIX *pSelf); + +/** Set one parameter for a single instance of the PCM downmix module. + * @param[in] self Handle of PCM downmix instance. + * @param[in] param Parameter to be set. Can be one from the ::PCMDMX_PARAM + *list. + * @param[in] value Parameter value. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_SetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + const INT value); + +/** Get one parameter value of a single PCM downmix module instance. + * @param[in] self Handle of PCM downmix module instance. + * @param[in] param Parameter to query. Can be one from the ::PCMDMX_PARAM + *list. + * @param[out] pValue Pointer to buffer receiving the parameter value. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_GetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + INT *const pValue); + +/** \cond + * Extract relevant downmix meta-data directly from a given bitstream. The + *function can handle both data specified in ETSI TS 101 154 or ISO/IEC + *14496-3:2009/Amd.4:2013. + * @param[in] self Handle of PCM downmix instance. + * @param[in] hBitStream Handle of FDK bitstream buffer. + * @param[in] ancDataBits Length of ancillary data in bits. + * @param[in] isMpeg2 Flag indicating wheter the ancillary data is from a + *MPEG-1/2 or a MPEG-4 stream. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Parse(HANDLE_PCM_DOWNMIX self, + HANDLE_FDK_BITSTREAM hBitStream, UINT ancDataBits, + int isMpeg2); +/** \endcond */ + +/** Read from a given ancillary data buffer and extract the relevant downmix + *meta-data. The function can handle both data specified in ETSI TS 101 154 or + *ISO/IEC 14496-3:2009/Amd.4:2013. + * @param[in] self Handle of PCM downmix instance. + * @param[in] pAncDataBuf Pointer to ancillary buffer holding the data. + * @param[in] ancDataBytes Size of ancillary data in bytes. + * @param[in] isMpeg2 Flag indicating wheter the ancillary data is from a + *MPEG-1/2 or a MPEG-4 stream. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_ReadDvbAncData(HANDLE_PCM_DOWNMIX self, UCHAR *pAncDataBuf, + UINT ancDataBytes, int isMpeg2); + +/** Set the matrix mixdown information extracted from the PCE of an AAC + *bitstream. + * @param[in] self Handle of PCM downmix instance. + * @param[in] matrixMixdownPresent Matrix mixdown index present flag extracted + *from PCE. + * @param[in] matrixMixdownIdx The 2 bit matrix mixdown index extracted + *from PCE. + * @param[in] pseudoSurroundEnable The pseudo surround enable flag extracted + *from PCE. + * @returns Returns an error code of type + *::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce(HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable); + +/** Reset the module. + * @param[in] self Handle of PCM downmix instance. + * @param[in] flags Flags telling which parts of the module shall be reset. + * See \ref pcmDmxResetFlags for details. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Reset(HANDLE_PCM_DOWNMIX self, UINT flags); + +/** Create a mixdown, bypass or extend the output signal depending on the + *modules settings and the respective given input configuration. + * + * \param[in] self Handle of PCM downmix module instance. + * \param[in,out] pPcmBuf Pointer to time buffer with PCM samples. + * \param[in] pcmBufSize Size of pPcmBuf buffer. + * \param[in] frameSize The I/O block size which is the number of samples per channel. + * \param[in,out] nChannels Pointer to buffer that holds the number of input channels and + * where the amount of output channels is written + *to. + * \param[in] fInterleaved Input and output samples are processed interleaved. + * \param[in,out] channelType Array were the corresponding channel type for each output audio + * channel is stored into. + * \param[in,out] channelIndices Array were the corresponding channel type index for each output + * audio channel is stored into. + * \param[in] mapDescr Pointer to a FDK channel mapping descriptor that contains the + * channel mapping to be used. + * \param[out] pDmxOutScale Pointer on a field receiving the scale factor that has to be + * applied on all samples afterwards. If the + *handed pointer is NULL the final scaling is done internally. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame(HANDLE_PCM_DOWNMIX self, DMX_PCM *pPcmBuf, + const int pcmBufSize, UINT frameSize, + INT *nChannels, INT fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + INT *pDmxOutScale); + +/** Close an instance of the PCM downmix module. + * @param[in,out] pSelf Pointer to a buffer containing the handle of the + *instance. + * @returns Returns an error code of type ::PCMDMX_ERROR. + **/ +PCMDMX_ERROR pcmDmx_Close(HANDLE_PCM_DOWNMIX *pSelf); + +/** Get library info for this module. + * @param[out] info Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code of type ::PCMDMX_ERROR. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* PCMDMX_LIB_H */ diff --git a/fdk-aac/libPCMutils/src/limiter.cpp b/fdk-aac/libPCMutils/src/limiter.cpp new file mode 100644 index 0000000..a799a51 --- /dev/null +++ b/fdk-aac/libPCMutils/src/limiter.cpp @@ -0,0 +1,570 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Matthias Neusinger + + Description: Hard limiter for clipping prevention + +*******************************************************************************/ + +#include "limiter.h" +#include "FDK_core.h" + +/* library version */ +#include "version.h" +/* library title */ +#define TDLIMIT_LIB_TITLE "TD Limiter Lib" + +/* create limiter */ +TDLimiterPtr pcmLimiter_Create(unsigned int maxAttackMs, unsigned int releaseMs, + FIXP_DBL threshold, unsigned int maxChannels, + UINT maxSampleRate) { + TDLimiterPtr limiter = NULL; + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + /* calc attack and release time in samples */ + attack = (unsigned int)(maxAttackMs * maxSampleRate / 1000); + release = (unsigned int)(releaseMs * maxSampleRate / 1000); + + /* alloc limiter struct */ + limiter = (TDLimiterPtr)FDKcalloc(1, sizeof(struct TDLimiter)); + if (!limiter) return NULL; + + /* alloc max and delay buffers */ + limiter->maxBuf = (FIXP_DBL*)FDKcalloc(attack + 1, sizeof(FIXP_DBL)); + limiter->delayBuf = + (FIXP_DBL*)FDKcalloc(attack * maxChannels, sizeof(FIXP_DBL)); + + if (!limiter->maxBuf || !limiter->delayBuf) { + pcmLimiter_Destroy(limiter); + return NULL; + } + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + /* init parameters */ + limiter->attackMs = maxAttackMs; + limiter->maxAttackMs = maxAttackMs; + limiter->releaseMs = releaseMs; + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->threshold = threshold >> TDL_GAIN_SCALING; + limiter->channels = maxChannels; + limiter->maxChannels = maxChannels; + limiter->sampleRate = maxSampleRate; + limiter->maxSampleRate = maxSampleRate; + + pcmLimiter_Reset(limiter); + + return limiter; +} + +/* apply limiter */ +TDLIMITER_ERROR pcmLimiter_Apply(TDLimiterPtr limiter, PCM_LIM* samplesIn, + INT_PCM* samplesOut, FIXP_DBL* RESTRICT pGain, + const INT* RESTRICT gain_scale, + const UINT gain_size, const UINT gain_delay, + const UINT nSamples) { + unsigned int i, j; + FIXP_DBL tmp1; + FIXP_DBL tmp2; + FIXP_DBL tmp, old, gain, additionalGain = 0, additionalGainUnfiltered; + FIXP_DBL minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); + + FDK_ASSERT(gain_size == 1); + FDK_ASSERT(gain_delay <= nSamples); + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + { + unsigned int channels = limiter->channels; + unsigned int attack = limiter->attack; + FIXP_DBL attackConst = limiter->attackConst; + FIXP_DBL releaseConst = limiter->releaseConst; + FIXP_DBL threshold = limiter->threshold; + + FIXP_DBL max = limiter->max; + FIXP_DBL* maxBuf = limiter->maxBuf; + unsigned int maxBufIdx = limiter->maxBufIdx; + FIXP_DBL cor = limiter->cor; + FIXP_DBL* delayBuf = limiter->delayBuf; + unsigned int delayBufIdx = limiter->delayBufIdx; + + FIXP_DBL smoothState0 = limiter->smoothState0; + FIXP_DBL additionalGainSmoothState = limiter->additionalGainFilterState; + FIXP_DBL additionalGainSmoothState1 = limiter->additionalGainFilterState1; + + if (!gain_delay) { + additionalGain = pGain[0]; + if (gain_scale[0] > 0) { + additionalGain <<= gain_scale[0]; + } else { + additionalGain >>= -gain_scale[0]; + } + } + + for (i = 0; i < nSamples; i++) { + if (gain_delay) { + if (i < gain_delay) { + additionalGainUnfiltered = limiter->additionalGainPrev; + } else { + additionalGainUnfiltered = pGain[0]; + } + + /* Smooth additionalGain */ + /* [b,a] = butter(1, 0.01) */ + static const FIXP_SGL b[] = {FL2FXCONST_SGL(0.015466 * 2.0), + FL2FXCONST_SGL(0.015466 * 2.0)}; + static const FIXP_SGL a[] = {(FIXP_SGL)MAXVAL_SGL, + FL2FXCONST_SGL(-0.96907)}; + additionalGain = -fMult(additionalGainSmoothState, a[1]) + + fMultDiv2(additionalGainUnfiltered, b[0]) + + fMultDiv2(additionalGainSmoothState1, b[1]); + additionalGainSmoothState1 = additionalGainUnfiltered; + additionalGainSmoothState = additionalGain; + + /* Apply the additional scaling that has no delay and no smoothing */ + if (gain_scale[0] > 0) { + additionalGain <<= gain_scale[0]; + } else { + additionalGain >>= -gain_scale[0]; + } + } + /* get maximum absolute sample value of all channels, including the + * additional gain. */ + tmp1 = (FIXP_DBL)0; + for (j = 0; j < channels; j++) { + tmp2 = PCM_LIM2FIXP_DBL(samplesIn[j]); + tmp2 = fAbs(tmp2); + tmp2 = FIXP_DBL(INT(tmp2) ^ INT((tmp2 >> (SAMPLE_BITS_LIM - 1)))); + tmp1 = fMax(tmp1, tmp2); + } + tmp = fMult(tmp1, additionalGain); + + /* set threshold as lower border to save calculations in running maximum + * algorithm */ + tmp = fMax(tmp, threshold); + + /* running maximum */ + old = maxBuf[maxBufIdx]; + maxBuf[maxBufIdx] = tmp; + + if (tmp >= max) { + /* new sample is greater than old maximum, so it is the new maximum */ + max = tmp; + } else if (old < max) { + /* maximum does not change, as the sample, which has left the window was + not the maximum */ + } else { + /* the old maximum has left the window, we have to search the complete + buffer for the new max */ + max = maxBuf[0]; + for (j = 1; j <= attack; j++) { + max = fMax(max, maxBuf[j]); + } + } + maxBufIdx++; + if (maxBufIdx >= attack + 1) maxBufIdx = 0; + + /* calc gain */ + /* gain is downscaled by one, so that gain = 1.0 can be represented */ + if (max > threshold) { + gain = fDivNorm(threshold, max) >> 1; + } else { + gain = FL2FXCONST_DBL(1.0f / (1 << 1)); + } + + /* gain smoothing, method: TDL_EXPONENTIAL */ + /* first order IIR filter with attack correction to avoid overshoots */ + + /* correct the 'aiming' value of the exponential attack to avoid the + * remaining overshoot */ + if (gain < smoothState0) { + cor = fMin(cor, + fMultDiv2((gain - fMultDiv2(FL2FXCONST_SGL(0.1f * (1 << 1)), + smoothState0)), + FL2FXCONST_SGL(1.11111111f / (1 << 1))) + << 2); + } else { + cor = gain; + } + + /* smoothing filter */ + if (cor < smoothState0) { + smoothState0 = + fMult(attackConst, (smoothState0 - cor)) + cor; /* attack */ + smoothState0 = fMax(smoothState0, gain); /* avoid overshooting target */ + } else { + /* sign inversion twice to round towards +infinity, + so that gain can converge to 1.0 again, + for bit-identical output when limiter is not active */ + smoothState0 = + -fMult(releaseConst, -(smoothState0 - cor)) + cor; /* release */ + } + + gain = smoothState0; + + FIXP_DBL* p_delayBuf = &delayBuf[delayBufIdx * channels + 0]; + if (gain < FL2FXCONST_DBL(1.0f / (1 << 1))) { + gain <<= 1; + /* lookahead delay, apply gain */ + for (j = 0; j < channels; j++) { + tmp = p_delayBuf[j]; + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + + /* Apply gain to delayed signal */ + tmp = fMultDiv2(tmp, gain); + + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( + tmp, TDL_GAIN_SCALING + 1, DFRACT_BITS)); + } + gain >>= 1; + } else { + /* lookahead delay, apply gain=1.0f */ + for (j = 0; j < channels; j++) { + tmp = p_delayBuf[j]; + p_delayBuf[j] = fMult((FIXP_PCM_LIM)samplesIn[j], additionalGain); + samplesOut[j] = (INT_PCM)FX_DBL2FX_PCM((FIXP_DBL)SATURATE_LEFT_SHIFT( + tmp, TDL_GAIN_SCALING, DFRACT_BITS)); + } + } + + delayBufIdx++; + if (delayBufIdx >= attack) { + delayBufIdx = 0; + } + + /* save minimum gain factor */ + if (gain < minGain) { + minGain = gain; + } + + /* advance sample pointer by samples */ + samplesIn += channels; + samplesOut += channels; + } + + limiter->max = max; + limiter->maxBufIdx = maxBufIdx; + limiter->cor = cor; + limiter->delayBufIdx = delayBufIdx; + + limiter->smoothState0 = smoothState0; + limiter->additionalGainFilterState = additionalGainSmoothState; + limiter->additionalGainFilterState1 = additionalGainSmoothState1; + + limiter->minGain = minGain; + + limiter->additionalGainPrev = pGain[0]; + + return TDLIMIT_OK; + } +} + +/* set limiter threshold */ +TDLIMITER_ERROR pcmLimiter_SetThreshold(TDLimiterPtr limiter, + FIXP_DBL threshold) { + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + limiter->threshold = threshold >> TDL_GAIN_SCALING; + + return TDLIMIT_OK; +} + +/* reset limiter */ +TDLIMITER_ERROR pcmLimiter_Reset(TDLimiterPtr limiter) { + if (limiter != NULL) { + limiter->maxBufIdx = 0; + limiter->delayBufIdx = 0; + limiter->max = (FIXP_DBL)0; + limiter->cor = FL2FXCONST_DBL(1.0f / (1 << 1)); + limiter->smoothState0 = FL2FXCONST_DBL(1.0f / (1 << 1)); + limiter->minGain = FL2FXCONST_DBL(1.0f / (1 << 1)); + + limiter->additionalGainPrev = + FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); + limiter->additionalGainFilterState = + FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); + limiter->additionalGainFilterState1 = + FL2FXCONST_DBL(1.0f / (1 << TDL_GAIN_SCALING)); + + FDKmemset(limiter->maxBuf, 0, (limiter->attack + 1) * sizeof(FIXP_DBL)); + FDKmemset(limiter->delayBuf, 0, + limiter->attack * limiter->channels * sizeof(FIXP_DBL)); + } else { + return TDLIMIT_INVALID_HANDLE; + } + + return TDLIMIT_OK; +} + +/* destroy limiter */ +TDLIMITER_ERROR pcmLimiter_Destroy(TDLimiterPtr limiter) { + if (limiter != NULL) { + FDKfree(limiter->maxBuf); + FDKfree(limiter->delayBuf); + + FDKfree(limiter); + } else { + return TDLIMIT_INVALID_HANDLE; + } + return TDLIMIT_OK; +} + +/* get delay in samples */ +unsigned int pcmLimiter_GetDelay(TDLimiterPtr limiter) { + FDK_ASSERT(limiter != NULL); + return limiter->attack; +} + +/* get maximum gain reduction of last processed block */ +INT pcmLimiter_GetMaxGainReduction(TDLimiterPtr limiter) { + /* maximum gain reduction in dB = -20 * log10(limiter->minGain) + = -20 * log2(limiter->minGain)/log2(10) = -6.0206*log2(limiter->minGain) */ + int e_ans; + FIXP_DBL loggain, maxGainReduction; + + FDK_ASSERT(limiter != NULL); + + loggain = fLog2(limiter->minGain, 1, &e_ans); + + maxGainReduction = fMult(loggain, FL2FXCONST_DBL(-6.0206f / (1 << 3))); + + return fixp_roundToInt(maxGainReduction, (e_ans + 3)); +} + +/* set number of channels */ +TDLIMITER_ERROR pcmLimiter_SetNChannels(TDLimiterPtr limiter, + unsigned int nChannels) { + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (nChannels > limiter->maxChannels) return TDLIMIT_INVALID_PARAMETER; + + limiter->channels = nChannels; + // pcmLimiter_Reset(limiter); + + return TDLIMIT_OK; +} + +/* set sampling rate */ +TDLIMITER_ERROR pcmLimiter_SetSampleRate(TDLimiterPtr limiter, + UINT sampleRate) { + unsigned int attack, release; + FIXP_DBL attackConst, releaseConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (sampleRate > limiter->maxSampleRate) return TDLIMIT_INVALID_PARAMETER; + + /* update attack and release time in samples */ + attack = (unsigned int)(limiter->attackMs * sampleRate / 1000); + release = (unsigned int)(limiter->releaseMs * sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->releaseConst = releaseConst; + limiter->sampleRate = sampleRate; + + /* reset */ + // pcmLimiter_Reset(limiter); + + return TDLIMIT_OK; +} + +/* set attack time */ +TDLIMITER_ERROR pcmLimiter_SetAttack(TDLimiterPtr limiter, + unsigned int attackMs) { + unsigned int attack; + FIXP_DBL attackConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + if (attackMs > limiter->maxAttackMs) return TDLIMIT_INVALID_PARAMETER; + + /* calculate attack time in samples */ + attack = (unsigned int)(attackMs * limiter->sampleRate / 1000); + + /* attackConst = pow(0.1, 1.0 / (attack + 1)) */ + exponent = invFixp(attack + 1); + attackConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + attackConst = scaleValue(attackConst, e_ans); + + limiter->attack = attack; + limiter->attackConst = attackConst; + limiter->attackMs = attackMs; + + return TDLIMIT_OK; +} + +/* set release time */ +TDLIMITER_ERROR pcmLimiter_SetRelease(TDLimiterPtr limiter, + unsigned int releaseMs) { + unsigned int release; + FIXP_DBL releaseConst, exponent; + INT e_ans; + + if (limiter == NULL) return TDLIMIT_INVALID_HANDLE; + + /* calculate release time in samples */ + release = (unsigned int)(releaseMs * limiter->sampleRate / 1000); + + /* releaseConst = (float)pow(0.1, 1.0 / (release + 1)) */ + exponent = invFixp(release + 1); + releaseConst = fPow(FL2FXCONST_DBL(0.1f), 0, exponent, 0, &e_ans); + releaseConst = scaleValue(releaseConst, e_ans); + + limiter->releaseConst = releaseConst; + limiter->releaseMs = releaseMs; + + return TDLIMIT_OK; +} + +/* Get library info for this module. */ +TDLIMITER_ERROR pcmLimiter_GetLibInfo(LIB_INFO* info) { + int i; + + if (info == NULL) { + return TDLIMIT_INVALID_PARAMETER; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return TDLIMIT_UNKNOWN; + } + + /* Add the library info */ + info[i].module_id = FDK_TDLIMIT; + info[i].version = + LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = PCMUTIL_LIB_BUILD_DATE; + info[i].build_time = PCMUTIL_LIB_BUILD_TIME; + info[i].title = TDLIMIT_LIB_TITLE; + + /* Set flags */ + info[i].flags = CAPF_LIMITER; + + /* Add lib info for FDK tools (if not yet done). */ + FDK_toolsGetLibInfo(info); + + return TDLIMIT_OK; +} diff --git a/fdk-aac/libPCMutils/src/pcm_utils.cpp b/fdk-aac/libPCMutils/src/pcm_utils.cpp new file mode 100644 index 0000000..5dd18d9 --- /dev/null +++ b/fdk-aac/libPCMutils/src/pcm_utils.cpp @@ -0,0 +1,195 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Arthur Tritthart, Alfonso Pino Garcia + + Description: Functions that perform (de)interleaving combined with format +change + +*******************************************************************************/ + +#include "pcm_utils.h" + +/* library version */ +#include "version.h" + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, LONG *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_DBL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (LONG)In[0]; + In += frameSize; + } + } +} + +void FDK_interleave(const FIXP_DBL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_DBL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (SHORT)FX_DBL2FX_SGL(In[0]); + In += frameSize; + } + } +} + +void FDK_interleave(const FIXP_SGL *RESTRICT pIn, SHORT *RESTRICT pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT sample = 0; sample < length; sample++) { + const FIXP_SGL *In = &pIn[sample]; + for (UINT ch = 0; ch < channels; ch++) { + *pOut++ = (SHORT)In[0]; + In += frameSize; + } + } +} + +void FDK_deinterleave(const LONG *RESTRICT pIn, SHORT *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + SHORT *pOut = _pOut + length * ch; + const LONG *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = (SHORT)(In[0] >> 16); + In += channels; + } + } +} + +void FDK_deinterleave(const LONG *RESTRICT pIn, LONG *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + LONG *pOut = _pOut + length * ch; + const LONG *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = In[0]; + In += channels; + } + } +} + +void FDK_deinterleave(const SHORT *RESTRICT pIn, SHORT *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + SHORT *pOut = _pOut + length * ch; + const SHORT *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = In[0]; + In += channels; + } + } +} + +void FDK_deinterleave(const SHORT *RESTRICT pIn, LONG *RESTRICT _pOut, + const UINT channels, const UINT frameSize, + const UINT length) { + for (UINT ch = 0; ch < channels; ch++) { + LONG *pOut = _pOut + length * ch; + const SHORT *In = &pIn[ch]; + for (UINT sample = 0; sample < frameSize; sample++) { + *pOut++ = (LONG)In[0] << 16; + In += channels; + } + } +} diff --git a/fdk-aac/libPCMutils/src/pcmdmx_lib.cpp b/fdk-aac/libPCMutils/src/pcmdmx_lib.cpp new file mode 100644 index 0000000..2070dbc --- /dev/null +++ b/fdk-aac/libPCMutils/src/pcmdmx_lib.cpp @@ -0,0 +1,2662 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): Christian Griebel + + Description: Defines functions that perform downmixing or a simple channel + expansion in the PCM time domain. + +*******************************************************************************/ + +#include "pcmdmx_lib.h" + +#include "genericStds.h" +#include "fixpoint_math.h" +#include "FDK_core.h" + +/* library version */ +#include "version.h" +/* library title */ +#define PCMDMX_LIB_TITLE "PCM Downmix Lib" + +#define FALSE 0 +#define TRUE 1 +#define IN 0 +#define OUT 1 + +/* Type definitions: */ +#define FIXP_DMX FIXP_SGL +#define FX_DMX2FX_DBL(x) FX_SGL2FX_DBL((FIXP_SGL)(x)) +#define FX_DBL2FX_DMX(x) FX_DBL2FX_SGL(x) +#define FL2FXCONST_DMX(x) FL2FXCONST_SGL(x) +#define MAXVAL_DMX MAXVAL_SGL +#define FX_DMX2SHRT(x) ((SHORT)(x)) +#define FX_DMX2FL(x) FX_DBL2FL(FX_DMX2FX_DBL(x)) + +/* Fixed and unique channel group indices. + * The last group index has to be smaller than ( 4 ). */ +#define CH_GROUP_FRONT (0) +#define CH_GROUP_SIDE (1) +#define CH_GROUP_REAR (2) +#define CH_GROUP_LFE (3) + +/* Fixed and unique channel plain indices. */ +#define CH_PLAIN_NORMAL (0) +#define CH_PLAIN_TOP (1) +#define CH_PLAIN_BOTTOM (2) + +/* The ordering of the following fixed channel labels has to be in MPEG-4 style. + * From the center to the back with left and right channel interleaved (starting + * with left). The last channel label index has to be smaller than ( 8 ). */ +#define CENTER_FRONT_CHANNEL (0) /* C */ +#define LEFT_FRONT_CHANNEL (1) /* L */ +#define RIGHT_FRONT_CHANNEL (2) /* R */ +#define LEFT_REAR_CHANNEL \ + (3) /* Lr (aka left back channel) or center back channel */ +#define RIGHT_REAR_CHANNEL (4) /* Rr (aka right back channel) */ +#define LOW_FREQUENCY_CHANNEL (5) /* Lf */ +#define LEFT_MULTIPRPS_CHANNEL (6) /* Left multipurpose channel */ +#define RIGHT_MULTIPRPS_CHANNEL (7) /* Right multipurpose channel */ + +/* 22.2 channel specific fixed channel lables: */ +#define LEFT_SIDE_CHANNEL (8) /* Lss */ +#define RIGHT_SIDE_CHANNEL (9) /* Rss */ +#define CENTER_REAR_CHANNEL (10) /* Cs */ +#define CENTER_FRONT_CHANNEL_TOP (11) /* Cv */ +#define LEFT_FRONT_CHANNEL_TOP (12) /* Lv */ +#define RIGHT_FRONT_CHANNEL_TOP (13) /* Rv */ +#define LEFT_SIDE_CHANNEL_TOP (14) /* Lvss */ +#define RIGHT_SIDE_CHANNEL_TOP (15) /* Rvss */ +#define CENTER_SIDE_CHANNEL_TOP (16) /* Ts */ +#define LEFT_REAR_CHANNEL_TOP (17) /* Lvr */ +#define RIGHT_REAR_CHANNEL_TOP (18) /* Rvr */ +#define CENTER_REAR_CHANNEL_TOP (19) /* Cvr */ +#define CENTER_FRONT_CHANNEL_BOTTOM (20) /* Cb */ +#define LEFT_FRONT_CHANNEL_BOTTOM (21) /* Lb */ +#define RIGHT_FRONT_CHANNEL_BOTTOM (22) /* Rb */ +#define LOW_FREQUENCY_CHANNEL_2 (23) /* LFE2 */ + +/* More constants */ +#define ONE_CHANNEL (1) +#define TWO_CHANNEL (2) +#define SIX_CHANNEL (6) +#define EIGHT_CHANNEL (8) +#define TWENTY_FOUR_CHANNEL (24) + +#define PCMDMX_THRESHOLD_MAP_HEAT_1 (0) /* Store only exact matches */ +#define PCMDMX_THRESHOLD_MAP_HEAT_2 (20) +#define PCMDMX_THRESHOLD_MAP_HEAT_3 \ + (256) /* Do not assign normal channels to LFE */ + +#define SP_Z_NRM (0) +#define SP_Z_TOP (2) +#define SP_Z_BOT (-2) +#define SP_Z_LFE (-18) +#define SP_Z_MUL (8) /* Should be smaller than SP_Z_LFE */ + +typedef struct { + SCHAR x; /* horizontal position: center (0), left (-), right (+) */ + SCHAR y; /* deepth position: front, side, back, position */ + SCHAR z; /* heigth positions: normal, top, bottom, lfe */ +} PCM_DMX_SPEAKER_POSITION; + +/* CAUTION: The maximum x-value should be less or equal to + * PCMDMX_SPKR_POS_X_MAX_WIDTH. */ +static const PCM_DMX_SPEAKER_POSITION spkrSlotPos[] = { + /* x, y, z */ + {0, 0, SP_Z_NRM}, /* 0 CENTER_FRONT_CHANNEL */ + {-2, 0, SP_Z_NRM}, /* 1 LEFT_FRONT_CHANNEL */ + {2, 0, SP_Z_NRM}, /* 2 RIGHT_FRONT_CHANNEL */ + {-3, 4, SP_Z_NRM}, /* 3 LEFT_REAR_CHANNEL */ + {3, 4, SP_Z_NRM}, /* 4 RIGHT_REAR_CHANNEL */ + {0, 0, SP_Z_LFE}, /* 5 LOW_FREQUENCY_CHANNEL */ + {-2, 2, SP_Z_MUL}, /* 6 LEFT_MULTIPRPS_CHANNEL */ + {2, 2, SP_Z_MUL} /* 7 RIGHT_MULTIPRPS_CHANNEL */ +}; + +/* List of packed channel modes */ +typedef enum { /* CH_MODE____ */ + CH_MODE_UNDEFINED = 0x0000, + /* 1 channel */ + CH_MODE_1_0_0_0 = 0x0001, /* chCfg 1 */ + /* 2 channels */ + CH_MODE_2_0_0_0 = 0x0002 /* chCfg 2 */ + /* 3 channels */ + , + CH_MODE_3_0_0_0 = 0x0003, /* chCfg 3 */ + CH_MODE_2_0_1_0 = 0x0102, + CH_MODE_2_0_0_1 = 0x1002, + /* 4 channels */ + CH_MODE_3_0_1_0 = 0x0103, /* chCfg 4 */ + CH_MODE_2_0_2_0 = 0x0202, + CH_MODE_2_0_1_1 = 0x1102, + CH_MODE_4_0_0_0 = 0x0004, + /* 5 channels */ + CH_MODE_3_0_2_0 = 0x0203, /* chCfg 5 */ + CH_MODE_2_0_2_1 = 0x1202, + CH_MODE_3_0_1_1 = 0x1103, + CH_MODE_3_2_0_0 = 0x0023, + CH_MODE_5_0_0_0 = 0x0005, + /* 6 channels */ + CH_MODE_3_0_2_1 = 0x1203, /* chCfg 6 */ + CH_MODE_3_2_0_1 = 0x1023, + CH_MODE_3_2_1_0 = 0x0123, + CH_MODE_5_0_1_0 = 0x0105, + CH_MODE_6_0_0_0 = 0x0006, + /* 7 channels */ + CH_MODE_2_2_2_1 = 0x1222, + CH_MODE_3_0_3_1 = 0x1303, /* chCfg 11 */ + CH_MODE_3_2_1_1 = 0x1123, + CH_MODE_3_2_2_0 = 0x0223, + CH_MODE_3_0_2_2 = 0x2203, + CH_MODE_5_0_2_0 = 0x0205, + CH_MODE_5_0_1_1 = 0x1105, + CH_MODE_7_0_0_0 = 0x0007, + /* 8 channels */ + CH_MODE_3_2_2_1 = 0x1223, + CH_MODE_3_0_4_1 = 0x1403, /* chCfg 12 */ + CH_MODE_5_0_2_1 = 0x1205, /* chCfg 7 + 14 */ + CH_MODE_5_2_1_0 = 0x0125, + CH_MODE_3_2_1_2 = 0x2123, + CH_MODE_2_2_2_2 = 0x2222, + CH_MODE_3_0_3_2 = 0x2303, + CH_MODE_8_0_0_0 = 0x0008 + +} PCM_DMX_CHANNEL_MODE; + +/* These are the channel configurations linked to + the number of output channels give by the user: */ +static const PCM_DMX_CHANNEL_MODE outChModeTable[(8) + 1] = { + CH_MODE_UNDEFINED, + CH_MODE_1_0_0_0, /* 1 channel */ + CH_MODE_2_0_0_0 /* 2 channels */ + , + CH_MODE_3_0_0_0, /* 3 channels */ + CH_MODE_3_0_1_0, /* 4 channels */ + CH_MODE_3_0_2_0, /* 5 channels */ + CH_MODE_3_0_2_1 /* 6 channels */ + , + CH_MODE_3_0_3_1, /* 7 channels */ + CH_MODE_3_0_4_1 /* 8 channels */ +}; + +static const FIXP_DMX abMixLvlValueTab[8] = { + FL2FXCONST_DMX(0.500f), /* scaled by 1 */ + FL2FXCONST_DMX(0.841f), FL2FXCONST_DMX(0.707f), FL2FXCONST_DMX(0.596f), + FL2FXCONST_DMX(0.500f), FL2FXCONST_DMX(0.422f), FL2FXCONST_DMX(0.355f), + FL2FXCONST_DMX(0.0f)}; + +static const FIXP_DMX lfeMixLvlValueTab[16] = { + /* value, scale */ + FL2FXCONST_DMX(0.7905f), /* 2 */ + FL2FXCONST_DMX(0.5000f), /* 2 */ + FL2FXCONST_DMX(0.8395f), /* 1 */ + FL2FXCONST_DMX(0.7065f), /* 1 */ + FL2FXCONST_DMX(0.5945f), /* 1 */ + FL2FXCONST_DMX(0.500f), /* 1 */ + FL2FXCONST_DMX(0.841f), /* 0 */ + FL2FXCONST_DMX(0.707f), /* 0 */ + FL2FXCONST_DMX(0.596f), /* 0 */ + FL2FXCONST_DMX(0.500f), /* 0 */ + FL2FXCONST_DMX(0.316f), /* 0 */ + FL2FXCONST_DMX(0.178f), /* 0 */ + FL2FXCONST_DMX(0.100f), /* 0 */ + FL2FXCONST_DMX(0.032f), /* 0 */ + FL2FXCONST_DMX(0.010f), /* 0 */ + FL2FXCONST_DMX(0.000f) /* 0 */ +}; + +/* MPEG matrix mixdown: + Set 1: L' = (1 + 2^-0.5 + A )^-1 * [L + C * 2^-0.5 + A * Ls]; + R' = (1 + 2^-0.5 + A )^-1 * [R + C * 2^-0.5 + A * Rs]; + + Set 2: L' = (1 + 2^-0.5 + 2A )^-1 * [L + C * 2^-0.5 - A * (Ls + Rs)]; + R' = (1 + 2^-0.5 + 2A )^-1 * [R + C * 2^-0.5 + A * (Ls + Rs)]; + + M = (3 + 2A)^-1 * [L + C + R + A*(Ls + Rs)]; +*/ +static const FIXP_DMX mpegMixDownIdx2Coef[4] = { + FL2FXCONST_DMX(0.70710678f), FL2FXCONST_DMX(0.5f), + FL2FXCONST_DMX(0.35355339f), FL2FXCONST_DMX(0.0f)}; + +static const FIXP_DMX mpegMixDownIdx2PreFact[3][4] = { + {/* Set 1: */ + FL2FXCONST_DMX(0.4142135623730950f), FL2FXCONST_DMX(0.4530818393219728f), + FL2FXCONST_DMX(0.4852813742385703f), FL2FXCONST_DMX(0.5857864376269050f)}, + {/* Set 2: */ + FL2FXCONST_DMX(0.3203772410170407f), FL2FXCONST_DMX(0.3693980625181293f), + FL2FXCONST_DMX(0.4142135623730950f), FL2FXCONST_DMX(0.5857864376269050f)}, + {/* Mono DMX set: */ + FL2FXCONST_DMX(0.2265409196609864f), FL2FXCONST_DMX(0.25f), + FL2FXCONST_DMX(0.2697521433898179f), FL2FXCONST_DMX(0.3333333333333333f)}}; + +#define TYPE_NONE (0x00) +#define TYPE_PCE_DATA (0x01) +#define TYPE_DSE_CLEV_DATA (0x02) +#define TYPE_DSE_SLEV_DATA (0x04) +#define TYPE_DSE_DMIX_AB_DATA (0x08) +#define TYPE_DSE_DMIX_LFE_DATA (0x10) +#define TYPE_DSE_DMX_GAIN_DATA (0x20) +#define TYPE_DSE_DMX_CGL_DATA (0x40) +#define TYPE_DSE_DATA (0x7E) + +typedef struct { + UINT typeFlags; + /* From DSE */ + UCHAR cLevIdx; + UCHAR sLevIdx; + UCHAR dmixIdxA; + UCHAR dmixIdxB; + UCHAR dmixIdxLfe; + UCHAR dmxGainIdx2; + UCHAR dmxGainIdx5; + /* From PCE */ + UCHAR matrixMixdownIdx; + /* Attributes: */ + SCHAR pseudoSurround; /*!< If set to 1 the signal is pseudo surround + compatible. The value 0 tells that it is not. If the + value is -1 the information is not available. */ + UINT expiryCount; /*!< Counter to monitor the life time of a meta data set. */ + +} DMX_BS_META_DATA; + +/* Default metadata */ +static const DMX_BS_META_DATA dfltMetaData = {0, 2, 2, 2, 2, 15, + 0, 0, 0, -1, 0}; + +/* Dynamic (user) params: + See the definition of PCMDMX_PARAM for details on the specific fields. */ +typedef struct { + DMX_PROFILE_TYPE dmxProfile; /*!< Linked to DMX_PRFL_STANDARD */ + UINT expiryFrame; /*!< Linked to DMX_BS_DATA_EXPIRY_FRAME */ + DUAL_CHANNEL_MODE dualChannelMode; /*!< Linked to DMX_DUAL_CHANNEL_MODE */ + PSEUDO_SURROUND_MODE + pseudoSurrMode; /*!< Linked to DMX_PSEUDO_SURROUND_MODE */ + SHORT numOutChannelsMin; /*!< Linked to MIN_NUMBER_OF_OUTPUT_CHANNELS */ + SHORT numOutChannelsMax; /*!< Linked to MAX_NUMBER_OF_OUTPUT_CHANNELS */ + UCHAR frameDelay; /*!< Linked to DMX_BS_DATA_DELAY */ + +} PCM_DMX_USER_PARAMS; + +/* Modules main data structure: */ +struct PCM_DMX_INSTANCE { + /* Metadata */ + DMX_BS_META_DATA bsMetaData[(1) + 1]; + PCM_DMX_USER_PARAMS userParams; + + UCHAR applyProcessing; /*!< Flag to en-/disable modules processing. + The max channel limiting is done independently. */ +}; + +/* Memory allocation macro */ +C_ALLOC_MEM(PcmDmxInstance, struct PCM_DMX_INSTANCE, 1) + +static UINT getSpeakerDistance(PCM_DMX_SPEAKER_POSITION posA, + PCM_DMX_SPEAKER_POSITION posB) { + PCM_DMX_SPEAKER_POSITION diff; + + diff.x = posA.x - posB.x; + diff.y = posA.y - posB.y; + diff.z = posA.z - posB.z; + + return ((diff.x * diff.x) + (diff.y * diff.y) + (diff.z * diff.z)); +} + +static PCM_DMX_SPEAKER_POSITION getSpeakerPos(AUDIO_CHANNEL_TYPE chType, + UCHAR chIndex, UCHAR numChInGrp) { +#define PCMDMX_SPKR_POS_X_MAX_WIDTH (3) +#define PCMDMX_SPKR_POS_Y_SPREAD (2) +#define PCMDMX_SPKR_POS_Z_SPREAD (2) + + PCM_DMX_SPEAKER_POSITION spkrPos = {0, 0, 0}; + AUDIO_CHANNEL_TYPE chGrp = (AUDIO_CHANNEL_TYPE)(chType & 0x0F); + unsigned fHasCenter = numChInGrp & 0x1; + unsigned chGrpWidth = numChInGrp >> 1; + unsigned fIsCenter = 0; + unsigned fIsLfe = (chType == ACT_LFE) ? 1 : 0; + int offset = 0; + + FDK_ASSERT(chIndex < numChInGrp); + + if ((chGrp == ACT_FRONT) && fHasCenter) { + if (chIndex == 0) fIsCenter = 1; + chIndex = (UCHAR)fMax(0, chIndex - 1); + } else if (fHasCenter && (chIndex == numChInGrp - 1)) { + fIsCenter = 1; + } + /* now all even indices are left (-) */ + if (!fIsCenter) { + offset = chIndex >> 1; + if ((chGrp > ACT_FRONT) && (chType != ACT_SIDE) && !fIsLfe) { + /* the higher the index the lower the distance to the center position */ + offset = chGrpWidth - fHasCenter - offset; + } + if ((chIndex & 0x1) == 0) { /* even */ + offset = -(offset + 1); + } else { + offset += 1; + } + } + /* apply the offset */ + if (chType == ACT_SIDE) { + spkrPos.x = (offset < 0) ? -PCMDMX_SPKR_POS_X_MAX_WIDTH + : PCMDMX_SPKR_POS_X_MAX_WIDTH; + spkrPos.y = /* 1x */ PCMDMX_SPKR_POS_Y_SPREAD + (SCHAR)fAbs(offset) - 1; + spkrPos.z = 0; + } else { + unsigned spread = + ((chGrpWidth == 1) && (!fIsLfe)) ? PCMDMX_SPKR_POS_X_MAX_WIDTH - 1 : 1; + spkrPos.x = (SCHAR)offset * (SCHAR)spread; + if (fIsLfe) { + spkrPos.y = 0; + spkrPos.z = SP_Z_LFE; + } else { + spkrPos.y = (SCHAR)fMax((SCHAR)chGrp - 1, 0) * PCMDMX_SPKR_POS_Y_SPREAD; + spkrPos.z = (SCHAR)chType >> 4; + if (spkrPos.z == 2) { /* ACT_BOTTOM */ + spkrPos.z = -1; + } + spkrPos.z *= PCMDMX_SPKR_POS_Z_SPREAD; + } + } + return spkrPos; +} + +/** Return the channel mode of a given horizontal channel plain (normal, top, + *bottom) for a given channel configuration. NOTE: This function shall get + *obsolete once the channel mode has been changed to be nonambiguous. + * @param [in] Index of the requested channel plain. + * @param [in] The packed channel mode for the complete channel configuration + *(all plains). + * @param [in] The MPEG-4 channel configuration index which is necessary in + *cases where the (packed) channel mode is ambiguous. + * @returns Returns the packed channel mode of the requested channel plain. + **/ +static PCM_DMX_CHANNEL_MODE getChMode4Plain( + const int plainIndex, const PCM_DMX_CHANNEL_MODE totChMode, + const int chCfg) { + PCM_DMX_CHANNEL_MODE plainChMode = totChMode; + + switch (totChMode) { + case CH_MODE_5_0_2_1: + if (chCfg == 14) { + switch (plainIndex) { + case CH_PLAIN_BOTTOM: + plainChMode = (PCM_DMX_CHANNEL_MODE)0x0000; + break; + case CH_PLAIN_TOP: + plainChMode = CH_MODE_2_0_0_0; + break; + case CH_PLAIN_NORMAL: + default: + plainChMode = CH_MODE_3_0_2_1; + break; + } + } + break; + default: + break; + } + + return plainChMode; +} + +static inline UINT getIdxSum(UCHAR numCh) { + UINT result = 0; + int i; + for (i = 1; i < numCh; i += 1) { + result += i; + } + return result; +} + +/** Evaluate a given channel configuration and extract a packed channel mode. In + *addition the function generates a channel offset table for the mapping to the + *internal representation. This function is the inverse to the + *getChannelDescription() routine. + * @param [in] The total number of channels of the given configuration. + * @param [in] Array holding the corresponding channel types for each channel. + * @param [in] Array holding the corresponding channel type indices for each + *channel. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @param [out] The generated packed channel mode that represents the given + *input configuration. + * @returns Returns an error code. + **/ +static PCMDMX_ERROR getChannelMode( + const UINT numChannels, /* in */ + const AUDIO_CHANNEL_TYPE channelType[], /* in */ + UCHAR channelIndices[], /* in */ + UCHAR offsetTable[(8)], /* out */ + PCM_DMX_CHANNEL_MODE *chMode /* out */ +) { + UINT idxSum[(3)][(4)]; + UCHAR numCh[(3)][(4)]; + UCHAR mapped[(8)]; + PCM_DMX_SPEAKER_POSITION spkrPos[(8)]; + PCMDMX_ERROR err = PCMDMX_OK; + unsigned ch, numMappedInChs = 0; + unsigned startSlot; + unsigned stopSlot = LOW_FREQUENCY_CHANNEL; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(offsetTable != NULL); + FDK_ASSERT(chMode != NULL); + + /* For details see ISO/IEC 13818-7:2005(E), 8.5.3 Channel configuration */ + FDKmemclear(idxSum, (3) * (4) * sizeof(UINT)); + FDKmemclear(numCh, (3) * (4) * sizeof(UCHAR)); + FDKmemclear(mapped, (8) * sizeof(UCHAR)); + FDKmemclear(spkrPos, (8) * sizeof(PCM_DMX_SPEAKER_POSITION)); + /* Init output */ + FDKmemset(offsetTable, 255, (8) * sizeof(UCHAR)); + *chMode = CH_MODE_UNDEFINED; + + /* Determine how many channels are assigned to each channels each group: */ + for (ch = 0; ch < numChannels; ch += 1) { + unsigned chGrp = fMax( + (channelType[ch] & 0x0F) - 1, + 0); /* Assign all undefined channels (ACT_NONE) to front channels. */ + numCh[channelType[ch] >> 4][chGrp] += 1; + idxSum[channelType[ch] >> 4][chGrp] += channelIndices[ch]; + } + if (numChannels > TWO_CHANNEL) { + int chGrp; + /* Sanity check on the indices */ + for (chGrp = 0; chGrp < (4); chGrp += 1) { + int plane; + for (plane = 0; plane < (3); plane += 1) { + if (idxSum[plane][chGrp] != getIdxSum(numCh[plane][chGrp])) { + unsigned idxCnt = 0; + for (ch = 0; ch < numChannels; ch += 1) { + if (channelType[ch] == + (AUDIO_CHANNEL_TYPE)((plane << 4) | ((chGrp + 1) & 0xF))) { + channelIndices[ch] = idxCnt++; + } + } + err = PCMDMX_INVALID_CH_CONFIG; + } + } + } + } + /* Mapping HEAT 1: + * Determine the speaker position of each input channel and map it to a + * internal slot if it matches exactly (with zero distance). */ + for (ch = 0; ch < numChannels; ch += 1) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + unsigned chGrp = fMax( + (channelType[ch] & 0x0F) - 1, + 0); /* Assign all undefined channels (ACT_NONE) to front channels. */ + + spkrPos[ch] = getSpeakerPos(channelType[ch], channelIndices[ch], + numCh[channelType[ch] >> 4][chGrp]); + + for (mapCh = 0; mapCh <= stopSlot; mapCh += 1) { + if (offsetTable[mapCh] == 255) { + UINT dist = getSpeakerDistance(spkrPos[ch], spkrSlotPos[mapCh]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if (mapDist <= PCMDMX_THRESHOLD_MAP_HEAT_1) { + offsetTable[mapPos] = (UCHAR)ch; + mapped[ch] = 1; + numMappedInChs += 1; + } + } + + /* Mapping HEAT 2: + * Go through the unmapped input channels and assign them to the internal + * slots that matches best (least distance). But assign center channels to + * center slots only. */ + startSlot = + ((numCh[CH_PLAIN_NORMAL][CH_GROUP_FRONT] & 0x1) || (numChannels >= (8))) + ? 0 + : 1; + for (ch = 0; ch < (unsigned)numChannels; ch += 1) { + if (!mapped[ch]) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + + for (mapCh = startSlot; mapCh <= stopSlot; mapCh += 1) { + if (offsetTable[mapCh] == 255) { + UINT dist = getSpeakerDistance(spkrPos[ch], spkrSlotPos[mapCh]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if ((mapPos <= stopSlot) && (mapDist < PCMDMX_THRESHOLD_MAP_HEAT_2) && + (((spkrPos[ch].x != 0) && (spkrSlotPos[mapPos].x != 0)) /* XOR */ + || ((spkrPos[ch].x == 0) && + (spkrSlotPos[mapPos].x == + 0)))) { /* Assign center channels to center slots only. */ + offsetTable[mapPos] = (UCHAR)ch; + mapped[ch] = 1; + numMappedInChs += 1; + } + } + } + + /* Mapping HEAT 3: + * Assign the rest by searching for the nearest input channel for each + * internal slot. */ + for (ch = startSlot; (ch < (8)) && (numMappedInChs < numChannels); ch += 1) { + if (offsetTable[ch] == 255) { + UINT mapDist = (unsigned)-1; + unsigned mapCh, mapPos = (unsigned)-1; + + for (mapCh = 0; mapCh < (unsigned)numChannels; mapCh += 1) { + if (!mapped[mapCh]) { + UINT dist = getSpeakerDistance(spkrPos[mapCh], spkrSlotPos[ch]); + if (dist < mapDist) { + mapPos = mapCh; + mapDist = dist; + } + } + } + if (mapDist < PCMDMX_THRESHOLD_MAP_HEAT_3) { + offsetTable[ch] = (UCHAR)mapPos; + mapped[mapPos] = 1; + numMappedInChs += 1; + if ((spkrPos[mapPos].x == 0) && (spkrSlotPos[ch].x != 0) && + (numChannels < + (8))) { /* Skip the paired slot if we assigned a center channel. */ + ch += 1; + } + } + } + } + + /* Finaly compose the channel mode */ + for (ch = 0; ch < (4); ch += 1) { + int plane, numChInGrp = 0; + for (plane = 0; plane < (3); plane += 1) { + numChInGrp += numCh[plane][ch]; + } + *chMode = (PCM_DMX_CHANNEL_MODE)(*chMode | (numChInGrp << (ch * 4))); + } + + return err; +} + +/** Generate a channel offset table and complete channel description for a given + *(packed) channel mode. This function is the inverse to the getChannelMode() + *routine but does not support weird channel configurations. + * @param [in] The packed channel mode of the configuration to be processed. + * @param [in] Array containing the channel mapping to be used (From MPEG PCE + *ordering to whatever is required). + * @param [out] Array where corresponding channel types for each channels are + *stored into. + * @param [out] Array where corresponding channel type indices for each output + *channel are stored into. + * @param [out] Array where the buffer offsets for each channel are stored into. + * @returns None. + **/ +static void getChannelDescription( + const PCM_DMX_CHANNEL_MODE chMode, /* in */ + const FDK_channelMapDescr *const mapDescr, /* in */ + AUDIO_CHANNEL_TYPE channelType[], /* out */ + UCHAR channelIndices[], /* out */ + UCHAR offsetTable[(8)] /* out */ +) { + int grpIdx, plainIdx, numPlains = 1, numTotalChannels = 0; + int chCfg, ch = 0; + + FDK_ASSERT(channelType != NULL); + FDK_ASSERT(channelIndices != NULL); + FDK_ASSERT(mapDescr != NULL); + FDK_ASSERT(offsetTable != NULL); + + /* Init output arrays */ + FDKmemclear(channelType, (8) * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemclear(channelIndices, (8) * sizeof(UCHAR)); + FDKmemset(offsetTable, 255, (8) * sizeof(UCHAR)); + + /* Summerize to get the total number of channels */ + for (grpIdx = 0; grpIdx < (4); grpIdx += 1) { + numTotalChannels += (chMode >> (grpIdx * 4)) & 0xF; + } + + /* Get the appropriate channel map */ + switch (chMode) { + case CH_MODE_1_0_0_0: + case CH_MODE_2_0_0_0: + case CH_MODE_3_0_0_0: + case CH_MODE_3_0_1_0: + case CH_MODE_3_0_2_0: + case CH_MODE_3_0_2_1: + chCfg = numTotalChannels; + break; + case CH_MODE_3_0_3_1: + chCfg = 11; + break; + case CH_MODE_3_0_4_1: + chCfg = 12; + break; + case CH_MODE_5_0_2_1: + chCfg = 7; + break; + default: + /* fallback */ + chCfg = 0; + break; + } + + /* Compose channel offset table */ + + for (plainIdx = 0; plainIdx < numPlains; plainIdx += 1) { + PCM_DMX_CHANNEL_MODE plainChMode; + UCHAR numChInGrp[(4)]; + + plainChMode = getChMode4Plain(plainIdx, chMode, chCfg); + + /* Extract the number of channels per group */ + numChInGrp[CH_GROUP_FRONT] = plainChMode & 0xF; + numChInGrp[CH_GROUP_SIDE] = (plainChMode >> 4) & 0xF; + numChInGrp[CH_GROUP_REAR] = (plainChMode >> 8) & 0xF; + numChInGrp[CH_GROUP_LFE] = (plainChMode >> 12) & 0xF; + + /* Non-symmetric channels */ + if ((numChInGrp[CH_GROUP_FRONT] & 0x1) && (plainIdx == CH_PLAIN_NORMAL)) { + /* Odd number of front channels -> we have a center channel. + In MPEG-4 the center has the index 0. */ + int mappedIdx = FDK_chMapDescr_getMapValue(mapDescr, (UCHAR)ch, chCfg); + offsetTable[CENTER_FRONT_CHANNEL] = (UCHAR)mappedIdx; + channelType[mappedIdx] = ACT_FRONT; + channelIndices[mappedIdx] = 0; + ch += 1; + } + + for (grpIdx = 0; grpIdx < (4); grpIdx += 1) { + AUDIO_CHANNEL_TYPE type = ACT_NONE; + int chMapPos = 0, maxChannels = 0; + int chIdx = 0; /* Index of channel within the specific group */ + + switch (grpIdx) { + case CH_GROUP_FRONT: + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_FRONT); + switch (plainIdx) { + default: + chMapPos = LEFT_FRONT_CHANNEL; + chIdx = numChInGrp[grpIdx] & 0x1; + break; + } + maxChannels = 3; + break; + case CH_GROUP_SIDE: + /* Always map side channels to the multipurpose group. */ + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_SIDE); + if (plainIdx == CH_PLAIN_TOP) { + chMapPos = LEFT_SIDE_CHANNEL_TOP; + maxChannels = 3; + } else { + chMapPos = LEFT_MULTIPRPS_CHANNEL; + maxChannels = 2; + } + break; + case CH_GROUP_REAR: + type = (AUDIO_CHANNEL_TYPE)((plainIdx << 4) | ACT_BACK); + if (plainIdx == CH_PLAIN_TOP) { + chMapPos = LEFT_REAR_CHANNEL_TOP; + maxChannels = 3; + } else { + chMapPos = LEFT_REAR_CHANNEL; + maxChannels = 2; + } + break; + case CH_GROUP_LFE: + if (plainIdx == CH_PLAIN_NORMAL) { + type = ACT_LFE; + chMapPos = LOW_FREQUENCY_CHANNEL; + maxChannels = 1; + } + break; + default: + break; + } + + /* Map all channels in this group */ + for (; chIdx < numChInGrp[grpIdx]; chIdx += 1) { + int mappedIdx = FDK_chMapDescr_getMapValue(mapDescr, (UCHAR)ch, chCfg); + if ((chIdx == maxChannels) || (offsetTable[chMapPos] < 255)) { + /* No space left in this channel group! */ + if (offsetTable[LEFT_MULTIPRPS_CHANNEL] == + 255) { /* Use the multipurpose group: */ + chMapPos = LEFT_MULTIPRPS_CHANNEL; + } else { + FDK_ASSERT(0); + } + } + offsetTable[chMapPos] = (UCHAR)mappedIdx; + channelType[mappedIdx] = type; + channelIndices[mappedIdx] = (UCHAR)chIdx; + chMapPos += 1; + ch += 1; + } + } + } +} + +/** Private helper function for downmix matrix manipulation that initializes + * one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of channel (row) to be initialized. + * @returns Nothing to return. + **/ +static void dmxInitChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int outCh) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (inCh == outCh) { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.5f); + mixScales[outCh][inCh] = 1; + } else { + mixFactors[outCh][inCh] = FL2FXCONST_DMX(0.0f); + mixScales[outCh][inCh] = 0; + } + } +} + +/** Private helper function for downmix matrix manipulation that does a reset + * of one row in a given downmix matrix (corresponding to one output channel). + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of channel (row) to be cleared/reset. + * @returns Nothing to return. + **/ +static void dmxClearChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int outCh) { + FDK_ASSERT((outCh >= 0) && (outCh < (8))); + FDKmemclear(&mixFactors[outCh], (8) * sizeof(FIXP_DMX)); + FDKmemclear(&mixScales[outCh], (8) * sizeof(INT)); +} + +/** Private helper function for downmix matrix manipulation that applies a + *source channel (row) scaled by a given mix factor to a destination channel + *(row) in a given downmix matrix. Existing mix factors of the destination + *channel (row) will get overwritten. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static void dmxSetChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int dstCh, + const unsigned int srcCh, const FIXP_DMX factor, + const INT scale) { + int ch; + for (ch = 0; ch < (8); ch += 1) { + if (mixFactors[srcCh][ch] != (FIXP_DMX)0) { + mixFactors[dstCh][ch] = + FX_DBL2FX_DMX(fMult(mixFactors[srcCh][ch], factor)); + mixScales[dstCh][ch] = mixScales[srcCh][ch] + scale; + } + } +} + +/** Private helper function for downmix matrix manipulation that adds a source + *channel (row) scaled by a given mix factor to a destination channel (row) in a + *given downmix matrix. + * @param [inout] Pointer to fixed-point parts of the downmix matrix. + * @param [inout] Pointer to scale factor matrix associated to the downmix + *factors. + * @param [in] Index of source channel (row). + * @param [in] Index of destination channel (row). + * @param [in] Fixed-point part of mix factor to be applied. + * @param [in] Scale factor of mix factor to be applied. + * @returns Nothing to return. + **/ +static void dmxAddChannel(FIXP_DMX mixFactors[(8)][(8)], + INT mixScales[(8)][(8)], const unsigned int dstCh, + const unsigned int srcCh, const FIXP_DMX factor, + const INT scale) { + int ch; + for (ch = 0; ch < (8); ch += 1) { + FIXP_DBL addFact = fMult(mixFactors[srcCh][ch], factor); + if (addFact != (FIXP_DMX)0) { + INT newScale = mixScales[srcCh][ch] + scale; + if (mixFactors[dstCh][ch] != (FIXP_DMX)0) { + if (newScale > mixScales[dstCh][ch]) { + mixFactors[dstCh][ch] >>= newScale - mixScales[dstCh][ch]; + } else { + addFact >>= mixScales[dstCh][ch] - newScale; + newScale = mixScales[dstCh][ch]; + } + } + mixFactors[dstCh][ch] += FX_DBL2FX_DMX(addFact); + mixScales[dstCh][ch] = newScale; + } + } +} + +/** Private function that creates a downmix factor matrix depending on the input + and output + * configuration, the user parameters as well as the given metadata. This + function is the modules + * brain and hold all downmix algorithms. + * @param [in] Flag that indicates if inChMode holds a real (packed) channel + mode or has been converted to a MPEG-4 channel configuration index. + * @param [in] Dependent on the inModeIsCfg flag this field hands in a (packed) + channel mode or the corresponding MPEG-4 channel configuration index.of the + input configuration. + * @param [in] The (packed) channel mode of the output configuration. + * @param [in] Pointer to structure holding all current user parameter. + * @param [in] Pointer to field holding all current meta data. + * @param [out] Pointer to fixed-point parts of the downmix matrix. Normalized + to one scale factor. + * @param [out] The common scale factor of the downmix matrix. + * @returns An error code. + **/ +static PCMDMX_ERROR getMixFactors(const UCHAR inModeIsCfg, + PCM_DMX_CHANNEL_MODE inChMode, + const PCM_DMX_CHANNEL_MODE outChMode, + const PCM_DMX_USER_PARAMS *pParams, + const DMX_BS_META_DATA *pMetaData, + FIXP_DMX mixFactors[(8)][(8)], + INT *pOutScale) { + PCMDMX_ERROR err = PCMDMX_OK; + INT mixScales[(8)][(8)]; + INT maxScale = 0; + int numInChannel; + int numOutChannel; + int dmxMethod; + unsigned int outCh, inChCfg = 0; + unsigned int valid[(8)] = {0}; + + FDK_ASSERT(pMetaData != NULL); + FDK_ASSERT(mixFactors != NULL); + /* Check on a supported output configuration. + Add new one only after extensive testing! */ + if (!((outChMode == CH_MODE_1_0_0_0) || (outChMode == CH_MODE_2_0_0_0) || + (outChMode == CH_MODE_3_0_2_1) || (outChMode == CH_MODE_3_0_4_1) || + (outChMode == CH_MODE_5_0_2_1))) { + FDK_ASSERT(0); + } + + if (inModeIsCfg) { + /* Convert channel config to channel mode: */ + inChCfg = (unsigned int)inChMode; + switch (inChCfg) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + inChMode = outChModeTable[inChCfg]; + break; + case 11: + inChMode = CH_MODE_3_0_3_1; + break; + case 12: + inChMode = CH_MODE_3_0_4_1; + break; + case 7: + case 14: + inChMode = CH_MODE_5_0_2_1; + break; + default: + FDK_ASSERT(0); + } + } + + /* Extract the total number of input channels */ + numInChannel = (inChMode & 0xF) + ((inChMode >> 4) & 0xF) + + ((inChMode >> 8) & 0xF) + ((inChMode >> 12) & 0xF); + /* Extract the total number of output channels */ + numOutChannel = (outChMode & 0xF) + ((outChMode >> 4) & 0xF) + + ((outChMode >> 8) & 0xF) + ((outChMode >> 12) & 0xF); + + /* MPEG ammendment 4 aka ETSI metadata and fallback mode: */ + + /* Create identity DMX matrix: */ + for (outCh = 0; outCh < (8); outCh += 1) { + dmxInitChannel(mixFactors, mixScales, outCh); + } + if (((inChMode >> 12) & 0xF) == 0) { + /* Clear empty or wrongly mapped input channel */ + dmxClearChannel(mixFactors, mixScales, LOW_FREQUENCY_CHANNEL); + } + + /* FIRST STAGE: */ + if (numInChannel > SIX_CHANNEL) { /* Always use MPEG equations either with + meta data or with default values. */ + FIXP_DMX dMixFactA, dMixFactB; + INT dMixScaleA, dMixScaleB; + int isValidCfg = TRUE; + + /* Get factors from meta data */ + dMixFactA = abMixLvlValueTab[pMetaData->dmixIdxA]; + dMixScaleA = (pMetaData->dmixIdxA == 0) ? 1 : 0; + dMixFactB = abMixLvlValueTab[pMetaData->dmixIdxB]; + dMixScaleB = (pMetaData->dmixIdxB == 0) ? 1 : 0; + + /* Check if input is in the list of supported configurations */ + switch (inChMode) { + case CH_MODE_3_2_1_1: /* chCfg 11 but with side channels */ + case CH_MODE_3_2_1_0: + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + FDK_FALLTHROUGH; + case CH_MODE_3_0_3_1: /* chCfg 11 */ + /* 6.1ch: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Cs*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Cs*dmix_b_idx; */ + dmxClearChannel( + mixFactors, mixScales, + RIGHT_MULTIPRPS_CHANNEL); /* clear empty input channel */ + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + /* 7.1ch Surround Back: C' = C; L' = L; R' = R; LFE' = LFE; + Ls' = Ls*dmix_a_idx + Lsr*dmix_b_idx; + Rs' = Rs*dmix_a_idx + Rsr*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + break; + case CH_MODE_5_0_1_0: + case CH_MODE_5_0_1_1: + dmxClearChannel(mixFactors, mixScales, + RIGHT_REAR_CHANNEL); /* clear empty input channel */ + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, + LEFT_REAR_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + FDK_FALLTHROUGH; + case CH_MODE_5_2_1_0: + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + FDK_FALLTHROUGH; + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + if (inChCfg == 14) { + /* 7.1ch Front Height: C' = C; Ls' = Ls; Rs' = Rs; LFE' = LFE; + L' = L*dmix_a_idx + Lv*dmix_b_idx; + R' = R*dmix_a_idx + Rv*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + } else { + /* 7.1ch Front: Ls' = Ls; Rs' = Rs; LFE' = LFE; + C' = C + (Lc+Rc)*dmix_a_idx; + L' = L + Lc*dmix_b_idx; + R' = R + Rc*dmix_b_idx; */ + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactA, dMixScaleA); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_MULTIPRPS_CHANNEL, dMixFactB, dMixScaleB); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 1); + } + break; + default: + /* Nothing to do. Just use the identity matrix. */ + isValidCfg = FALSE; + err = PCMDMX_INVALID_MODE; + break; + } + + /* Add additional DMX gain */ + if ((isValidCfg == TRUE) && + (pMetaData->dmxGainIdx5 != 0)) { /* Apply DMX gain 5 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx5 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx5 & 0x3F; + + /* 10^(dmx_gain_5/80) */ + dmxGain = FX_DBL2FX_DMX( + fLdPow(FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign * val * (LONG)FL2FXCONST_DBL(0.0125f)), 0, + &dmxScale)); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LEFT_REAR_CHANNEL, LEFT_REAR_CHANNEL, + dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_REAR_CHANNEL, + RIGHT_REAR_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, LOW_FREQUENCY_CHANNEL, + LOW_FREQUENCY_CHANNEL, dmxGain, dmxScale); + } + + /* Mark the output channels */ + valid[CENTER_FRONT_CHANNEL] = 1; + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + valid[LEFT_REAR_CHANNEL] = 1; + valid[RIGHT_REAR_CHANNEL] = 1; + valid[LOW_FREQUENCY_CHANNEL] = 1; + + /* Update channel mode for the next stage */ + inChMode = CH_MODE_3_0_2_1; + } + + /* For the X (> 6) to 6 channel downmix we had no choice. + To mix from 6 to 2 (or 1) channel(s) we have several possibilities (MPEG + DSE | MPEG PCE | ITU | ARIB | DLB). Use profile and the metadata + available flags to determine which equation to use: */ + +#define DMX_METHOD_MPEG_AMD4 1 +#define DMX_METHOD_MPEG_LEGACY 2 +#define DMX_METHOD_ARIB_JAPAN 4 +#define DMX_METHOD_ITU_RECOM 8 +#define DMX_METHOD_CUSTOM 16 + + dmxMethod = DMX_METHOD_MPEG_AMD4; /* default */ + + if ((pParams->dmxProfile == DMX_PRFL_FORCE_MATRIX_MIX) && + (pMetaData->typeFlags & TYPE_PCE_DATA)) { + dmxMethod = DMX_METHOD_MPEG_LEGACY; + } else if (!(pMetaData->typeFlags & + (TYPE_DSE_CLEV_DATA | TYPE_DSE_SLEV_DATA))) { + switch (pParams->dmxProfile) { + default: + case DMX_PRFL_STANDARD: + /* dmxMethod = DMX_METHOD_MPEG_AMD4; */ + break; + case DMX_PRFL_MATRIX_MIX: + case DMX_PRFL_FORCE_MATRIX_MIX: + if (pMetaData->typeFlags & TYPE_PCE_DATA) { + dmxMethod = DMX_METHOD_MPEG_LEGACY; + } + break; + case DMX_PRFL_ARIB_JAPAN: + dmxMethod = DMX_METHOD_ARIB_JAPAN; + break; + } + } + + /* SECOND STAGE: */ + if (numOutChannel <= TWO_CHANNEL) { + /* Create DMX matrix according to input configuration */ + switch (inChMode) { + case CH_MODE_2_0_0_0: /* chCfg 2 */ + /* Apply the dual channel mode. */ + switch (pParams->dualChannelMode) { + case CH1_MODE: /* L' = 0.707 * Ch1; + R' = 0.707 * Ch1; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + break; + case CH2_MODE: /* L' = 0.707 * Ch2; + R' = 0.707 * Ch2; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; + R' = 0.5*Ch1 + 0.5*Ch2; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.5f), 0); + break; + default: + case STEREO_MODE: + /* Nothing to do */ + break; + } + break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_2_0_1_0: { + FIXP_DMX sMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*S; R' = 0.707*R + 0.5*S; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + sMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*S; R' = R + 0.707*S; */ + sMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_0_0: /* chCfg 3 */ + { + FIXP_DMX cMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*C; R' = 0.707*R + 0.5*C; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + cMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*C; R' = R + 0.707*C; */ + cMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_1_0: /* chCfg 4 */ + { + FIXP_DMX csMixLvl; + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* L' = 0.707*L + 0.5*C + 0.5*S; R' = 0.707*R + 0.5*C + 0.5*S; */ + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, FL2FXCONST_DMX(0.707f), 0); + csMixLvl = FL2FXCONST_DMX(0.5f); + } else { /* L' = L + 0.707*C + 0.707*S; + R' = R + 0.707*C + 0.707*S; */ + csMixLvl = FL2FXCONST_DMX(0.707f); + } + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, csMixLvl, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, csMixLvl, 0); + } break; + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - - */ + case CH_MODE_3_0_2_0: /* chCfg 5 */ + case CH_MODE_3_0_2_1: /* chCfg 6 */ + { + switch (dmxMethod) { + default: + case DMX_METHOD_MPEG_AMD4: { + FIXP_DMX cMixLvl, sMixLvl, lMixLvl; + INT cMixScale, sMixScale, lMixScale; + + /* Get factors from meta data */ + cMixLvl = abMixLvlValueTab[pMetaData->cLevIdx]; + cMixScale = (pMetaData->cLevIdx == 0) ? 1 : 0; + sMixLvl = abMixLvlValueTab[pMetaData->sLevIdx]; + sMixScale = (pMetaData->sLevIdx == 0) ? 1 : 0; + lMixLvl = lfeMixLvlValueTab[pMetaData->dmixIdxLfe]; + if (pMetaData->dmixIdxLfe <= 1) { + lMixScale = 2; + } else if (pMetaData->dmixIdxLfe <= 5) { + lMixScale = 1; + } else { + lMixScale = 0; + } + /* Setup the DMX matrix */ + if ((pParams->pseudoSurrMode == FORCE_PS_DMX) || + ((pParams->pseudoSurrMode == AUTO_PS_DMX) && + (pMetaData->pseudoSurround == + 1))) { /* L' = L + C*clev - (Ls+Rs)*slev + LFE*lflev; + R' = R + C*clev + (Ls+Rs)*slev + LFE*lflev; */ + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, -sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, -sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + } else { /* L' = L + C*clev + Ls*slev + LFE*llev; + R' = R + C*clev + Rs*slev + LFE*llev; */ + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, cMixLvl, cMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, sMixLvl, sMixScale); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LOW_FREQUENCY_CHANNEL, lMixLvl, lMixScale); + } + + /* Add additional DMX gain */ + if (pMetaData->dmxGainIdx2 != 0) { /* Apply DMX gain 2 */ + FIXP_DMX dmxGain; + INT dmxScale; + INT sign = (pMetaData->dmxGainIdx2 & 0x40) ? -1 : 1; + INT val = pMetaData->dmxGainIdx2 & 0x3F; + + /* 10^(dmx_gain_2/80) */ + dmxGain = FX_DBL2FX_DMX( + fLdPow(FL2FXCONST_DBL(0.830482023721841f), 2, /* log2(10) */ + (FIXP_DBL)(sign * val * (LONG)FL2FXCONST_DBL(0.0125f)), + 0, &dmxScale)); + /* Currently only positive scale factors supported! */ + if (dmxScale < 0) { + dmxGain >>= -dmxScale; + dmxScale = 0; + } + + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, dmxGain, dmxScale); + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, dmxGain, dmxScale); + } + } break; + case DMX_METHOD_ARIB_JAPAN: + case DMX_METHOD_MPEG_LEGACY: { + FIXP_DMX flev, clev, slevLL, slevLR, slevRL, slevRR; + FIXP_DMX mtrxMixDwnCoef = + mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx]; + + if ((pParams->pseudoSurrMode == FORCE_PS_DMX) || + ((pParams->pseudoSurrMode == AUTO_PS_DMX) && + (pMetaData->pseudoSurround == 1))) { + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* 3/2 input: L' = 0.707 * [L+0.707*C-k*Ls-k*Rs]; + R' = 0.707 * [R+0.707*C+k*Ls+k*Rs]; */ + flev = mpegMixDownIdx2Coef[0]; /* a = 0.707 */ + } else { /* 3/2 input: L' = (1.707+2*A)^-1 * + [L+0.707*C-A*Ls-A*Rs]; R' = (1.707+2*A)^-1 * + [R+0.707*C+A*Ls+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[1][pMetaData->matrixMixdownIdx]; + } + slevRR = slevRL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLL = slevLR = -slevRL; + } else { + if (dmxMethod == DMX_METHOD_ARIB_JAPAN) { + /* 3/2 input: L' = 0.707 * [L+0.707*C+k*Ls]; + R' = 0.707 * [R+0.707*C+k*Rs]; */ + flev = mpegMixDownIdx2Coef[0]; /* a = 0.707 */ + } else { /* 3/2 input: L' = (1.707+A)^-1 * [L+0.707*C+A*Ls]; + R' = (1.707+A)^-1 * [R+0.707*C+A*Rs]; */ + flev = mpegMixDownIdx2PreFact[0][pMetaData->matrixMixdownIdx]; + } + slevRR = slevLL = FX_DBL2FX_DMX(fMult(flev, mtrxMixDwnCoef)); + slevLR = slevRL = (FIXP_DMX)0; + } + /* common factor */ + clev = + FX_DBL2FX_DMX(fMult(flev, mpegMixDownIdx2Coef[0] /* 0.707 */)); + + dmxSetChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, flev, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, clev, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, slevLL, 0); + dmxAddChannel(mixFactors, mixScales, LEFT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, slevLR, 0); + + dmxSetChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, flev, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + CENTER_FRONT_CHANNEL, clev, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + LEFT_REAR_CHANNEL, slevRL, 0); + dmxAddChannel(mixFactors, mixScales, RIGHT_FRONT_CHANNEL, + RIGHT_REAR_CHANNEL, slevRR, 0); + } break; + } /* switch (dmxMethod) */ + } break; + default: + /* This configuration does not fit to any known downmix equation! */ + err = PCMDMX_INVALID_MODE; + break; + } /* switch (inChMode) */ + + /* Mark the output channels */ + FDKmemclear(valid, (8) * sizeof(unsigned int)); + valid[LEFT_FRONT_CHANNEL] = 1; + valid[RIGHT_FRONT_CHANNEL] = 1; + } + + if (numOutChannel == ONE_CHANNEL) { + FIXP_DMX monoMixLevel; + INT monoMixScale = 0; + + dmxClearChannel(mixFactors, mixScales, + CENTER_FRONT_CHANNEL); /* C is not in the mix */ + + if (dmxMethod == + DMX_METHOD_MPEG_LEGACY) { /* C' = (3+2*A)^-1 * [C+L+R+A*Ls+A+Rs]; */ + monoMixLevel = mpegMixDownIdx2PreFact[2][pMetaData->matrixMixdownIdx]; + + mixFactors[CENTER_FRONT_CHANNEL][CENTER_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][LEFT_FRONT_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_FRONT_CHANNEL] = monoMixLevel; + monoMixLevel = FX_DBL2FX_DMX(fMult( + monoMixLevel, mpegMixDownIdx2Coef[pMetaData->matrixMixdownIdx])); + mixFactors[CENTER_FRONT_CHANNEL][LEFT_REAR_CHANNEL] = monoMixLevel; + mixFactors[CENTER_FRONT_CHANNEL][RIGHT_REAR_CHANNEL] = monoMixLevel; + } else { + switch (dmxMethod) { + case DMX_METHOD_MPEG_AMD4: + /* C' = L + R; */ + monoMixLevel = FL2FXCONST_DMX(0.5f); + monoMixScale = 1; + break; + default: + /* C' = 0.5*L + 0.5*R; */ + monoMixLevel = FL2FXCONST_DMX(0.5f); + monoMixScale = 0; + break; + } + dmxSetChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + LEFT_FRONT_CHANNEL, monoMixLevel, monoMixScale); + dmxAddChannel(mixFactors, mixScales, CENTER_FRONT_CHANNEL, + RIGHT_FRONT_CHANNEL, monoMixLevel, monoMixScale); + } + + /* Mark the output channel */ + FDKmemclear(valid, (8) * sizeof(unsigned int)); + valid[CENTER_FRONT_CHANNEL] = 1; + } + +#define MAX_SEARCH_START_VAL (-7) + + { + LONG chSum[(8)]; + INT chSumMax = MAX_SEARCH_START_VAL; + + /* Determine the current maximum scale factor */ + for (outCh = 0; outCh < (8); outCh += 1) { + if (valid[outCh] != 0) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (mixScales[outCh][inCh] > maxScale) { /* Store the new maximum */ + maxScale = mixScales[outCh][inCh]; + } + } + } + } + + /* Individualy analyse output chanal levels */ + for (outCh = 0; outCh < (8); outCh += 1) { + chSum[outCh] = MAX_SEARCH_START_VAL; + if (valid[outCh] != 0) { + int ovrflwProtScale = 0; + unsigned int inCh; + + /* Accumulate all factors for each output channel */ + chSum[outCh] = 0; + for (inCh = 0; inCh < (8); inCh += 1) { + SHORT addFact = FX_DMX2SHRT(mixFactors[outCh][inCh]); + if (mixScales[outCh][inCh] <= maxScale) { + addFact >>= maxScale - mixScales[outCh][inCh]; + } else { + addFact <<= mixScales[outCh][inCh] - maxScale; + } + chSum[outCh] += addFact; + } + if (chSum[outCh] > (LONG)MAXVAL_SGL) { + while (chSum[outCh] > (LONG)MAXVAL_SGL) { + ovrflwProtScale += 1; + chSum[outCh] >>= 1; + } + } else if (chSum[outCh] > 0) { + while ((chSum[outCh] << 1) <= (LONG)MAXVAL_SGL) { + ovrflwProtScale -= 1; + chSum[outCh] <<= 1; + } + } + /* Store the differential scaling in the same array */ + chSum[outCh] = ovrflwProtScale; + } + } + + for (outCh = 0; outCh < (8); outCh += 1) { + if ((valid[outCh] != 0) && + (chSum[outCh] > chSumMax)) { /* Store the new maximum */ + chSumMax = chSum[outCh]; + } + } + maxScale = fMax(maxScale + chSumMax, 0); + + /* Normalize all factors */ + for (outCh = 0; outCh < (8); outCh += 1) { + if (valid[outCh] != 0) { + unsigned int inCh; + for (inCh = 0; inCh < (8); inCh += 1) { + if (mixFactors[outCh][inCh] != (FIXP_DMX)0) { + if (mixScales[outCh][inCh] <= maxScale) { + mixFactors[outCh][inCh] >>= maxScale - mixScales[outCh][inCh]; + } else { + mixFactors[outCh][inCh] <<= mixScales[outCh][inCh] - maxScale; + } + mixScales[outCh][inCh] = maxScale; + } + } + } + } + } + + /* return the scale factor */ + *pOutScale = maxScale; + + return (err); +} + +/** Open and initialize an instance of the PCM downmix module + * @param [out] Pointer to a buffer receiving the handle of the new instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Open(HANDLE_PCM_DOWNMIX *pSelf) { + HANDLE_PCM_DOWNMIX self; + + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + *pSelf = NULL; + + self = (HANDLE_PCM_DOWNMIX)GetPcmDmxInstance(0); + if (self == NULL) { + return (PCMDMX_OUT_OF_MEMORY); + } + + /* Reset the full instance */ + pcmDmx_Reset(self, PCMDMX_RESET_FULL); + + *pSelf = self; + + return (PCMDMX_OK); +} + +/** Reset all static values like e.g. mixdown coefficients. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Flags telling which parts of the module shall be reset. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Reset(HANDLE_PCM_DOWNMIX self, UINT flags) { + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + if (flags & PCMDMX_RESET_PARAMS) { + PCM_DMX_USER_PARAMS *pParams = &self->userParams; + + pParams->dualChannelMode = STEREO_MODE; + pParams->pseudoSurrMode = NEVER_DO_PS_DMX; + pParams->numOutChannelsMax = (6); + pParams->numOutChannelsMin = (0); + pParams->frameDelay = 0; + pParams->expiryFrame = (0); + + self->applyProcessing = 0; + } + + if (flags & PCMDMX_RESET_BS_DATA) { + int slot; + /* Init all slots with a default set */ + for (slot = 0; slot <= (1); slot += 1) { + FDKmemcpy(&self->bsMetaData[slot], &dfltMetaData, + sizeof(DMX_BS_META_DATA)); + } + } + + return (PCMDMX_OK); +} + +/** Set one parameter for one instance of the PCM downmix module. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [in] Parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + const INT value) { + switch (param) { + case DMX_PROFILE_SETTING: + switch ((DMX_PROFILE_TYPE)value) { + case DMX_PRFL_STANDARD: + case DMX_PRFL_MATRIX_MIX: + case DMX_PRFL_FORCE_MATRIX_MIX: + case DMX_PRFL_ARIB_JAPAN: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.dmxProfile = (DMX_PROFILE_TYPE)value; + break; + + case DMX_BS_DATA_EXPIRY_FRAME: + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.expiryFrame = (value > 0) ? (UINT)value : 0; + break; + + case DMX_BS_DATA_DELAY: + if ((value > (1)) || (value < 0)) { + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + self->userParams.frameDelay = (UCHAR)value; + break; + + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: + case 0: + case ONE_CHANNEL: + case TWO_CHANNEL: + case SIX_CHANNEL: + case EIGHT_CHANNEL: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMin = (value > 0) ? (SHORT)value : -1; + if ((value > 0) && (self->userParams.numOutChannelsMax > 0) && + (value > self->userParams + .numOutChannelsMax)) { /* MIN > MAX would be an invalid + state. Thus set MAX = MIN in + this case. */ + self->userParams.numOutChannelsMax = self->userParams.numOutChannelsMin; + } + break; + + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + switch (value) { /* supported output channels */ + case -1: + case 0: + case ONE_CHANNEL: + case TWO_CHANNEL: + case SIX_CHANNEL: + case EIGHT_CHANNEL: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + /* Store the new value */ + self->userParams.numOutChannelsMax = (value > 0) ? (SHORT)value : -1; + if ((value > 0) && + (value < self->userParams + .numOutChannelsMin)) { /* MAX < MIN would be an invalid + state. Thus set MIN = MAX in + this case. */ + self->userParams.numOutChannelsMin = self->userParams.numOutChannelsMax; + } + break; + + case DMX_DUAL_CHANNEL_MODE: + switch ((DUAL_CHANNEL_MODE)value) { + case STEREO_MODE: + case CH1_MODE: + case CH2_MODE: + case MIXED_MODE: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.dualChannelMode = (DUAL_CHANNEL_MODE)value; + self->applyProcessing = ((DUAL_CHANNEL_MODE)value != STEREO_MODE) + ? 1 + : 0; /* Force processing if necessary. */ + break; + + case DMX_PSEUDO_SURROUND_MODE: + switch ((PSEUDO_SURROUND_MODE)value) { + case NEVER_DO_PS_DMX: + case AUTO_PS_DMX: + case FORCE_PS_DMX: + break; + default: + return (PCMDMX_UNABLE_TO_SET_PARAM); + } + if (self == NULL) return (PCMDMX_INVALID_HANDLE); + self->userParams.pseudoSurrMode = (PSEUDO_SURROUND_MODE)value; + break; + + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + +/** Get one parameter value of one PCM downmix module instance. + * @param [in] Handle of PCM downmix module instance. + * @param [in] Parameter to be set. + * @param [out] Pointer to buffer receiving the parameter value. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_GetParam(HANDLE_PCM_DOWNMIX self, const PCMDMX_PARAM param, + INT *const pValue) { + PCM_DMX_USER_PARAMS *pUsrParams; + + if ((self == NULL) || (pValue == NULL)) { + return (PCMDMX_INVALID_HANDLE); + } + pUsrParams = &self->userParams; + + switch (param) { + case DMX_PROFILE_SETTING: + *pValue = (INT)pUsrParams->dmxProfile; + break; + case DMX_BS_DATA_EXPIRY_FRAME: + *pValue = (INT)pUsrParams->expiryFrame; + break; + case DMX_BS_DATA_DELAY: + *pValue = (INT)pUsrParams->frameDelay; + break; + case MIN_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMin; + break; + case MAX_NUMBER_OF_OUTPUT_CHANNELS: + *pValue = (INT)pUsrParams->numOutChannelsMax; + break; + case DMX_DUAL_CHANNEL_MODE: + *pValue = (INT)pUsrParams->dualChannelMode; + break; + case DMX_PSEUDO_SURROUND_MODE: + *pValue = (INT)pUsrParams->pseudoSurrMode; + break; + default: + return (PCMDMX_UNKNOWN_PARAM); + } + + return (PCMDMX_OK); +} + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_Parse(HANDLE_PCM_DOWNMIX self, HANDLE_FDK_BITSTREAM hBs, + UINT ancDataBits, int isMpeg2) { + PCMDMX_ERROR errorStatus = PCMDMX_OK; + +#define MAX_DSE_ANC_BYTES (16) /* 15 bytes */ +#define ANC_DATA_SYNC_BYTE (0xBC) /* ancillary data sync byte. */ + + DMX_BS_META_DATA *pBsMetaData; + + int skip4Dmx = 0, skip4Ext = 0; + int dmxLvlAvail = 0, extDataAvail = 0; + UINT foundNewData = 0; + UINT minAncBits = ((isMpeg2) ? 5 : 3) * 8; + + if ((self == NULL) || (hBs == NULL)) { + return (PCMDMX_INVALID_HANDLE); + } + + /* sanity checks */ + if ((ancDataBits < minAncBits) || (ancDataBits > FDKgetValidBits(hBs))) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + pBsMetaData = &self->bsMetaData[0]; + + if (isMpeg2) { + /* skip DVD ancillary data */ + FDKpushFor(hBs, 16); + } + + /* check sync word */ + if (FDKreadBits(hBs, 8) != ANC_DATA_SYNC_BYTE) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + /* skip MPEG audio type and Dolby surround mode */ + FDKpushFor(hBs, 4); + + if (isMpeg2) { + /* int numAncBytes = */ FDKreadBits(hBs, 4); + /* advanced dynamic range control */ + if (FDKreadBit(hBs)) skip4Dmx += 24; + /* dialog normalization */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + /* reproduction_level */ + if (FDKreadBit(hBs)) skip4Dmx += 8; + } else { + FDKpushFor(hBs, 2); /* drc presentation mode */ + pBsMetaData->pseudoSurround = (SCHAR)FDKreadBit(hBs); + FDKpushFor(hBs, 4); /* reserved bits */ + } + + /* downmixing levels MPEGx status */ + dmxLvlAvail = FDKreadBit(hBs); + + if (isMpeg2) { + /* scale factor CRC status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + } else { + /* ancillary data extension status */ + extDataAvail = FDKreadBit(hBs); + } + + /* audio coding and compression status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* coarse grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + /* fine grain timecode status */ + if (FDKreadBit(hBs)) skip4Ext += 16; + + /* skip the useless data to get to the DMX levels */ + FDKpushFor(hBs, skip4Dmx); + + /* downmix_levels_MPEGX */ + if (dmxLvlAvail) { + if (FDKreadBit(hBs)) { /* center_mix_level_on */ + pBsMetaData->cLevIdx = (UCHAR)FDKreadBits(hBs, 3); + foundNewData |= TYPE_DSE_CLEV_DATA; + } else { + FDKreadBits(hBs, 3); + } + if (FDKreadBit(hBs)) { /* surround_mix_level_on */ + pBsMetaData->sLevIdx = (UCHAR)FDKreadBits(hBs, 3); + foundNewData |= TYPE_DSE_SLEV_DATA; + } else { + FDKreadBits(hBs, 3); + } + } + + /* skip the useless data to get to the ancillary data extension */ + FDKpushFor(hBs, skip4Ext); + + /* anc data extension (MPEG-4 only) */ + if (extDataAvail) { + int extDmxLvlSt, extDmxGainSt, extDmxLfeSt; + + FDKreadBit(hBs); /* reserved bit */ + extDmxLvlSt = FDKreadBit(hBs); + extDmxGainSt = FDKreadBit(hBs); + extDmxLfeSt = FDKreadBit(hBs); + FDKreadBits(hBs, 4); /* reserved bits */ + + if (extDmxLvlSt) { + pBsMetaData->dmixIdxA = (UCHAR)FDKreadBits(hBs, 3); + pBsMetaData->dmixIdxB = (UCHAR)FDKreadBits(hBs, 3); + FDKreadBits(hBs, 2); /* reserved bits */ + foundNewData |= TYPE_DSE_DMIX_AB_DATA; + } + if (extDmxGainSt) { + pBsMetaData->dmxGainIdx5 = (UCHAR)FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + pBsMetaData->dmxGainIdx2 = (UCHAR)FDKreadBits(hBs, 7); + FDKreadBit(hBs); /* reserved bit */ + foundNewData |= TYPE_DSE_DMX_GAIN_DATA; + } + if (extDmxLfeSt) { + pBsMetaData->dmixIdxLfe = (UCHAR)FDKreadBits(hBs, 4); + FDKreadBits(hBs, 4); /* reserved bits */ + foundNewData |= TYPE_DSE_DMIX_LFE_DATA; + } + } + + /* final sanity check on the amount of read data */ + if ((INT)FDKgetValidBits(hBs) < 0) { + errorStatus = PCMDMX_CORRUPT_ANC_DATA; + } + + if ((errorStatus == PCMDMX_OK) && (foundNewData != 0)) { + /* announce new data */ + pBsMetaData->typeFlags |= foundNewData; + /* reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + + return (errorStatus); +} + +/* + * Read DMX meta-data from a data stream element. + */ +PCMDMX_ERROR pcmDmx_ReadDvbAncData(HANDLE_PCM_DOWNMIX self, UCHAR *pAncDataBuf, + UINT ancDataBytes, int isMpeg2) { + PCMDMX_ERROR errorStatus = PCMDMX_OK; + FDK_BITSTREAM bs; + HANDLE_FDK_BITSTREAM hBs = &bs; + + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + /* sanity checks */ + if ((pAncDataBuf == NULL) || (ancDataBytes == 0)) { + return (PCMDMX_CORRUPT_ANC_DATA); + } + + FDKinitBitStream(hBs, pAncDataBuf, MAX_DSE_ANC_BYTES, ancDataBytes * 8, + BS_READER); + + errorStatus = pcmDmx_Parse(self, hBs, ancDataBytes * 8, isMpeg2); + + return (errorStatus); +} + +/** Set the matrix mixdown information extracted from the PCE of an AAC + *bitstream. Note: Call only if matrix_mixdown_idx_present is true. + * @param [in] Handle of PCM downmix module instance. + * @param [in] The 2 bit matrix mixdown index extracted from PCE. + * @param [in] The pseudo surround enable flag extracted from PCE. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_SetMatrixMixdownFromPce(HANDLE_PCM_DOWNMIX self, + int matrixMixdownPresent, + int matrixMixdownIdx, + int pseudoSurroundEnable) { + if (self == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + { + DMX_BS_META_DATA *pBsMetaData = &self->bsMetaData[0]; + + if (matrixMixdownPresent) { + pBsMetaData->pseudoSurround = (pseudoSurroundEnable) ? 1 : 0; + pBsMetaData->matrixMixdownIdx = matrixMixdownIdx & 0x03; + pBsMetaData->typeFlags |= TYPE_PCE_DATA; + /* Reset expiry counter */ + pBsMetaData->expiryCount = 0; + } + } + + return (PCMDMX_OK); +} + +/** Apply down or up mixing. + * @param [in] Handle of PCM downmix module instance. + * @param [inout] Pointer to buffer that hold the time domain signal. + * @param [in] Pointer where the amount of output samples is returned into. + * @param [in] Size of pPcmBuf. + * @param [inout] Pointer where the amount of output channels is returned into. + * @param [in] Input and output samples are processed interleaved. + * @param [inout] Array where the corresponding channel type for each output + *audio channel is stored into. + * @param [inout] Array where the corresponding channel type index for each + *output audio channel is stored into. + * @param [in] Array containing the out channel mapping to be used (From MPEG + *PCE ordering to whatever is required). + * @param [out] Pointer on a field receiving the scale factor that has to be + *applied on all samples afterwards. If the handed pointer is NULL scaling is + *done internally. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_ApplyFrame(HANDLE_PCM_DOWNMIX self, DMX_PCM *pPcmBuf, + const int pcmBufSize, UINT frameSize, + INT *nChannels, INT fInterleaved, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr, + INT *pDmxOutScale) { + PCM_DMX_USER_PARAMS *pParam = NULL; + PCMDMX_ERROR errorStatus = PCMDMX_OK; + DUAL_CHANNEL_MODE dualChannelMode; + PCM_DMX_CHANNEL_MODE inChMode; + PCM_DMX_CHANNEL_MODE outChMode; + INT devNull; /* Just a dummy to avoid a lot of branches in the code */ + int numOutChannels, numInChannels; + int inStride, outStride, offset; + int dmxMaxScale, dmxScale; + int slot; + UCHAR inOffsetTable[(8)]; + + DMX_BS_META_DATA bsMetaData; + + if ((self == NULL) || (nChannels == NULL) || (channelType == NULL) || + (channelIndices == NULL) || (!FDK_chMapDescr_isValid(mapDescr))) { + return (PCMDMX_INVALID_HANDLE); + } + + /* Init the output scaling */ + dmxScale = 0; + if (pDmxOutScale != NULL) { + /* Avoid final scaling internally and hand it to the outside world. */ + *pDmxOutScale = 0; + dmxMaxScale = (3); + } else { + /* Apply the scaling internally. */ + pDmxOutScale = &devNull; /* redirect to temporal stack memory */ + dmxMaxScale = 0; + } + + pParam = &self->userParams; + numInChannels = *nChannels; + + /* Perform some input sanity checks */ + if (pPcmBuf == NULL) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (frameSize == 0) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (numInChannels == 0) { + return (PCMDMX_INVALID_ARGUMENT); + } + if (numInChannels > (8)) { + return (PCMDMX_INVALID_CH_CONFIG); + } + + /* Check on misconfiguration */ + FDK_ASSERT((pParam->numOutChannelsMax <= 0) || + (pParam->numOutChannelsMax >= pParam->numOutChannelsMin)); + + /* Determine if the module has to do processing */ + if ((self->applyProcessing == 0) && + ((pParam->numOutChannelsMax <= 0) || + (pParam->numOutChannelsMax >= numInChannels)) && + (pParam->numOutChannelsMin <= numInChannels)) { + /* Nothing to do */ + return (errorStatus); + } + + /* Determine the number of output channels */ + if ((pParam->numOutChannelsMax > 0) && + (numInChannels > pParam->numOutChannelsMax)) { + numOutChannels = pParam->numOutChannelsMax; + } else if (numInChannels < pParam->numOutChannelsMin) { + numOutChannels = pParam->numOutChannelsMin; + } else { + numOutChannels = numInChannels; + } + + /* Check I/O buffer size */ + if ((UINT)pcmBufSize < (UINT)numOutChannels * frameSize) { + return (PCMDMX_OUTPUT_BUFFER_TOO_SMALL); + } + + dualChannelMode = pParam->dualChannelMode; + + /* Analyse input channel configuration and get channel offset + * table that can be accessed with the fixed channel labels. */ + errorStatus = getChannelMode(numInChannels, channelType, channelIndices, + inOffsetTable, &inChMode); + if (PCMDMX_IS_FATAL_ERROR(errorStatus) || (inChMode == CH_MODE_UNDEFINED)) { + /* We don't need to restore because the channel + configuration has not been changed. Just exit. */ + return (PCMDMX_INVALID_CH_CONFIG); + } + + /* Set input stride and offset */ + if (fInterleaved) { + inStride = numInChannels; + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Reset downmix meta data if necessary */ + if ((pParam->expiryFrame > 0) && + (++self->bsMetaData[0].expiryCount > + pParam + ->expiryFrame)) { /* The metadata read from bitstream is too old. */ +#ifdef FDK_ASSERT_ENABLE + PCMDMX_ERROR err = pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA); + FDK_ASSERT(err == PCMDMX_OK); +#else + pcmDmx_Reset(self, PCMDMX_RESET_BS_DATA); +#endif + } + FDKmemcpy(&bsMetaData, &self->bsMetaData[pParam->frameDelay], + sizeof(DMX_BS_META_DATA)); + /* Maintain delay line */ + for (slot = pParam->frameDelay; slot > 0; slot -= 1) { + FDKmemcpy(&self->bsMetaData[slot], &self->bsMetaData[slot - 1], + sizeof(DMX_BS_META_DATA)); + } + + /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * - - - - - - - - - - - - - - - - - - */ + if (numInChannels > numOutChannels) { /* Apply downmix */ + DMX_PCM *pInPcm[(8)] = {NULL}; + DMX_PCM *pOutPcm[(8)] = {NULL}; + FIXP_DMX mixFactors[(8)][(8)]; + UCHAR outOffsetTable[(8)]; + UINT sample; + int chCfg = 0; + int bypScale = 0; + + if (numInChannels > SIX_CHANNEL) { + AUDIO_CHANNEL_TYPE multiPurposeChType[2]; + + /* Get the type of the multipurpose channels */ + multiPurposeChType[0] = + channelType[inOffsetTable[LEFT_MULTIPRPS_CHANNEL]]; + multiPurposeChType[1] = + channelType[inOffsetTable[RIGHT_MULTIPRPS_CHANNEL]]; + + /* Check if the input configuration is one defined in the standard. */ + switch (inChMode) { + case CH_MODE_5_0_2_1: /* chCfg 7 || 14 */ + /* Further analyse the input config to distinguish the two + * CH_MODE_5_0_2_1 configs. */ + if ((multiPurposeChType[0] == ACT_FRONT_TOP) && + (multiPurposeChType[1] == ACT_FRONT_TOP)) { + chCfg = 14; + } else { + chCfg = 7; + } + break; + case CH_MODE_3_0_3_1: /* chCfg 11 */ + chCfg = 11; + break; + case CH_MODE_3_0_4_1: /* chCfg 12 */ + chCfg = 12; + break; + default: + chCfg = 0; /* Not a known config */ + break; + } + } + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + FDK_ASSERT(outChMode != CH_MODE_UNDEFINED); + + /* Get channel description and channel mapping for the desired output + * configuration. */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* Now there is no way back because we modified the channel configuration! + */ + + /* Create the DMX matrix */ + errorStatus = + getMixFactors((chCfg > 0) ? 1 : 0, + (chCfg > 0) ? (PCM_DMX_CHANNEL_MODE)chCfg : inChMode, + outChMode, pParam, &bsMetaData, mixFactors, &dmxScale); + /* No fatal errors can occur here. The function is designed to always return + a valid matrix. The error code is used to signal configurations and + matrices that are not conform to any standard. */ + + /* Determine the final scaling */ + bypScale = fMin(dmxMaxScale, dmxScale); + *pDmxOutScale += bypScale; + dmxScale -= bypScale; + + { /* Set channel pointer for input. Remove empty cols. */ + int inCh, outCh, map[(8)]; + int ch = 0; + for (inCh = 0; inCh < (8); inCh += 1) { + if (inOffsetTable[inCh] < (UCHAR)numInChannels) { + pInPcm[ch] = &pPcmBuf[inOffsetTable[inCh] * offset]; + map[ch++] = inCh; + } + } + for (; ch < (8); ch += 1) { + map[ch] = ch; + } + + /* Remove unused cols from factor matrix */ + for (inCh = 0; inCh < numInChannels; inCh += 1) { + if (inCh != map[inCh]) { + for (outCh = 0; outCh < (8); outCh += 1) { + mixFactors[outCh][inCh] = mixFactors[outCh][map[inCh]]; + } + } + } + + /* Set channel pointer for output. Remove empty cols. */ + ch = 0; + for (outCh = 0; outCh < (8); outCh += 1) { + if (outOffsetTable[outCh] < (UCHAR)numOutChannels) { + pOutPcm[ch] = &pPcmBuf[outOffsetTable[outCh] * offset]; + map[ch++] = outCh; + } + } + for (; ch < (8); ch += 1) { + map[ch] = ch; + } + + /* Remove unused rows from factor matrix */ + for (outCh = 0; outCh < numOutChannels; outCh += 1) { + if (outCh != map[outCh]) { + FDKmemcpy(&mixFactors[outCh], &mixFactors[map[outCh]], + (8) * sizeof(FIXP_DMX)); + } + } + } + + /* Sample processing loop */ + for (sample = 0; sample < frameSize; sample++) { + DMX_PCM tIn[(8)] = {0}; + FIXP_DBL tOut[(8)] = {(FIXP_DBL)0}; + int inCh, outCh; + + /* Preload all input samples */ + for (inCh = 0; inCh < numInChannels; inCh += 1) { + if (pInPcm[inCh] != NULL) { + tIn[inCh] = *pInPcm[inCh]; + pInPcm[inCh] += inStride; + } else { + tIn[inCh] = (DMX_PCM)0; + } + } + /* Apply downmix coefficients to input samples and accumulate for output + */ + for (outCh = 0; outCh < numOutChannels; outCh += 1) { + for (inCh = 0; inCh < numInChannels; inCh += 1) { + tOut[outCh] += fMult((DMX_PCMF)tIn[inCh], mixFactors[outCh][inCh]); + } + FDK_ASSERT(pOutPcm[outCh] >= pPcmBuf); + FDK_ASSERT(pOutPcm[outCh] < &pPcmBuf[pcmBufSize]); + /* Write sample */ + *pOutPcm[outCh] = (DMX_PCM)SATURATE_SHIFT( + tOut[outCh], DFRACT_BITS - DMX_PCM_BITS - dmxScale, DMX_PCM_BITS); + pOutPcm[outCh] += outStride; + } + } + + /* Update the number of output channels */ + *nChannels = numOutChannels; + + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - */ + else if (numInChannels < numOutChannels) { /* Apply rudimentary upmix */ + /* Set up channel pointer */ + UCHAR outOffsetTable[(8)]; + + /* FIRST STAGE + Create a stereo/dual channel signal */ + if (numInChannels == ONE_CHANNEL) { + DMX_PCM *pInPcm[(8)]; + DMX_PCM *pOutLF, *pOutRF; + UINT sample; + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? TWO_CHANNEL : 1; + outChMode = outChModeTable[TWO_CHANNEL]; + + /* Get channel description and channel mapping for this + * stages number of output channels (always STEREO). */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* Now there is no way back because we modified the channel configuration! + */ + + /* Set input channel pointer. The first channel is always at index 0. */ + pInPcm[CENTER_FRONT_CHANNEL] = + &pPcmBuf[(frameSize - 1) * + inStride]; /* Considering input mapping could lead to a + invalid pointer here if the channel is not + declared to be a front channel. */ + + /* Set output channel pointer (for this stage). */ + pOutLF = &pPcmBuf[outOffsetTable[LEFT_FRONT_CHANNEL] * offset + + (frameSize - 1) * outStride]; + pOutRF = &pPcmBuf[outOffsetTable[RIGHT_FRONT_CHANNEL] * offset + + (frameSize - 1) * outStride]; + + /* 1/0 input: */ + for (sample = 0; sample < frameSize; sample++) { + /* L' = C; R' = C; */ + *pOutLF = *pOutRF = *pInPcm[CENTER_FRONT_CHANNEL]; + + pInPcm[CENTER_FRONT_CHANNEL] -= inStride; + pOutLF -= outStride; + pOutRF -= outStride; + } + + /* Prepare for next stage: */ + inStride = outStride; + inChMode = outChMode; + FDKmemcpy(inOffsetTable, outOffsetTable, (8) * sizeof(UCHAR)); + } + + /* SECOND STAGE + Extend with zero channels to achieved the desired number of output + channels. */ + if (numOutChannels > TWO_CHANNEL) { + DMX_PCM *pIn[(8)] = {NULL}; + DMX_PCM *pOut[(8)] = {NULL}; + UINT sample; + AUDIO_CHANNEL_TYPE inChTypes[(8)]; + UCHAR inChIndices[(8)]; + UCHAR numChPerGrp[2][(4)]; + int nContentCh = 0; /* Number of channels with content */ + int nEmptyCh = 0; /* Number of channels with content */ + int ch, chGrp, isCompatible = 1; + + /* Do not change the signalling which is the channel types and indices. + Just reorder and add channels. So first save the input signalling. */ + FDKmemcpy(inChTypes, channelType, + numInChannels * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemclear(inChTypes + numInChannels, + ((8) - numInChannels) * sizeof(AUDIO_CHANNEL_TYPE)); + FDKmemcpy(inChIndices, channelIndices, numInChannels * sizeof(UCHAR)); + FDKmemclear(inChIndices + numInChannels, + ((8) - numInChannels) * sizeof(UCHAR)); + + /* Set this stages output stride and channel mode: */ + outStride = (fInterleaved) ? numOutChannels : 1; + outChMode = outChModeTable[numOutChannels]; + FDK_ASSERT(outChMode != CH_MODE_UNDEFINED); + + /* Check if input channel config can be easily mapped to the desired + * output config. */ + for (chGrp = 0; chGrp < (4); chGrp += 1) { + numChPerGrp[IN][chGrp] = (inChMode >> (chGrp * 4)) & 0xF; + numChPerGrp[OUT][chGrp] = (outChMode >> (chGrp * 4)) & 0xF; + + if (numChPerGrp[IN][chGrp] > numChPerGrp[OUT][chGrp]) { + isCompatible = 0; + break; + } + } + + if (isCompatible) { + /* Get new channel description and channel + * mapping for the desired output channel mode. */ + getChannelDescription(outChMode, mapDescr, channelType, channelIndices, + outOffsetTable); + /* If the input config has a back center channel but the output + config has not, copy it to left and right (if available). */ + if ((numChPerGrp[IN][CH_GROUP_REAR] % 2) && + !(numChPerGrp[OUT][CH_GROUP_REAR] % 2)) { + if (numChPerGrp[IN][CH_GROUP_REAR] == 1) { + inOffsetTable[RIGHT_REAR_CHANNEL] = + inOffsetTable[LEFT_REAR_CHANNEL]; + } else if (numChPerGrp[IN][CH_GROUP_REAR] == 3) { + inOffsetTable[RIGHT_MULTIPRPS_CHANNEL] = + inOffsetTable[LEFT_MULTIPRPS_CHANNEL]; + } + } + } else { + /* Just copy and extend the original config */ + FDKmemcpy(outOffsetTable, inOffsetTable, (8) * sizeof(UCHAR)); + } + + /* Set I/O channel pointer. + Note: The following assignment algorithm clears the channel offset + tables. Thus they can not be used afterwards. */ + for (ch = 0; ch < (8); ch += 1) { + if ((outOffsetTable[ch] < 255) && + (inOffsetTable[ch] < 255)) { /* Set I/O pointer: */ + pIn[nContentCh] = + &pPcmBuf[inOffsetTable[ch] * offset + (frameSize - 1) * inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[ch] * offset + + (frameSize - 1) * outStride]; + /* Update signalling */ + channelType[outOffsetTable[ch]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[ch]] = inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[ch] = 255; + nContentCh += 1; + } + } + if (isCompatible) { + /* Assign the remaining input channels. + This is just a safety appliance. We should never need it. */ + for (ch = 0; ch < (8); ch += 1) { + if (inOffsetTable[ch] < 255) { + int outCh; + for (outCh = 0; outCh < (8); outCh += 1) { + if (outOffsetTable[outCh] < 255) { + break; + } + } + if (outCh >= (8)) { + FDK_ASSERT(0); + break; + } + /* Set I/O pointer: */ + pIn[nContentCh] = &pPcmBuf[inOffsetTable[ch] * offset + + (frameSize - 1) * inStride]; + pOut[nContentCh] = &pPcmBuf[outOffsetTable[outCh] * offset + + (frameSize - 1) * outStride]; + /* Update signalling */ + FDK_ASSERT(inOffsetTable[outCh] < numInChannels); + FDK_ASSERT(outOffsetTable[outCh] < numOutChannels); + channelType[outOffsetTable[outCh]] = inChTypes[inOffsetTable[ch]]; + channelIndices[outOffsetTable[outCh]] = + inChIndices[inOffsetTable[ch]]; + inOffsetTable[ch] = 255; + outOffsetTable[outCh] = 255; + nContentCh += 1; + } + } + /* Set the remaining output channel pointer */ + for (ch = 0; ch < (8); ch += 1) { + if (outOffsetTable[ch] < 255) { + pOut[nContentCh + nEmptyCh] = &pPcmBuf[outOffsetTable[ch] * offset + + (frameSize - 1) * outStride]; + /* Expand output signalling */ + channelType[outOffsetTable[ch]] = ACT_NONE; + channelIndices[outOffsetTable[ch]] = (UCHAR)nEmptyCh; + outOffsetTable[ch] = 255; + nEmptyCh += 1; + } + } + } else { + /* Set the remaining output channel pointer */ + for (ch = nContentCh; ch < numOutChannels; ch += 1) { + pOut[ch] = &pPcmBuf[ch * offset + (frameSize - 1) * outStride]; + /* Expand output signalling */ + channelType[ch] = ACT_NONE; + channelIndices[ch] = (UCHAR)nEmptyCh; + nEmptyCh += 1; + } + } + + /* First copy the channels that have signal */ + for (sample = 0; sample < frameSize; sample += 1) { + DMX_PCM tIn[(8)]; + /* Read all channel samples */ + for (ch = 0; ch < nContentCh; ch += 1) { + tIn[ch] = *pIn[ch]; + pIn[ch] -= inStride; + } + /* Write all channel samples */ + for (ch = 0; ch < nContentCh; ch += 1) { + *pOut[ch] = tIn[ch]; + pOut[ch] -= outStride; + } + } + + /* Clear all the other channels */ + for (sample = 0; sample < frameSize; sample++) { + for (ch = nContentCh; ch < numOutChannels; ch += 1) { + *pOut[ch] = (DMX_PCM)0; + pOut[ch] -= outStride; + } + } + } + + /* update the number of output channels */ + *nChannels = numOutChannels; + } /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - */ + else if (numInChannels == numOutChannels) { + /* Don't need to change the channel description here */ + + switch (numInChannels) { + case 2: { /* Set up channel pointer */ + DMX_PCM *pInPcm[(8)]; + DMX_PCM *pOutL, *pOutR; + FIXP_DMX flev; + + UINT sample; + + if (fInterleaved) { + inStride = numInChannels; + outStride = + 2; /* fixed !!! (below stereo is donwmixed to mono if required */ + offset = 1; /* Channel specific offset factor */ + } else { + inStride = 1; + outStride = 1; + offset = frameSize; /* Channel specific offset factor */ + } + + /* Set input channel pointer */ + pInPcm[LEFT_FRONT_CHANNEL] = + &pPcmBuf[inOffsetTable[LEFT_FRONT_CHANNEL] * offset]; + pInPcm[RIGHT_FRONT_CHANNEL] = + &pPcmBuf[inOffsetTable[RIGHT_FRONT_CHANNEL] * offset]; + + /* Set output channel pointer (same as input) */ + pOutL = pInPcm[LEFT_FRONT_CHANNEL]; + pOutR = pInPcm[RIGHT_FRONT_CHANNEL]; + + /* Set downmix levels: */ + flev = FL2FXCONST_DMX(0.70710678f); + /* 2/0 input: */ + switch (dualChannelMode) { + case CH1_MODE: /* L' = 0.707 * Ch1; R' = 0.707 * Ch1 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (DMX_PCM)SATURATE_RIGHT_SHIFT( + fMult((DMX_PCMF)*pInPcm[LEFT_FRONT_CHANNEL], flev), + DFRACT_BITS - DMX_PCM_BITS, DMX_PCM_BITS); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + case CH2_MODE: /* L' = 0.707 * Ch2; R' = 0.707 * Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (DMX_PCM)SATURATE_RIGHT_SHIFT( + fMult((DMX_PCMF)*pInPcm[RIGHT_FRONT_CHANNEL], flev), + DFRACT_BITS - DMX_PCM_BITS, DMX_PCM_BITS); + + pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + case MIXED_MODE: /* L' = 0.5*Ch1 + 0.5*Ch2; R' = 0.5*Ch1 + 0.5*Ch2 */ + for (sample = 0; sample < frameSize; sample++) { + *pOutL = *pOutR = (*pInPcm[LEFT_FRONT_CHANNEL] >> 1) + + (*pInPcm[RIGHT_FRONT_CHANNEL] >> 1); + + pInPcm[LEFT_FRONT_CHANNEL] += inStride; + pInPcm[RIGHT_FRONT_CHANNEL] += inStride; + pOutL += outStride; + pOutR += outStride; + } + break; + default: + case STEREO_MODE: + /* nothing to do */ + break; + } + } break; + + default: + /* nothing to do */ + break; + } + } + + return (errorStatus); +} + +/** Close an instance of the PCM downmix module. + * @param [inout] Pointer to a buffer containing the handle of the instance. + * @returns Returns an error code. + **/ +PCMDMX_ERROR pcmDmx_Close(HANDLE_PCM_DOWNMIX *pSelf) { + if (pSelf == NULL) { + return (PCMDMX_INVALID_HANDLE); + } + + FreePcmDmxInstance(pSelf); + *pSelf = NULL; + + return (PCMDMX_OK); +} + +/** Get library info for this module. + * @param [out] Pointer to an allocated LIB_INFO structure. + * @returns Returns an error code. + */ +PCMDMX_ERROR pcmDmx_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return PCMDMX_INVALID_ARGUMENT; + } + + /* Add the library info */ + info[i].module_id = FDK_PCMDMX; + info[i].version = + LIB_VERSION(PCMUTIL_LIB_VL0, PCMUTIL_LIB_VL1, PCMUTIL_LIB_VL2); + LIB_VERSION_STRING(info + i); + info[i].build_date = PCMUTIL_LIB_BUILD_DATE; + info[i].build_time = PCMUTIL_LIB_BUILD_TIME; + info[i].title = PCMDMX_LIB_TITLE; + + /* Set flags */ + info[i].flags = 0 | CAPF_DMX_BLIND /* At least blind downmixing is possible */ + | CAPF_DMX_PCE /* Guided downmix with data from MPEG-2/4 + Program Config Elements (PCE). */ + | CAPF_DMX_ARIB /* PCE guided downmix with slightly different + equations and levels. */ + | CAPF_DMX_DVB /* Guided downmix with data from DVB ancillary + data fields. */ + | CAPF_DMX_CH_EXP /* Simple upmixing by dublicating channels + or adding zero channels. */ + | CAPF_DMX_6_CH | CAPF_DMX_8_CH; + + /* Add lib info for FDK tools (if not yet done). */ + FDK_toolsGetLibInfo(info); + + return PCMDMX_OK; +} diff --git a/fdk-aac/libPCMutils/src/version.h b/fdk-aac/libPCMutils/src/version.h new file mode 100644 index 0000000..fa31af1 --- /dev/null +++ b/fdk-aac/libPCMutils/src/version.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** PCM utility library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#if !defined(VERSION_H) +#define VERSION_H + +/* library info */ +#define PCMUTIL_LIB_VL0 3 +#define PCMUTIL_LIB_VL1 0 +#define PCMUTIL_LIB_VL2 0 +#define PCMUTIL_LIB_TITLE "PCM Utility Lib" +#ifdef __ANDROID__ +#define PCMUTIL_LIB_BUILD_DATE "" +#define PCMUTIL_LIB_BUILD_TIME "" +#else +#define PCMUTIL_LIB_BUILD_DATE __DATE__ +#define PCMUTIL_LIB_BUILD_TIME __TIME__ +#endif + +#endif /* !defined(VERSION_H) */ diff --git a/fdk-aac/libSACdec/include/sac_dec_errorcodes.h b/fdk-aac/libSACdec/include/sac_dec_errorcodes.h new file mode 100644 index 0000000..ee8b9f8 --- /dev/null +++ b/fdk-aac/libSACdec/include/sac_dec_errorcodes.h @@ -0,0 +1,157 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: error codes for mpeg surround decoder + +*******************************************************************************/ + +#ifndef SAC_DEC_ERRORCODES_H +#define SAC_DEC_ERRORCODES_H + +typedef enum { + + __mps_error_start = -1000, + + MPS_OK = 0, + + /* generic/init errors */ + MPS_NOTOK = __mps_error_start, + + MPS_OUTOFMEMORY, + MPS_INVALID_HANDLE, + MPS_INVALID_PARAMETER, /* SetParam not successfull */ + MPS_UNSUPPORTED_HRTFMODEL, /* SetHRTFModel() not successfull */ + MPS_UNSUPPORTED_HRTFFREQ, /* SetHRTFModel() not successfull */ + + MPS_UNSUPPORTED_UPMIX_TYPE, /* CheckLevelTreeUpmixType() */ + MPS_UNSUPPORTED_FORMAT, /* various functions; unknown aot or no_channels in + filterbank */ + MPS_OUTPUT_BUFFER_TOO_SMALL, /* Size of provided output time buffer is too + small */ + + /* ssc errors */ + MPS_INVALID_PARAMETERBANDS, /* unsupported numParameterBands in + SpatialDecDecodeHeader() */ + MPS_INVALID_TREECONFIG, + MPS_INVALID_HRTFSET, /* SpatialDecDecodeHeader() */ + MPS_INVALID_TTT, /* SpatialDecDecodeHeader() */ + MPS_INVALID_BOXIDX, /* ecDataDec() */ + MPS_INVALID_SETIDX, /* ecDataDec() */ + MPS_INVALID_QUANTMODE, /* SpatialDecParseSpecificConfig() */ + MPS_UNEQUAL_SSC, /* FDK_SpatialDecCompareSpatialSpecificConfigHeader() */ + MPS_UNSUPPORTED_CONFIG, /* number of core channels; 3DStereoInversion; */ + + /* parse errors */ + MPS_PARSE_ERROR, + MPS_INVALID_TEMPSHAPE, /* SpatialDecParseFrameData() */ + + /* render errors */ + MPS_WRONG_PARAMETERSETS, + MPS_WRONG_PARAMETERBANDS, /* decodeAndMapFrameSmg() */ + MPS_WRONG_TREECONFIG, + MPS_WRONG_BLINDCONFIG, + MPS_WRONG_OTT, + MPS_WRONG_QUANTMODE, + MPS_RESDEC_ERROR, + MPS_APPLY_M2_ERROR, /* error in applyM2x()selection */ + + __mps_error_end + +} SACDEC_ERROR; + +#endif diff --git a/fdk-aac/libSACdec/include/sac_dec_lib.h b/fdk-aac/libSACdec/include/sac_dec_lib.h new file mode 100644 index 0000000..9913279 --- /dev/null +++ b/fdk-aac/libSACdec/include/sac_dec_lib.h @@ -0,0 +1,477 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: Space Decoder + +*******************************************************************************/ + +#ifndef SAC_DEC_LIB_H +#define SAC_DEC_LIB_H + +#include "common_fix.h" +#include "FDK_audio.h" +#include "sac_dec_errorcodes.h" +#include "FDK_bitstream.h" +#include "FDK_qmf_domain.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * \brief MPEG Surround input data interface mode. + **/ +typedef enum { + SAC_INTERFACE_QMF = + 0, /*!< Use QMF domain interface for the input downmix audio. */ + SAC_INTERFACE_TIME, /*!< Use time domain interface for the input downmix + audio. */ + SAC_INTERFACE_AUTO /*!< */ +} SAC_INPUT_CONFIG; + +/** + * \brief MPEG Surround output mode. + **/ +typedef enum { + SACDEC_OUT_MODE_NORMAL = + 0, /*!< Normal multi channel processing without output restrictions. */ + SACDEC_OUT_MODE_BINAURAL, /*!< Two channel output with binaural processsing. + */ + SACDEC_OUT_MODE_STEREO, /*!< Always two channel output mode. */ + SACDEC_OUT_MODE_6CHANNEL /*!< Always process with 5.1 channel output. */ +} SAC_DEC_OUTPUT_MODE; + +/** + * \brief MPEG Surround binaural HRTF model. + * HRTF will be applied only in combination with upmixtype + *SAC_UPMIX_TYPE_BINAURAL. + **/ +typedef enum { + SAC_BINAURAL_HRTF_KEMAR = 0, + SAC_BINAURAL_HRTF_VAST, + SAC_BINAURAL_HRTF_MPSVT, + SAC_BINAURAL_SINGLE_HRTFS +} SAC_BINAURAL_HRTF_MODEL; + +/** + * \brief MPEG Surround decoder instance available. + **/ +typedef enum { + SAC_INSTANCE_NOT_FULL_AVAILABLE = + 0, /*!< MPEG Surround decoder instance not full available. */ + SAC_INSTANCE_FULL_AVAILABLE /*!< MPEG Surround decoder instance full + available. */ +} SAC_INSTANCE_AVAIL; + +/** + * \brief MPEG Surround decoder dynamic parameters. + * + * Use mpegSurroundDecoder_SetParam() function to configure internal status of + * following parameters. + */ +typedef enum { + SACDEC_OUTPUT_MODE = 0x0001, /*!< Set MPEG Surround decoder output mode. See + SAC_DEC_OUTPUT_MODE. */ + SACDEC_BLIND_ENABLE = + 0x0002, /*!< Multi channel output without MPEG Surround side info. */ + SACDEC_PARTIALLY_COMPLEX = + 0x0003, /*!< Set partially complex flag for MPEG Surround. + 0: Use complex valued QMF data. + 1: Use real valued QMF data (low power mode) */ + SACDEC_INTERFACE = + 0x0004, /*!< Select signal input interface for MPEG Surround. + Switch time interface off: 0 + Switch time interface on: 1 */ + SACDEC_BS_DELAY = 0x0005, /*!< Select bit stream delay for MPEG Surround. + Switch bit stream delay off: 0 + Switch bit stream delay on: 1 */ + SACDEC_BINAURAL_QUALITY = + 0x0102, /*!< Set binaural quality for MPEG Surround binaural mode. + 0: Low Complexity, + 1: High Quality */ + SACDEC_BINAURAL_DISTANCE = 0x0103, /*!< Set perceived distance for binaural + playback (binaural mode only). The valid + values range from 0 to 100. Where 100 + corresponds to the farthest perceived + distance. */ + SACDEC_BINAURAL_DIALOG_CLARITY = + 0x0104, /*!< Set dialog clarity (for binaural playback). + The valid values range from 0 to 100. */ + SACDEC_BINAURAL_FRONT_ANGLE = 0x0105, /*!< Set angle between the virtual front + speaker pair (binaural mode only). + The valid range is from 0 to 180 + angular degrees. */ + SACDEC_BINAURAL_BACK_ANGLE = 0x0106, /*!< Set angle between the virtual back + speaker pair (binaural mode only). The + valid range is from 0 to 180 angular + degrees. */ + SACDEC_BINAURAL_PRESET = 0x0107, /*!< Set a virtual speaker setup preset for + binaural playback (binaural mode only). + This meta-parameter implicitly modifies + the following parameters: + SACDEC_BINAURAL_DISTANCE, + SACDEC_BINAURAL_DIALOG_CLARITY, + SACDEC_BINAURAL_FRONT_ANGLE and + SACDEC_BINAURAL_BACK_ANGLE. + The following presets are available: + 1: Dry room + 2: Living room (default) + 3: Cinema */ + + SACDEC_BS_INTERRUPTION = + 0x0200, /*!< If the given value is unequal to 0 hint the MPEG Surround + decoder that the next input data is discontinuous, because of + frame loss, seeking, etc. Announce the decoder that the + bitstream data was interrupted (fSync = 0). This will cause the + surround decoder not to parse any new bitstream data until a + new header with a valid Spatial Specific Config and a + independently decodable frame is found. Specially important + when the MPEG Surround data is split accross several frames + (for example in the case of AAC-LC downmix with 1024 + framelength and 2048 surround frame length) and a discontinuity + in the bitstream data occurs. If fSync is 1, assume that MPEG + Surround data is in sync (out of band config for example). */ + SACDEC_CLEAR_HISTORY = 0x0201, /*!< If the given value is unequal to 0 clear + all internal states (delay lines, QMF + states, ...) of the MPEG Surround decoder. + This will cause a discontinuity in the audio + output signal. */ + + SACDEC_CONCEAL_NUM_KEEP_FRAMES = + 0x0301, /*!< Error concealment: The Number of frames the module keeps the + last spatial image before fading to the particular spatial + scenario starts. The default is 10 frames. */ + SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH = + 0x0302, /*!< Error concealment: Length of the slope (in frames) the module + creates to fade from the last spatial scenario to the + particular default scenario (downmix) in case of consecutive + errors. Default is 5. */ + SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH = + 0x0303, /*!< Error concealment: Length of the slope (in frames) the module + creates to fade from the default spatial scenario (downmix) to + the current scenario after fade-out. Default parameter value + is 5. */ + SACDEC_CONCEAL_NUM_RELEASE_FRAMES = + 0x0304 /*!< Error concealment: The number of error free frames before the + module starts fading from default to the current spatial + scenario. Default parameter value is 3 frames. */ +} SACDEC_PARAM; + +#define PCM_MPS INT_PCM + +/** + * \brief MPEG Surround decoder handle. + */ +typedef struct MpegSurroundDecoder CMpegSurroundDecoder; + +/** + * \brief Check if the full MPEG Surround decoder instance is allocated. + * + * Check if the full MPEG Surround decoder instance is allocated. + * + * \param pMpegSurroundDecoder A pointer to a decoder stucture. + * + * \return SACDEC_ERROR error code + */ +SAC_INSTANCE_AVAIL +mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Open one instance of the MPEG Surround decoder. + * + * Allocate one instance of decoder and input buffers. + * - Allocate decoder structure + * - Allocate input buffers (QMF/time/MPS data) + * + * \param pMpegSurroundDecoder A pointer to a decoder handle; filled on + * return. + * \param splitMemoryAllocation Allocate only outer layer of MPS decoder. Core + * part is reallocated later if needed. + * \param stereoConfigIndex USAC: Save memory by opening the MPS decoder + * for a specific stereoConfigIndex. (Needs optimization macros enabled.) + * \param pQmfDomain Pointer to QMF domain data structure. + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Open( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +/** + * \brief Init one instance of the MPEG Surround decoder. + * + * Init one instance of the MPEG Surround decoder + * + * \param pMpegSurroundDecoder A pointer to a decoder handle; + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Init( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Read and parse SpatialSpecificConfig. + * + * \param pMpegSurroundDecoder A pointer to a decoder handle. + * \param hBs bitstream handle config parsing data source. + * + * \return SACDEC_ERROR error code + */ +SACDEC_ERROR mpegSurroundDecoder_Config( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize, + INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes, + const UCHAR configMode, UCHAR *configChanged); + +SACDEC_ERROR +mpegSurroundDecoder_ConfigureQmfDomain( + CMpegSurroundDecoder *pMpegSurroundDecoder, + SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate, + AUDIO_OBJECT_TYPE coreCodec); + +/** + * \brief Parse MPEG Surround data without header + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param hBs Bit stream handle data input source + * \param pMpsDataBits Pointer to number of valid bits in extension + * payload. Function updates mpsDataBits while parsing bitstream. + * \param fGlobalIndependencyFlag Global independency flag of current frame. + * + * \return Error code. + */ +int mpegSurroundDecoder_ParseNoHeader( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + int *pMpsDataBits, int fGlobalIndependencyFlag); + +/* #ifdef SACDEC_MPS_ENABLE */ +/** + * \brief Parse MPEG Surround data with header. Header is ancType, ancStart, + ancStop (4 bits total). Body is ancDataSegmentByte[i]. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param hBs Bit stream handle data input source + * \param pMpsDataBits Pointer to number of valid bits in extension + payload. Function updates mpsDataBits while parsing bitstream. Needs to be a + multiple of 8 + 4 (4 bits header). + * \param coreCodec The audio object type of the core codec handling + the downmix input signal. + * \param sampleRate Samplerate of input downmix data. + * \param nChannels Amount of input channels. + * \param frameSize Amount of input samples. + * \param fGlobalIndependencyFlag Global independency flag of current frame. + * + * \return Error code. + */ +int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder, + HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits, + AUDIO_OBJECT_TYPE coreCodec, int sampleRate, + int frameSize, int fGlobalIndependencyFlag); +/* #endif */ + +/** + * \brief Apply MPEG Surround upmix. + * + * Process one downmix audio frame and decode one surround frame if it applies. + * Downmix framing can be different from surround framing, so depending on the + * frame size of the downmix audio data and the framing being used by the MPEG + * Surround decoder, it could be that only every second call, for example, of + * this function actually surround data was decoded. The returned value of + * frameSize will be zero, if no surround data was decoded. + * + * Decoding one MPEG Surround frame. Depending on interface configuration + * mpegSurroundDecoder_SetParam(self, SACDEC_INTERFACE, value), the QMF or time + * interface will be applied. External access to QMF buffer interface can be + * achieved by mpegSurroundDecoder_GetQmfBuffer() call before decode frame. + * While using time interface, pTimeData buffer will be shared as input and + * output buffer. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. + * \param pTimeData Pointer to time buffer. Depending on interface + * configuration, the content of pTimeData is ignored, and the internal QMF + * buffer will be used as input data source. + * Otherwise, the MPEG Surround processing is applied to the timesignal + * pTimeData. For both variants, the resulting MPEG + * Surround signal is written into pTimeData. + * \param timeDataSize Size of pTimeData (available buffer size). + * \param timeDataFrameSize Frame size of input timedata + * \param nChannels Pointer where the amount of input channels is + * given and amount of output channels is returned. + * \param frameSize Pointer where the amount of output samples is + * returned into. + * \param channelType Array were the corresponding channel type for + * each output audio channel is stored into. + * \param channelIndices Array were the corresponding channel type index + * for each output audio channel is stored into. + * \param mapDescr Channep map descriptor for output channel mapping + * to be used (From MPEG PCE ordering to whatever is required). + * + * \return Error code. + */ +int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, + INT_PCM *input, PCM_MPS *pTimeData, + const int timeDataSize, int timeDataFrameSize, + int *nChannels, int *frameSize, int sampleRate, + AUDIO_OBJECT_TYPE coreCodec, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr); + +/** + * \brief Deallocate a MPEG Surround decoder instance. + * \param pMpegSurroundDecoder A decoder handle. + * \return No return value. + */ +void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Free config dependent MPEG Surround memory. + * \param pMpegSurroundDecoder A decoder handle. + * \return error. + */ +SACDEC_ERROR mpegSurroundDecoder_FreeMem( + CMpegSurroundDecoder *pMpegSurroundDecoder); + +/** + * \brief Set one single MPEG Surround decoder parameter. + * + * \param pMpegSurroundDecoder A MPEG Surrround decoder handle. Must not be + * NULL pointer. + * \param param Parameter to be set. See SACDEC_PARAM. + * \param value Parameter value. See SACDEC_PARAM. + * + * \return 0 on sucess, and non-zero on failure. + */ +SACDEC_ERROR mpegSurroundDecoder_SetParam( + CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param, + const INT value); + +/** + * \brief Retrieve MPEG Surround decoder library info and fill info list with all depending library infos. + * \param libInfo Pointer to library info list to be filled. + * \return 0 on sucess, and non-zero on failure. + **/ +int mpegSurroundDecoder_GetLibInfo(LIB_INFO *libInfo); + +/** + * \brief Set one single MPEG Surround decoder parameter. + * + * \param pMpegSurroundDecoder A valid MPEG Surrround decoder handle. + * + * \return The additional signal delay caused by the module. + */ +UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self); + +/** + * \brief Get info on whether the USAC pseudo LR feature is active. + * + * \param pMpegSurroundDecoder A valid MPEG Surrround decoder handle. + * \param bsPseudoLr Pointer to return wether pseudo LR USAC feature + * is used. + * + * \return 0 on sucess, and non-zero on failure. + */ +SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR( + CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* #ifndef SAC_DEC_LIB_H */ diff --git a/fdk-aac/libSACdec/src/sac_bitdec.cpp b/fdk-aac/libSACdec/src/sac_bitdec.cpp new file mode 100644 index 0000000..883e1e8 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_bitdec.cpp @@ -0,0 +1,2167 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec bitstream decoder + +*******************************************************************************/ + +#include "sac_bitdec.h" + +#include "sac_dec_errorcodes.h" +#include "nlc_dec.h" +#include "sac_rom.h" +#include "FDK_matrixCalloc.h" +#include "sac_tsd.h" + +enum { + ottVsTotInactiv = 0, + ottVsTotDb1Activ = 1, + ottVsTotDb2Activ = 2, + ottVsTotDb1Db2Activ = 3 +}; + +static SACDEC_ERROR SpatialDecDecodeHelperInfo( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType) { + int i; + UINT syntaxFlags; + + /* Determine bit stream syntax */ + syntaxFlags = 0; + switch (pSpatialSpecificConfig->coreCodec) { + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + syntaxFlags |= SACDEC_SYNTAX_LD; + break; + case AOT_USAC: + syntaxFlags |= SACDEC_SYNTAX_USAC; + break; + case AOT_NONE: + default: + return MPS_UNSUPPORTED_FORMAT; + } + + pSpatialSpecificConfig->syntaxFlags = syntaxFlags; + + switch (pSpatialSpecificConfig->treeConfig) { + case TREE_212: { + pSpatialSpecificConfig->ottCLDdefault[0] = 0; + } break; + default: + return MPS_INVALID_TREECONFIG; + } + + if (syntaxFlags & SACDEC_SYNTAX_USAC) { + if (pSpatialSpecificConfig->bsOttBandsPhasePresent) { + pSpatialSpecificConfig->numOttBandsIPD = + pSpatialSpecificConfig->bsOttBandsPhase; + } else { + int numParameterBands; + + numParameterBands = pSpatialSpecificConfig->freqRes; + switch (numParameterBands) { + case 4: + case 5: + pSpatialSpecificConfig->numOttBandsIPD = 2; + break; + case 7: + pSpatialSpecificConfig->numOttBandsIPD = 3; + break; + case 10: + pSpatialSpecificConfig->numOttBandsIPD = 5; + break; + case 14: + pSpatialSpecificConfig->numOttBandsIPD = 7; + break; + case 20: + case 28: + pSpatialSpecificConfig->numOttBandsIPD = 10; + break; + default: + return MPS_INVALID_PARAMETERBANDS; + } + } + } else { + pSpatialSpecificConfig->numOttBandsIPD = 0; + } + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + { + pSpatialSpecificConfig->bitstreamOttBands[i] = + pSpatialSpecificConfig->freqRes; + } + { + pSpatialSpecificConfig->numOttBands[i] = + pSpatialSpecificConfig->bitstreamOttBands[i]; + if (syntaxFlags & SACDEC_SYNTAX_USAC && + !pSpatialSpecificConfig->bsOttBandsPhasePresent) { + if (pSpatialSpecificConfig->bResidualCoding && + pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent && + (pSpatialSpecificConfig->numOttBandsIPD < + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands)) { + pSpatialSpecificConfig->numOttBandsIPD = + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands; + } + } + } + } /* i */ + + return MPS_OK; +} + +/******************************************************************************* + Functionname: SpatialDecParseExtensionConfig + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +static SACDEC_ERROR SpatialDecParseExtensionConfig( + HANDLE_FDK_BITSTREAM bitstream, SPATIAL_SPECIFIC_CONFIG *config, + int numOttBoxes, int numTttBoxes, int numOutChan, int bitsAvailable) { + SACDEC_ERROR err = MPS_OK; + INT ba = bitsAvailable; + + config->sacExtCnt = 0; + config->bResidualCoding = 0; + + ba = fMin((int)FDKgetValidBits(bitstream), ba); + + while ((ba >= 8) && (config->sacExtCnt < MAX_NUM_EXT_TYPES)) { + int bitsRead, nFillBits; + INT tmp; + UINT sacExtLen; + + config->sacExtType[config->sacExtCnt] = FDKreadBits(bitstream, 4); + ba -= 4; + + sacExtLen = FDKreadBits(bitstream, 4); + ba -= 4; + + if (sacExtLen == 15) { + sacExtLen += FDKreadBits(bitstream, 8); + ba -= 8; + if (sacExtLen == 15 + 255) { + sacExtLen += FDKreadBits(bitstream, 16); + ba -= 16; + } + } + + tmp = (INT)FDKgetValidBits( + bitstream); /* Extension config payload start anchor. */ + if ((tmp <= 0) || (tmp < (INT)sacExtLen * 8) || (ba < (INT)sacExtLen * 8)) { + err = MPS_PARSE_ERROR; + goto bail; + } + + switch (config->sacExtType[config->sacExtCnt]) { + default:; /* unknown extension data => do nothing */ + } + + /* skip remaining extension data */ + bitsRead = tmp - FDKgetValidBits(bitstream); + nFillBits = 8 * sacExtLen - bitsRead; + + if (nFillBits < 0) { + err = MPS_PARSE_ERROR; + goto bail; + } else { + /* Skip fill bits or an unkown extension. */ + FDKpushFor(bitstream, nFillBits); + } + + ba -= 8 * sacExtLen; + config->sacExtCnt++; + } + +bail: + return err; +} + +SACDEC_ERROR SpatialDecParseSpecificConfigHeader( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType) { + SACDEC_ERROR err = MPS_OK; + INT numFillBits; + int sacHeaderLen = 0; + int sacTimeAlignFlag = 0; + + sacTimeAlignFlag = FDKreadBits(bitstream, 1); + sacHeaderLen = FDKreadBits(bitstream, 7); + + if (sacHeaderLen == 127) { + sacHeaderLen += FDKreadBits(bitstream, 16); + } + numFillBits = (INT)FDKgetValidBits(bitstream); + + err = SpatialDecParseSpecificConfig(bitstream, pSpatialSpecificConfig, + sacHeaderLen, coreCodec); + + numFillBits -= + (INT)FDKgetValidBits(bitstream); /* the number of read bits (tmpBits) */ + numFillBits = (8 * sacHeaderLen) - numFillBits; + if (numFillBits < 0) { + /* Parsing went wrong */ + err = MPS_PARSE_ERROR; + } + /* Move to the very end of the SSC */ + FDKpushBiDirectional(bitstream, numFillBits); + + if ((err == MPS_OK) && sacTimeAlignFlag) { + /* not supported */ + FDKreadBits(bitstream, 16); + err = MPS_UNSUPPORTED_CONFIG; + } + + /* Derive additional helper variables */ + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, (UPMIXTYPE)upmixType); + + return err; +} + +SACDEC_ERROR SpatialDecParseMps212Config( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate, + AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex, + INT coreSbrFrameLengthIndex) { + int i; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + pSpatialSpecificConfig->stereoConfigIndex = stereoConfigIndex; + pSpatialSpecificConfig->coreSbrFrameLengthIndex = coreSbrFrameLengthIndex; + pSpatialSpecificConfig->freqRes = + (SPATIALDEC_FREQ_RES)freqResTable[FDKreadBits(bitstream, 3)]; + if (pSpatialSpecificConfig->freqRes == 0) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + switch (coreCodec) { + case AOT_DRM_USAC: + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + /* tempShapeConfig = (bsTempShapeConfigDrm == 1) ? 3 : 0 */ + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)(FDKreadBits(bitstream, 1) * 3); + pSpatialSpecificConfig->decorrConfig = (SPATIALDEC_DECORR_CONF)0; + pSpatialSpecificConfig->bsDecorrType = 0; + break; + case AOT_USAC: + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2); + pSpatialSpecificConfig->decorrConfig = + (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->decorrConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + pSpatialSpecificConfig->bsDecorrType = 0; + break; + default: + return MPS_UNSUPPORTED_FORMAT; + } + pSpatialSpecificConfig->nTimeSlots = (coreSbrFrameLengthIndex == 4) ? 64 : 32; + pSpatialSpecificConfig->bsHighRateMode = (UCHAR)FDKreadBits(bitstream, 1); + + { + pSpatialSpecificConfig->bsPhaseCoding = (UCHAR)FDKreadBits(bitstream, 1); + pSpatialSpecificConfig->bsOttBandsPhasePresent = + (UCHAR)FDKreadBits(bitstream, 1); + if (pSpatialSpecificConfig->bsOttBandsPhasePresent) { + if (MAX_PARAMETER_BANDS < (pSpatialSpecificConfig->bsOttBandsPhase = + FDKreadBits(bitstream, 5))) { + return MPS_PARSE_ERROR; + } + } else { + pSpatialSpecificConfig->bsOttBandsPhase = 0; + } + } + + if (stereoConfigIndex > 1) { /* do residual coding */ + pSpatialSpecificConfig->bResidualCoding = 1; + pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 1; + if (pSpatialSpecificConfig->freqRes < + (pSpatialSpecificConfig->ResidualConfig->nResidualBands = + FDKreadBits(bitstream, 5))) { + return MPS_PARSE_ERROR; + } + pSpatialSpecificConfig->bsOttBandsPhase = + fMax(pSpatialSpecificConfig->bsOttBandsPhase, + pSpatialSpecificConfig->ResidualConfig->nResidualBands); + pSpatialSpecificConfig->bsPseudoLr = (UCHAR)FDKreadBits(bitstream, 1); + + if (pSpatialSpecificConfig->bsPhaseCoding) { + pSpatialSpecificConfig->bsPhaseCoding = 3; + } + } else { + pSpatialSpecificConfig->bResidualCoding = 0; + pSpatialSpecificConfig->ResidualConfig->bResidualPresent = 0; + } + + if (pSpatialSpecificConfig->tempShapeConfig == 2) { + switch (coreCodec) { + case AOT_USAC: + pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1); + break; + default: /* added to avoid compiler warning */ + break; /* added to avoid compiler warning */ + } + } + + /* Static parameters */ + + pSpatialSpecificConfig->samplingFreq = + samplingRate; /* wrong for stereoConfigIndex == 3 but value is unused */ + pSpatialSpecificConfig->treeConfig = SPATIALDEC_MODE_RSVD7; + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + + pSpatialSpecificConfig->bArbitraryDownmix = 0; + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + if (coreCodec == AOT_DRM_USAC) { + /* MPS payload is MPEG conform -> no need for pseudo DRM AOT */ + coreCodec = AOT_USAC; + } + pSpatialSpecificConfig->coreCodec = coreCodec; + + /* Derive additional helper variables */ + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + + return MPS_OK; +} + +SACDEC_ERROR SpatialDecParseSpecificConfig( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen, + AUDIO_OBJECT_TYPE coreCodec) { + SACDEC_ERROR err = MPS_OK; + int i; + int bsSamplingFreqIndex; + int bsFreqRes, b3DaudioMode = 0; + int numHeaderBits; + int cfgStartPos, bitsAvailable; + + FDKmemclear(pSpatialSpecificConfig, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + cfgStartPos = FDKgetValidBits(bitstream); + /* It might be that we do not know the SSC length beforehand. */ + if (sacHeaderLen == 0) { + bitsAvailable = cfgStartPos; + } else { + bitsAvailable = 8 * sacHeaderLen; + if (bitsAvailable > cfgStartPos) { + err = MPS_PARSE_ERROR; + goto bail; + } + } + + bsSamplingFreqIndex = FDKreadBits(bitstream, 4); + + if (bsSamplingFreqIndex == 15) { + pSpatialSpecificConfig->samplingFreq = FDKreadBits(bitstream, 24); + } else { + pSpatialSpecificConfig->samplingFreq = + samplingFreqTable[bsSamplingFreqIndex]; + if (pSpatialSpecificConfig->samplingFreq == 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + } + + pSpatialSpecificConfig->nTimeSlots = FDKreadBits(bitstream, 5) + 1; + if ((pSpatialSpecificConfig->nTimeSlots < 1) || + (pSpatialSpecificConfig->nTimeSlots > MAX_TIME_SLOTS)) { + err = MPS_PARSE_ERROR; + goto bail; + } + + bsFreqRes = FDKreadBits(bitstream, 3); + + pSpatialSpecificConfig->freqRes = + (SPATIALDEC_FREQ_RES)freqResTable_LD[bsFreqRes]; + + pSpatialSpecificConfig->treeConfig = + (SPATIALDEC_TREE_CONFIG)FDKreadBits(bitstream, 4); + + if (pSpatialSpecificConfig->treeConfig != SPATIALDEC_MODE_RSVD7) { + err = MPS_UNSUPPORTED_CONFIG; + goto bail; + } + + { + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nTttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numTttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + } + + pSpatialSpecificConfig->quantMode = + (SPATIALDEC_QUANT_MODE)FDKreadBits(bitstream, 2); + + pSpatialSpecificConfig->bArbitraryDownmix = FDKreadBits(bitstream, 1); + + pSpatialSpecificConfig->bsFixedGainDMX = + (SPATIALDEC_FIXED_GAINS)FDKreadBits(bitstream, 3); + + pSpatialSpecificConfig->tempShapeConfig = + (SPATIALDEC_TS_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->tempShapeConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + pSpatialSpecificConfig->decorrConfig = + (SPATIALDEC_DECORR_CONF)FDKreadBits(bitstream, 2); + if (pSpatialSpecificConfig->decorrConfig > 2) { + return MPS_PARSE_ERROR; /* reserved value */ + } + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + for (i = 0; i < pSpatialSpecificConfig->nTttBoxes; i++) { + int bTttDualMode = FDKreadBits(bitstream, 1); + FDKreadBits(bitstream, 3); /* not supported */ + + if (bTttDualMode) { + FDKreadBits(bitstream, 8); /* not supported */ + } + } + + if (pSpatialSpecificConfig->tempShapeConfig == 2) { + pSpatialSpecificConfig->envQuantMode = FDKreadBits(bitstream, 1); + } + + if (b3DaudioMode) { + if (FDKreadBits(bitstream, 2) == 0) { /* b3DaudioHRTFset ? */ + int hc; + int HRTFnumBand; + int HRTFfreqRes = FDKreadBits(bitstream, 3); + int HRTFnumChan = FDKreadBits(bitstream, 4); + int HRTFasymmetric = FDKreadBits(bitstream, 1); + + HRTFnumBand = freqResTable_LD[HRTFfreqRes]; + + for (hc = 0; hc < HRTFnumChan; hc++) { + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelLeft[hc][hb] */ + if (HRTFasymmetric) { + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFlevelRight[hc][hb] */ + } + if (FDKreadBits(bitstream, 1)) { /* HRTFphase[hc] ? */ + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFphaseLR[hc][hb] */ + } + if (FDKreadBits(bitstream, 1)) { /* HRTFicc[hc] ? */ + FDKpushFor(bitstream, HRTFnumBand * 6); /* HRTFiccLR[hc][hb] */ + } + } + } + } + + FDKbyteAlign(bitstream, + cfgStartPos); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment + with respect to the beginning of the syntactic + element in which ByteAlign() occurs. */ + + numHeaderBits = cfgStartPos - (INT)FDKgetValidBits(bitstream); + bitsAvailable -= numHeaderBits; + if (bitsAvailable < 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + + pSpatialSpecificConfig->sacExtCnt = 0; + pSpatialSpecificConfig->bResidualCoding = 0; + + err = SpatialDecParseExtensionConfig( + bitstream, pSpatialSpecificConfig, pSpatialSpecificConfig->nOttBoxes, + pSpatialSpecificConfig->nTttBoxes, + pSpatialSpecificConfig->nOutputChannels, bitsAvailable); + + FDKbyteAlign( + bitstream, + cfgStartPos); /* Same alignment anchor as above because + SpatialExtensionConfig() always reads full bytes */ + + pSpatialSpecificConfig->coreCodec = coreCodec; + + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + +bail: + if (sacHeaderLen > 0) { + /* If the config is of known length then assure that the + bitbuffer is exactly at its end when leaving the function. */ + FDKpushBiDirectional( + bitstream, + (sacHeaderLen * 8) - (cfgStartPos - (INT)FDKgetValidBits(bitstream))); + } + + return err; +} + +int SpatialDecDefaultSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots, + int sacDecoderLevel, int isBlind, int numCoreChannels) + +{ + int err = MPS_OK; + int i; + + FDK_ASSERT(coreCodec != AOT_NONE); + FDK_ASSERT(nTimeSlots > 0); + FDK_ASSERT(samplingFreq > 0); + + pSpatialSpecificConfig->coreCodec = coreCodec; + pSpatialSpecificConfig->samplingFreq = samplingFreq; + pSpatialSpecificConfig->nTimeSlots = nTimeSlots; + if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) || + (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD)) + pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_23; + else + pSpatialSpecificConfig->freqRes = SPATIALDEC_FREQ_RES_28; + + { + pSpatialSpecificConfig->treeConfig = + SPATIALDEC_MODE_RSVD7; /* 212 configuration */ + } + + { + pSpatialSpecificConfig->nOttBoxes = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOttBoxes; + pSpatialSpecificConfig->nInputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numInputChannels; + pSpatialSpecificConfig->nOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig].numOutputChannels; + } + + pSpatialSpecificConfig->quantMode = SPATIALDEC_QUANT_FINE_DEF; + pSpatialSpecificConfig->bArbitraryDownmix = 0; + pSpatialSpecificConfig->bResidualCoding = 0; + if ((pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_ELD) || + (pSpatialSpecificConfig->coreCodec == AOT_ER_AAC_LD)) + pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_RSVD2; + else + pSpatialSpecificConfig->bsFixedGainDMX = SPATIALDEC_GAIN_MODE0; + + pSpatialSpecificConfig->tempShapeConfig = SPATIALDEC_TS_TPNOWHITE; + pSpatialSpecificConfig->decorrConfig = SPATIALDEC_DECORR_MODE0; + + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + pSpatialSpecificConfig->OttConfig[i].nOttBands = 0; + } + + return err; +} + +/******************************************************************************* + Functionname: coarse2fine + ******************************************************************************* + + Description: + Parameter index mapping from coarse to fine quantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static void coarse2fine(SCHAR *data, DATA_TYPE dataType, int startBand, + int numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + data[i] <<= 1; + } + + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + if (data[i] == -14) + data[i] = -15; + else if (data[i] == 14) + data[i] = 15; + } + } +} + +/******************************************************************************* + Functionname: fine2coarse + ******************************************************************************* + + Description: + Parameter index mapping from fine to coarse quantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static void fine2coarse(SCHAR *data, DATA_TYPE dataType, int startBand, + int numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + /* Note: the if cases below actually make a difference (negative values) */ + if (dataType == t_CLD) + data[i] /= 2; + else + data[i] >>= 1; + } +} + +/******************************************************************************* + Functionname: getStrideMap + ******************************************************************************* + + Description: + Index Mapping accroding to pbStrides + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static int getStrideMap(int freqResStride, int startBand, int stopBand, + int *aStrides) { + int i, pb, pbStride, dataBands, strOffset; + + pbStride = pbStrideTable[freqResStride]; + dataBands = (stopBand - startBand - 1) / pbStride + 1; + + aStrides[0] = startBand; + for (pb = 1; pb <= dataBands; pb++) { + aStrides[pb] = aStrides[pb - 1] + pbStride; + } + strOffset = 0; + while (aStrides[dataBands] > stopBand) { + if (strOffset < dataBands) strOffset++; + for (i = strOffset; i <= dataBands; i++) { + aStrides[i]--; + } + } + + return dataBands; +} + +/******************************************************************************* + Functionname: ecDataDec + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + + +*******************************************************************************/ + +static SACDEC_ERROR ecDataDec( + const SPATIAL_BS_FRAME *frame, UINT syntaxFlags, + HANDLE_FDK_BITSTREAM bitstream, LOSSLESSDATA *const llData, + SCHAR (*data)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], SCHAR **lastdata, + int datatype, int boxIdx, int startBand, int stopBand, SCHAR defaultValue) { + SACDEC_ERROR err = MPS_OK; + int i, j, pb, dataSets, setIdx, bsDataPair, dataBands, oldQuantCoarseXXX; + INT aStrides[MAX_PARAMETER_BANDS + 1] = {0}; + + dataSets = 0; + for (i = 0; i < frame->numParameterSets; i++) { + llData->bsXXXDataMode[i] = (SCHAR)FDKreadBits(bitstream, 2); + + if ((frame->bsIndependencyFlag == 1) && (i == 0) && + (llData->bsXXXDataMode[i] == 1 || + llData->bsXXXDataMode[i] == 2)) { /* This check catches bitstreams + generated by older encoder that + cause trouble */ + return MPS_PARSE_ERROR; + } + if ((i >= frame->numParameterSets - 1) && + (llData->bsXXXDataMode[i] == + 2)) { /* The interpolation mode must not be active for the last + parameter set */ + return MPS_PARSE_ERROR; + } + + if (llData->bsXXXDataMode[i] == 3) { + dataSets++; + } + } + + setIdx = 0; + bsDataPair = 0; + oldQuantCoarseXXX = llData->state->bsQuantCoarseXXXprevParse; + + for (i = 0; i < frame->numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 0) { + for (pb = startBand; pb < stopBand; pb++) { + lastdata[boxIdx][pb] = defaultValue; + } + + oldQuantCoarseXXX = 0; + } + + if (llData->bsXXXDataMode[i] == 3) { + if (bsDataPair) { + bsDataPair = 0; + } else { + bsDataPair = FDKreadBits(bitstream, 1); + llData->bsQuantCoarseXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 1); + llData->bsFreqResStrideXXX[setIdx] = (UCHAR)FDKreadBits(bitstream, 2); + + if (llData->bsQuantCoarseXXX[setIdx] != oldQuantCoarseXXX) { + if (oldQuantCoarseXXX) { + coarse2fine(lastdata[boxIdx], (DATA_TYPE)datatype, startBand, + stopBand - startBand); + } else { + fine2coarse(lastdata[boxIdx], (DATA_TYPE)datatype, startBand, + stopBand - startBand); + } + } + + dataBands = getStrideMap(llData->bsFreqResStrideXXX[setIdx], startBand, + stopBand, aStrides); + + for (pb = 0; pb < dataBands; pb++) { + lastdata[boxIdx][startBand + pb] = lastdata[boxIdx][aStrides[pb]]; + } + + if (boxIdx > MAX_NUM_OTT) return MPS_INVALID_BOXIDX; + if ((setIdx + bsDataPair) > MAX_PARAMETER_SETS) + return MPS_INVALID_SETIDX; + + /* DECODER_TYPE defined in FDK_tools */ + DECODER_TYPE this_decoder_type = SAC_DECODER; + if (syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) { + this_decoder_type = USAC_DECODER; + } else if (syntaxFlags & SACDEC_SYNTAX_LD) { + this_decoder_type = SAOC_DECODER; + } + + err = (SACDEC_ERROR)EcDataPairDec( + this_decoder_type, bitstream, data[boxIdx][setIdx + 0], + data[boxIdx][setIdx + 1], lastdata[boxIdx], (DATA_TYPE)datatype, + startBand, dataBands, bsDataPair, llData->bsQuantCoarseXXX[setIdx], + !(frame->bsIndependencyFlag && (i == 0)) || (setIdx > 0)); + if (err != MPS_OK) goto bail; + + if (datatype == t_IPD) { + const SCHAR mask = (llData->bsQuantCoarseXXX[setIdx]) ? 7 : 15; + for (pb = 0; pb < dataBands; pb++) { + for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) { + lastdata[boxIdx][j] = + data[boxIdx][setIdx + bsDataPair][startBand + pb] & mask; + } + } + } else { + for (pb = 0; pb < dataBands; pb++) { + for (j = aStrides[pb]; j < aStrides[pb + 1]; j++) { + lastdata[boxIdx][j] = + data[boxIdx][setIdx + bsDataPair][startBand + pb]; + } + } + } + + oldQuantCoarseXXX = llData->bsQuantCoarseXXX[setIdx]; + + if (bsDataPair) { + llData->bsQuantCoarseXXX[setIdx + 1] = + llData->bsQuantCoarseXXX[setIdx]; + llData->bsFreqResStrideXXX[setIdx + 1] = + llData->bsFreqResStrideXXX[setIdx]; + } + setIdx += bsDataPair + 1; + } /* !bsDataPair */ + } /* llData->bsXXXDataMode[i] == 3 */ + } + + llData->state->bsQuantCoarseXXXprevParse = oldQuantCoarseXXX; + +bail: + return err; +} + +/******************************************************************************* + Functionname: parseArbitraryDownmixData + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR parseArbitraryDownmixData( + spatialDec *self, const SPATIAL_SPECIFIC_CONFIG *pSSC, + const UINT syntaxFlags, const SPATIAL_BS_FRAME *frame, + HANDLE_FDK_BITSTREAM bitstream) { + SACDEC_ERROR err = MPS_OK; + int ch; + int offset = pSSC->nOttBoxes; + + /* CLD (arbitrary down-mix gains) */ + for (ch = 0; ch < pSSC->nInputChannels; ch++) { + err = ecDataDec(frame, syntaxFlags, bitstream, + &frame->CLDLosslessData[offset + ch], + frame->cmpArbdmxGainIdx, self->cmpArbdmxGainIdxPrev, t_CLD, + ch, 0, pSSC->freqRes, arbdmxGainDefault); + if (err != MPS_OK) return err; + } + + return err; + +} /* parseArbitraryDownmixData */ + +/******************************************************************************* + Functionname: SpatialDecParseFrame + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ + +static int nBitsParamSlot(int i) { + int bitsParamSlot; + + bitsParamSlot = fMax(0, DFRACT_BITS - 1 - fNormz((FIXP_DBL)i)); + if ((1 << bitsParamSlot) < i) { + bitsParamSlot++; + } + FDK_ASSERT((bitsParamSlot >= 0) && (bitsParamSlot <= 32)); + + return bitsParamSlot; +} + +SACDEC_ERROR SpatialDecParseFrameData( + spatialDec_struct *self, SPATIAL_BS_FRAME *frame, + HANDLE_FDK_BITSTREAM bitstream, + const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType, + int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + int bsFramingType, dataBands, ps, pg, i; + int pb; + int numTempShapeChan = 0; + int bsNumOutputChannels = + treePropertyTable[pSpatialSpecificConfig->treeConfig] + .numOutputChannels; /* CAUTION: Maybe different to + pSpatialSpecificConfig->treeConfig in some + modes! */ + int paramSetErr = 0; + UINT alignAnchor = FDKgetValidBits( + bitstream); /* Anchor for ByteAlign() function. See comment below. */ + UINT syntaxFlags; + + syntaxFlags = pSpatialSpecificConfig->syntaxFlags; + + if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + pSpatialSpecificConfig->bsHighRateMode == 0) { + bsFramingType = 0; /* fixed framing */ + frame->numParameterSets = 1; + } else { + bsFramingType = FDKreadBits(bitstream, 1); + if (syntaxFlags & SACDEC_SYNTAX_LD) + frame->numParameterSets = FDKreadBits(bitstream, 1) + 1; + else + frame->numParameterSets = FDKreadBits(bitstream, 3) + 1; + } + + /* Any error after this line shall trigger parameter invalidation at bail + * label. */ + paramSetErr = 1; + + if (frame->numParameterSets >= MAX_PARAMETER_SETS) { + goto bail; + } + + /* Basic config check. */ + if (pSpatialSpecificConfig->nInputChannels <= 0 || + pSpatialSpecificConfig->nOutputChannels <= 0) { + err = MPS_UNSUPPORTED_CONFIG; + goto bail; + } + + if (bsFramingType) { + int prevParamSlot = -1; + int bitsParamSlot; + + { + bitsParamSlot = nBitsParamSlot(pSpatialSpecificConfig->nTimeSlots); + + for (i = 0; i < frame->numParameterSets; i++) { + frame->paramSlot[i] = FDKreadBits(bitstream, bitsParamSlot); + /* Sanity check */ + if ((frame->paramSlot[i] <= prevParamSlot) || + (frame->paramSlot[i] >= pSpatialSpecificConfig->nTimeSlots)) { + err = MPS_PARSE_ERROR; + goto bail; + } + prevParamSlot = frame->paramSlot[i]; + } + } + } else { + for (i = 0; i < frame->numParameterSets; i++) { + frame->paramSlot[i] = ((pSpatialSpecificConfig->nTimeSlots * (i + 1)) / + frame->numParameterSets) - + 1; + } + } + + if ((syntaxFlags & (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + fGlobalIndependencyFlag) { + frame->bsIndependencyFlag = 1; + } else { + frame->bsIndependencyFlag = (UCHAR)FDKreadBits(bitstream, 1); + } + + /* + * OttData() + */ + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->CLDLosslessData[i], + frame->cmpOttCLDidx, self->cmpOttCLDidxPrev, t_CLD, i, 0, + pSpatialSpecificConfig->bitstreamOttBands[i], + pSpatialSpecificConfig->ottCLDdefault[i]); + if (err != MPS_OK) { + goto bail; + } + } /* i < numOttBoxes */ + + { + for (i = 0; i < pSpatialSpecificConfig->nOttBoxes; i++) { + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->ICCLosslessData[i], + frame->cmpOttICCidx, self->cmpOttICCidxPrev, t_ICC, i, 0, + pSpatialSpecificConfig->bitstreamOttBands[i], ICCdefault); + if (err != MPS_OK) { + goto bail; + } + } /* i < numOttBoxes */ + } /* !oneICC */ + + if ((pSpatialSpecificConfig->treeConfig == SPATIALDEC_MODE_RSVD7) && + (pSpatialSpecificConfig->bsPhaseCoding)) { + frame->phaseMode = FDKreadBits(bitstream, 1); + + if (frame->phaseMode == 0) { + for (pb = 0; pb < pSpatialSpecificConfig->numOttBandsIPD; pb++) { + self->cmpOttIPDidxPrev[0][pb] = 0; + for (i = 0; i < frame->numParameterSets; i++) { + frame->cmpOttIPDidx[0][i][pb] = 0; + // frame->ottIPDidx[0][i][pb] = 0; + } + /* self->ottIPDidxPrev[0][pb] = 0; */ + } + frame->OpdSmoothingMode = 0; + } else { + frame->OpdSmoothingMode = FDKreadBits(bitstream, 1); + err = ecDataDec(frame, syntaxFlags, bitstream, &frame->IPDLosslessData[0], + frame->cmpOttIPDidx, self->cmpOttIPDidxPrev, t_IPD, 0, 0, + pSpatialSpecificConfig->numOttBandsIPD, IPDdefault); + if (err != MPS_OK) { + goto bail; + } + } + } + + /* + * SmgData() + */ + + { + if (!pSpatialSpecificConfig->bsHighRateMode && + (syntaxFlags & SACDEC_SYNTAX_USAC)) { + for (ps = 0; ps < frame->numParameterSets; ps++) { + frame->bsSmoothMode[ps] = 0; + } + } else { + for (ps = 0; ps < frame->numParameterSets; ps++) { + frame->bsSmoothMode[ps] = (UCHAR)FDKreadBits(bitstream, 2); + if (frame->bsSmoothMode[ps] >= 2) { + frame->bsSmoothTime[ps] = (UCHAR)FDKreadBits(bitstream, 2); + } + if (frame->bsSmoothMode[ps] == 3) { + frame->bsFreqResStrideSmg[ps] = (UCHAR)FDKreadBits(bitstream, 2); + dataBands = (pSpatialSpecificConfig->freqRes - 1) / + pbStrideTable[frame->bsFreqResStrideSmg[ps]] + + 1; + for (pg = 0; pg < dataBands; pg++) { + frame->bsSmgData[ps][pg] = (UCHAR)FDKreadBits(bitstream, 1); + } + } + } /* ps < numParameterSets */ + } + } + + /* + * TempShapeData() + */ + if ((pSpatialSpecificConfig->tempShapeConfig == 3) && + (syntaxFlags & SACDEC_SYNTAX_USAC)) { + int TsdErr; + TsdErr = TsdRead(bitstream, pSpatialSpecificConfig->nTimeSlots, + &frame->TsdData[0]); + if (TsdErr) { + err = MPS_PARSE_ERROR; + goto bail; + } + } else { + frame->TsdData[0].bsTsdEnable = 0; + } + + for (i = 0; i < bsNumOutputChannels; i++) { + frame->tempShapeEnableChannelSTP[i] = 0; + frame->tempShapeEnableChannelGES[i] = 0; + } + + if ((pSpatialSpecificConfig->tempShapeConfig == 1) || + (pSpatialSpecificConfig->tempShapeConfig == 2)) { + int bsTempShapeEnable = FDKreadBits(bitstream, 1); + if (bsTempShapeEnable) { + numTempShapeChan = + tempShapeChanTable[pSpatialSpecificConfig->tempShapeConfig - 1] + [pSpatialSpecificConfig->treeConfig]; + switch (pSpatialSpecificConfig->tempShapeConfig) { + case 1: /* STP */ + for (i = 0; i < numTempShapeChan; i++) { + int stpEnable = FDKreadBits(bitstream, 1); + frame->tempShapeEnableChannelSTP[i] = stpEnable; + } + break; + case 2: /* GES */ + { + UCHAR gesChannelEnable[MAX_OUTPUT_CHANNELS]; + + for (i = 0; i < numTempShapeChan; i++) { + gesChannelEnable[i] = (UCHAR)FDKreadBits(bitstream, 1); + frame->tempShapeEnableChannelGES[i] = gesChannelEnable[i]; + } + for (i = 0; i < numTempShapeChan; i++) { + if (gesChannelEnable[i]) { + int envShapeData_tmp[MAX_TIME_SLOTS]; + if (huff_dec_reshape(bitstream, envShapeData_tmp, + pSpatialSpecificConfig->nTimeSlots) != 0) { + err = MPS_PARSE_ERROR; + goto bail; + } + for (int ts = 0; ts < pSpatialSpecificConfig->nTimeSlots; ts++) { + if (!(envShapeData_tmp[ts] >= 0) && + (envShapeData_tmp[ts] <= 4)) { + err = MPS_PARSE_ERROR; + goto bail; + } + frame->bsEnvShapeData[i][ts] = (UCHAR)envShapeData_tmp[ts]; + } + } + } + } break; + default: + err = MPS_INVALID_TEMPSHAPE; + goto bail; + } + } /* bsTempShapeEnable */ + } /* pSpatialSpecificConfig->tempShapeConfig != 0 */ + + if (pSpatialSpecificConfig->bArbitraryDownmix != 0) { + err = parseArbitraryDownmixData(self, pSpatialSpecificConfig, syntaxFlags, + frame, bitstream); + if (err != MPS_OK) goto bail; + } + + if (1 && (!(syntaxFlags & (SACDEC_SYNTAX_USAC)))) { + FDKbyteAlign(bitstream, + alignAnchor); /* ISO/IEC FDIS 23003-1: 5.2. ... byte alignment + with respect to the beginning of the syntactic + element in which ByteAlign() occurs. */ + } + +bail: + if (err != MPS_OK && paramSetErr != 0) { + /* Since the parameter set data has already been written to the instance we + * need to ... */ + frame->numParameterSets = 0; /* ... signal that it is corrupt ... */ + } + + return err; + +} /* SpatialDecParseFrame */ + +/******************************************************************************* + Functionname: createMapping + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void createMapping(int aMap[MAX_PARAMETER_BANDS + 1], int startBand, + int stopBand, int stride) { + int inBands, outBands, bandsAchived, bandsDiff, incr, k, i; + int vDk[MAX_PARAMETER_BANDS + 1]; + inBands = stopBand - startBand; + outBands = (inBands - 1) / stride + 1; + + if (outBands < 1) { + outBands = 1; + } + + bandsAchived = outBands * stride; + bandsDiff = inBands - bandsAchived; + for (i = 0; i < outBands; i++) { + vDk[i] = stride; + } + + if (bandsDiff > 0) { + incr = -1; + k = outBands - 1; + } else { + incr = 1; + k = 0; + } + + while (bandsDiff != 0) { + vDk[k] = vDk[k] - incr; + k = k + incr; + bandsDiff = bandsDiff + incr; + if (k >= outBands) { + if (bandsDiff > 0) { + k = outBands - 1; + } else if (bandsDiff < 0) { + k = 0; + } + } + } + aMap[0] = startBand; + for (i = 0; i < outBands; i++) { + aMap[i + 1] = aMap[i] + vDk[i]; + } +} /* createMapping */ + +/******************************************************************************* + Functionname: mapFrequency + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void mapFrequency(const SCHAR *pInput, /* Input */ + SCHAR *pOutput, /* Output */ + int *pMap, /* Mapping function */ + int dataBands) /* Number of data Bands */ +{ + int i, j; + int startBand0 = pMap[0]; + + for (i = 0; i < dataBands; i++) { + int startBand, stopBand, value; + + value = pInput[i + startBand0]; + + startBand = pMap[i]; + stopBand = pMap[i + 1]; + for (j = startBand; j < stopBand; j++) { + pOutput[j] = value; + } + } +} + +/******************************************************************************* + Functionname: deq + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static int deqIdx(int value, int paramType) { + int idx = -1; + + switch (paramType) { + case t_CLD: + if (((value + 15) >= 0) && ((value + 15) < 31)) { + idx = (value + 15); + } + break; + + case t_ICC: + if ((value >= 0) && (value < 8)) { + idx = value; + } + break; + + case t_IPD: + /* (+/-)15 * MAX_PARAMETER_BANDS for differential coding in frequency + * domain (according to rbl) */ + if ((value >= -420) && (value <= 420)) { + idx = (value & 0xf); + } + break; + + default: + FDK_ASSERT(0); + } + + return idx; +} + + /******************************************************************************* + Functionname: factorFunct + ******************************************************************************* + + Description: + + Arguments: + + Return: + + *******************************************************************************/ + +#define SF_IDX (7) +#define SF_FACTOR (3) +#define SCALE_FACTOR (1 << SF_FACTOR) +#define SCALE_CLD_C1C2 (1 << SF_CLD_C1C2) + +static FIXP_DBL factorFunct(FIXP_DBL ottVsTotDb, INT quantMode) { + FIXP_DBL factor; + + if (ottVsTotDb > FL2FXCONST_DBL(0.0)) { + ottVsTotDb = FL2FXCONST_DBL(0.0); + } + + ottVsTotDb = -ottVsTotDb; + + switch (quantMode) { + case 0: + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + break; + case 1: + if (ottVsTotDb >= FL2FXCONST_DBL(21.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(5.0f / SCALE_FACTOR); + else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + else + factor = (fMult(FL2FXCONST_DBL(0.2f), ottVsTotDb) + + FL2FXCONST_DBL(0.8f / SCALE_CLD_C1C2)) + << (SF_CLD_C1C2 - SF_FACTOR); + break; + case 2: + if (ottVsTotDb >= FL2FXCONST_DBL(25.0f / SCALE_CLD_C1C2)) { + FDK_ASSERT(SF_FACTOR == 3); + factor = (FIXP_DBL) + MAXVAL_DBL; /* avoid warning: FL2FXCONST_DBL(8.0f/SCALE_FACTOR) */ + } else if (ottVsTotDb <= FL2FXCONST_DBL(1.0f / SCALE_CLD_C1C2)) + factor = FL2FXCONST_DBL(1.0f / SCALE_FACTOR); + else + factor = (fMult(FL2FXCONST_DBL(7.0f / 24.0f), ottVsTotDb) + + FL2FXCONST_DBL((17.0f / 24.0f) / SCALE_CLD_C1C2)) + << (SF_CLD_C1C2 - SF_FACTOR); + break; + default: + factor = FL2FXCONST_DBL(0.0f); + } + + return (factor); +} + +/******************************************************************************* + Functionname: factorCLD + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void factorCLD(SCHAR *idx, FIXP_DBL ottVsTotDb, FIXP_DBL *ottVsTotDb1, + FIXP_DBL *ottVsTotDb2, SCHAR ottVsTotDbMode, + INT quantMode) { + FIXP_DBL factor; + FIXP_DBL cldIdxFract; + INT cldIdx; + + factor = factorFunct(ottVsTotDb, quantMode); + + cldIdxFract = + fMult((FIXP_DBL)((*idx) << ((DFRACT_BITS - 1) - SF_IDX)), factor); + cldIdxFract += FL2FXCONST_DBL(15.5f / (1 << (SF_FACTOR + SF_IDX))); + cldIdx = fixp_truncateToInt(cldIdxFract, SF_FACTOR + SF_IDX); + + cldIdx = fMin(cldIdx, 30); + cldIdx = fMax(cldIdx, 0); + + *idx = cldIdx - 15; + + if (ottVsTotDbMode & ottVsTotDb1Activ) + (*ottVsTotDb1) = ottVsTotDb + dequantCLD_c1[cldIdx]; + + if (ottVsTotDbMode & ottVsTotDb2Activ) + (*ottVsTotDb2) = ottVsTotDb + dequantCLD_c1[30 - cldIdx]; +} + +/******************************************************************************* + Functionname: mapIndexData + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR mapIndexData( + LOSSLESSDATA *llData, SCHAR ***outputDataIdx, SCHAR ***outputIdxData, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + SCHAR ***diffIdxData, SCHAR xttIdx, SCHAR **idxPrev, int paramIdx, + int paramType, int startBand, int stopBand, SCHAR defaultValue, + int numParameterSets, const int *paramSlot, int extendFrame, int quantMode, + SpatialDecConcealmentInfo *concealmentInfo, SCHAR ottVsTotDbMode, + FIXP_DBL (*pOttVsTotDbIn)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + FIXP_DBL (*pOttVsTotDb1)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + FIXP_DBL (*pOttVsTotDb2)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) { + int aParamSlots[MAX_PARAMETER_SETS]; + int aInterpolate[MAX_PARAMETER_SETS]; + + int dataSets; + int aMap[MAX_PARAMETER_BANDS + 1]; + + int setIdx, i, band, parmSlot; + int dataBands; + int ps, pb; + int i1; + + if (numParameterSets > MAX_PARAMETER_SETS) return MPS_WRONG_PARAMETERSETS; + + dataSets = 0; + for (i = 0; i < numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 3) { + aParamSlots[dataSets] = i; + dataSets++; + } + } + + setIdx = 0; + + /* Main concealment stage is here: */ + SpatialDecConcealment_Apply( + concealmentInfo, cmpIdxData[xttIdx], + (diffIdxData != NULL) ? diffIdxData[xttIdx] : NULL, idxPrev[xttIdx], + llData->bsXXXDataMode, startBand, stopBand, defaultValue, paramType, + numParameterSets); + + /* Prepare data */ + for (i = 0; i < numParameterSets; i++) { + if (llData->bsXXXDataMode[i] == 0) { + llData->nocmpQuantCoarseXXX[i] = 0; + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = defaultValue; + } + for (band = startBand; band < stopBand; band++) { + idxPrev[xttIdx][band] = outputIdxData[xttIdx][i][band]; + } + /* Because the idxPrev are also set to the defaultValue -> signalize fine + */ + llData->state->bsQuantCoarseXXXprev = 0; + } + + if (llData->bsXXXDataMode[i] == 1) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band]; + } + llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev; + } + + if (llData->bsXXXDataMode[i] == 2) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] = idxPrev[xttIdx][band]; + } + llData->nocmpQuantCoarseXXX[i] = llData->state->bsQuantCoarseXXXprev; + aInterpolate[i] = 1; + } else { + aInterpolate[i] = 0; + } + + if (llData->bsXXXDataMode[i] == 3) { + int stride; + + parmSlot = aParamSlots[setIdx]; + stride = pbStrideTable[llData->bsFreqResStrideXXX[setIdx]]; + dataBands = (stopBand - startBand - 1) / stride + 1; + createMapping(aMap, startBand, stopBand, stride); + mapFrequency(&cmpIdxData[xttIdx][setIdx][0], + &outputIdxData[xttIdx][parmSlot][0], aMap, dataBands); + for (band = startBand; band < stopBand; band++) { + idxPrev[xttIdx][band] = outputIdxData[xttIdx][parmSlot][band]; + } + llData->state->bsQuantCoarseXXXprev = llData->bsQuantCoarseXXX[setIdx]; + llData->nocmpQuantCoarseXXX[i] = llData->bsQuantCoarseXXX[setIdx]; + + setIdx++; + } + if (diffIdxData != NULL) { + for (band = startBand; band < stopBand; band++) { + outputIdxData[xttIdx][i][band] += diffIdxData[xttIdx][i][band]; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + /* Map all coarse data to fine */ + for (i = 0; i < numParameterSets; i++) { + if (llData->nocmpQuantCoarseXXX[i] == 1) { + coarse2fine(outputIdxData[xttIdx][i], (DATA_TYPE)paramType, startBand, + stopBand - startBand); + llData->nocmpQuantCoarseXXX[i] = 0; + } + } + + /* Interpolate */ + i1 = 0; + for (i = 0; i < numParameterSets; i++) { + int xi, i2, x1, x2; + + if (aInterpolate[i] != 1) { + i1 = i; + } + i2 = i; + while (aInterpolate[i2] == 1) { + i2++; + } + x1 = paramSlot[i1]; + xi = paramSlot[i]; + x2 = paramSlot[i2]; + + if (aInterpolate[i] == 1) { + if (i2 >= numParameterSets) return MPS_WRONG_PARAMETERSETS; + for (band = startBand; band < stopBand; band++) { + int yi, y1, y2; + y1 = outputIdxData[xttIdx][i1][band]; + y2 = outputIdxData[xttIdx][i2][band]; + if (x1 != x2) { + yi = y1 + (xi - x1) * (y2 - y1) / (x2 - x1); + } else { + yi = y1 /*+ (xi-x1)*(y2-y1)/1e-12*/; + } + outputIdxData[xttIdx][i][band] = yi; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + /* Dequantize data and apply factorCLD if necessary */ + for (ps = 0; ps < numParameterSets; ps++) { + if (quantMode && (paramType == t_CLD)) { + if (pOttVsTotDbIn == 0) return MPS_WRONG_OTT; + if ((pOttVsTotDb1 == 0) && (ottVsTotDbMode == ottVsTotDb1Activ)) + return MPS_WRONG_OTT; + if ((pOttVsTotDb2 == 0) && (ottVsTotDbMode == ottVsTotDb2Activ)) + return MPS_WRONG_OTT; + + for (pb = startBand; pb < stopBand; pb++) { + factorCLD(&(outputIdxData[xttIdx][ps][pb]), (*pOttVsTotDbIn)[ps][pb], + (pOttVsTotDb1 != NULL) ? &((*pOttVsTotDb1)[ps][pb]) : NULL, + (pOttVsTotDb2 != NULL) ? &((*pOttVsTotDb2)[ps][pb]) : NULL, + ottVsTotDbMode, quantMode); + } + } + + /* Dequantize data */ + for (band = startBand; band < stopBand; band++) { + outputDataIdx[xttIdx][ps][band] = + deqIdx(outputIdxData[xttIdx][ps][band], paramType); + if (outputDataIdx[xttIdx][ps][band] == -1) { + outputDataIdx[xttIdx][ps][band] = defaultValue; + } + } + } /* for( i = 0 ; i < numParameterSets; i++ ) */ + + if (extendFrame) { + for (band = startBand; band < stopBand; band++) { + outputDataIdx[xttIdx][numParameterSets][band] = + outputDataIdx[xttIdx][numParameterSets - 1][band]; + } + } + + return MPS_OK; +} + +/******************************************************************************* + Functionname: decodeAndMapFrameOtt + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameOtt(HANDLE_SPATIAL_DEC self, + SPATIAL_BS_FRAME *pCurBs) { + int i, ottIdx; + int numOttBoxes; + + SACDEC_ERROR err = MPS_OK; + + numOttBoxes = self->numOttBoxes; + + switch (self->treeConfig) { + default: { + if (self->quantMode != 0) { + goto bail; + } + } + for (i = 0; i < numOttBoxes; i++) { + err = mapIndexData( + &pCurBs->CLDLosslessData[i], /* LOSSLESSDATA *llData,*/ + self->ottCLD__FDK, self->outIdxData, + pCurBs + ->cmpOttCLDidx, /* int + cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + */ + NULL, /* no differential data */ + i, /* int xttIdx, Which ott/ttt index to use for input and + output buffers */ + self->ottCLDidxPrev, /* int + idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS], + */ + i, t_CLD, 0, /* int startBand, */ + self->pConfigCurrent->bitstreamOttBands[i], /* int stopBand, */ + self->pConfigCurrent->ottCLDdefault[i], /* int defaultValue, */ + pCurBs->numParameterSets, /* int numParameterSets) */ + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + + } /* for(i = 0; i < numOttBoxes ; i++ ) */ + break; + } /* case */ + + for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) { + /* Read ICC */ + err = mapIndexData( + &pCurBs->ICCLosslessData[ottIdx], /* LOSSLESSDATA *llData,*/ + self->ottICC__FDK, self->outIdxData, + pCurBs + ->cmpOttICCidx, /* int + cmpIdxData[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS], + */ + self->ottICCdiffidx, /* differential data */ + ottIdx, /* int xttIdx, Which ott/ttt index to use for input and + output buffers */ + self->ottICCidxPrev, /* int idxPrev[MAX_NUM_OTT][MAX_PARAMETER_BANDS], + */ + ottIdx, t_ICC, 0, /* int startBand, */ + self->pConfigCurrent->bitstreamOttBands[ottIdx], /* int stopBand, */ + ICCdefault, /* int defaultValue, */ + pCurBs->numParameterSets, /* int numParameterSets) */ + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + } /* ottIdx */ + + if ((self->treeConfig == TREE_212) && (self->phaseCoding)) { + if (pCurBs->phaseMode == 0) { + for (int pb = 0; pb < self->pConfigCurrent->numOttBandsIPD; pb++) { + self->ottIPDidxPrev[0][pb] = 0; + } + } + for (ottIdx = 0; ottIdx < numOttBoxes; ottIdx++) { + err = mapIndexData( + &pCurBs->IPDLosslessData[ottIdx], self->ottIPD__FDK, self->outIdxData, + pCurBs->cmpOttIPDidx, NULL, ottIdx, self->ottIPDidxPrev, ottIdx, + t_IPD, 0, self->numOttBandsIPD, IPDdefault, pCurBs->numParameterSets, + pCurBs->paramSlot, self->extendFrame, self->quantMode, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + } + } + +bail: + + return MPS_OK; + +} /* decodeAndMapFrameOtt */ + +/******************************************************************************* + Functionname: decodeAndMapFrameSmg + ******************************************************************************* + + Description: + Decode smoothing flags + + Arguments: + +Input: + +Output: + + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameSmg(HANDLE_SPATIAL_DEC self, + const SPATIAL_BS_FRAME *frame) { + int ps, pb, pg, pbStride, dataBands, pbStart, pbStop, + aGroupToBand[MAX_PARAMETER_BANDS + 1]; + + if (frame->numParameterSets > MAX_PARAMETER_SETS) + return MPS_WRONG_PARAMETERSETS; + if (self->bitstreamParameterBands > MAX_PARAMETER_BANDS) + return MPS_WRONG_PARAMETERBANDS; + + for (ps = 0; ps < frame->numParameterSets; ps++) { + switch (frame->bsSmoothMode[ps]) { + case 0: + self->smgTime[ps] = 256; + FDKmemclear(self->smgData[ps], + self->bitstreamParameterBands * sizeof(UCHAR)); + break; + + case 1: + if (ps > 0) { + self->smgTime[ps] = self->smgTime[ps - 1]; + FDKmemcpy(self->smgData[ps], self->smgData[ps - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + } else { + self->smgTime[ps] = self->smoothState->prevSmgTime; + FDKmemcpy(self->smgData[ps], self->smoothState->prevSmgData, + self->bitstreamParameterBands * sizeof(UCHAR)); + } + break; + + case 2: + self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]]; + for (pb = 0; pb < self->bitstreamParameterBands; pb++) { + self->smgData[ps][pb] = 1; + } + break; + + case 3: + self->smgTime[ps] = smgTimeTable[frame->bsSmoothTime[ps]]; + pbStride = pbStrideTable[frame->bsFreqResStrideSmg[ps]]; + dataBands = (self->bitstreamParameterBands - 1) / pbStride + 1; + createMapping(aGroupToBand, 0, self->bitstreamParameterBands, pbStride); + for (pg = 0; pg < dataBands; pg++) { + pbStart = aGroupToBand[pg]; + pbStop = aGroupToBand[pg + 1]; + for (pb = pbStart; pb < pbStop; pb++) { + self->smgData[ps][pb] = frame->bsSmgData[ps][pg]; + } + } + break; + } + } + + self->smoothState->prevSmgTime = self->smgTime[frame->numParameterSets - 1]; + FDKmemcpy(self->smoothState->prevSmgData, + self->smgData[frame->numParameterSets - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + + if (self->extendFrame) { + self->smgTime[frame->numParameterSets] = + self->smgTime[frame->numParameterSets - 1]; + FDKmemcpy(self->smgData[frame->numParameterSets], + self->smgData[frame->numParameterSets - 1], + self->bitstreamParameterBands * sizeof(UCHAR)); + } + + return MPS_OK; +} + +/******************************************************************************* + Functionname: decodeAndMapFrameArbdmx + ******************************************************************************* + + Description: + Do delta decoding and dequantization + + Arguments: + +Input: + +Output: + +*******************************************************************************/ +static SACDEC_ERROR decodeAndMapFrameArbdmx(HANDLE_SPATIAL_DEC self, + const SPATIAL_BS_FRAME *frame) { + SACDEC_ERROR err = MPS_OK; + int ch; + int offset = self->numOttBoxes; + + for (ch = 0; ch < self->numInputChannels; ch++) { + err = mapIndexData(&frame->CLDLosslessData[offset + ch], + self->arbdmxGain__FDK, self->outIdxData, + frame->cmpArbdmxGainIdx, NULL, /* no differential data */ + ch, self->arbdmxGainIdxPrev, offset + ch, t_CLD, 0, + self->bitstreamParameterBands, + 0 /*self->arbdmxGainDefault*/, frame->numParameterSets, + frame->paramSlot, self->extendFrame, 0, + &(self->concealInfo), ottVsTotInactiv, NULL, NULL, NULL); + if (err != MPS_OK) goto bail; + } + +bail: + return err; +} /* decodeAndMapFrameArbdmx */ + +/******************************************************************************* + Functionname: SpatialDecDecodeFrame + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame) { + SACDEC_ERROR err = MPS_OK; + + self->extendFrame = 0; + if (frame->paramSlot[frame->numParameterSets - 1] != self->timeSlots - 1) { + self->extendFrame = 1; + } + + self->TsdTs = 0; + + /****** DTDF and MAP DATA ********/ + if ((err = decodeAndMapFrameOtt(self, frame)) != MPS_OK) goto bail; + + if ((err = decodeAndMapFrameSmg(self, frame)) != MPS_OK) goto bail; + + if (self->arbitraryDownmix != 0) { + if ((err = decodeAndMapFrameArbdmx(self, frame)) != MPS_OK) goto bail; + } + + if (self->extendFrame) { + frame->numParameterSets = + fixMin(MAX_PARAMETER_SETS, frame->numParameterSets + 1); + frame->paramSlot[frame->numParameterSets - 1] = self->timeSlots - 1; + + for (int p = 0; p < frame->numParameterSets; p++) { + if (frame->paramSlot[p] > self->timeSlots - 1) { + frame->paramSlot[p] = self->timeSlots - 1; + err = MPS_PARSE_ERROR; + } + } + if (err != MPS_OK) { + goto bail; + } + } + +bail: + return err; +} /* SpatialDecDecodeFrame() */ + +/******************************************************************************* + Functionname: SpatialDecodeHeader + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR SpatialDecDecodeHeader( + spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig) { + SACDEC_ERROR err = MPS_OK; + int i; + + self->samplingFreq = pSpatialSpecificConfig->samplingFreq; + self->timeSlots = pSpatialSpecificConfig->nTimeSlots; + self->frameLength = self->timeSlots * self->qmfBands; + self->bitstreamParameterBands = pSpatialSpecificConfig->freqRes; + + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) + self->hybridBands = self->qmfBands; + else + self->hybridBands = SacGetHybridSubbands(self->qmfBands); + self->tp_hybBandBorder = 12; + + self->numParameterBands = self->bitstreamParameterBands; + + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + switch (self->numParameterBands) { + case 4: + self->kernels = kernels_4_to_64; + break; + case 5: + self->kernels = kernels_5_to_64; + break; + case 7: + self->kernels = kernels_7_to_64; + break; + case 9: + self->kernels = kernels_9_to_64; + break; + case 12: + self->kernels = kernels_12_to_64; + break; + case 15: + self->kernels = kernels_15_to_64; + break; + case 23: + self->kernels = kernels_23_to_64; + break; + default: + return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */ + } + } else { + switch (self->numParameterBands) { + case 4: + self->kernels = kernels_4_to_71; + break; + case 5: + self->kernels = kernels_5_to_71; + break; + case 7: + self->kernels = kernels_7_to_71; + break; + case 10: + self->kernels = kernels_10_to_71; + break; + case 14: + self->kernels = kernels_14_to_71; + break; + case 20: + self->kernels = kernels_20_to_71; + break; + case 28: + self->kernels = kernels_28_to_71; + break; + default: + return MPS_INVALID_PARAMETERBANDS; /* unsupported numParameterBands */ + } + } + + /* create param to hyb band table */ + FDKmemclear(self->param2hyb, (MAX_PARAMETER_BANDS + 1) * sizeof(int)); + for (i = 0; i < self->hybridBands; i++) { + self->param2hyb[self->kernels[i] + 1] = i + 1; + } + { + int pb = self->kernels[i - 1] + 2; + for (; pb < (MAX_PARAMETER_BANDS + 1); pb++) { + self->param2hyb[pb] = i; + } + for (pb = 0; pb < MAX_PARAMETER_BANDS; pb += 1) { + self->kernels_width[pb] = self->param2hyb[pb + 1] - self->param2hyb[pb]; + } + } + + self->treeConfig = pSpatialSpecificConfig->treeConfig; + + self->numOttBoxes = pSpatialSpecificConfig->nOttBoxes; + + self->numInputChannels = pSpatialSpecificConfig->nInputChannels; + + self->numOutputChannels = pSpatialSpecificConfig->nOutputChannels; + + self->quantMode = pSpatialSpecificConfig->quantMode; + + self->arbitraryDownmix = pSpatialSpecificConfig->bArbitraryDownmix; + + self->numM2rows = self->numOutputChannels; + + { + self->residualCoding = 0; + if (self->arbitraryDownmix == 2) + self->arbitraryDownmix = 1; /* no arbitrary downmix residuals */ + } + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC)) { + self->residualCoding = pSpatialSpecificConfig->bResidualCoding; + } + + self->clipProtectGain__FDK = + FX_CFG2FX_DBL(clipGainTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]); + self->clipProtectGainSF__FDK = + clipGainSFTable__FDK[pSpatialSpecificConfig->bsFixedGainDMX]; + + self->tempShapeConfig = pSpatialSpecificConfig->tempShapeConfig; + + self->decorrConfig = pSpatialSpecificConfig->decorrConfig; + + if (self->upmixType == UPMIXTYPE_BYPASS) { + self->numOutputChannels = self->numInputChannels; + } + + self->numOutputChannelsAT = self->numOutputChannels; + + self->numOttBandsIPD = pSpatialSpecificConfig->numOttBandsIPD; + self->phaseCoding = pSpatialSpecificConfig->bsPhaseCoding; + for (i = 0; i < self->numOttBoxes; i++) { + { + self->pConfigCurrent->bitstreamOttBands[i] = + self->bitstreamParameterBands; + } + self->numOttBands[i] = self->pConfigCurrent->bitstreamOttBands[i]; + } /* i */ + + if (self->residualCoding) { + int numBoxes = self->numOttBoxes; + for (i = 0; i < numBoxes; i++) { + self->residualPresent[i] = + pSpatialSpecificConfig->ResidualConfig[i].bResidualPresent; + + if (self->residualPresent[i]) { + self->residualBands[i] = + pSpatialSpecificConfig->ResidualConfig[i].nResidualBands; + /* conversion from hybrid bands to qmf bands */ + self->residualQMFBands[i] = + fMax(self->param2hyb[self->residualBands[i]] + 3 - 10, + 3); /* simplification for the lowest 10 hybrid bands */ + } else { + self->residualBands[i] = 0; + self->residualQMFBands[i] = 0; + } + } + } /* self->residualCoding */ + else { + int boxes = self->numOttBoxes; + for (i = 0; i < boxes; i += 1) { + self->residualPresent[i] = 0; + self->residualBands[i] = 0; + } + } + + switch (self->treeConfig) { + case TREE_212: + self->numDirektSignals = 1; + self->numDecorSignals = 1; + self->numXChannels = 1; + if (self->arbitraryDownmix == 2) { + self->numXChannels += 1; + } + self->numVChannels = self->numDirektSignals + self->numDecorSignals; + break; + default: + return MPS_INVALID_TREECONFIG; + } + + self->highRateMode = pSpatialSpecificConfig->bsHighRateMode; + self->decorrType = pSpatialSpecificConfig->bsDecorrType; + + SpatialDecDecodeHelperInfo(pSpatialSpecificConfig, UPMIXTYPE_NORMAL); + + return err; +} + +/******************************************************************************* + Functionname: SpatialDecCreateBsFrame + ******************************************************************************* + + Description: Create spatial bitstream structure + + Arguments: spatialDec* self + const SPATIAL_BS_FRAME **bsFrame + + Return: - + +*******************************************************************************/ +SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame, + BS_LL_STATE *llState) { + SPATIAL_BS_FRAME *pBs = bsFrame; + + const int maxNumOtt = MAX_NUM_OTT; + const int maxNumInputChannels = MAX_INPUT_CHANNELS; + + FDK_ALLOCATE_MEMORY_1D_P( + pBs->cmpOttIPDidx, maxNumOtt * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, + SCHAR, SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) + + /* Arbitrary Downmix */ + FDK_ALLOCATE_MEMORY_1D_P( + pBs->cmpArbdmxGainIdx, + maxNumInputChannels * MAX_PARAMETER_SETS * MAX_PARAMETER_BANDS, SCHAR, + SCHAR(*)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]) + + /* Lossless control */ + FDK_ALLOCATE_MEMORY_1D(pBs->CLDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + FDK_ALLOCATE_MEMORY_1D(pBs->ICCLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + + FDK_ALLOCATE_MEMORY_1D(pBs->IPDLosslessData, MAX_NUM_PARAMETERS, LOSSLESSDATA) + + pBs->newBsData = 0; + pBs->numParameterSets = 1; + + /* Link lossless states */ + for (int x = 0; x < MAX_NUM_PARAMETERS; x++) { + pBs->CLDLosslessData[x].state = &llState->CLDLosslessState[x]; + pBs->ICCLosslessData[x].state = &llState->ICCLosslessState[x]; + + pBs->IPDLosslessData[x].state = &llState->IPDLosslessState[x]; + } + + return MPS_OK; + +bail: + return MPS_OUTOFMEMORY; +} + +/******************************************************************************* + Functionname: SpatialDecCloseBsFrame + ******************************************************************************* + + Description: Close spatial bitstream structure + + Arguments: spatialDec* self + + Return: - + +*******************************************************************************/ +void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *pBs) { + if (pBs != NULL) { + /* These arrays contain the compact indices, only one value per pbstride, + * only paramsets actually containing data. */ + + FDK_FREE_MEMORY_1D(pBs->cmpOttIPDidx); + + /* Arbitrary Downmix */ + FDK_FREE_MEMORY_1D(pBs->cmpArbdmxGainIdx); + + /* Lossless control */ + FDK_FREE_MEMORY_1D(pBs->IPDLosslessData); + FDK_FREE_MEMORY_1D(pBs->CLDLosslessData); + FDK_FREE_MEMORY_1D(pBs->ICCLosslessData); + } +} diff --git a/fdk-aac/libSACdec/src/sac_bitdec.h b/fdk-aac/libSACdec/src/sac_bitdec.h new file mode 100644 index 0000000..cb0c7d2 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_bitdec.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec bitstream decoder + +*******************************************************************************/ + +/*! + \file + \brief Spatial Audio bitstream decoder +*/ + +#ifndef SAC_BITDEC_H +#define SAC_BITDEC_H + +#include "sac_dec.h" + +typedef struct { + SCHAR numInputChannels; + SCHAR numOutputChannels; + SCHAR numOttBoxes; + SCHAR numTttBoxes; + SCHAR ottModeLfe[MAX_NUM_OTT]; +} TREEPROPERTIES; + +enum { TREE_212 = 7, TREE_DUMMY = 255 }; + +enum { QUANT_FINE = 0, QUANT_EBQ1 = 1, QUANT_EBQ2 = 2 }; + +SACDEC_ERROR SpatialDecParseSpecificConfigHeader( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, SPATIAL_DEC_UPMIX_TYPE upmixType); + +SACDEC_ERROR SpatialDecParseMps212Config( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int samplingRate, + AUDIO_OBJECT_TYPE coreCodec, INT stereoConfigIndex, + INT coreSbrFrameLengthIndex); + +SACDEC_ERROR SpatialDecParseSpecificConfig( + HANDLE_FDK_BITSTREAM bitstream, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, int sacHeaderLen, + AUDIO_OBJECT_TYPE coreCodec); + +int SpatialDecDefaultSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int samplingFreq, int nTimeSlots, + int sacDecoderLevel, int isBlind, int coreChannels); + +SACDEC_ERROR SpatialDecCreateBsFrame(SPATIAL_BS_FRAME *bsFrame, + BS_LL_STATE *llState); + +void SpatialDecCloseBsFrame(SPATIAL_BS_FRAME *bsFrame); + +SACDEC_ERROR SpatialDecParseFrameData( + spatialDec *self, SPATIAL_BS_FRAME *frame, HANDLE_FDK_BITSTREAM bitstream, + const SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, UPMIXTYPE upmixType, + int fGlobalIndependencyFlag); + +SACDEC_ERROR SpatialDecDecodeFrame(spatialDec *self, SPATIAL_BS_FRAME *frame); + +SACDEC_ERROR SpatialDecDecodeHeader( + spatialDec *self, SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig); + +#endif diff --git a/fdk-aac/libSACdec/src/sac_calcM1andM2.cpp b/fdk-aac/libSACdec/src/sac_calcM1andM2.cpp new file mode 100644 index 0000000..6e5a145 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_calcM1andM2.cpp @@ -0,0 +1,848 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec M1 and M2 calculation + +*******************************************************************************/ + +#include "sac_calcM1andM2.h" +#include "sac_bitdec.h" +#include "sac_process.h" +#include "sac_rom.h" +#include "sac_smoothing.h" +#include "FDK_trigFcts.h" + +/* assorted definitions and constants */ + +#define ABS_THR2 1.0e-9 +#define SQRT2_FDK \ + ((FIXP_DBL)FL2FXCONST_DBL(0.70710678118f)) /* FDKsqrt(2.0) scaled by 0.5 */ + +static void param2UMX_PS__FDK(spatialDec* self, + FIXP_DBL H11[MAX_PARAMETER_BANDS], + FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], + FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], + FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx, + int parameterSetIndx, int resBands); + +static void param2UMX_PS_Core__FDK( + const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS], + const int numOttBands, const int resBands, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]); + +static void param2UMX_PS_IPD_OPD__FDK( + spatialDec* self, const SPATIAL_BS_FRAME* frame, + FIXP_DBL H11re[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS], + FIXP_DBL H21re[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS], + int ottBoxIndx, int parameterSetIndx, int residualBands); + +static void param2UMX_Prediction__FDK( + spatialDec* self, FIXP_DBL H11re[MAX_PARAMETER_BANDS], + FIXP_DBL H11im[MAX_PARAMETER_BANDS], FIXP_DBL H12re[MAX_PARAMETER_BANDS], + FIXP_DBL H12im[MAX_PARAMETER_BANDS], FIXP_DBL H21re[MAX_PARAMETER_BANDS], + FIXP_DBL H21im[MAX_PARAMETER_BANDS], FIXP_DBL H22re[MAX_PARAMETER_BANDS], + FIXP_DBL H22im[MAX_PARAMETER_BANDS], int ottBoxIndx, int parameterSetIndx, + int resBands); + +/* static void SpatialDecCalculateM0(spatialDec* self,int ps); */ +static SACDEC_ERROR SpatialDecCalculateM1andM2_212( + spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame); + +/******************************************************************************* + Functionname: SpatialDecGetResidualIndex + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ +int SpatialDecGetResidualIndex(spatialDec* self, int row) { + return row2residual[self->treeConfig][row]; +} + +/******************************************************************************* + Functionname: UpdateAlpha + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + +*******************************************************************************/ +static void updateAlpha(spatialDec* self) { + int nChIn = self->numInputChannels; + int ch; + + for (ch = 0; ch < nChIn; ch++) { + FIXP_DBL alpha = /* FL2FXCONST_DBL(1.0f) */ (FIXP_DBL)MAXVAL_DBL; + + self->arbdmxAlphaPrev__FDK[ch] = self->arbdmxAlpha__FDK[ch]; + + self->arbdmxAlpha__FDK[ch] = alpha; + } +} + +/******************************************************************************* + Functionname: SpatialDecCalculateM1andM2 + ******************************************************************************* + Description: + Arguments: +*******************************************************************************/ +SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps, + const SPATIAL_BS_FRAME* frame) { + SACDEC_ERROR err = MPS_OK; + + if ((self->arbitraryDownmix != 0) && (ps == 0)) { + updateAlpha(self); + } + + self->pActivM2ParamBands = NULL; + + switch (self->upmixType) { + case UPMIXTYPE_BYPASS: + case UPMIXTYPE_NORMAL: + switch (self->treeConfig) { + case TREE_212: + err = SpatialDecCalculateM1andM2_212(self, ps, frame); + break; + default: + err = MPS_WRONG_TREECONFIG; + }; + break; + + default: + err = MPS_WRONG_TREECONFIG; + } + + if (err != MPS_OK) { + goto bail; + } + +bail: + return err; +} + +/******************************************************************************* + Functionname: SpatialDecCalculateM1andM2_212 + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR SpatialDecCalculateM1andM2_212( + spatialDec* self, int ps, const SPATIAL_BS_FRAME* frame) { + SACDEC_ERROR err = MPS_OK; + int pb; + + FIXP_DBL H11re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H12re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H21re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H22re[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H11im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + FIXP_DBL H21im[MAX_PARAMETER_BANDS] = {FL2FXCONST_DBL(0.0f)}; + + INT phaseCoding = self->phaseCoding; + + switch (phaseCoding) { + case 1: + /* phase coding: yes; residuals: no */ + param2UMX_PS_IPD_OPD__FDK(self, frame, H11re, H12re, H21re, H22re, NULL, + NULL, 0, ps, self->residualBands[0]); + break; + case 3: + /* phase coding: yes; residuals: yes */ + param2UMX_Prediction__FDK(self, H11re, H11im, H12re, NULL, H21re, H21im, + H22re, NULL, 0, ps, self->residualBands[0]); + break; + default: + if (self->residualCoding) { + /* phase coding: no; residuals: yes */ + param2UMX_Prediction__FDK(self, H11re, NULL, H12re, NULL, H21re, NULL, + H22re, NULL, 0, ps, self->residualBands[0]); + } else { + /* phase coding: no; residuals: no */ + param2UMX_PS__FDK(self, H11re, H12re, H21re, H22re, NULL, NULL, 0, ps, + 0); + } + break; + } + + for (pb = 0; pb < self->numParameterBands; pb++) { + self->M2Real__FDK[0][0][pb] = (H11re[pb]); + self->M2Real__FDK[0][1][pb] = (H12re[pb]); + + self->M2Real__FDK[1][0][pb] = (H21re[pb]); + self->M2Real__FDK[1][1][pb] = (H22re[pb]); + } + if (phaseCoding == 3) { + for (pb = 0; pb < self->numParameterBands; pb++) { + self->M2Imag__FDK[0][0][pb] = (H11im[pb]); + self->M2Imag__FDK[1][0][pb] = (H21im[pb]); + self->M2Imag__FDK[0][1][pb] = (FIXP_DBL)0; // H12im[pb]; + self->M2Imag__FDK[1][1][pb] = (FIXP_DBL)0; // H22im[pb]; + } + } + + if (self->phaseCoding == 1) { + SpatialDecSmoothOPD( + self, frame, + ps); /* INPUT: PhaseLeft, PhaseRight, (opdLeftState, opdRightState) */ + } + + return err; +} + +/******************************************************************************* + Functionname: param2UMX_PS_Core + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS_Core__FDK( + const SCHAR cld[MAX_PARAMETER_BANDS], const SCHAR icc[MAX_PARAMETER_BANDS], + const int numOttBands, const int resBands, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS]) { + int band; + + if ((c_l != NULL) && (c_r != NULL)) { + for (band = 0; band < numOttBands; band++) { + SpatialDequantGetCLDValues(cld[band], &c_l[band], &c_r[band]); + } + } + + band = 0; + FDK_ASSERT(resBands == 0); + for (; band < numOttBands; band++) { + /* compute mixing variables: */ + const int idx1 = cld[band]; + const int idx2 = icc[band]; + H11[band] = FX_CFG2FX_DBL(H11_nc[idx1][idx2]); + H21[band] = FX_CFG2FX_DBL(H11_nc[30 - idx1][idx2]); + H12[band] = FX_CFG2FX_DBL(H12_nc[idx1][idx2]); + H22[band] = FX_CFG2FX_DBL(-H12_nc[30 - idx1][idx2]); + } +} + +/******************************************************************************* + Functionname: param2UMX_PS + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS__FDK(spatialDec* self, + FIXP_DBL H11[MAX_PARAMETER_BANDS], + FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], + FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], + FIXP_DBL c_r[MAX_PARAMETER_BANDS], int ottBoxIndx, + int parameterSetIndx, int residualBands) { + int band; + param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx], + self->ottICC__FDK[ottBoxIndx][parameterSetIndx], + self->numOttBands[ottBoxIndx], residualBands, H11, H12, + H21, H22, c_l, c_r); + + for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands; + band++) { + H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f); + } +} + +#define N_CLD (31) +#define N_IPD (16) + +static const FIXP_DBL sinIpd_tab[N_IPD] = { + FIXP_DBL(0x00000000), FIXP_DBL(0x30fbc54e), FIXP_DBL(0x5a827999), + FIXP_DBL(0x7641af3d), FIXP_DBL(0x7fffffff), FIXP_DBL(0x7641af3d), + FIXP_DBL(0x5a82799a), FIXP_DBL(0x30fbc54d), FIXP_DBL(0xffffffff), + FIXP_DBL(0xcf043ab3), FIXP_DBL(0xa57d8666), FIXP_DBL(0x89be50c3), + FIXP_DBL(0x80000000), FIXP_DBL(0x89be50c3), FIXP_DBL(0xa57d8666), + FIXP_DBL(0xcf043ab2), +}; + +/* cosIpd[i] = sinIpd[(i+4)&15] */ +#define SIN_IPD(a) (sinIpd_tab[(a)]) +#define COS_IPD(a) (sinIpd_tab[((a) + 4) & 15]) //(cosIpd_tab[(a)]) + +static const FIXP_SGL sqrt_one_minus_ICC2[8] = { + FL2FXCONST_SGL(0.0f), + FL2FXCONST_SGL(0.349329357483736f), + FL2FXCONST_SGL(0.540755219669676f), + FL2FXCONST_SGL(0.799309172723546f), + FL2FXCONST_SGL(0.929968187843004f), + FX_DBL2FXCONST_SGL(MAXVAL_DBL), + FL2FXCONST_SGL(0.80813303360276f), + FL2FXCONST_SGL(0.141067359796659f), +}; + +/* exponent of sqrt(CLD) */ +static const SCHAR sqrt_CLD_e[N_CLD] = { + -24, -7, -6, -5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 0, 1, + 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 25}; + +static const FIXP_DBL sqrt_CLD_m[N_CLD] = { + FL2FXCONST_DBL(0.530542153566195f), + FL2FXCONST_DBL(0.719796896243647f), + FL2FXCONST_DBL(0.64f), + FL2FXCONST_DBL(0.569049411212455f), + FL2FXCONST_DBL(0.505964425626941f), + FL2FXCONST_DBL(0.899746120304559f), + FL2FXCONST_DBL(0.635462587779425f), + FL2FXCONST_DBL(0.897614763441571f), + FL2FXCONST_DBL(0.633957276984445f), + FL2FXCONST_DBL(0.895488455427336f), + FL2FXCONST_DBL(0.632455532033676f), + FL2FXCONST_DBL(0.796214341106995f), + FL2FXCONST_DBL(0.501187233627272f), + FL2FXCONST_DBL(0.630957344480193f), + FL2FXCONST_DBL(0.794328234724281f), + FL2FXCONST_DBL(0.5f), + FL2FXCONST_DBL(0.629462705897084f), + FL2FXCONST_DBL(0.792446596230557f), + FL2FXCONST_DBL(0.99763115748444f), + FL2FXCONST_DBL(0.627971607877395f), + FL2FXCONST_DBL(0.790569415042095f), + FL2FXCONST_DBL(0.558354490188704f), + FL2FXCONST_DBL(0.788696680600242f), + FL2FXCONST_DBL(0.557031836333591f), + FL2FXCONST_DBL(0.786828382371355f), + FL2FXCONST_DBL(0.555712315637163f), + FL2FXCONST_DBL(0.988211768802619f), + FL2FXCONST_DBL(0.87865832060992f), + FL2FXCONST_DBL(0.78125f), + FL2FXCONST_DBL(0.694640394546454f), + FL2FXCONST_DBL(0.942432183077448f), +}; + +static const FIXP_DBL CLD_m[N_CLD] = { + FL2FXCONST_DBL(0.281474976710656f), + FL2FXCONST_DBL(0.518107571841987f), + FL2FXCONST_DBL(0.4096f), + FL2FXCONST_DBL(0.323817232401242f), + FL2FXCONST_DBL(0.256f), + FL2FXCONST_DBL(0.809543081003105f), + FL2FXCONST_DBL(0.403812700467324f), + FL2FXCONST_DBL(0.805712263548267f), + FL2FXCONST_DBL(0.401901829041533f), + FL2FXCONST_DBL(0.801899573803636f), + FL2FXCONST_DBL(0.4f), + FL2FXCONST_DBL(0.633957276984445f), + FL2FXCONST_DBL(0.251188643150958f), + FL2FXCONST_DBL(0.398107170553497f), + FL2FXCONST_DBL(0.630957344480193f), + FL2FXCONST_DBL(0.25f), + FL2FXCONST_DBL(0.396223298115278f), + FL2FXCONST_DBL(0.627971607877395f), + FL2FXCONST_DBL(0.995267926383743f), + FL2FXCONST_DBL(0.394348340300121f), + FL2FXCONST_DBL(0.625f), + FL2FXCONST_DBL(0.311759736713887f), + FL2FXCONST_DBL(0.62204245398984f), + FL2FXCONST_DBL(0.310284466689172f), + FL2FXCONST_DBL(0.619098903305123f), + FL2FXCONST_DBL(0.308816177750818f), + FL2FXCONST_DBL(0.9765625f), + FL2FXCONST_DBL(0.772040444377046f), + FL2FXCONST_DBL(0.6103515625f), + FL2FXCONST_DBL(0.482525277735654f), + FL2FXCONST_DBL(0.888178419700125), +}; + +static FIXP_DBL dequantIPD_CLD_ICC_splitAngle__FDK_Function(INT ipdIdx, + INT cldIdx, + INT iccIdx) { + FIXP_DBL cld; + SpatialDequantGetCLD2Values(cldIdx, &cld); + + /*const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL; + const int one_e = 0;*/ + const FIXP_DBL one_m = FL2FXCONST_DBL(0.5f); + const int one_e = 1; + /* iidLin = sqrt(cld); */ + FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx]; + int iidLin_e = sqrt_CLD_e[cldIdx]; + /* iidLin2 = cld; */ + FIXP_DBL iidLin2_m = CLD_m[cldIdx]; + int iidLin2_e = sqrt_CLD_e[cldIdx] << 1; + /* iidLin21 = iidLin2 + 1.0f; */ + int iidLin21_e; + FIXP_DBL iidLin21_m = + fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e); + /* iidIcc2 = iidLin * icc * 2.0f; */ + FIXP_CFG icc = dequantICC__FDK[iccIdx]; + FIXP_DBL temp1_m, temp1c_m; + int temp1_e, temp1c_e; + temp1_m = fMult(iidLin_m, icc); + temp1_e = iidLin_e + 1; + + FIXP_DBL cosIpd, sinIpd; + cosIpd = COS_IPD(ipdIdx); + sinIpd = SIN_IPD(ipdIdx); + + temp1c_m = fMult(temp1_m, cosIpd); + temp1c_e = temp1_e; //+cosIpd_e; + + int temp2_e, temp3_e, inv_temp3_e, ratio_e; + FIXP_DBL temp2_m = + fAddNorm(iidLin21_m, iidLin21_e, temp1c_m, temp1c_e, &temp2_e); + FIXP_DBL temp3_m = + fAddNorm(iidLin21_m, iidLin21_e, temp1_m, temp1_e, &temp3_e); + /* calculate 1/temp3 needed later */ + inv_temp3_e = temp3_e; + FIXP_DBL inv_temp3_m = invFixp(temp3_m, &inv_temp3_e); + FIXP_DBL ratio_m = + fAddNorm(fMult(inv_temp3_m, temp2_m), (inv_temp3_e + temp2_e), + FL2FXCONST_DBL(1e-9f), 0, &ratio_e); + + int weight2_e, tempb_atan2_e; + FIXP_DBL weight2_m = + fPow(ratio_m, ratio_e, FL2FXCONST_DBL(0.5f), -1, &weight2_e); + /* atan2(w2*sinIpd, w1*iidLin + w2*cosIpd) = atan2(w2*sinIpd, (2 - w2)*iidLin + * + w2*cosIpd) = atan2(w2*sinIpd, 2*iidLin + w2*(cosIpd - iidLin)); */ + /* tmpa_atan2 = w2*sinIpd; tmpb_atan2 = 2*iidLin + w2*(cosIpd - iidLin); */ + FIXP_DBL tempb_atan2_m = iidLin_m; + tempb_atan2_e = iidLin_e + 1; + int add_tmp1_e = 0; + FIXP_DBL add_tmp1_m = fAddNorm(cosIpd, 0, -iidLin_m, iidLin_e, &add_tmp1_e); + FIXP_DBL add_tmp2_m = fMult(add_tmp1_m, weight2_m); + int add_tmp2_e = add_tmp1_e + weight2_e; + tempb_atan2_m = fAddNorm(tempb_atan2_m, tempb_atan2_e, add_tmp2_m, add_tmp2_e, + &tempb_atan2_e); + + FIXP_DBL tempa_atan2_m = fMult(weight2_m, sinIpd); + int tempa_atan2_e = weight2_e; // + sinIpd_e; + + if (tempa_atan2_e > tempb_atan2_e) { + tempb_atan2_m = (tempb_atan2_m >> (tempa_atan2_e - tempb_atan2_e)); + tempb_atan2_e = tempa_atan2_e; + } else if (tempb_atan2_e > tempa_atan2_e) { + tempa_atan2_m = (tempa_atan2_m >> (tempb_atan2_e - tempa_atan2_e)); + } + + return fixp_atan2(tempa_atan2_m, tempb_atan2_m); +} + +static void calculateOpd(spatialDec* self, INT ottBoxIndx, INT parameterSetIndx, + FIXP_DBL opd[MAX_PARAMETER_BANDS]) { + INT band; + + for (band = 0; band < self->numOttBandsIPD; band++) { + INT idxCld = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band]; + INT idxIpd = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band]; + INT idxIcc = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band]; + FIXP_DBL cld, ipd; + + ipd = FX_CFG2FX_DBL(dequantIPD__FDK[idxIpd]); + + SpatialDequantGetCLD2Values(idxCld, &cld); + + /* ipd(idxIpd==8) == PI */ + if ((cld == FL2FXCONST_DBL(0.0f)) && (idxIpd == 8)) { + opd[2 * band] = FL2FXCONST_DBL(0.0f); + } else { + opd[2 * band] = (dequantIPD_CLD_ICC_splitAngle__FDK_Function( + idxIpd, idxCld, idxIcc) >> + (IPD_SCALE - AT2O_SF)); + } + opd[2 * band + 1] = opd[2 * band] - ipd; + } +} + +/* wrap phase in rad to the range of 0 <= x < 2*pi */ +static FIXP_DBL wrapPhase(FIXP_DBL phase) { + while (phase < (FIXP_DBL)0) phase += PIx2__IPD; + while (phase >= PIx2__IPD) phase -= PIx2__IPD; + FDK_ASSERT((phase >= (FIXP_DBL)0) && (phase < PIx2__IPD)); + + return phase; +} + +/******************************************************************************* + Functionname: param2UMX_PS_IPD + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static void param2UMX_PS_IPD_OPD__FDK( + spatialDec* self, const SPATIAL_BS_FRAME* frame, + FIXP_DBL H11[MAX_PARAMETER_BANDS], FIXP_DBL H12[MAX_PARAMETER_BANDS], + FIXP_DBL H21[MAX_PARAMETER_BANDS], FIXP_DBL H22[MAX_PARAMETER_BANDS], + FIXP_DBL c_l[MAX_PARAMETER_BANDS], FIXP_DBL c_r[MAX_PARAMETER_BANDS], + int ottBoxIndx, int parameterSetIndx, int residualBands) { + INT band; + FIXP_DBL opd[2 * MAX_PARAMETER_BANDS]; + INT numOttBands = self->numOttBands[ottBoxIndx]; + INT numIpdBands; + + numIpdBands = frame->phaseMode ? self->numOttBandsIPD : 0; + + FDK_ASSERT(self->residualCoding == 0); + + param2UMX_PS_Core__FDK(self->ottCLD__FDK[ottBoxIndx][parameterSetIndx], + self->ottICC__FDK[ottBoxIndx][parameterSetIndx], + self->numOttBands[ottBoxIndx], residualBands, H11, H12, + H21, H22, c_l, c_r); + + for (band = self->numOttBands[ottBoxIndx]; band < self->numParameterBands; + band++) { + H11[band] = H21[band] = H12[band] = H22[band] = FL2FXCONST_DBL(0.f); + } + + if (frame->phaseMode) { + calculateOpd(self, ottBoxIndx, parameterSetIndx, opd); + + for (band = 0; band < numIpdBands; band++) { + self->PhaseLeft__FDK[band] = wrapPhase(opd[2 * band]); + self->PhaseRight__FDK[band] = wrapPhase(opd[2 * band + 1]); + } + } + + for (band = numIpdBands; band < numOttBands; band++) { + self->PhaseLeft__FDK[band] = FL2FXCONST_DBL(0.0f); + self->PhaseRight__FDK[band] = FL2FXCONST_DBL(0.0f); + } +} + +FDK_INLINE void param2UMX_Prediction_Core__FDK( + FIXP_DBL* H11re, FIXP_DBL* H11im, FIXP_DBL* H12re, FIXP_DBL* H12im, + FIXP_DBL* H21re, FIXP_DBL* H21im, FIXP_DBL* H22re, FIXP_DBL* H22im, + int cldIdx, int iccIdx, int ipdIdx, int band, int numOttBandsIPD, + int resBands) { +#define MAX_WEIGHT (1.2f) + FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */ + + if ((band < numOttBandsIPD) && (cldIdx == 15) && (iccIdx == 0) && + (ipdIdx == 8)) { + const FIXP_DBL gain = + FL2FXCONST_DBL(0.5f / MAX_WEIGHT) >> SCALE_PARAM_M2_212_PRED; + + *H11re = gain; + if (band < resBands) { + *H21re = gain; + *H12re = gain; + *H22re = -gain; + } else { + *H21re = -gain; + *H12re = (FIXP_DBL)0; + *H22re = (FIXP_DBL)0; + } + if ((H11im != NULL) && + (H21im != NULL) /*&& (H12im!=NULL) && (H22im!=NULL)*/) { + *H11im = (FIXP_DBL)0; + *H21im = (FIXP_DBL)0; + /* *H12im = (FIXP_DBL)0; */ + /* *H22im = (FIXP_DBL)0; */ + } + } else { + const FIXP_DBL one_m = (FIXP_DBL)MAXVAL_DBL; + const int one_e = 0; + /* iidLin = sqrt(cld); */ + FIXP_DBL iidLin_m = sqrt_CLD_m[cldIdx]; + int iidLin_e = sqrt_CLD_e[cldIdx]; + /* iidLin2 = cld; */ + FIXP_DBL iidLin2_m = CLD_m[cldIdx]; + int iidLin2_e = sqrt_CLD_e[cldIdx] << 1; + /* iidLin21 = iidLin2 + 1.0f; */ + int iidLin21_e; + FIXP_DBL iidLin21_m = + fAddNorm(iidLin2_m, iidLin2_e, one_m, one_e, &iidLin21_e); + /* iidIcc2 = iidLin * icc * 2.0f; */ + FIXP_CFG icc = dequantICC__FDK[iccIdx]; + int iidIcc2_e = iidLin_e + 1; + FIXP_DBL iidIcc2_m = fMult(iidLin_m, icc); + FIXP_DBL temp_m, sqrt_temp_m, inv_temp_m, weight_m; + int temp_e, sqrt_temp_e, inv_temp_e, weight_e, scale; + FIXP_DBL cosIpd, sinIpd; + + cosIpd = COS_IPD((band < numOttBandsIPD) ? ipdIdx : 0); + sinIpd = SIN_IPD((band < numOttBandsIPD) ? ipdIdx : 0); + + /* temp = iidLin21 + iidIcc2 * cosIpd; */ + temp_m = fAddNorm(iidLin21_m, iidLin21_e, fMult(iidIcc2_m, cosIpd), + iidIcc2_e, &temp_e); + + /* calculate 1/temp needed later */ + inv_temp_e = temp_e; + inv_temp_m = invFixp(temp_m, &inv_temp_e); + + /* 1/weight = sqrt(temp) * 1/sqrt(iidLin21) */ + if (temp_e & 1) { + sqrt_temp_m = temp_m >> 1; + sqrt_temp_e = (temp_e + 1) >> 1; + } else { + sqrt_temp_m = temp_m; + sqrt_temp_e = temp_e >> 1; + } + sqrt_temp_m = sqrtFixp(sqrt_temp_m); + if (iidLin21_e & 1) { + iidLin21_e += 1; + iidLin21_m >>= 1; + } + /* weight_[m,e] is actually 1/weight in the next few lines */ + weight_m = invSqrtNorm2(iidLin21_m, &weight_e); + weight_e -= iidLin21_e >> 1; + weight_m = fMult(sqrt_temp_m, weight_m); + weight_e += sqrt_temp_e; + scale = fNorm(weight_m); + weight_m = scaleValue(weight_m, scale); + weight_e -= scale; + /* weight = 0.5 * max(1/weight, 1/maxWeight) */ + if ((weight_e < 0) || + ((weight_e == 0) && (weight_m < FL2FXCONST_DBL(1.f / MAX_WEIGHT)))) { + weight_m = FL2FXCONST_DBL(1.f / MAX_WEIGHT); + weight_e = 0; + } + weight_e -= 1; + + { + FIXP_DBL alphaRe_m, alphaIm_m, accu_m; + int alphaRe_e, alphaIm_e, accu_e; + /* alphaRe = (1.0f - iidLin2) / temp; */ + alphaRe_m = fAddNorm(one_m, one_e, -iidLin2_m, iidLin2_e, &alphaRe_e); + alphaRe_m = fMult(alphaRe_m, inv_temp_m); + alphaRe_e += inv_temp_e; + + /* H11re = weight - alphaRe * weight; */ + /* H21re = weight + alphaRe * weight; */ + accu_m = fMult(alphaRe_m, weight_m); + accu_e = alphaRe_e + weight_e; + { + int accu2_e; + FIXP_DBL accu2_m; + accu2_m = fAddNorm(weight_m, weight_e, -accu_m, accu_e, &accu2_e); + *H11re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED); + accu2_m = fAddNorm(weight_m, weight_e, accu_m, accu_e, &accu2_e); + *H21re = scaleValue(accu2_m, accu2_e - SCALE_PARAM_M2_212_PRED); + } + + if ((H11im != NULL) && + (H21im != NULL) /*&& (H12im != NULL) && (H22im != NULL)*/) { + /* alphaIm = -iidIcc2 * sinIpd / temp; */ + alphaIm_m = fMult(-iidIcc2_m, sinIpd); + alphaIm_m = fMult(alphaIm_m, inv_temp_m); + alphaIm_e = iidIcc2_e + inv_temp_e; + /* H11im = -alphaIm * weight; */ + /* H21im = alphaIm * weight; */ + accu_m = fMult(alphaIm_m, weight_m); + accu_e = alphaIm_e + weight_e; + accu_m = scaleValue(accu_m, accu_e - SCALE_PARAM_M2_212_PRED); + *H11im = -accu_m; + *H21im = accu_m; + + /* *H12im = (FIXP_DBL)0; */ + /* *H22im = (FIXP_DBL)0; */ + } + } + if (band < resBands) { + FIXP_DBL weight = + scaleValue(weight_m, weight_e - SCALE_PARAM_M2_212_PRED); + *H12re = weight; + *H22re = -weight; + } else { + /* beta = 2.0f * iidLin * (float) sqrt(1.0f - icc * icc) * weight / temp; + */ + FIXP_DBL beta_m; + int beta_e; + beta_m = FX_SGL2FX_DBL(sqrt_one_minus_ICC2[iccIdx]); + beta_e = 1; /* multipication with 2.0f */ + beta_m = fMult(beta_m, weight_m); + beta_e += weight_e; + beta_m = fMult(beta_m, iidLin_m); + beta_e += iidLin_e; + beta_m = fMult(beta_m, inv_temp_m); + beta_e += inv_temp_e; + + beta_m = scaleValue(beta_m, beta_e - SCALE_PARAM_M2_212_PRED); + *H12re = beta_m; + *H22re = -beta_m; + } + } +} + +static void param2UMX_Prediction__FDK(spatialDec* self, FIXP_DBL* H11re, + FIXP_DBL* H11im, FIXP_DBL* H12re, + FIXP_DBL* H12im, FIXP_DBL* H21re, + FIXP_DBL* H21im, FIXP_DBL* H22re, + FIXP_DBL* H22im, int ottBoxIndx, + int parameterSetIndx, int resBands) { + int band; + FDK_ASSERT((H12im == NULL) && (H22im == NULL)); /* always == 0 */ + + for (band = 0; band < self->numParameterBands; band++) { + int cldIdx = self->ottCLD__FDK[ottBoxIndx][parameterSetIndx][band]; + int iccIdx = self->ottICC__FDK[ottBoxIndx][parameterSetIndx][band]; + int ipdIdx = self->ottIPD__FDK[ottBoxIndx][parameterSetIndx][band]; + + param2UMX_Prediction_Core__FDK( + &H11re[band], (H11im ? &H11im[band] : NULL), &H12re[band], NULL, + &H21re[band], (H21im ? &H21im[band] : NULL), &H22re[band], NULL, cldIdx, + iccIdx, ipdIdx, band, self->numOttBandsIPD, resBands); + } +} + +/******************************************************************************* + Functionname: initM1andM2 + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag, + int configChanged) { + SACDEC_ERROR err = MPS_OK; + + self->bOverwriteM1M2prev = (configChanged && !initStatesFlag) ? 1 : 0; + + { self->numM2rows = self->numOutputChannels; } + + if (initStatesFlag) { + int i, j, k; + + for (i = 0; i < self->numM2rows; i++) { + for (j = 0; j < self->numVChannels; j++) { + for (k = 0; k < MAX_PARAMETER_BANDS; k++) { + self->M2Real__FDK[i][j][k] = FL2FXCONST_DBL(0); + self->M2RealPrev__FDK[i][j][k] = FL2FXCONST_DBL(0); + } + } + } + } + + return err; +} diff --git a/fdk-aac/libSACdec/src/sac_calcM1andM2.h b/fdk-aac/libSACdec/src/sac_calcM1andM2.h new file mode 100644 index 0000000..996238d --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_calcM1andM2.h @@ -0,0 +1,129 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec M1 and M2 calculation + +*******************************************************************************/ + +/* sa_calcM1andM2.h */ + +#ifndef SAC_CALCM1ANDM2_H +#define SAC_CALCM1ANDM2_H + +#include "sac_dec.h" + +#define SCALE_PARAM_M1 3 + +/* Scaling of M2 matrix, but only for binaural upmix type. */ +#define SCALE_PARAM_CALC_M2 (3) +#define SCALE_PARAM_M2_515X (3) +#define SCALE_PARAM_M2_525 (SCALE_PARAM_M1 + HRG_SF + 1 - SCALE_PARAM_CALC_M2) +#define SCALE_PARAM_M2_212_PRED (3) +/* Scaling of spectral data after applying M2 matrix, but only for binaural + upmix type Scaling is compensated later in synthesis qmf filterbank */ +#define SCALE_DATA_APPLY_M2 (1) + +SACDEC_ERROR initM1andM2(spatialDec* self, int initStatesFlag, + int configChanged); + +int SpatialDecGetResidualIndex(spatialDec* self, int row); + +SACDEC_ERROR SpatialDecCalculateM1andM2(spatialDec* self, int ps, + const SPATIAL_BS_FRAME* frame); + +#endif /* SAC_CALCM1ANDM2_H */ diff --git a/fdk-aac/libSACdec/src/sac_dec.cpp b/fdk-aac/libSACdec/src/sac_dec.cpp new file mode 100644 index 0000000..4537d6e --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec.cpp @@ -0,0 +1,1509 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library + +*******************************************************************************/ + +#include "sac_dec_errorcodes.h" +#include "sac_dec.h" + +#include "sac_process.h" +#include "sac_bitdec.h" +#include "sac_smoothing.h" +#include "sac_calcM1andM2.h" +#include "sac_reshapeBBEnv.h" +#include "sac_stp.h" +#include "sac_rom.h" + +#include "FDK_decorrelate.h" + +#include "FDK_trigFcts.h" +#include "FDK_matrixCalloc.h" + +/* static int pbStrideTable[] = {1, 2, 5, 28}; see sac_rom.cpp */ + +enum { + APPLY_M2_NONE = 0, /* init value */ + APPLY_M2 = 1, /* apply m2 fallback implementation */ + APPLY_M2_MODE212 = 2, /* apply m2 for 212 mode */ + APPLY_M2_MODE212_Res_PhaseCoding = + 3 /* apply m2 for 212 mode with residuals and phase coding */ +}; + +/******************************************************************************************/ +/* function: FDK_SpatialDecInitDefaultSpatialSpecificConfig */ +/* output: struct of type SPATIAL_SPECIFIC_CONFIG */ +/* input: core coder audio object type */ +/* input: nr of core channels */ +/* input: sampling rate */ +/* input: nr of time slots */ +/* input: decoder level */ +/* input: flag indicating upmix type blind */ +/* */ +/* returns: error code */ +/******************************************************************************************/ +int FDK_SpatialDecInitDefaultSpatialSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq, + int nTimeSlots, int decoderLevel, int isBlind) { + return SpatialDecDefaultSpecificConfig(pSpatialSpecificConfig, coreCodec, + samplingFreq, nTimeSlots, decoderLevel, + isBlind, coreChannels); +} + +/******************************************************************************************/ +/* function: FDK_SpatialDecCompareSpatialSpecificConfigHeader */ +/* input: 2 pointers to a ssc */ +/* */ +/* output: - */ +/* returns: error code (0 = equal, <>0 unequal) */ +/******************************************************************************************/ +int FDK_SpatialDecCompareSpatialSpecificConfigHeader( + SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2) { + int result = MPS_OK; + + /* we assume: every bit must be equal */ + if (FDKmemcmp(pSsc1, pSsc2, sizeof(SPATIAL_SPECIFIC_CONFIG)) != 0) { + result = MPS_UNEQUAL_SSC; + } + return result; +} + +/******************************************************************************* + Functionname: SpatialDecClearFrameData + ******************************************************************************* + + Description: Clear/Fake frame data to avoid misconfiguration and allow proper + error concealment. + Arguments: + Input: self (frame data) + Output: No return value. + +*******************************************************************************/ +static void SpatialDecClearFrameData( + spatialDec *self, /* Shall be removed */ + SPATIAL_BS_FRAME *bsFrame, const SACDEC_CREATION_PARAMS *const setup) { + int i; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(bsFrame != NULL); + FDK_ASSERT(setup != NULL); + + /* do not apply shaping tools (GES or STP) */ + for (i = 0; i < setup->maxNumOutputChannels; + i += 1) { /* MAX_OUTPUT_CHANNELS */ + bsFrame->tempShapeEnableChannelSTP[i] = 0; + bsFrame->tempShapeEnableChannelGES[i] = 0; + } + + bsFrame->TsdData->bsTsdEnable = 0; + + /* use only 1 parameter set at the end of the frame */ + bsFrame->numParameterSets = 1; + bsFrame->paramSlot[0] = self->timeSlots - 1; + + /* parameter smoothing tool set to off */ + bsFrame->bsSmoothMode[0] = 0; + + /* reset residual data */ + { + int resQmfBands, resTimeSlots = (1); + + resQmfBands = setup->maxNumQmfBands; + + for (i = 0; i < setup->bProcResidual + ? fMin(setup->maxNumResChannels, + setup->maxNumOttBoxes + setup->maxNumInputChannels) + : 0; + i += 1) { + for (int j = 0; j < resTimeSlots; j += 1) { + for (int k = 0; k < resQmfBands; k += 1) { + self->qmfResidualReal__FDK[i][j][k] = FL2FXCONST_DBL(0.0f); + self->qmfResidualImag__FDK[i][j][k] = FL2FXCONST_DBL(0.0f); + } + } + } + } + + return; +} + +/******************************************************************************* + Functionname: FDK_SpatialDecOpen + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config, + int stereoConfigIndex) { + int i; + int lfSize, hfSize; + spatialDec *self = NULL; + SACDEC_CREATION_PARAMS setup; + + switch (config->decoderLevel) { + case DECODER_LEVEL_0: /* 212 maxNumOutputChannels== 2 */ + setup.maxNumInputChannels = 1; + setup.maxNumOutputChannels = 2; + setup.maxNumQmfBands = 64; + setup.maxNumXChannels = 2; + setup.maxNumVChannels = 2; + setup.maxNumDecorChannels = 1; + setup.bProcResidual = 1; + setup.maxNumResidualChannels = 0; + setup.maxNumOttBoxes = 1; + setup.maxNumParams = setup.maxNumInputChannels + setup.maxNumOttBoxes; + break; + default: + return NULL; + } + + setup.maxNumResChannels = 1; + + { + switch (config->maxNumOutputChannels) { + case OUTPUT_CHANNELS_2_0: + setup.maxNumOutputChannels = fMin(setup.maxNumOutputChannels, 2); + break; + case OUTPUT_CHANNELS_DEFAULT: + default: + break; + } + } + + setup.maxNumHybridBands = SacGetHybridSubbands(setup.maxNumQmfBands); + + switch (config->decoderMode) { + case EXT_HQ_ONLY: + setup.maxNumCmplxQmfBands = setup.maxNumQmfBands; + setup.maxNumCmplxHybBands = setup.maxNumHybridBands; + break; + default: + setup.maxNumCmplxQmfBands = fixMax(PC_NUM_BANDS, setup.maxNumQmfBands); + setup.maxNumCmplxHybBands = + fixMax(PC_NUM_HYB_BANDS, setup.maxNumHybridBands); + break; + } /* switch config->decoderMode */ + + FDK_ALLOCATE_MEMORY_1D_INT(self, 1, spatialDec, SECT_DATA_L2) + + self->createParams = setup; + + FDK_ALLOCATE_MEMORY_1D(self->param2hyb, MAX_PARAMETER_BANDS + 1, int) + + FDK_ALLOCATE_MEMORY_1D(self->numOttBands, setup.maxNumOttBoxes, int) + + /* allocate arrays */ + + FDK_ALLOCATE_MEMORY_1D(self->smgTime, MAX_PARAMETER_SETS, int) + FDK_ALLOCATE_MEMORY_2D(self->smgData, MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, + UCHAR) + + FDK_ALLOCATE_MEMORY_3D(self->ottCLD__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottICC__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottIPD__FDK, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + + /* Last parameters from prev frame */ + FDK_ALLOCATE_MEMORY_2D(self->ottCLDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->ottICCidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->ottICCdiffidx, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->ottIPDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->arbdmxGainIdxPrev, setup.maxNumInputChannels, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->cmpOttCLDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_2D(self->cmpOttICCidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_3D(self->outIdxData, setup.maxNumOttBoxes, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_3D(self->arbdmxGain__FDK, setup.maxNumInputChannels, + MAX_PARAMETER_SETS, MAX_PARAMETER_BANDS, SCHAR) + FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlpha__FDK, setup.maxNumInputChannels, + FIXP_DBL) + FDK_ALLOCATE_MEMORY_1D(self->arbdmxAlphaPrev__FDK, setup.maxNumInputChannels, + FIXP_DBL) + FDK_ALLOCATE_MEMORY_2D(self->cmpArbdmxGainIdxPrev, setup.maxNumInputChannels, + MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_2D(self->cmpOttIPDidxPrev, setup.maxNumOttBoxes, + MAX_PARAMETER_BANDS, SCHAR) + + FDK_ALLOCATE_MEMORY_3D_INT(self->M2Real__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_3D(self->M2Imag__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL) + + FDK_ALLOCATE_MEMORY_3D_INT(self->M2RealPrev__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_3D(self->M2ImagPrev__FDK, setup.maxNumOutputChannels, + setup.maxNumVChannels, MAX_PARAMETER_BANDS, FIXP_DBL) + + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED( + self->qmfInputReal__FDK, setup.maxNumInputChannels, setup.maxNumQmfBands, + FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED( + self->qmfInputImag__FDK, setup.maxNumInputChannels, + setup.maxNumCmplxQmfBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputReal__FDK, setup.maxNumInputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybInputImag__FDK, setup.maxNumInputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + if (setup.bProcResidual) { + FDK_ALLOCATE_MEMORY_1D(self->qmfResidualReal__FDK, setup.maxNumResChannels, + FIXP_DBL **) + FDK_ALLOCATE_MEMORY_1D(self->qmfResidualImag__FDK, setup.maxNumResChannels, + FIXP_DBL **) + + FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK, setup.maxNumResChannels, + FIXP_DBL *) + FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK, setup.maxNumResChannels, + FIXP_DBL *) + + for (i = 0; i < setup.maxNumResChannels; i++) { + int resQmfBands = (config->decoderMode == EXT_LP_ONLY) + ? PC_NUM_BANDS + : setup.maxNumQmfBands; + int resHybBands = (config->decoderMode == EXT_LP_ONLY) + ? PC_NUM_HYB_BANDS + : setup.maxNumHybridBands; + /* Alignment is needed for USAC residuals because QMF analysis directly + * writes to this buffer. */ + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualReal__FDK[i], (1), + resQmfBands, FIXP_DBL, SECT_DATA_L1) + FDK_ALLOCATE_MEMORY_2D_INT_ALIGNED(self->qmfResidualImag__FDK[i], (1), + resQmfBands, FIXP_DBL, SECT_DATA_L1) + + FDK_ALLOCATE_MEMORY_1D(self->hybResidualReal__FDK[i], + setup.maxNumHybridBands, FIXP_DBL) + FDK_ALLOCATE_MEMORY_1D(self->hybResidualImag__FDK[i], resHybBands, + FIXP_DBL) + } + } /* if (setup.bProcResidual) */ + + FDK_ALLOCATE_MEMORY_2D_INT(self->wReal__FDK, setup.maxNumVChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->wImag__FDK, setup.maxNumVChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealDry__FDK, + setup.maxNumOutputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagDry__FDK, + setup.maxNumOutputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputRealWet__FDK, + setup.maxNumOutputChannels, + setup.maxNumHybridBands, FIXP_DBL, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D_INT(self->hybOutputImagWet__FDK, + setup.maxNumOutputChannels, + setup.maxNumCmplxHybBands, FIXP_DBL, SECT_DATA_L2) + + FDK_ALLOCATE_MEMORY_1D(self->hybridSynthesis, setup.maxNumOutputChannels, + FDK_SYN_HYB_FILTER) + + FDK_ALLOCATE_MEMORY_1D( + self->hybridAnalysis, + setup.bProcResidual ? setup.maxNumInputChannels + setup.maxNumResChannels + : setup.maxNumInputChannels, + FDK_ANA_HYB_FILTER) + + lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID; + { + hfSize = + BUFFER_LEN_HF * ((setup.maxNumQmfBands - MAX_QMF_BANDS_TO_HYBRID) + + (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID)); + } + + FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFdmx, + setup.maxNumInputChannels, lfSize, FIXP_DBL, + SECT_DATA_L2) { + FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFdmx, + setup.maxNumInputChannels, hfSize, FIXP_DBL) + } + + for (i = 0; i < setup.maxNumInputChannels; i++) { + FIXP_DBL *pHybridAnaStatesHFdmx; + + pHybridAnaStatesHFdmx = self->pHybridAnaStatesHFdmx[i]; + + FDKhybridAnalysisOpen(&self->hybridAnalysis[i], + self->pHybridAnaStatesLFdmx[i], + lfSize * sizeof(FIXP_DBL), pHybridAnaStatesHFdmx, + hfSize * sizeof(FIXP_DBL)); + } + if (setup.bProcResidual) { + lfSize = 2 * BUFFER_LEN_LF * MAX_QMF_BANDS_TO_HYBRID; + hfSize = BUFFER_LEN_HF * + ((((config->decoderMode == EXT_LP_ONLY) ? PC_NUM_BANDS + : setup.maxNumQmfBands) - + MAX_QMF_BANDS_TO_HYBRID) + + (setup.maxNumCmplxQmfBands - MAX_QMF_BANDS_TO_HYBRID)); + + FDK_ALLOCATE_MEMORY_2D_INT(self->pHybridAnaStatesLFres, + setup.maxNumResChannels, lfSize, FIXP_DBL, + SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_2D(self->pHybridAnaStatesHFres, setup.maxNumResChannels, + hfSize, FIXP_DBL) + + for (i = setup.maxNumInputChannels; + i < (setup.maxNumInputChannels + setup.maxNumResChannels); i++) { + FDKhybridAnalysisOpen( + &self->hybridAnalysis[i], + self->pHybridAnaStatesLFres[i - setup.maxNumInputChannels], + lfSize * sizeof(FIXP_DBL), + self->pHybridAnaStatesHFres[i - setup.maxNumInputChannels], + hfSize * sizeof(FIXP_DBL)); + } + } + + FDK_ALLOCATE_MEMORY_1D(self->smoothState, 1, SMOOTHING_STATE) + FDK_ALLOCATE_MEMORY_1D(self->reshapeBBEnvState, 1, RESHAPE_BBENV_STATE) + + FDK_ALLOCATE_MEMORY_1D(self->apDecor, setup.maxNumDecorChannels, DECORR_DEC) + FDK_ALLOCATE_MEMORY_2D_INT(self->pDecorBufferCplx, setup.maxNumDecorChannels, + (2 * ((825) + (373))), FIXP_DBL, SECT_DATA_L2) + + for (i = 0; i < setup.maxNumDecorChannels; i++) { + if (FDKdecorrelateOpen(&self->apDecor[i], self->pDecorBufferCplx[i], + (2 * ((825) + (373))))) { + goto bail; + } + } + + if (subbandTPCreate(&self->hStpDec) != MPS_OK) { + goto bail; + } + + /* save general decoder configuration */ + self->decoderLevel = config->decoderLevel; + self->decoderMode = config->decoderMode; + self->binauralMode = config->binauralMode; + + /* preinitialize configuration */ + self->partiallyComplex = (config->decoderMode != EXT_HQ_ONLY) ? 1 : 0; + + /* Set to default state */ + SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_ALL); + + /* Everything is fine so return the handle */ + return self; + +bail: + /* Collector for all errors. + Deallocate all memory and return a invalid handle. */ + FDK_SpatialDecClose(self); + + return NULL; +} + +/******************************************************************************* + Functionname: isValidConfig + ******************************************************************************* + + Description: Validate if configuration is supported in present instance + + Arguments: + + Return: 1: all okay + 0: configuration not supported +*******************************************************************************/ +static int isValidConfig(spatialDec const *const self, + const SPATIAL_DEC_UPMIX_TYPE upmixType, + SPATIALDEC_PARAM const *const pUserParams, + const AUDIO_OBJECT_TYPE coreAot) { + UPMIXTYPE nUpmixType; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(pUserParams != NULL); + + nUpmixType = (UPMIXTYPE)upmixType; + + switch (nUpmixType) { + case UPMIXTYPE_BYPASS: /* UPMIX_TYPE_BYPASS */ + break; + case UPMIXTYPE_NORMAL: /* UPMIX_TYPE_NORMAL */ + break; + default: + return 0; /* unsupported upmixType */ + } + + return 1; /* upmixType supported */ +} + +static SACDEC_ERROR CheckLevelTreeUpmixType( + const SACDEC_CREATION_PARAMS *const pCreateParams, + const SPATIAL_SPECIFIC_CONFIG *const pSsc, const int decoderLevel, + const UPMIXTYPE upmixType) { + SACDEC_ERROR err = MPS_OK; + int nOutputChannels, treeConfig; + + FDK_ASSERT(pCreateParams != NULL); + FDK_ASSERT(pSsc != NULL); + + treeConfig = pSsc->treeConfig; + + switch (decoderLevel) { + case 0: { + if (treeConfig != SPATIALDEC_MODE_RSVD7) { + err = MPS_INVALID_TREECONFIG; + goto bail; + } + break; + } + default: + err = MPS_INVALID_PARAMETER /* MPS_UNIMPLEMENTED */; + goto bail; + } + + switch (upmixType) { + case UPMIXTYPE_BYPASS: + nOutputChannels = pSsc->nInputChannels; + break; + default: + nOutputChannels = pSsc->nOutputChannels; + break; + } + + /* Is sufficient memory allocated. */ + if ((pSsc->nInputChannels > pCreateParams->maxNumInputChannels) || + (nOutputChannels > pCreateParams->maxNumOutputChannels) || + (pSsc->nOttBoxes > pCreateParams->maxNumOttBoxes)) { + err = MPS_INVALID_PARAMETER; + } + +bail: + return err; +} + +void SpatialDecInitParserContext(spatialDec *self) { + int i, j; + + for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) { + for (j = 0; j < MAX_PARAMETER_BANDS; j++) { + self->ottCLDidxPrev[i][j] = 0; + self->ottICCidxPrev[i][j] = 0; + self->cmpOttCLDidxPrev[i][j] = 0; + self->cmpOttICCidxPrev[i][j] = 0; + } + } + for (i = 0; i < self->createParams.maxNumInputChannels; i++) { + for (j = 0; j < MAX_PARAMETER_BANDS; j++) { + self->arbdmxGainIdxPrev[i][j] = 0; + self->cmpArbdmxGainIdxPrev[i][j] = 0; + } + } +} + +/******************************************************************************* + Functionname: FDK_SpatialDecInit + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + int nQmfBands, + SPATIAL_DEC_UPMIX_TYPE const upmixType, + SPATIALDEC_PARAM *pUserParams, UINT initFlags) { + SACDEC_ERROR err = MPS_OK; + int nCh, i, j, k; + int maxQmfBands; + int bypassMode = 0; + + self->useFDreverb = 0; + + /* check configuration parameter */ + if (!isValidConfig(self, upmixType, pUserParams, + pSpatialSpecificConfig->coreCodec)) { + return MPS_INVALID_PARAMETER; + } + + /* check tree configuration */ + err = CheckLevelTreeUpmixType(&self->createParams, pSpatialSpecificConfig, + self->decoderLevel, (UPMIXTYPE)upmixType); + if (err != MPS_OK) { + goto bail; + } + + /* Store and update instance after all checks passed successfully: */ + self->upmixType = (UPMIXTYPE)upmixType; + + if (initFlags & MPEGS_INIT_PARAMS_ERROR_CONCEALMENT) { /* At least one error + concealment + parameter changed */ + err = SpatialDecConcealment_SetParam( + &self->concealInfo, SAC_DEC_CONCEAL_METHOD, pUserParams->concealMethod); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_NUM_KEEP_FRAMES, + pUserParams->concealNumKeepFrames); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam( + &self->concealInfo, SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH, + pUserParams->concealFadeOutSlopeLength); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH, + pUserParams->concealFadeInSlopeLength); + if (err != MPS_OK) { + goto bail; + } + err = SpatialDecConcealment_SetParam(&self->concealInfo, + SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES, + pUserParams->concealNumReleaseFrames); + if (err != MPS_OK) { + goto bail; + } + } + + if (initFlags & + MPEGS_INIT_STATES_ERROR_CONCEALMENT) { /* Set to default state */ + SpatialDecConcealment_Init(&self->concealInfo, MPEGS_CONCEAL_RESET_STATE); + } + + /* determine bypass mode */ + bypassMode |= pUserParams->bypassMode; + bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0); + + /* static decoder scale depends on number of qmf bands */ + switch (nQmfBands) { + case 16: + case 24: + case 32: + self->staticDecScale = 21; + break; + case 64: + self->staticDecScale = 22; + break; + default: + return MPS_INVALID_PARAMETER; + } + + self->numParameterSetsPrev = 1; + + self->qmfBands = nQmfBands; + /* self->hybridBands will be updated in SpatialDecDecodeHeader() below. */ + + self->bShareDelayWithSBR = 0; + + err = SpatialDecDecodeHeader(self, pSpatialSpecificConfig); + if (err != MPS_OK) { + goto bail; + } + + self->stereoConfigIndex = pSpatialSpecificConfig->stereoConfigIndex; + + if (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) { + self->qmfInputDelayBufPos = 0; + self->pc_filterdelay = 1; /* Division by 0 not possible */ + } + + maxQmfBands = self->qmfBands; + + /* init residual decoder */ + + /* init tonality smoothing */ + if (initFlags & MPEGS_INIT_STATES_PARAM) { + initParameterSmoothing(self); + } + + /* init GES */ + initBBEnv(self, (initFlags & MPEGS_INIT_STATES_GES) ? 1 : 0); + + /* Clip protection is applied only for normal processing. */ + if (!isTwoChMode(self->upmixType) && !bypassMode) { + self->staticDecScale += self->clipProtectGainSF__FDK; + } + + { + UINT flags = 0; + INT initStatesFlag = (initFlags & MPEGS_INIT_STATES_ANA_QMF_FILTER) ? 1 : 0; + INT useLdFilter = + (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) ? 1 : 0; + + flags = self->pQmfDomain->globalConf.flags_requested; + flags &= (~(UINT)QMF_FLAG_LP); + + if (initStatesFlag) + flags &= ~QMF_FLAG_KEEP_STATES; + else + flags |= QMF_FLAG_KEEP_STATES; + + if (useLdFilter) + flags |= QMF_FLAG_MPSLDFB; + else + flags &= ~QMF_FLAG_MPSLDFB; + + self->pQmfDomain->globalConf.flags_requested = flags; + FDK_QmfDomain_Configure(self->pQmfDomain); + + /* output scaling */ + for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { + int outputScale = 0, outputGain_e = 0, scale = 0; + FIXP_DBL outputGain_m = getChGain(self, nCh, &outputGain_e); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + outputScale += + self->clipProtectGainSF__FDK; /* consider clip protection scaling at + synthesis qmf */ + } + + scale = outputScale; + + qmfChangeOutScalefactor(&self->pQmfDomain->QmfDomainOut[nCh].fb, scale); + qmfChangeOutGain(&self->pQmfDomain->QmfDomainOut[nCh].fb, outputGain_m, + outputGain_e); + } + } + + for (nCh = 0; nCh < self->numOutputChannelsAT; nCh++) { + FDKhybridSynthesisInit(&self->hybridSynthesis[nCh], THREE_TO_TEN, + self->qmfBands, maxQmfBands); + } + + /* for input, residual channels and arbitrary down-mix residual channels */ + for (nCh = 0; nCh < self->createParams.maxNumInputChannels; nCh++) { + FDKhybridAnalysisInit( + &self->hybridAnalysis[nCh], THREE_TO_TEN, self->qmfBands, maxQmfBands, + (initFlags & MPEGS_INIT_STATES_ANA_HYB_FILTER) ? 1 : 0); + } + for (; nCh < (self->createParams.bProcResidual + ? (self->createParams.maxNumInputChannels + + self->createParams.maxNumResChannels) + : self->createParams.maxNumInputChannels); + nCh++) { + FDKhybridAnalysisInit(&self->hybridAnalysis[nCh], THREE_TO_TEN, maxQmfBands, + maxQmfBands, 0); + } + + { + for (k = 0; k < self->numDecorSignals; k++) { + int errCode, idec; + FDK_DECORR_TYPE decorrType = DECORR_PS; + decorrType = DECORR_LD; + if (self->pConfigCurrent->syntaxFlags & + (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) { + decorrType = + ((self->treeConfig == TREE_212) && (self->decorrType == DECORR_PS)) + ? DECORR_PS + : DECORR_USAC; + } + { + idec = k; + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + if (self->treeConfig == TREE_212 && k == 0) { + idec = 2; + } + } + } + errCode = FDKdecorrelateInit( + &self->apDecor[k], self->hybridBands, decorrType, DUCKER_AUTOMATIC, + self->decorrConfig, idec, 0, /* self->partiallyComplex */ + 0, 0, /* isLegacyPS */ + (initFlags & MPEGS_INIT_STATES_DECORRELATOR) ? 1 : 0); + if (errCode) return MPS_NOTOK; + } + } /* !self->partiallyComplex */ + + err = initM1andM2(self, (initFlags & MPEGS_INIT_STATES_M1M2) ? 1 : 0, + (initFlags & MPEGS_INIT_CONFIG) ? 1 : 0); + if (err != MPS_OK) return err; + + /* Initialization of previous frame data */ + if (initFlags & MPEGS_INIT_STATES_PARAM) { + for (i = 0; i < self->createParams.maxNumOttBoxes; i += 1) { + /* reset icc diff data */ + for (k = 0; k < MAX_PARAMETER_SETS; k += 1) { + for (j = 0; j < MAX_PARAMETER_BANDS; j += 1) { + self->ottICCdiffidx[i][k][j] = 0; + } + } + } + /* Parameter Smoothing */ + /* robustness: init with one of the values of smgTimeTable[] = {64, 128, + 256, 512} to avoid division by zero in calcFilterCoeff__FDK() */ + self->smoothState->prevSmgTime = smgTimeTable[2]; /* == 256 */ + FDKmemclear(self->smoothState->prevSmgData, + MAX_PARAMETER_BANDS * sizeof(UCHAR)); + FDKmemclear(self->smoothState->opdLeftState__FDK, + MAX_PARAMETER_BANDS * sizeof(FIXP_DBL)); + FDKmemclear(self->smoothState->opdRightState__FDK, + MAX_PARAMETER_BANDS * sizeof(FIXP_DBL)); + } + + self->prevTimeSlot = -1; + self->curTimeSlot = + MAX_TIME_SLOTS + 1; /* Initialize with a invalid value to trigger + concealment if first frame has no valid data. */ + self->curPs = 0; + + subbandTPInit(self->hStpDec); + +bail: + return err; +} + +void SpatialDecChannelProperties(spatialDec *self, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr) { + if ((self == NULL) || (channelType == NULL) || (channelIndices == NULL) || + (mapDescr == NULL)) { + return; /* no extern buffer to be filled */ + } + + if (self->numOutputChannelsAT != + treePropertyTable[self->treeConfig].numOutputChannels) { + int ch; + /* Declare all channels to be front channels: */ + for (ch = 0; ch < self->numOutputChannelsAT; ch += 1) { + channelType[ch] = ACT_FRONT; + channelIndices[ch] = ch; + } + } else { + /* ISO/IEC FDIS 23003-1:2006(E), page 46, Table 40 bsTreeConfig */ + switch (self->treeConfig) { + case TREE_212: + channelType[0] = ACT_FRONT; + channelIndices[0] = 0; + channelType[1] = ACT_FRONT; + channelIndices[1] = 1; + break; + default:; + } + } +} + +/******************************************************************************* + Functionname: FDK_SpatialDecClose + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ + +void FDK_SpatialDecClose(spatialDec *self) { + if (self) { + int k; + + if (self->apDecor != NULL) { + for (k = 0; k < self->createParams.maxNumDecorChannels; k++) { + FDKdecorrelateClose(&(self->apDecor[k])); + } + FDK_FREE_MEMORY_1D(self->apDecor); + } + if (self->pDecorBufferCplx != NULL) { + FDK_FREE_MEMORY_2D(self->pDecorBufferCplx); + } + + subbandTPDestroy(&self->hStpDec); + + FDK_FREE_MEMORY_1D(self->reshapeBBEnvState); + FDK_FREE_MEMORY_1D(self->smoothState); + + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFdmx); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFdmx); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesLFres); + FDK_FREE_MEMORY_2D(self->pHybridAnaStatesHFres); + FDK_FREE_MEMORY_1D(self->hybridAnalysis); + + FDK_FREE_MEMORY_1D(self->hybridSynthesis); + + /* The time buffer is passed to the decoder from outside to avoid copying + * (zero copy). */ + /* FDK_FREE_MEMORY_2D(self->timeOut__FDK); */ + + FDK_FREE_MEMORY_2D(self->hybOutputImagWet__FDK); + FDK_FREE_MEMORY_2D(self->hybOutputRealWet__FDK); + + FDK_FREE_MEMORY_2D(self->hybOutputImagDry__FDK); + FDK_FREE_MEMORY_2D(self->hybOutputRealDry__FDK); + + FDK_FREE_MEMORY_2D(self->wImag__FDK); + FDK_FREE_MEMORY_2D(self->wReal__FDK); + + if (self->createParams.bProcResidual) { + int i; + + for (i = 0; i < self->createParams.maxNumResChannels; i++) { + if (self->hybResidualImag__FDK != NULL) + FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK[i]); + if (self->hybResidualReal__FDK != NULL) + FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK[i]); + if (self->qmfResidualImag__FDK != NULL) + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualImag__FDK[i]); + if (self->qmfResidualReal__FDK != NULL) + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfResidualReal__FDK[i]); + } + + FDK_FREE_MEMORY_1D(self->hybResidualImag__FDK); + FDK_FREE_MEMORY_1D(self->hybResidualReal__FDK); + + FDK_FREE_MEMORY_1D(self->qmfResidualImag__FDK); + FDK_FREE_MEMORY_1D(self->qmfResidualReal__FDK); + + } /* self->createParams.bProcResidual */ + + FDK_FREE_MEMORY_2D(self->hybInputImag__FDK); + FDK_FREE_MEMORY_2D(self->hybInputReal__FDK); + + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputImag__FDK); + FDK_FREE_MEMORY_2D_ALIGNED(self->qmfInputReal__FDK); + + FDK_FREE_MEMORY_3D(self->M2ImagPrev__FDK); + + FDK_FREE_MEMORY_3D(self->M2RealPrev__FDK); + + FDK_FREE_MEMORY_3D(self->M2Imag__FDK); + + FDK_FREE_MEMORY_3D(self->M2Real__FDK); + + FDK_FREE_MEMORY_1D(self->arbdmxAlphaPrev__FDK); + FDK_FREE_MEMORY_1D(self->arbdmxAlpha__FDK); + + FDK_FREE_MEMORY_3D(self->arbdmxGain__FDK); + + FDK_FREE_MEMORY_3D(self->ottIPD__FDK); + FDK_FREE_MEMORY_3D(self->ottICC__FDK); + FDK_FREE_MEMORY_3D(self->ottCLD__FDK); + + /* Last parameters from prev frame */ + FDK_FREE_MEMORY_2D(self->ottCLDidxPrev); + FDK_FREE_MEMORY_2D(self->ottICCidxPrev); + FDK_FREE_MEMORY_3D(self->ottICCdiffidx); + FDK_FREE_MEMORY_2D(self->ottIPDidxPrev); + FDK_FREE_MEMORY_2D(self->arbdmxGainIdxPrev); + + FDK_FREE_MEMORY_2D(self->cmpOttCLDidxPrev); + FDK_FREE_MEMORY_2D(self->cmpOttICCidxPrev); + FDK_FREE_MEMORY_3D(self->outIdxData); + FDK_FREE_MEMORY_2D(self->cmpOttIPDidxPrev); + FDK_FREE_MEMORY_2D(self->cmpArbdmxGainIdxPrev); + + FDK_FREE_MEMORY_2D(self->smgData); + FDK_FREE_MEMORY_1D(self->smgTime); + + FDK_FREE_MEMORY_1D(self->numOttBands); + + FDK_FREE_MEMORY_1D(self->param2hyb); + + FDK_FREE_MEMORY_1D(self); + } + + return; +} + +/** + * \brief Apply Surround bypass buffer copies + * \param self spatialDec handle + * \param hybInputReal + * \param hybInputImag + * \param hybOutputReal + * \param hybOutputImag + * \param numInputChannels amount if input channels available in hybInputReal + * and hybInputImag, which may differ from self->numInputChannels. + */ +static void SpatialDecApplyBypass(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, + const int numInputChannels) { + int complexHybBands; + + complexHybBands = self->hybridBands; + + { + int ch; + int rf = -1, lf = -1, cf = -1; /* Right Front, Left Front, Center Front */ + + /* Determine output channel indices according to tree config */ + switch (self->treeConfig) { + case TREE_212: /* 212 */ + lf = 0; + rf = 1; + break; + default:; + } + + /* Note: numInputChannels might not match the tree config ! */ + switch (numInputChannels) { + case 1: + if (cf > 0) { + FDKmemcpy(hybOutputReal[cf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[cf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + } else { + FDKmemcpy(hybOutputReal[lf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputReal[rf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[lf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[rf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + } + break; + case 2: + FDK_ASSERT(lf != -1); + FDK_ASSERT(rf != -1); + FDKmemcpy(hybOutputReal[lf], hybInputReal[0], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputReal[rf], hybInputReal[1], + self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[lf], hybInputImag[0], + complexHybBands * sizeof(FIXP_DBL)); + FDKmemcpy(hybOutputImag[rf], hybInputImag[1], + complexHybBands * sizeof(FIXP_DBL)); + break; + } + for (ch = 0; ch < self->numOutputChannelsAT; ch++) { + if (ch == lf || ch == rf || ch == cf) { + continue; /* Skip bypassed channels */ + } + FDKmemclear(hybOutputReal[ch], self->hybridBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputImag[ch], complexHybBands * sizeof(FIXP_DBL)); + } + } +} + +/******************************************************************************* + Functionname: SpatialDecApplyParameterSets + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +static SACDEC_ERROR SpatialDecApplyParameterSets( + spatialDec *self, const SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE mode, + PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */ + FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */ + UINT nSamples, UINT controlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + FIXP_SGL alpha; + + int ts; + int ch; + int hyb; + + int prevSlot = self->prevTimeSlot; + int ps = self->curPs; + int ts_io = 0; /* i/o dependent slot */ + int bypassMode = (controlFlags & MPEGS_BYPASSMODE) ? 1 : 0; + + /* Bypass can be triggered by the upmixType, too. */ + bypassMode |= ((self->upmixType == UPMIXTYPE_BYPASS) ? 1 : 0); + + /* + * Decode available slots + */ + for (ts = self->curTimeSlot; + ts <= fixMin(self->curTimeSlot + (int)nSamples / self->qmfBands - 1, + self->timeSlots - 1); + ts++, ts_io++) { + int currSlot = frame->paramSlot[ps]; + + /* + * Get new parameter set + */ + if (ts == prevSlot + 1) { + err = SpatialDecCalculateM1andM2(self, ps, + frame); /* input: ottCLD, ottICC, ... */ + /* output: M1param(Real/Imag), M2(Real/Imag) */ + if (err != MPS_OK) { + bypassMode = 1; + if (self->errInt == MPS_OK) { + /* store internal error befor it gets overwritten */ + self->errInt = err; + } + err = MPS_OK; + } + + if ((ps == 0) && (self->bOverwriteM1M2prev != 0)) { + /* copy matrix entries of M1/M2 of the first parameter set to the + previous matrices (of the last frame). This avoids the interpolation + of incompatible values. E.g. for residual bands the coefficients are + calculated differently compared to non-residual bands. + */ + SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */ + /* output: M(1/2)param(Real/Imag)Prev */ + self->bOverwriteM1M2prev = 0; + } + + SpatialDecSmoothM1andM2( + self, frame, + ps); /* input: M1param(Real/Imag)(Prev), M2(Real/Imag)(Prev) */ + /* output: M1param(Real/Imag), M2(Real/Imag) */ + } + + alpha = FX_DBL2FX_SGL(fDivNorm(ts - prevSlot, currSlot - prevSlot)); + + switch (mode) { + case INPUTMODE_QMF_SBR: + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) + self->bShareDelayWithSBR = 0; /* We got no hybrid delay */ + else + self->bShareDelayWithSBR = 1; + SpatialDecFeedQMF(self, qmfInDataReal, qmfInDataImag, ts_io, bypassMode, + self->qmfInputReal__FDK, self->qmfInputImag__FDK, + self->numInputChannels); + break; + case INPUTMODE_TIME: + self->bShareDelayWithSBR = 0; + SpatialDecQMFAnalysis(self, inData, ts_io, bypassMode, + self->qmfInputReal__FDK, self->qmfInputImag__FDK, + self->numInputChannels); + break; + default: + break; + } + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + self->residualCoding) { + int offset; + ch = 1; + + offset = self->pQmfDomain->globalConf.nBandsSynthesis * + self->pQmfDomain->globalConf.nQmfTimeSlots; + + { + const PCM_MPS *inSamples = + &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis]; + + CalculateSpaceAnalysisQmf( + &self->pQmfDomain->QmfDomainIn[ch].fb, inSamples + (ch * offset), + self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0]); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + FIXP_DBL *RESTRICT self_qmfResidualReal__FDK_0_0 = + &self->qmfResidualReal__FDK[0][0][0]; + FIXP_DBL *RESTRICT self_qmfResidualImag__FDK_0_0 = + &self->qmfResidualImag__FDK[0][0][0]; + + if ((self->pQmfDomain->globalConf.nBandsAnalysis == 24) && + !(self->stereoConfigIndex == 3)) { + for (i = 0; i < self->qmfBands; i++) { + self_qmfResidualReal__FDK_0_0[i] = + fMult(self_qmfResidualReal__FDK_0_0[i] << 1, + self->clipProtectGain__FDK); + self_qmfResidualImag__FDK_0_0[i] = + fMult(self_qmfResidualImag__FDK_0_0[i] << 1, + self->clipProtectGain__FDK); + } + } else { + for (i = 0; i < self->qmfBands; i++) { + self_qmfResidualReal__FDK_0_0[i] = fMult( + self_qmfResidualReal__FDK_0_0[i], self->clipProtectGain__FDK); + self_qmfResidualImag__FDK_0_0[i] = fMult( + self_qmfResidualImag__FDK_0_0[i], self->clipProtectGain__FDK); + } + } + } + } + } + + SpatialDecHybridAnalysis( + self, /* input: qmfInput(Real/Imag), qmfResidual(Real/Imag) */ + self->qmfInputReal__FDK, self->qmfInputImag__FDK, + self->hybInputReal__FDK, self->hybInputImag__FDK, ts, numInputChannels); + + if (bypassMode) { + SpatialDecApplyBypass( + self, self->hybInputReal__FDK, /* input: hybInput(Real/Imag) */ + self->hybInputImag__FDK, + self->hybOutputRealDry__FDK, /* output: hybOutput(Real/Imag)Dry */ + self->hybOutputImagDry__FDK, numInputChannels); + } else /* !bypassMode */ + { + FIXP_DBL *pxReal[MAX_NUM_XCHANNELS] = {NULL}; + FIXP_DBL *pxImag[MAX_NUM_XCHANNELS] = {NULL}; + + SpatialDecCreateX(self, + self->hybInputReal__FDK, /* input: hybInput(Real/Imag), + hybResidual(Real/Imag) */ + self->hybInputImag__FDK, pxReal, pxImag); + + { + SpatialDecApplyM1_CreateW_Mode212( + self, frame, pxReal, pxImag, + self->wReal__FDK, /* output: w(Real/Imag) */ + self->wImag__FDK); + } + if (err != MPS_OK) goto bail; + + int applyM2Config = APPLY_M2_NONE; + + applyM2Config = APPLY_M2; + if ((self->pConfigCurrent->syntaxFlags & + (SACDEC_SYNTAX_USAC | SACDEC_SYNTAX_RSVD50)) && + (self->tempShapeConfig != 1) && (self->tempShapeConfig != 2)) { + if (self->phaseCoding == 3) + applyM2Config = APPLY_M2_MODE212_Res_PhaseCoding; + else + applyM2Config = APPLY_M2_MODE212; + } + + switch (applyM2Config) { + case APPLY_M2_MODE212: { + err = SpatialDecApplyM2_Mode212( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK); + } break; + case APPLY_M2_MODE212_Res_PhaseCoding: + err = SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK); + break; + case APPLY_M2: + err = SpatialDecApplyM2( + self, ps, alpha, self->wReal__FDK, self->wImag__FDK, + self->hybOutputRealDry__FDK, self->hybOutputImagDry__FDK, + self->hybOutputRealWet__FDK, self->hybOutputImagWet__FDK); + break; + default: + err = MPS_APPLY_M2_ERROR; + goto bail; + } + + if (err != MPS_OK) goto bail; + + if ((self->tempShapeConfig == 2) && (!isTwoChMode(self->upmixType))) { + SpatialDecReshapeBBEnv(self, frame, + ts); /* input: reshapeBBEnvState, + hybOutput(Real/Imag)(Dry/Wet), + hybInput(Real/Imag) */ + } /* output: hybOutput(Real/Imag)Dry */ + + /* Merge parts of the dry and wet QMF buffers. */ + if ((self->tempShapeConfig == 1) && (!isTwoChMode(self->upmixType))) { + for (ch = 0; ch < self->numOutputChannels; ch++) { + for (hyb = 0; hyb < self->tp_hybBandBorder; hyb++) { + self->hybOutputRealDry__FDK[ch][hyb] += + self->hybOutputRealWet__FDK[ch][hyb]; + self->hybOutputImagDry__FDK[ch][hyb] += + self->hybOutputImagWet__FDK[ch][hyb]; + } /* loop hyb */ + } /* loop ch */ + err = subbandTPApply( + self, frame); /* input: hStpDec, hybOutput(Real/Imag)Dry/Wet */ + /* output: hStpDec, hybOutput(Real/Imag)Dry */ + if (err != MPS_OK) goto bail; + } /* (self->tempShapeConfig == 1) */ + else { + /* The wet signal is added to the dry signal in applyM2 if GES and STP + * are disabled */ + if ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) { + int nHybBands; + nHybBands = self->hybridBands; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + FIXP_DBL *RESTRICT pRealDry = self->hybOutputRealDry__FDK[ch]; + FIXP_DBL *RESTRICT pImagDry = self->hybOutputImagDry__FDK[ch]; + FIXP_DBL *RESTRICT pRealWet = self->hybOutputRealWet__FDK[ch]; + FIXP_DBL *RESTRICT pImagWet = self->hybOutputImagWet__FDK[ch]; + for (hyb = 0; hyb < nHybBands; hyb++) { + pRealDry[hyb] += pRealWet[hyb]; + pImagDry[hyb] += pImagWet[hyb]; + } /* loop hyb */ + for (; hyb < self->hybridBands; hyb++) { + pRealDry[hyb] += pRealWet[hyb]; + } /* loop hyb */ + } /* loop ch */ + } /* ( self->tempShapeConfig == 1 ) || ( self->tempShapeConfig == 2 ) */ + } /* !self->tempShapeConfig == 1 */ + } /* !bypassMode */ + + if (self->phaseCoding == 1) { + /* only if bsPhaseCoding == 1 and bsResidualCoding == 0 */ + + SpatialDecApplyPhase( + self, alpha, (ts == currSlot) /* signal the last slot of the set */ + ); + } + + /* + * Synthesis Filtering + */ + + err = SpatialDecSynthesis( + self, ts_io, + self->hybOutputRealDry__FDK, /* input: hybOutput(Real/Imag)Dry */ + self->hybOutputImagDry__FDK, self->timeOut__FDK, /* output: timeOut */ + numInputChannels, mapDescr); + + if (err != MPS_OK) goto bail; + + /* + * Update parameter buffer + */ + if (ts == currSlot) { + SpatialDecBufferMatrices(self); /* input: M(1/2)param(Real/Imag) */ + /* output: M(1/2)param(Real/Imag)Prev */ + + prevSlot = currSlot; + ps++; + } /* if (ts==currSlot) */ + + } /* ts loop */ + + /* + * Save parameter states + */ + self->prevTimeSlot = prevSlot; + self->curTimeSlot = ts; + self->curPs = ps; + +bail: + + return err; +} + +SACDEC_ERROR SpatialDecApplyFrame( + spatialDec *self, + SPATIAL_BS_FRAME *frame, /* parsed frame data to be applied */ + SPATIALDEC_INPUT_MODE inputMode, PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* QMF domain data l/r */ + FIXP_DBL **qmfInDataImag, /* QMF domain data l/r */ + PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */ + UINT nSamples, UINT *pControlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + int fDecAndMapFrameData; + int controlFlags; + + FDK_ASSERT(self != NULL); + FDK_ASSERT(pControlFlags != NULL); + FDK_ASSERT(pcmOutBuf != NULL); + + self->errInt = err; /* Init internal error */ + + controlFlags = *pControlFlags; + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + (self->stereoConfigIndex > 1)) { + numInputChannels = + 1; /* Do not count residual channel as input channel. It is handled + seperately. */ + } + + /* Check if input amount of channels is consistent */ + if (numInputChannels != self->numInputChannels) { + controlFlags |= MPEGS_CONCEAL; + if (numInputChannels > self->createParams.maxNumInputChannels) { + return MPS_INVALID_PARAMETER; + } + } + + self->timeOut__FDK = pcmOutBuf; + + /* Determine local function control flags */ + fDecAndMapFrameData = frame->newBsData; + + if (((fDecAndMapFrameData == + 0) /* assures that conceal flag will not be set for blind mode */ + && (self->curTimeSlot + (int)nSamples / self->qmfBands > + self->timeSlots)) || + (frame->numParameterSets == + 0)) { /* New input samples but missing side info */ + fDecAndMapFrameData = 1; + controlFlags |= MPEGS_CONCEAL; + } + + if ((fDecAndMapFrameData == 0) && + (frame->paramSlot[fMax(0, frame->numParameterSets - 1)] != + (self->timeSlots - 1) || + self->curTimeSlot > + frame->paramSlot[self->curPs])) { /* Detected faulty parameter slot + data. */ + fDecAndMapFrameData = 1; + controlFlags |= MPEGS_CONCEAL; + } + + /* Update concealment state machine */ + SpatialDecConcealment_UpdateState( + &self->concealInfo, + (controlFlags & MPEGS_CONCEAL) + ? 0 + : 1); /* convert from conceal flag to frame ok flag */ + + if (fDecAndMapFrameData) { + /* Reset spatial framing control vars */ + frame->newBsData = 0; + self->prevTimeSlot = -1; + self->curTimeSlot = 0; + self->curPs = 0; + + if (controlFlags & MPEGS_CONCEAL) { + /* Reset frame data to avoid misconfiguration. */ + SpatialDecClearFrameData(self, frame, &self->createParams); + } + + { + err = SpatialDecDecodeFrame(self, frame); /* input: ... */ + /* output: decodeAndMapFrameDATA */ + } + + if (err != MPS_OK) { + /* Rescue strategy is to apply bypass mode in order + to keep at least the downmix channels continuous. */ + controlFlags |= MPEGS_CONCEAL; + if (self->errInt == MPS_OK) { + /* store internal error befor it gets overwritten */ + self->errInt = err; + } + } + } + + err = SpatialDecApplyParameterSets( + self, frame, inputMode, inData, qmfInDataReal, qmfInDataImag, nSamples, + controlFlags | ((err == MPS_OK) ? 0 : MPEGS_BYPASSMODE), numInputChannels, + mapDescr); + if (err != MPS_OK) { + goto bail; + } + +bail: + + *pControlFlags = controlFlags; + + return err; +} diff --git a/fdk-aac/libSACdec/src/sac_dec.h b/fdk-aac/libSACdec/src/sac_dec.h new file mode 100644 index 0000000..992acad --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec.h @@ -0,0 +1,539 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library structures + +*******************************************************************************/ + +#ifndef SAC_DEC_H +#define SAC_DEC_H + +#include "common_fix.h" + +#include "sac_dec_interface.h" /* library interface in ../include */ + +#include "FDK_qmf_domain.h" +#include "sac_qmf.h" +#include "FDK_bitstream.h" /* mp4 bitbuffer */ +#include "sac_calcM1andM2.h" +#include "FDK_hybrid.h" +#include "FDK_decorrelate.h" +#include "sac_reshapeBBEnv.h" + +#include "sac_dec_conceal.h" + +#include "sac_tsd.h" + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +#define ICCdefault 0 +#define IPDdefault 0 +#define arbdmxGainDefault 0 +#define CPCdefault 10 +#define tttCLD1default 15 +#define tttCLD2default 0 + +#define IS_HQ_ONLY(aot) \ + ((aot) == AOT_ER_AAC_LD || (aot) == AOT_ER_AAC_ELD || (aot) == AOT_USAC || \ + (aot) == AOT_RSVD50) + +#define SCONST(x) FL2FXCONST_DBL(x) + +#define PC_NUM_BANDS (8) +#define PC_NUM_HYB_BANDS (PC_NUM_BANDS - 3 + 10) +#define ABS_THR (1e-9f * 32768 * 32768) + +#define MAX_HYBRID_BANDS (MAX_NUM_QMF_BANDS - 3 + 10) +#define HYBRID_FILTER_DELAY (6) + +#define MAX_RESIDUAL_FRAMES (4) +#define MAX_RESIDUAL_BISTREAM \ + (836) /* 48000 bps * 3 res / (8 * 44100 / 2048 ) */ +#define MAX_MDCT_COEFFS (1024) +#define SACDEC_RESIDUAL_BS_BUF_SIZE \ + (1024) /* used to setup and check residual bitstream buffer */ + +#define MAX_NUM_PARAMS (MAX_NUM_OTT + 4 * MAX_NUM_TTT + MAX_INPUT_CHANNELS) +#define MAX_NUM_PARAMETERS (MAX(MAX_NUM_PARAMS, MAX_NUM_OTT)) + +#define MAX_PARAMETER_SETS (9) + +#define MAX_M2_INPUT (MAX_OUTPUT_CHANNELS) /* 3 direct + 5 diffuse */ + +#define MAX_QMF_BANDS_TO_HYBRID \ + (3) /* 3 bands are filtered again in "40 bands" case */ +#define PROTO_LEN (13) +#define BUFFER_LEN_LF (PROTO_LEN) +#define BUFFER_LEN_HF ((PROTO_LEN - 1) / 2) + +#define MAX_NO_DECORR_CHANNELS (MAX_OUTPUT_CHANNELS) +#define HRTF_AZIMUTHS (5) + +#define MAX_NUM_OTT_AT 0 + +/* left out */ + +typedef enum { + UPMIXTYPE_BYPASS = -1, /*just bypass the input channels without processing*/ + UPMIXTYPE_NORMAL = 0 /*multichannel loudspeaker upmix with spatial data*/ +} UPMIXTYPE; + +static inline int isTwoChMode(UPMIXTYPE upmixType) { + int retval = 0; + return retval; +} + + /* left out end */ + +#define MPEGS_BYPASSMODE (0x00000001) +#define MPEGS_CONCEAL (0x00000002) + +typedef struct STP_DEC *HANDLE_STP_DEC; + +typedef struct { + SCHAR bsQuantCoarseXXXprev; + SCHAR bsQuantCoarseXXXprevParse; +} LOSSLESSSTATE; + +typedef struct { + SCHAR bsXXXDataMode[MAX_PARAMETER_SETS]; + SCHAR bsQuantCoarseXXX[MAX_PARAMETER_SETS]; + SCHAR bsFreqResStrideXXX[MAX_PARAMETER_SETS]; + SCHAR nocmpQuantCoarseXXX[MAX_PARAMETER_SETS]; + LOSSLESSSTATE *state; /* Link to persistent state information */ +} LOSSLESSDATA; + +struct SPATIAL_BS_FRAME_struct { + UCHAR bsIndependencyFlag; + UCHAR newBsData; + UCHAR numParameterSets; + + /* + If bsFramingType == 0, then the paramSlot[ps] for 0 <= ps < numParamSets is + calculated as follows: paramSlot[ps] = ceil(numSlots*(ps+1)/numParamSets) - 1 + Otherwise, it is + paramSlot[ps] = bsParamSlot[ps] + */ + INT paramSlot[MAX_PARAMETER_SETS]; + + /* These arrays contain the compact indices, only one value per pbstride, only + * paramsets actually containing data. */ + /* These values are written from the parser in ecDataDec() and read during + * decode in mapIndexData() */ + SCHAR cmpOttCLDidx[MAX_NUM_OTT + MAX_NUM_OTT_AT][MAX_PARAMETER_SETS] + [MAX_PARAMETER_BANDS]; + SCHAR cmpOttICCidx[MAX_NUM_OTT][MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + + /* Smoothing */ + UCHAR bsSmoothMode[MAX_PARAMETER_SETS]; + UCHAR bsSmoothTime[MAX_PARAMETER_SETS]; + UCHAR bsFreqResStrideSmg[MAX_PARAMETER_SETS]; + UCHAR bsSmgData[MAX_PARAMETER_SETS] + [MAX_PARAMETER_BANDS]; /* smoothing flags, one if band is + smoothed, otherwise zero */ + + /* Arbitrary Downmix */ + SCHAR (*cmpArbdmxGainIdx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + + /* Lossless control */ + LOSSLESSDATA *CLDLosslessData; + LOSSLESSDATA *ICCLosslessData; + /* LOSSLESSDATA *ADGLosslessData; -> is stored in CLDLosslessData[offset] */ + + LOSSLESSDATA *IPDLosslessData; + SCHAR (*cmpOttIPDidx)[MAX_PARAMETER_SETS][MAX_PARAMETER_BANDS]; + int phaseMode; + int OpdSmoothingMode; + + UCHAR tempShapeEnableChannelGES[MAX_OUTPUT_CHANNELS]; /*!< GES side info. */ + UCHAR bsEnvShapeData[MAX_OUTPUT_CHANNELS] + [MAX_TIME_SLOTS]; /*!< GES side info (quantized). */ + + UCHAR tempShapeEnableChannelSTP[MAX_OUTPUT_CHANNELS]; /*!< STP side info. */ + + TSD_DATA TsdData[1]; /*!< TSD data structure. */ +}; + +typedef struct { + /* Lossless state */ + LOSSLESSSTATE CLDLosslessState[MAX_NUM_PARAMETERS]; + LOSSLESSSTATE ICCLosslessState[MAX_NUM_PARAMETERS]; + LOSSLESSSTATE IPDLosslessState[MAX_NUM_PARAMETERS]; +} BS_LL_STATE; + +typedef struct { + int prevParamSlot; + int prevSmgTime; + UCHAR prevSmgData[MAX_PARAMETER_BANDS]; + + FIXP_DBL opdLeftState__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL opdRightState__FDK[MAX_PARAMETER_BANDS]; + +} SMOOTHING_STATE; + +typedef struct { + FIXP_DBL alpha__FDK; + FIXP_DBL beta__FDK; + FIXP_DBL partNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS] + [BB_ENV_SIZE]; + FIXP_DBL normNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + FIXP_DBL frameNrgPrev__FDK[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT partNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT partNrgPrev2SF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT normNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; + INT frameNrgPrevSF[2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS]; +} RESHAPE_BBENV_STATE; + +typedef struct { + int maxNumInputChannels; + int maxNumOutputChannels; + int maxNumQmfBands; + int maxNumHybridBands; + int maxNumXChannels; + int maxNumVChannels; + int maxNumDecorChannels; + int maxNumCmplxQmfBands; + int maxNumCmplxHybBands; + int maxNumResChannels; + int bProcResidual; /* process residual */ + int maxNumResidualChannels; + int maxNumOttBoxes; + int maxNumParams; + +} SACDEC_CREATION_PARAMS; + +struct spatialDec_struct { + SACDEC_ERROR + errInt; /* Field to store internal errors. + Will be clear at the very beginning of each process call. */ + int staticDecScale; /* static scale of decoder */ + + /* GENERAL */ + int samplingFreq; /* [Hz] */ + CFG_LEVEL decoderLevel; /* 0..5 */ + CFG_EXTENT decoderMode; + CFG_BINAURAL binauralMode; + + SACDEC_CREATION_PARAMS createParams; + + int numComplexProcessingBands; + + int treeConfig; /* TREE_5151 = 5151, TREE_5152 = 5152, TREE_525 = 525, defined + in sac_bitdec.h */ + + int numInputChannels; /* 1 (M) or 2 (L,R) */ + int numOutputChannels; /* 6 for 3/2.1 (FL,FR,FC,LF,BL,BR) */ + int numOttBoxes; /* number of ott boxes */ + int numM2rows; + + int numOutputChannelsAT; /* Number of output channels after arbitrary tree + processing */ + + int quantMode; /* QUANT_FINE, QUANT_EBQ1, QUANT_EBQ2, defined in sac_bitdec.h + */ + int arbitraryDownmix; /* (arbitraryDownmix != 0) 1 arbitrary downmix data + present, 2 arbitrary downmix residual data present*/ + int residualCoding; /* (residualCoding != 0) => residual coding data present + */ + UCHAR nrResidualFrame; + UCHAR nrArbDownmixResidualFrame; + FDK_BITSTREAM **hResidualBitstreams; + int tempShapeConfig; /* */ + int decorrType; /* Indicates to use PS or none PS decorrelator. */ + int decorrConfig; /* chosen decorrelator */ + int envQuantMode; /* quantization mode of envelope reshaping data */ + + FIXP_DBL clipProtectGain__FDK; /* global gain for upmix */ + char clipProtectGainSF__FDK; /* global gain for upmix */ + + /* Currently ignoring center decorr + numVChannels = numDirektSignals + numDecorSignals */ + int numDirektSignals; /* needed for W, Number of direkt signals 515 -> 1 525 + -> 3 */ + int wStartResidualIdx; /* Where to start read residuals for W, = 0 for 515, = + 1 for 525 since one residual is used in V */ + int numDecorSignals; /* needed for W, Number of residual and decorrelated + signals, = 2, 3 for center deccorelation*/ + int numVChannels; /* direct signals + decorelator signals */ + int numXChannels; /* direct input signals + TTT-residuals */ + + int timeSlots; /* length of spatial frame in QMF samples */ + int curTimeSlot; /* pointer to the current time slot used for hyperframing */ + int prevTimeSlot; /* */ + int curPs; + int frameLength; /* number of output waveform samples/channel/frame */ + UPMIXTYPE upmixType; + int partiallyComplex; + int useFDreverb; + + int bShareDelayWithSBR; + + int tp_hybBandBorder; /* Hybrid band indicating the HP filter cut-off. */ + + /* FREQUENCY MAPPING */ + int qmfBands; + int hybridBands; + const SCHAR *kernels; /* Mapping hybrid band to parameter band. */ + + int TsdTs; /**< TSD QMF slot counter 0<= ts < numSlots */ + + int *param2hyb; /* Mapping parameter bands to hybrid bands */ + int kernels_width[MAX_PARAMETER_BANDS]; /* Mapping parmeter band to hybrid + band offsets. */ + + /* Residual coding */ + int residualSamplingFreq; + UCHAR residualPresent[MAX_NUM_OTT + MAX_NUM_TTT]; + UCHAR residualBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* 0, if no residual data + present for this box */ + UCHAR residualQMFBands[MAX_NUM_OTT + MAX_NUM_TTT]; /* needed for optimized + mdct2qmf calculation */ + SPATIAL_SPECIFIC_CONFIG *pConfigCurrent; + + int arbdmxFramesPerSpatialFrame; + int arbdmxUpdQMF; + + int numParameterBands; /* Number of parameter bands 40, 28, 20, 14, 10, ... + .*/ + int bitstreamParameterBands; + int *numOttBands; /* number of bands for each ott, is != numParameterBands for + LFEs */ + + /* 1 MAPPING */ + UCHAR extendFrame; + UCHAR numParameterSetsPrev; + + int *smgTime; + UCHAR **smgData; + + /* PARAMETER DATA decoded and dequantized */ + + /* Last parameters from prev frame required during decode in mapIndexData() + * and not touched during parse */ + SCHAR **ottCLDidxPrev; + SCHAR **ottICCidxPrev; + SCHAR **arbdmxGainIdxPrev; + SCHAR **ottIPDidxPrev; + SCHAR ***outIdxData; /* is this really persistent memory ? */ + + /* State mem required during parse in SpatialDecParseFrameData() */ + SCHAR **cmpOttCLDidxPrev; + SCHAR **cmpOttICCidxPrev; + SCHAR ***ottICCdiffidx; + SCHAR **cmpOttIPDidxPrev; + + /* State mem required in parseArbitraryDownmixData */ + SCHAR **cmpArbdmxGainIdxPrev; + + SCHAR ***ottCLD__FDK; + SCHAR ***ottICC__FDK; + + SCHAR ***arbdmxGain__FDK; /* Holds the artistic downmix correction index.*/ + + FIXP_DBL *arbdmxAlpha__FDK; + FIXP_DBL *arbdmxAlphaPrev__FDK; + + UCHAR stereoConfigIndex; + int highRateMode; + + int phaseCoding; + + SCHAR ***ottIPD__FDK; + + FIXP_DBL PhaseLeft__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhaseRight__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhasePrevLeft__FDK[MAX_PARAMETER_BANDS]; + FIXP_DBL PhasePrevRight__FDK[MAX_PARAMETER_BANDS]; + int numOttBandsIPD; + + /* GAIN MATRICIES FOR CURRENT and PREVIOUS PARMATER SET(s)*/ + FIXP_DBL ***M2Real__FDK; + FIXP_DBL ***M2Imag__FDK; + FIXP_DBL ***M2RealPrev__FDK; + FIXP_DBL ***M2ImagPrev__FDK; + + /* INPUT SIGNALS */ + FIXP_DBL ***qmfInputRealDelayBuffer__FDK; + FIXP_DBL ***qmfInputImagDelayBuffer__FDK; + + int pc_filterdelay; /* additional delay to align HQ with LP before hybird + analysis */ + int qmfInputDelayBufPos; + FIXP_DBL **qmfInputReal__FDK; + FIXP_DBL **qmfInputImag__FDK; + + FIXP_DBL **hybInputReal__FDK; + FIXP_DBL **hybInputImag__FDK; + + FIXP_DBL **binInputReverb; + + FIXP_DBL binGain, reverbGain; + FIXP_DBL binCenterGain, reverbCenterGain; + + /* RESIDUAL SIGNALS */ + + FIXP_DBL ***qmfResidualReal__FDK; + FIXP_DBL ***qmfResidualImag__FDK; + + FIXP_DBL **hybResidualReal__FDK; + FIXP_DBL **hybResidualImag__FDK; + + int qmfOutputRealDryDelayBufPos; + FIXP_DBL ***qmfOutputRealDryDelayBuffer__FDK; + FIXP_DBL ***qmfOutputImagDryFilterBuffer__FDK; + FIXP_DBL *qmfOutputImagDryFilterBufferBase__FDK; + + /* TEMPORARY SIGNALS */ + + FIXP_DBL **wReal__FDK; + FIXP_DBL **wImag__FDK; + + /* OUTPUT SIGNALS */ + FIXP_DBL **hybOutputRealDry__FDK; + FIXP_DBL **hybOutputImagDry__FDK; + FIXP_DBL **hybOutputRealWet__FDK; + FIXP_DBL **hybOutputImagWet__FDK; + PCM_MPS *timeOut__FDK; + + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + + FDK_ANA_HYB_FILTER + *hybridAnalysis; /*!< pointer Analysis hybrid filterbank array. */ + FDK_SYN_HYB_FILTER + *hybridSynthesis; /*!< pointer Synthesis hybrid filterbank array. */ + FIXP_DBL ** + pHybridAnaStatesLFdmx; /*!< pointer to analysis hybrid filter states LF */ + FIXP_DBL ** + pHybridAnaStatesHFdmx; /*!< pointer to analysis hybrid filter states HF */ + FIXP_DBL ** + pHybridAnaStatesLFres; /*!< pointer to analysis hybrid filter states LF */ + FIXP_DBL ** + pHybridAnaStatesHFres; /*!< pointer to analysis hybrid filter states HF */ + + DECORR_DEC *apDecor; /*!< pointer decorrelator array. */ + FIXP_DBL **pDecorBufferCplx; + + SMOOTHING_STATE *smoothState; /*!< Pointer to smoothing states. */ + + RESHAPE_BBENV_STATE *reshapeBBEnvState; /*!< GES handle. */ + SCHAR row2channelDmxGES[MAX_OUTPUT_CHANNELS]; + + HANDLE_STP_DEC hStpDec; /*!< STP handle. */ + + const UCHAR *pActivM2ParamBands; + + int bOverwriteM1M2prev; /* Overwrite previous M2/M2 params with first set of + new frame after SSC change (aka + decodeAfterConfigHasChangedFlag). */ + SpatialDecConcealmentInfo concealInfo; +}; + +#define SACDEC_SYNTAX_MPS 1 +#define SACDEC_SYNTAX_USAC 2 +#define SACDEC_SYNTAX_RSVD50 4 +#define SACDEC_SYNTAX_L2 8 +#define SACDEC_SYNTAX_L3 16 +#define SACDEC_SYNTAX_LD 32 + +static inline int GetProcBand(spatialDec_struct *self, int qs) { + return self->kernels[qs]; +} + +#endif /* SAC_DEC_H */ diff --git a/fdk-aac/libSACdec/src/sac_dec_conceal.cpp b/fdk-aac/libSACdec/src/sac_dec_conceal.cpp new file mode 100644 index 0000000..dfeef7b --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec_conceal.cpp @@ -0,0 +1,392 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Christian Ertel, Christian Griebel + + Description: SAC Dec error concealment + +*******************************************************************************/ + +#include "sac_dec_conceal.h" + +void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info, + const UINT resetFlags) { + FDK_ASSERT(info != NULL); + + if (resetFlags & MPEGS_CONCEAL_RESET_STATE) { + info->concealState = SpatialDecConcealState_Init; + /* Frame counters will be initialized implicitely in function + * SpatialDecConcealment_UpdateState(). */ + } + + if (resetFlags & MPEGS_CONCEAL_RESET_PARAMETER) { + /* Set default params */ + info->concealParams.method = MPEGS_CONCEAL_DEFAULT_METHOD; + info->concealParams.numKeepFrames = MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES; + info->concealParams.numFadeOutFrames = + MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH; + info->concealParams.numFadeInFrames = + MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH; + info->concealParams.numReleaseFrames = + MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES; + } + + return; +} + +int SpatialDecConcealment_Apply( + SpatialDecConcealmentInfo *info, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS], SCHAR **diffIdxData, + SCHAR * + idxPrev, /* char + idxPrev[SPATIALDEC_MAX_NUM_OTT][SPATIALDEC_MAX_PARAMETER_BANDS], + */ + SCHAR *bsXXXDataMode, const int startBand, const int stopBand, + const SCHAR defaultValue, const int paramType, const int numParamSets) { + int appliedProcessing = 0; + int band, dataMode = -1; + + FDK_ASSERT(info != NULL); + FDK_ASSERT(cmpIdxData != NULL); + FDK_ASSERT(idxPrev != NULL); + FDK_ASSERT(bsXXXDataMode != NULL); + + /* Processing depends only on the internal state */ + switch (info->concealState) { + case SpatialDecConcealState_Init: + dataMode = 0; /* default */ + break; + + case SpatialDecConcealState_Ok: + /* Nothing to do */ + break; + + case SpatialDecConcealState_Keep: + dataMode = 1; /* keep */ + break; + + case SpatialDecConcealState_FadeToDefault: { + /* Start simple fade out */ + FIXP_DBL fac = fDivNorm(info->cntStateFrames + 1, + info->concealParams.numFadeOutFrames + 1); + + for (band = startBand; band < stopBand; band += 1) { + /* idxPrev = fac * defaultValue + (1-fac) * idxPrev; */ + idxPrev[band] = + fMultI(fac, defaultValue - idxPrev[band]) + idxPrev[band]; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + } break; + + case SpatialDecConcealState_Default: + for (band = startBand; band < stopBand; band += 1) { + idxPrev[band] = defaultValue; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + break; + + case SpatialDecConcealState_FadeFromDefault: { + FIXP_DBL fac = fDivNorm(info->cntValidFrames + 1, + info->concealParams.numFadeInFrames + 1); + + for (band = startBand; band < stopBand; band += 1) { + /* idxPrev = fac * cmpIdxData + (1-fac) * defaultValue; */ + idxPrev[band] = + fMultI(fac, cmpIdxData[numParamSets - 1][band] - defaultValue) + + defaultValue; + } + dataMode = 1; /* keep */ + appliedProcessing = 1; + } break; + + default: + FDK_ASSERT(0); /* All valid states shall be handled above. */ + break; + } + + if (dataMode >= 0) { + int i; + for (i = 0; i < numParamSets; i += 1) { + bsXXXDataMode[i] = dataMode; + if (diffIdxData != NULL) { + for (band = startBand; band < stopBand; band += 1) { + diffIdxData[i][band] = 0; + } + } + } + } + + return appliedProcessing; +} + +void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info, + const int frameOk) { + FDK_ASSERT(info != NULL); + + if (frameOk) { + info->cntValidFrames += 1; + } else { + info->cntValidFrames = 0; + } + + switch (info->concealState) { + case SpatialDecConcealState_Init: + if (frameOk) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + info->cntStateFrames = 0; + } + break; + + case SpatialDecConcealState_Ok: + if (!frameOk) { + /* NEXT STATE: Keep */ + info->concealState = SpatialDecConcealState_Keep; + info->cntStateFrames = 0; + } + break; + + case SpatialDecConcealState_Keep: + info->cntStateFrames += 1; + if (frameOk) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } else { + if (info->cntStateFrames >= info->concealParams.numKeepFrames) { + if (info->concealParams.numFadeOutFrames == 0) { + /* NEXT STATE: Default */ + info->concealState = SpatialDecConcealState_Default; + } else { + /* NEXT STATE: Fade to default */ + info->concealState = SpatialDecConcealState_FadeToDefault; + info->cntStateFrames = 0; + } + } + } + break; + + case SpatialDecConcealState_FadeToDefault: + info->cntStateFrames += 1; + if (info->cntValidFrames > 0) { + /* NEXT STATE: Fade in from default */ + info->concealState = SpatialDecConcealState_FadeFromDefault; + info->cntStateFrames = 0; + } else { + if (info->cntStateFrames >= info->concealParams.numFadeOutFrames) { + /* NEXT STATE: Default */ + info->concealState = SpatialDecConcealState_Default; + } + } + break; + + case SpatialDecConcealState_Default: + if (info->cntValidFrames > 0) { + if (info->concealParams.numFadeInFrames == 0) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } else { + /* NEXT STATE: Fade in from default */ + info->concealState = SpatialDecConcealState_FadeFromDefault; + info->cntValidFrames = 0; + } + } + break; + + case SpatialDecConcealState_FadeFromDefault: + info->cntValidFrames += 1; + if (frameOk) { + if (info->cntValidFrames >= info->concealParams.numFadeInFrames) { + /* NEXT STATE: Ok */ + info->concealState = SpatialDecConcealState_Ok; + } + } else { + /* NEXT STATE: Fade to default */ + info->concealState = SpatialDecConcealState_FadeToDefault; + info->cntStateFrames = 0; + } + break; + + default: + FDK_ASSERT(0); /* All valid states should be handled above! */ + break; + } +} + +SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *self, + const SAC_DEC_CONCEAL_PARAM param, + const INT value) { + SACDEC_ERROR err = MPS_OK; + + switch (param) { + case SAC_DEC_CONCEAL_METHOD: + switch ((SpatialDecConcealmentMethod)value) { + case SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT: + case SAC_DEC_CONCEAL_BY_FADING_PARAMETERS: + break; + default: + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.method = (SpatialDecConcealmentMethod)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_NUM_KEEP_FRAMES: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numKeepFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numFadeOutFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numFadeInFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + case SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES: + if (value < 0) { + err = MPS_INVALID_PARAMETER; + goto bail; + } + if (self != NULL) { + /* store parameter value */ + self->concealParams.numReleaseFrames = (UINT)value; + } else { + err = MPS_INVALID_HANDLE; + goto bail; + } + break; + default: + err = MPS_INVALID_PARAMETER; + goto bail; + } + +bail: + return err; +} diff --git a/fdk-aac/libSACdec/src/sac_dec_conceal.h b/fdk-aac/libSACdec/src/sac_dec_conceal.h new file mode 100644 index 0000000..27f5249 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec_conceal.h @@ -0,0 +1,187 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Christian Ertel, Christian Griebel + + Description: SAC Dec error concealment + +*******************************************************************************/ + +#ifndef SAC_DEC_CONCEAL_H +#define SAC_DEC_CONCEAL_H + +#include "sac_dec_interface.h" + +/* Modules dynamic parameters: */ +typedef enum { + SAC_DEC_CONCEAL_METHOD = 0, + SAC_DEC_CONCEAL_NUM_KEEP_FRAMES, + SAC_DEC_CONCEAL_FADE_OUT_SLOPE_LENGTH, + SAC_DEC_CONCEAL_FADE_IN_SLOPE_LENGTH, + SAC_DEC_CONCEAL_NUM_RELEASE_FRAMES + +} SAC_DEC_CONCEAL_PARAM; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* sac_dec_interface.h */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef enum { + SAC_DEC_CONCEAL_WITH_ZERO_VALUED_OUTPUT = 0, + SAC_DEC_CONCEAL_BY_FADING_PARAMETERS = 1 + +} SpatialDecConcealmentMethod; +/* - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* Default dynamic parameter values: */ +#define MPEGS_CONCEAL_DEFAULT_METHOD SAC_DEC_CONCEAL_BY_FADING_PARAMETERS +#define MPEGS_CONCEAL_DEFAULT_NUM_KEEP_FRAMES (10) +#define MPEGS_CONCEAL_DEFAULT_FADE_OUT_SLOPE_LENGTH (5) +#define MPEGS_CONCEAL_DEFAULT_FADE_IN_SLOPE_LENGTH (5) +#define MPEGS_CONCEAL_DEFAULT_NUM_RELEASE_FRAMES (3) + +typedef enum { + SpatialDecConcealState_Init = 0, + SpatialDecConcealState_Ok, + SpatialDecConcealState_Keep, + SpatialDecConcealState_FadeToDefault, + SpatialDecConcealState_Default, + SpatialDecConcealState_FadeFromDefault + +} SpatialDecConcealmentState; + +typedef struct { + SpatialDecConcealmentMethod method; + + UINT numKeepFrames; + UINT numFadeOutFrames; + UINT numFadeInFrames; + UINT numReleaseFrames; + +} SpatialDecConcealmentParams; + +typedef struct { + SpatialDecConcealmentParams concealParams; /* User set params */ + SpatialDecConcealmentState + concealState; /* State of internal state machine (fade-in/out etc) */ + + UINT cntStateFrames; /* Counter for fade-in/out handling */ + UINT cntValidFrames; /* Counter for the number of consecutive good frames*/ + +} SpatialDecConcealmentInfo; + +/* Module reset flags */ +#define MPEGS_CONCEAL_RESET_STATE (0x01) +#define MPEGS_CONCEAL_RESET_PARAMETER (0x02) +#define MPEGS_CONCEAL_RESET_ALL (0xFF) + +void SpatialDecConcealment_Init(SpatialDecConcealmentInfo *info, + const UINT resetFlags); + +int SpatialDecConcealment_Apply(SpatialDecConcealmentInfo *info, + const SCHAR (*cmpIdxData)[MAX_PARAMETER_BANDS], + SCHAR **diffIdxData, SCHAR *idxPrev, + SCHAR *bsXXXDataMode, const int startBand, + const int stopBand, const SCHAR defaultValue, + const int paramType, const int numParamSets); + +void SpatialDecConcealment_UpdateState(SpatialDecConcealmentInfo *info, + const int frameOk); + +SACDEC_ERROR SpatialDecConcealment_SetParam(SpatialDecConcealmentInfo *info, + const SAC_DEC_CONCEAL_PARAM param, + const INT value); + +#endif /* SAC_DEC_CONCEAL_H */ diff --git a/fdk-aac/libSACdec/src/sac_dec_interface.h b/fdk-aac/libSACdec/src/sac_dec_interface.h new file mode 100644 index 0000000..a2eea92 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec_interface.h @@ -0,0 +1,335 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library Interface + +*******************************************************************************/ + +#ifndef SAC_DEC_INTERFACE_H +#define SAC_DEC_INTERFACE_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sac_dec_errorcodes.h" +#include "sac_dec_ssc_struct.h" + +/** + * \brief Baseline MPEG-Surround profile Level 1-5. + */ +typedef enum { + DECODER_LEVEL_0 = 0, /*!< Level 0: dummy level; 212 only */ + DECODER_LEVEL_6 = 6 /*!< Level 6: no support */ +} CFG_LEVEL; + +/* + * \brief Number of output channels restriction. + */ +typedef enum { + OUTPUT_CHANNELS_DEFAULT, /*!< Default configuration depending on Decoder Level + */ + OUTPUT_CHANNELS_2_0, /*!< Limitation to stereo output */ + OUTPUT_CHANNELS_5_1 /*!< Limitation to 5.1 output */ +} CFG_RESTRICTION; + +/* + * \brief Supported decoder mode. + */ +typedef enum { + EXT_HQ_ONLY = 0, /*!< High Quality processing only */ + EXT_LP_ONLY = 1, /*!< Low Power procesing only */ + EXT_HQ_AND_LP = 2 /*!< Support both HQ and LP processing */ +} CFG_EXTENT; + +/* + * \brief Supported binaural mode. + */ +typedef enum { + BINAURAL_NONE = -1 /*!< No binaural procesing supported */ +} CFG_BINAURAL; + +/** + * \brief Decoder configuration structure. + * + * These structure contains all parameters necessary for decoder open function. + * The configuration specifies the functional range of the decoder instance. + */ +typedef struct { + CFG_LEVEL decoderLevel; + CFG_EXTENT decoderMode; + CFG_RESTRICTION maxNumOutputChannels; + CFG_BINAURAL binauralMode; + +} SPATIAL_DEC_CONFIG; + +typedef enum { + INPUTMODE_QMF = 1000, + INPUTMODE_QMF_SBR = 1001, + INPUTMODE_TIME = 1002 +} SPATIALDEC_INPUT_MODE; + +/** + * \brief MPEG Surround upmix type mode. + **/ +typedef enum { + UPMIX_TYPE_BYPASS = + -1, /*!< Bypass the downmix channels from the core decoder. */ + UPMIX_TYPE_NORMAL = 0 /*!< Multi channel output. */ + +} SPATIAL_DEC_UPMIX_TYPE; + +/** + * \brief Dynamic decoder parameters. + */ +typedef struct { + /* Basics */ + UCHAR outputMode; + UCHAR blindEnable; + UCHAR bypassMode; + + /* Error concealment */ + UCHAR concealMethod; + UINT concealNumKeepFrames; + UINT concealFadeOutSlopeLength; + UINT concealFadeInSlopeLength; + UINT concealNumReleaseFrames; + +} SPATIALDEC_PARAM; + +/** + * \brief Flags which control the initialization + **/ +typedef enum { + MPEGS_INIT_NONE = 0x00000000, /*!< Indicates no initialization */ + + MPEGS_INIT_CONFIG = 0x00000010, /*!< Indicates a configuration change due to + SSC value changes */ + + MPEGS_INIT_STATES_ANA_QMF_FILTER = + 0x00000100, /*!< Controls the initialization of the analysis qmf filter + states */ + MPEGS_INIT_STATES_SYN_QMF_FILTER = + 0x00000200, /*!< Controls the initialization of the synthesis qmf filter + states */ + MPEGS_INIT_STATES_ANA_HYB_FILTER = 0x00000400, /*!< Controls the + initialization of the + analysis hybrid filter + states */ + MPEGS_INIT_STATES_DECORRELATOR = + 0x00000800, /*!< Controls the initialization of the decorrelator states */ + MPEGS_INIT_STATES_M1M2 = 0x00002000, /*!< Controls the initialization of the + history in m1 and m2 parameter + calculation */ + MPEGS_INIT_STATES_GES = 0x00004000, /*!< Controls the initialization of the + history in the ges calculation */ + MPEGS_INIT_STATES_REVERB = + 0x00008000, /*!< Controls the initialization of the reverb states */ + MPEGS_INIT_STATES_PARAM = + 0x00020000, /*!< Controls the initialization of the history of all other + parameter */ + MPEGS_INIT_STATES_ERROR_CONCEALMENT = + 0x00080000, /*!< Controls the initialization of the error concealment + module state */ + MPEGS_INIT_PARAMS_ERROR_CONCEALMENT = 0x00200000 /*!< Controls the + initialization of the + whole error concealment + parameter set */ + +} MPEGS_INIT_CTRL_FLAGS; + +#define MASK_MPEGS_INIT_ALL_STATES (0x000FFF00) +#define MASK_MPEGS_INIT_ALL_PARAMS (0x00F00000) + +typedef struct spatialDec_struct spatialDec, *HANDLE_SPATIAL_DEC; + +typedef struct SPATIAL_BS_FRAME_struct SPATIAL_BS_FRAME; + +typedef struct { + UINT sizePersistent; /* persistent memory */ + UINT sizeFastPersistent; /* fast persistent memory */ + +} MEM_REQUIREMENTS; + +#define PCM_MPS INT_PCM +#define PCM_MPSF FIXP_PCM + +#define FIXP_DBL2PCM_MPS(x) ((INT_PCM)FX_DBL2FX_PCM(x)) + +/* exposed functions (library interface) */ + +int FDK_SpatialDecCompareSpatialSpecificConfigHeader( + SPATIAL_SPECIFIC_CONFIG *pSsc1, SPATIAL_SPECIFIC_CONFIG *pSsc2); + +int FDK_SpatialDecInitDefaultSpatialSpecificConfig( + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + AUDIO_OBJECT_TYPE coreCodec, int coreChannels, int samplingFreq, + int nTimeSlots, int decoderLevel, int isBlind); + +spatialDec *FDK_SpatialDecOpen(const SPATIAL_DEC_CONFIG *config, + int stereoConfigIndex); + +/** + * \brief Initialize state variables of the MPS parser + */ +void SpatialDecInitParserContext(spatialDec *self); + +/** + * \brief Initialize state of MPS decoder. This may happen after the first parse + * operation. + */ +SACDEC_ERROR FDK_SpatialDecInit(spatialDec *self, SPATIAL_BS_FRAME *frame, + SPATIAL_SPECIFIC_CONFIG *pSpatialSpecificConfig, + int nQmfBands, + SPATIAL_DEC_UPMIX_TYPE const upmixType, + SPATIALDEC_PARAM *pUserParams, + UINT initFlags /* MPEGS_INIT_CTRL_FLAGS */ +); + +/** + * \brief Apply decoded MPEG Surround parameters to time domain or QMF down mix + * data. + * \param self spatial decoder handle. + * \param inData Pointer to time domain input down mix data if any. + * \param qmfInDataReal Pointer array of QMF domain down mix input data (real + * part). + * \param qmfInDataImag Pointer array of QMF domain down mix input data + * (imaginary part). + * \param pcmOutBuf Pointer to a time domain buffer were the upmixed output data + * will be stored into. + * \param nSamples Amount of audio samples per channel of down mix input data + * (frame length). + * \param pControlFlags pointer to control flags field; input/output. + * \param numInputChannels amount of down mix input channels. Might not match + * the current tree config, useful for internal sanity checks and bypass mode. + * \param channelMapping array containing the desired output channel ordering to + * transform MPEG PCE style ordering to any other channel ordering. First + * dimension is the total channel count. + */ +SACDEC_ERROR SpatialDecApplyFrame( + spatialDec *self, SPATIAL_BS_FRAME *frame, SPATIALDEC_INPUT_MODE inputMode, + PCM_MPS *inData, /* Time domain input */ + FIXP_DBL **qmfInDataReal, /* interleaved l/r */ + FIXP_DBL **qmfInDataImag, /* interleaved l/r */ + PCM_MPS *pcmOutBuf, /* MAX_OUTPUT_CHANNELS*MAX_TIME_SLOTS*NUM_QMF_BANDS] */ + UINT nSamples, UINT *pControlFlags, int numInputChannels, + const FDK_channelMapDescr *const mapDescr); + +/** + * \brief Fill given arrays with audio channel types and indices. + * \param self spatial decoder handle. + * \param channelType array where corresponding channel types fr each output + * channels are stored into. + * \param channelIndices array where corresponding channel type indices fr each + * output channels are stored into. + */ +void SpatialDecChannelProperties(spatialDec *self, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr); + +void FDK_SpatialDecClose(spatialDec *self); + +#ifdef __cplusplus +} +#endif + +#endif /* SAC_DEC_INTERFACE_H */ diff --git a/fdk-aac/libSACdec/src/sac_dec_lib.cpp b/fdk-aac/libSACdec/src/sac_dec_lib.cpp new file mode 100644 index 0000000..bf6dedf --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec_lib.cpp @@ -0,0 +1,1995 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Decoder Library Interface + +*******************************************************************************/ + +#include "sac_dec_lib.h" +#include "sac_dec_interface.h" +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "FDK_matrixCalloc.h" + +#define MPS_DATA_BUFFER_SIZE (2048) + +/** + * \brief MPEG Surround data indication. + **/ +typedef enum { + MPEGS_ANCTYPE_FRAME = 0, /*!< MPEG Surround frame, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_HEADER_AND_FRAME = 1, /*!< MPEG Surround header and MPEG + Surround frame, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_RESERVED_1 = 2, /*!< reserved, see ISO/IEC 23003-1 */ + MPEGS_ANCTYPE_RESERVED_2 = 3 /*!< reserved, see ISO/IEC 23003-1*/ +} MPEGS_ANCTYPE; + +/** + * \brief MPEG Surround data segment indication. + **/ +typedef enum { + MPEGS_CONTINUE = 0, /*!< Indicates if data segment continues a data block. */ + MPEGS_STOP = 1, /*!< Indicates if data segment ends a data block. */ + MPEGS_START = 2, /*!< Indicates if data segment begins a data block. */ + MPEGS_START_STOP = + 3 /*!< Indicates if data segment begins and ends a data block. */ +} MPEGS_ANCSTARTSTOP; + +/** + * \brief MPEG Surround synchronizaiton state. + * + * CAUTION: Changing the enumeration values can break the sync mechanism + *because it is based on comparing the state values. + **/ +typedef enum { + MPEGS_SYNC_LOST = + 0, /*!< Indicates lost sync because of current discontinuity. */ + MPEGS_SYNC_FOUND = 1, /*!< Parsed a valid header and (re)intialization was + successfully completed. */ + MPEGS_SYNC_COMPLETE = 2 /*!< In sync and continuous. Found an independent + frame in addition to MPEGS_SYNC_FOUND. + Precondition: MPEGS_SYNC_FOUND. */ +} MPEGS_SYNCSTATE; + +/** + * \brief MPEG Surround operation mode. + **/ +typedef enum { + MPEGS_OPMODE_EMM = 0, /*!< Mode: Enhanced Matrix Mode (Blind) */ + MPEGS_OPMODE_MPS_PAYLOAD = 1, /*!< Mode: Normal, Stereo or Binaural */ + MPEGS_OPMODE_NO_MPS_PAYLOAD = 2 /*!< Mode: no MPEG Surround payload */ +} MPEGS_OPMODE; + +/** + * \brief MPEG Surround init flags. + **/ +typedef enum { + MPEGS_INIT_OK = 0x00000000, /*!< indicate correct initialization */ + MPEGS_INIT_ENFORCE_REINIT = + 0x00000001, /*!< indicate complete initialization */ + + MPEGS_INIT_CHANGE_OUTPUT_MODE = + 0x00000010, /*!< indicate change of the output mode */ + MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX = + 0x00000020, /*!< indicate change of low power/high quality */ + MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE = + 0x00000040, /*!< indicate change of qmf/time interface */ + MPEGS_INIT_CHANGE_HEADER = 0x00000080, /*!< indicate change of header */ + + MPEGS_INIT_ERROR_PAYLOAD = + 0x00000100, /*!< indicate payload/ancType/ancStartStop error */ + + MPEGS_INIT_BS_INTERRUPTION = + 0x00001000, /*!< indicate bitstream interruption */ + MPEGS_INIT_CLEAR_HISTORY = + 0x00002000, /*!< indicate that all states shall be cleared */ + + /* Re-initialization of submodules */ + + MPEGS_INIT_CHANGE_CONCEAL_PARAMS = 0x00100000, /*!< indicate a change of at + least one error concealment + param */ + + /* No re-initialization needed, currently not used */ + MPEGS_INIT_CHANGE_BYPASS_MODE = + 0x01000000, /*!< indicate change of bypass mode */ + + /* Re-initialization needed, currently not used */ + MPEGS_INIT_ERROR_ANC_TYPE = 0x10000000, /*!< indicate ancType error*/ + MPEGS_INIT_ERROR_ANC_STARTSTOP = + 0x20000000 /*!< indicate ancStartStop error */ +} MPEGS_INIT_FLAGS; + +struct MpegSurroundDecoder { + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + UCHAR mpsData[MPS_DATA_BUFFER_SIZE]; /* Buffer for MPS payload accross more + than one segment */ + INT mpsDataBits; /* Amount of bits in mpsData */ + /* MPEG Surround decoder */ + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig[1]; /* SSC delay line which is + used during decoding */ + spatialDec *pSpatialDec; + SPATIAL_SPECIFIC_CONFIG + spatialSpecificConfigBackup; /* SSC used while parsing */ + + /* Creation parameter */ + UCHAR mpegSurroundDecoderLevel; + /* Run-time parameter */ + UCHAR mpegSurroundSscIsGlobalCfg; /* Flag telling that the SSC + (::spatialSpecificConfig) is a + out-of-band configuration. */ + UCHAR mpegSurroundUseTimeInterface; + + SPATIAL_BS_FRAME + bsFrames[1]; /* Bitstream Structs that contain data read from the + SpatialFrame() bitstream element */ + BS_LL_STATE llState; /* Bit stream parser state memory */ + UCHAR bsFrameParse; /* Current parse frame context index */ + UCHAR bsFrameDecode; /* Current decode/apply frame context index */ + UCHAR bsFrameDelay; /* Amount of frames delay between parsing and processing. + Required i.e. for interpolation error concealment. */ + + /* User prameters */ + SPATIALDEC_PARAM mpegSurroundUserParams; + + /* Internal flags */ + SPATIAL_DEC_UPMIX_TYPE upmixType; + int initFlags[1]; + MPEGS_ANCSTARTSTOP ancStartStopPrev; + MPEGS_SYNCSTATE fOnSync[1]; + + /* Inital decoder configuration */ + SPATIAL_DEC_CONFIG decConfig; +}; + +SACDEC_ERROR +static sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, + const INT coreCodec, const INT sampleRate, + const INT frameSize); + +static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc); + +/** + * \brief Get the number of QMF bands from the sampling frequency (in Hz) + **/ +static int mpegSurroundDecoder_GetNrOfQmfBands( + const SPATIAL_SPECIFIC_CONFIG *pSsc, UINT sampleRate) { + UINT samplingFrequency = sampleRate; + int qmfBands = 64; + + if (pSsc != NULL) { + switch (pSsc->coreCodec) { + case AOT_USAC: + if ((pSsc->stereoConfigIndex == 3)) { + static const UCHAR mapIdx2QmfBands[3] = {24, 32, 16}; + FDK_ASSERT((pSsc->coreSbrFrameLengthIndex >= 2) && + (pSsc->coreSbrFrameLengthIndex <= 4)); + qmfBands = mapIdx2QmfBands[pSsc->coreSbrFrameLengthIndex - 2]; + } + return qmfBands; + default: + samplingFrequency = pSsc->samplingFreq; + break; + } + } + + /* number of QMF bands depend on sampling frequency, see FDIS 23003-1:2006 + * Chapter 6.3.3 */ + if (samplingFrequency < 27713) { + qmfBands = 32; + } + if (samplingFrequency > 55426) { + qmfBands = 128; + } + + return qmfBands; +} + +/** + * \brief Analyse init flags + **/ +static int mpegSurroundDecoder_CalcInitFlags(SPATIAL_SPECIFIC_CONFIG *pSsc1, + SPATIAL_SPECIFIC_CONFIG *pSsc2, + int upmixTypeFlag, + int binauralQualityFlag, + int partiallyComplexFlag, + int *ctrlFlags) { + /* Analyse core coder */ + if (pSsc1->coreCodec != pSsc2->coreCodec) { + *ctrlFlags |= MASK_MPEGS_INIT_ALL_STATES; + *ctrlFlags |= MASK_MPEGS_INIT_ALL_PARAMS; + } else { + /* Analyse elements for initialization of space analysis qmf filterbank */ + if ((partiallyComplexFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq)) { + *ctrlFlags |= MPEGS_INIT_STATES_ANA_QMF_FILTER; + *ctrlFlags |= MPEGS_INIT_STATES_ANA_HYB_FILTER; + } + + /* Analyse elements for initialization of space synthesis qmf filterbank */ + if ((upmixTypeFlag) || (partiallyComplexFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->bsFixedGainDMX != pSsc2->bsFixedGainDMX)) { + *ctrlFlags |= MPEGS_INIT_STATES_SYN_QMF_FILTER; + } + + /* Analyse elements for initialization of decorrelator */ + if ((upmixTypeFlag) || (partiallyComplexFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->decorrConfig != pSsc2->decorrConfig)) { + *ctrlFlags |= MPEGS_INIT_STATES_DECORRELATOR; + } + + /* Analyse elements for initialization of m1 and m2 calculation */ + if ((upmixTypeFlag) || (binauralQualityFlag) || + (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->samplingFreq != pSsc2->samplingFreq)) + + { + *ctrlFlags |= MPEGS_INIT_STATES_M1M2; + } + + /* Analyse elements for initialization of GES */ + if ((upmixTypeFlag) || (pSsc1->treeConfig != pSsc2->treeConfig) || + (pSsc1->tempShapeConfig != pSsc2->tempShapeConfig)) { + *ctrlFlags |= MPEGS_INIT_STATES_GES; + } + + /* Analyse elements for initialization of FDreverb */ + if ((upmixTypeFlag) || (binauralQualityFlag) || (partiallyComplexFlag) || + (pSsc1->samplingFreq != pSsc2->samplingFreq) || + (pSsc1->nTimeSlots != pSsc2->nTimeSlots)) { + *ctrlFlags |= MPEGS_INIT_STATES_REVERB; + } + + /* Reset previous frame data whenever the config changes */ + if (*ctrlFlags & MPEGS_INIT_CONFIG) { + *ctrlFlags |= MPEGS_INIT_STATES_PARAM; + } + } + + return MPS_OK; +} + +/** + * \brief Reset MPEG Surround status info + **/ +static void updateMpegSurroundDecoderStatus( + CMpegSurroundDecoder *pMpegSurroundDecoder, int initFlags, + MPEGS_SYNCSTATE fOnSync, MPEGS_ANCSTARTSTOP ancStartStopPrev) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + initFlags; + if ((pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg != 0) && + (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] >= + MPEGS_SYNC_FOUND) && + (fOnSync < MPEGS_SYNC_FOUND)) { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + } else { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + fOnSync; + } + pMpegSurroundDecoder->ancStartStopPrev = ancStartStopPrev; +} + +static SACDEC_ERROR mpegSurroundDecoder_Create( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +SAC_INSTANCE_AVAIL +mpegSurroundDecoder_IsFullMpegSurroundDecoderInstanceAvailable( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SAC_INSTANCE_AVAIL instanceAvailable = SAC_INSTANCE_NOT_FULL_AVAILABLE; + + if (pMpegSurroundDecoder->pSpatialDec != NULL) { + instanceAvailable = SAC_INSTANCE_FULL_AVAILABLE; + } + + return instanceAvailable; +} + +SACDEC_ERROR mpegSurroundDecoder_Open( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + SACDEC_ERROR error; + + error = mpegSurroundDecoder_Create(pMpegSurroundDecoder, stereoConfigIndex, + pQmfDomain); + + return error; +} + +/** + * \brief Renamed function from getUpmixType to check_UParam_Build_DecConfig. + * This function checks if user params, decoder config and SSC are valid + * and if the decoder build can handle all this settings. + * The upmix type may be modified by this function. + * It is called in initMpegSurroundDecoder() after the ssc parse check, + * to have all checks in one place and to ensure these checks are always + * performed if config changes (inband and out-of-band). + * + * \param pUserParams User data handle. + * \param pDecConfig decoder config handle. + * \param pSsc spatial specific config handle. + * \param pUpmixType upmix type which is set by this function + * + * \return MPS_OK on sucess, and else on failure. + */ +static SACDEC_ERROR check_UParam_Build_DecConfig( + SPATIALDEC_PARAM const *pUserParams, SPATIAL_DEC_CONFIG const *pDecConfig, + const SPATIAL_SPECIFIC_CONFIG *pSsc, SPATIAL_DEC_UPMIX_TYPE *pUpmixType) { + int dmxChannels, outChannels, maxNumOutChannels; + + FDK_ASSERT(pUserParams != NULL); + FDK_ASSERT(pUpmixType != NULL); + + /* checks if implementation can handle the Ssc */ + + switch (pSsc->treeConfig) { + case SPATIALDEC_MODE_RSVD7: /* 212 */ + dmxChannels = 1; + outChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + /* ------------------------------------------- */ + + /* Analyse pDecConfig params */ + switch (pDecConfig->binauralMode) { + case BINAURAL_NONE: + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + switch (pDecConfig->decoderMode) { + case EXT_HQ_ONLY: + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + + switch (pDecConfig->maxNumOutputChannels) { + case OUTPUT_CHANNELS_DEFAULT: + /* No special restrictions -> Get the level restriction: */ + switch (pDecConfig->decoderLevel) { + case DECODER_LEVEL_0: + maxNumOutChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + break; + case OUTPUT_CHANNELS_2_0: + maxNumOutChannels = 2; + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + /* ------------------------- */ + + /* check if we can handle user params */ + if (pUserParams->blindEnable == 1) { + return MPS_UNSUPPORTED_CONFIG; + } + { + switch ((SAC_DEC_OUTPUT_MODE)pUserParams->outputMode) { + case SACDEC_OUT_MODE_NORMAL: + if (maxNumOutChannels >= outChannels) { + *pUpmixType = UPMIX_TYPE_NORMAL; + } else { + { *pUpmixType = UPMIX_TYPE_BYPASS; } + } + break; + case SACDEC_OUT_MODE_STEREO: + if (dmxChannels == 1) { + if (outChannels == 2) { + *pUpmixType = UPMIX_TYPE_NORMAL; + } + } else { + *pUpmixType = UPMIX_TYPE_BYPASS; + } + break; + case SACDEC_OUT_MODE_6CHANNEL: + if (outChannels > 6) { + { *pUpmixType = UPMIX_TYPE_BYPASS; } + } else { + *pUpmixType = UPMIX_TYPE_NORMAL; + } + break; + default: + return MPS_UNSUPPORTED_CONFIG; + } + } + + return MPS_OK; +} + +/** + * \brief Init MPEG Surround decoder. + **/ +static SACDEC_ERROR initMpegSurroundDecoder( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err; + int initFlags = MPEGS_INIT_NONE, initFlagsDec; + int upmixTypeCurr = pMpegSurroundDecoder->upmixType; + + FDK_ASSERT(pMpegSurroundDecoder != NULL); + + SPATIAL_SPECIFIC_CONFIG *const pSSCinput = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + SPATIAL_SPECIFIC_CONFIG *const pSSCtarget = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + initFlagsDec = + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]; + + if (pSSCinput->coreCodec != AOT_USAC) { + /* here we check if we have a valid Ssc */ + err = sscParseCheck(pSSCinput); + if (err != MPS_OK) goto bail; + } + + /* here we check if Ssc matches build; also check UParams and DecConfig */ + /* if desired upmixType is changes */ + err = check_UParam_Build_DecConfig( + &pMpegSurroundDecoder->mpegSurroundUserParams, + &pMpegSurroundDecoder->decConfig, pSSCinput, + &pMpegSurroundDecoder->upmixType); + if (err != MPS_OK) goto bail; + + /* init config */ + if (initFlagsDec & MPEGS_INIT_CHANGE_HEADER) { + initFlags |= MPEGS_INIT_CONFIG; + } + /* init all states */ + if (initFlagsDec & MPEGS_INIT_CLEAR_HISTORY) { + initFlags |= MASK_MPEGS_INIT_ALL_STATES; + } + if (initFlagsDec & MPEGS_INIT_CHANGE_CONCEAL_PARAMS) { + initFlags |= MPEGS_INIT_PARAMS_ERROR_CONCEALMENT; + } + + if (initFlagsDec & MPEGS_INIT_ENFORCE_REINIT) { + /* init all states */ + initFlags |= MASK_MPEGS_INIT_ALL_STATES; + initFlags |= MASK_MPEGS_INIT_ALL_PARAMS; + } else { + /* analyse states which have to be initialized */ + mpegSurroundDecoder_CalcInitFlags( + pSSCtarget, pSSCinput, + (upmixTypeCurr != + pMpegSurroundDecoder->upmixType), /* upmixType changed */ + 0, (initFlagsDec & MPEGS_INIT_CHANGE_PARTIALLY_COMPLEX) ? 1 : 0, + &initFlags); + } + + { + int nrOfQmfBands; + FDKmemcpy(pSSCtarget, pSSCinput, sizeof(SPATIAL_SPECIFIC_CONFIG)); + + nrOfQmfBands = mpegSurroundDecoder_GetNrOfQmfBands( + pSSCtarget, pSSCtarget->samplingFreq); + err = FDK_SpatialDecInit( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], + pSSCtarget, nrOfQmfBands, pMpegSurroundDecoder->upmixType, + &pMpegSurroundDecoder->mpegSurroundUserParams, initFlags); + + if (err != MPS_OK) goto bail; + + /* Signal that we got a header and can go on decoding */ + if (err == MPS_OK) { + initFlagsDec = MPEGS_INIT_OK; + { + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + } + } + } + +bail: + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] = + initFlagsDec; + return err; +} + +/** + * \brief Init MPEG Surround decoder. + **/ +SACDEC_ERROR mpegSurroundDecoder_Init( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err = MPS_OK; + + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + } + return err; +} + +/** + * \brief Open MPEG Surround decoder. + **/ +static SACDEC_ERROR mpegSurroundDecoder_Create( + CMpegSurroundDecoder **pMpegSurroundDecoder, int stereoConfigIndex, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + SACDEC_ERROR err = MPS_OK; + CMpegSurroundDecoder *sacDec = NULL; + spatialDec *self = NULL; + + /* decoderLevel decoderMode maxNumOutputChannels binauralMode */ + static const SPATIAL_DEC_CONFIG decConfig = { + (CFG_LEVEL)(0), EXT_HQ_ONLY, OUTPUT_CHANNELS_DEFAULT, BINAURAL_NONE}; + + if (*pMpegSurroundDecoder == NULL) { + FDK_ALLOCATE_MEMORY_1D(*pMpegSurroundDecoder, 1, CMpegSurroundDecoder) + + for (int i = 0; i < 1; i++) { + err = SpatialDecCreateBsFrame(&(*pMpegSurroundDecoder)->bsFrames[i], + &(*pMpegSurroundDecoder)->llState); + if (err != MPS_OK) { + sacDec = *pMpegSurroundDecoder; + goto bail; + } + } + (*pMpegSurroundDecoder)->pQmfDomain = pQmfDomain; + + (*pMpegSurroundDecoder)->bsFrameDelay = 1; + (*pMpegSurroundDecoder)->bsFrameParse = 0; + (*pMpegSurroundDecoder)->bsFrameDecode = 0; + + return err; + } else { + sacDec = *pMpegSurroundDecoder; + } + + if (sacDec->pSpatialDec == NULL) { + if ((self = FDK_SpatialDecOpen(&decConfig, stereoConfigIndex)) == NULL) { + err = MPS_OUTOFMEMORY; + goto bail; + } + } else { + self = sacDec->pSpatialDec; + } + + self->pQmfDomain = sacDec->pQmfDomain; + + sacDec->pSpatialDec = self; + + /* default parameter set */ + sacDec->mpegSurroundUserParams.outputMode = SACDEC_OUT_MODE_NORMAL; + sacDec->mpegSurroundUserParams.blindEnable = 0; + sacDec->mpegSurroundUserParams.bypassMode = 0; + sacDec->mpegSurroundUserParams.concealMethod = 1; + sacDec->mpegSurroundUserParams.concealNumKeepFrames = 10; + sacDec->mpegSurroundUserParams.concealFadeOutSlopeLength = 5; + sacDec->mpegSurroundUserParams.concealFadeInSlopeLength = 5; + sacDec->mpegSurroundUserParams.concealNumReleaseFrames = 3; + sacDec->mpegSurroundSscIsGlobalCfg = 0; + sacDec->mpegSurroundUseTimeInterface = 1; + sacDec->mpegSurroundDecoderLevel = decConfig.decoderLevel; + + sacDec->upmixType = UPMIX_TYPE_NORMAL; + + /* signalize spatial decoder re-initalization */ + updateMpegSurroundDecoderStatus(sacDec, MPEGS_INIT_ENFORCE_REINIT, + MPEGS_SYNC_LOST, MPEGS_STOP); + + /* return decoder instance */ + *pMpegSurroundDecoder = sacDec; + sacDec->decConfig = decConfig; + + SpatialDecInitParserContext(sacDec->pSpatialDec); + + return err; + +bail: + if (sacDec != NULL) { + mpegSurroundDecoder_Close(sacDec); + } + *pMpegSurroundDecoder = NULL; + if (err == MPS_OK) { + return MPS_OUTOFMEMORY; + } else { + return err; + } +} + +/** + * \brief Config MPEG Surround decoder. + **/ +SACDEC_ERROR mpegSurroundDecoder_Config( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + AUDIO_OBJECT_TYPE coreCodec, INT samplingRate, INT frameSize, + INT stereoConfigIndex, INT coreSbrFrameLengthIndex, INT configBytes, + const UCHAR configMode, UCHAR *configChanged) { + SACDEC_ERROR err = MPS_OK; + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfig; + SPATIAL_SPECIFIC_CONFIG *pSsc = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + + switch (coreCodec) { + case AOT_DRM_USAC: + case AOT_USAC: + if (configMode == AC_CM_DET_CFG_CHANGE) { + /* In config detection mode write spatial specific config parameters + * into temporarily allocated structure */ + err = SpatialDecParseMps212Config( + hBs, &spatialSpecificConfig, samplingRate, coreCodec, + stereoConfigIndex, coreSbrFrameLengthIndex); + pSsc = &spatialSpecificConfig; + } else { + err = SpatialDecParseMps212Config( + hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + samplingRate, coreCodec, stereoConfigIndex, + coreSbrFrameLengthIndex); + } + break; + case AOT_ER_AAC_ELD: + case AOT_ER_AAC_LD: + if (configMode == AC_CM_DET_CFG_CHANGE) { + /* In config detection mode write spatial specific config parameters + * into temporarily allocated structure */ + err = SpatialDecParseSpecificConfig(hBs, &spatialSpecificConfig, + configBytes, coreCodec); + pSsc = &spatialSpecificConfig; + } else { + err = SpatialDecParseSpecificConfig( + hBs, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + configBytes, coreCodec); + } + break; + default: + err = MPS_UNSUPPORTED_FORMAT; + break; + } + + if (err != MPS_OK) { + goto bail; + } + + err = sscCheckOutOfBand(pSsc, coreCodec, samplingRate, frameSize); + + if (err != MPS_OK) { + goto bail; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + return err; + } + + if (configMode & AC_CM_ALLOC_MEM) { + if (*configChanged) { + err = mpegSurroundDecoder_Open(&pMpegSurroundDecoder, stereoConfigIndex, + NULL); + if (err) { + return err; + } + } + } + + { + SPATIAL_SPECIFIC_CONFIG *sscParse = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, sscParse)) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse] |= + MPEGS_INIT_CHANGE_HEADER; + /* Error resilience code */ + if (pMpegSurroundDecoder->pSpatialDec == NULL) { + err = MPS_NOTOK; + goto bail; + } + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + } + } + + if (err == MPS_OK) { + /* We got a valid out-of-band configuration so label it accordingly. */ + pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 1; + } + +bail: + return err; +} + +/** + * \brief Determine MPEG Surround operation mode. + **/ +static MPEGS_OPMODE mpegSurroundOperationMode( + CMpegSurroundDecoder *pMpegSurroundDecoder, int mpsDataBits) { + MPEGS_OPMODE mode; + + { + if ((mpsDataBits > 0) && + (pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable == 0)) { + mode = MPEGS_OPMODE_MPS_PAYLOAD; /* Mode: Normal, Stereo or Binaural */ + } else { + mode = MPEGS_OPMODE_NO_MPS_PAYLOAD; /* Mode: No MPEG Surround Payload */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + } + + return (mode); +} + +/** + * \brief Check ssc for parse errors. + * This one is called in initMpegSurroundDecoder() + * to ensure checking of inband and out-of-band mps configs. + * Only parse errors checked here! Check for valid config is done + * in check_UParam_Build_DecConfig()! + * + * \param pSsc spatial specific config handle. + * + * \return MPS_OK on sucess, and else on parse error. + */ +static SACDEC_ERROR sscParseCheck(const SPATIAL_SPECIFIC_CONFIG *pSsc) { + if (pSsc->samplingFreq > 96000) return MPS_PARSE_ERROR; + if (pSsc->samplingFreq < 8000) return MPS_PARSE_ERROR; + + if ((pSsc->treeConfig < 0) || (pSsc->treeConfig > 7)) { + return MPS_PARSE_ERROR; + } + + if ((pSsc->quantMode < 0) || (pSsc->quantMode > 2)) { + return MPS_PARSE_ERROR; + } + + /* now we are sure there were no parsing errors */ + + return MPS_OK; +} + +/** + * \brief Check number of time slots + * + * Basically the mps frame length must be a multiple of the core coder frame + * length. The below table shows all valid configurations in detail. See ISO/IEC + * 23003-1: "Table 4A - Allowed values for bsFrameLength in the Baseline MPEG + * Surround Profile" + * + * Downmix Coder Downmix Code Allowed values for bsFrameLength + * Allowed frame sizes for normal, downsampled and upsampled MPS Framelength + * (QMF Samples) + * + * AAC 1024 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * AAC 960 15 14, 29, 44, 59 960 1920 2880 3840 + * downsampled MPS 30 29, 59 960 1920 upsampled MPS + * 7,5 14, 29, 44, 59 1920 3840 5760 7680 + * + * HE-AAC 1024/2048 32 31, 63 2048 4096 downsampled MPS + * 64 63 2048 upsampled MPS + * 16 15, 31, 47, 63 2048 4096 6144 8192 + * + * HE-AAC 960/1920 30 29, 59 1920 3840 downsampled MPS + * 60 59 1920 upsampled MPS + * 15 14, 29, 44, 59 1920 3840 5760 7680 + * + * BSAC 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * BSAC with SBR 32 31, 63 2048 4096 downsampled MPS + * 64 63 2048 upsampled MPS + * 16 15, 31, 47, 63 2048 4096 6144 8192 + * + * AAC LD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71 + * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS + * 16 15, 31, 47, 63 512 1024 1536 2048 + * + * AAC ELD 512 8 7, 15, 23, 31, 39, 47, 55, 63, 71 + * 512 1024 1536 2048 2560 3072 3584 4096 4608 downsampled MPS + * 16 15, 31, 47, 63 512 1024 1536 2048 + * + * AAC ELD with SBR 512/1024 16 15, 31, 47, 63 1024 2048 3072 4096 + * downsampled MPS 32 31, 63 1024 2048 upsampled MPS + * 8 7, 15, 23, 31, 39, 47, 55, 63, 71 1024 2048 3072 4096 + * 5120 6144 7168 8192 9216 + * + * MPEG1/2 Layer II 18 17, 35, 53, 71 1152 2304 3456 4608 + * downsampled MPS 36 35, 71 1152 2304 + * + * MPEG1/2 Layer III 18 17, 35, 53, 71 1152 2304 3456 4608 + * downsampled MPS 36 35, 71 1152 2304 + * + * \param frameLength + * \param qmfBands + * \param timeSlots + * + * \return error code + */ +SACDEC_ERROR checkTimeSlots(int frameLength, int qmfBands, int timeSlots) { + int len; + int maxFrameLength; + + if (qmfBands == 64) { + /* normal MPEG Surround */ + switch (frameLength) { + case 960: + case 1920: + maxFrameLength = 3840; + break; + case 1024: + case 2048: + maxFrameLength = 4096; + break; + case 512: + case 1152: + maxFrameLength = 4608; + break; + default: + return MPS_PARSE_ERROR; + } + } else if (qmfBands == 32) { + /* downsampled MPEG Surround */ + switch (frameLength) { + case 960: + case 1920: + maxFrameLength = 1920; + break; + case 512: + case 1024: + case 2048: + maxFrameLength = 2048; + break; + case 1152: + maxFrameLength = 2304; + break; + default: + return MPS_PARSE_ERROR; + } + } else if (qmfBands == 128) { + /* upsampled MPEG Surround */ + switch (frameLength) { + case 1920: + maxFrameLength = 7680; + break; + case 1024: + maxFrameLength = 9216; + break; + case 2048: + maxFrameLength = 8192; + break; + case 512: + case 960: + case 1152: + /* no break, no support for upsampled MPEG Surround */ + default: + return MPS_PARSE_ERROR; + } + } else { + return MPS_PARSE_ERROR; + } + + len = frameLength; + + while (len <= maxFrameLength) { + if (len == timeSlots * qmfBands) { + return MPS_OK; + } + len += frameLength; + } + return MPS_PARSE_ERROR; +} + +/** + * \brief Check ssc for consistency (e.g. bit errors could cause trouble) + * First of currently two ssc-checks. + * This (old) one is called in mpegSurroundDecoder_Apply() + * only if inband mps config is contained in stream. + * + * New ssc check is split in two functions sscParseCheck() and + * check_UParam_Build_DecConfig(). sscParseCheck() checks only for correct + * parsing. check_UParam_Build_DecConfig() is used to check if we have a + * valid config. Both are called in initMpegSurroundDecoder() to ensure + * checking of inband and out-of-band mps configs. + * + * If this function can be integrated into the new functions. + * We can remove this one. + * + * \param pSsc spatial specific config handle. + * \param frameLength + * \param sampleRate + * + * \return MPS_OK on sucess, and else on failure. + */ +static SACDEC_ERROR sscCheckInBand(SPATIAL_SPECIFIC_CONFIG *pSsc, + int frameLength, int sampleRate) { + SACDEC_ERROR err = MPS_OK; + int qmfBands; + + FDK_ASSERT(pSsc != NULL); + + /* check ssc for parse errors */ + if (sscParseCheck(pSsc) != MPS_OK) { + err = MPS_PARSE_ERROR; + } + + /* core fs and mps fs must match */ + if (pSsc->samplingFreq != sampleRate) { + err = MPS_PARSE_ERROR /* MPEGSDEC_SSC_PARSE_ERROR */; + } + + qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq); + + if (checkTimeSlots(frameLength, qmfBands, pSsc->nTimeSlots) != MPS_OK) { + err = MPS_PARSE_ERROR; + } + + return err; +} + +SACDEC_ERROR +mpegSurroundDecoder_ConfigureQmfDomain( + CMpegSurroundDecoder *pMpegSurroundDecoder, + SAC_INPUT_CONFIG sac_dec_interface, UINT coreSamplingRate, + AUDIO_OBJECT_TYPE coreCodec) { + SACDEC_ERROR err = MPS_OK; + FDK_QMF_DOMAIN_GC *pGC = NULL; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + pGC = &pMpegSurroundDecoder->pQmfDomain->globalConf; + if (pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg) { + SPATIAL_SPECIFIC_CONFIG *pSSC = + &pMpegSurroundDecoder->spatialSpecificConfigBackup; + if (sac_dec_interface == SAC_INTERFACE_TIME) { + /* For SAC_INTERFACE_QMF these parameters are set by SBR. */ + pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands( + pSSC, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for + SAC_INTERFACE_TIME */ + pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested; + pGC->nInputChannels_requested = + fMax((UINT)pSSC->nInputChannels, (UINT)pGC->nInputChannels_requested); + } + pGC->nOutputChannels_requested = + fMax((UINT)pSSC->nOutputChannels, (UINT)pGC->nOutputChannels_requested); + } else { + if (sac_dec_interface == SAC_INTERFACE_TIME) { + /* For SAC_INTERFACE_QMF these parameters are set by SBR. */ + pGC->nBandsAnalysis_requested = mpegSurroundDecoder_GetNrOfQmfBands( + NULL, coreSamplingRate); /* coreSamplingRate == outputSamplingRate for + SAC_INTERFACE_TIME */ + pGC->nBandsSynthesis_requested = pGC->nBandsAnalysis_requested; + pGC->nInputChannels_requested = + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels; + } + pGC->nOutputChannels_requested = + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumOutputChannels; + } + pGC->nQmfProcBands_requested = 64; + pGC->nQmfProcChannels_requested = + fMin((INT)pGC->nInputChannels_requested, + pMpegSurroundDecoder->pSpatialDec->createParams.maxNumInputChannels); + + if (coreCodec == AOT_ER_AAC_ELD) { + pGC->flags_requested |= QMF_FLAG_MPSLDFB; + pGC->flags_requested &= ~QMF_FLAG_CLDFB; + } + + return err; +} + +/** + * \brief Check out-of-band config + * + * \param pSsc spatial specific config handle. + * \param coreCodec core codec. + * \param sampleRate sampling frequency. + * + * \return errorStatus + */ +SACDEC_ERROR +sscCheckOutOfBand(const SPATIAL_SPECIFIC_CONFIG *pSsc, const INT coreCodec, + const INT sampleRate, const INT frameSize) { + FDK_ASSERT(pSsc != NULL); + int qmfBands = 0; + + /* check ssc for parse errors */ + if (sscParseCheck(pSsc) != MPS_OK) { + return MPS_PARSE_ERROR; + } + + switch (coreCodec) { + case AOT_USAC: + case AOT_DRM_USAC: + /* ISO/IEC 23003-1:2007(E), Chapter 6.3.3, Support for lower and higher + * sampling frequencies */ + if (pSsc->samplingFreq >= 55426) { + return MPS_PARSE_ERROR; + } + break; + case AOT_ER_AAC_LD: + case AOT_ER_AAC_ELD: + /* core fs and mps fs must match */ + if (pSsc->samplingFreq != sampleRate) { + return MPS_PARSE_ERROR; + } + + /* ISO/IEC 14496-3:2009 FDAM 3: Chapter 1.5.2.3, Levels for the Low Delay + * AAC v2 profile */ + if (pSsc->samplingFreq > 48000) { + return MPS_PARSE_ERROR; + } + + qmfBands = mpegSurroundDecoder_GetNrOfQmfBands(pSsc, pSsc->samplingFreq); + switch (frameSize) { + case 480: + if (!((qmfBands == 32) && (pSsc->nTimeSlots == 15))) { + return MPS_PARSE_ERROR; + } + break; + case 960: + if (!((qmfBands == 64) && (pSsc->nTimeSlots == 15))) { + return MPS_PARSE_ERROR; + } + break; + case 512: + if (!(((qmfBands == 32) && (pSsc->nTimeSlots == 16)) || + ((qmfBands == 64) && (pSsc->nTimeSlots == 8)))) { + return MPS_PARSE_ERROR; + } + break; + case 1024: + if (!((qmfBands == 64) && (pSsc->nTimeSlots == 16))) { + return MPS_PARSE_ERROR; + } + break; + default: + return MPS_PARSE_ERROR; + } + break; + default: + return MPS_PARSE_ERROR; + break; + } + + return MPS_OK; +} + +/** + * \brief Decode MPEG Surround frame. + **/ +int mpegSurroundDecoder_ParseNoHeader( + CMpegSurroundDecoder *pMpegSurroundDecoder, HANDLE_FDK_BITSTREAM hBs, + int *pMpsDataBits, int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + SPATIAL_SPECIFIC_CONFIG *sscParse; + int bitsAvail, numSacBits; + + if (pMpegSurroundDecoder == NULL || hBs == NULL) { + return MPS_INVALID_HANDLE; + } + + sscParse = &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + + bitsAvail = FDKgetValidBits(hBs); + + /* First spatial specific config is parsed into spatialSpecificConfigBackup, + * second spatialSpecificConfigBackup is copied into + * spatialSpecificConfig[bsFrameDecode] */ + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameParse]) { + FDKmemcpy(sscParse, &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sizeof(SPATIAL_SPECIFIC_CONFIG)); + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameParse] = + MPEGS_SYNC_FOUND; + } + + if (bitsAvail <= 0) { + err = MPS_PARSE_ERROR; + } else { + err = SpatialDecParseFrameData( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse], + hBs, sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType, + fGlobalIndependencyFlag); + if (err == MPS_OK) { + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData = 1; + } + } + + numSacBits = bitsAvail - (INT)FDKgetValidBits(hBs); + + if (numSacBits > bitsAvail) { + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData = 0; + err = MPS_PARSE_ERROR; + } + + *pMpsDataBits -= numSacBits; + + return err; +} + +/** + * \brief Check, if ancType is valid. + **/ +static int isValidAncType(CMpegSurroundDecoder *pMpegSurroundDecoder, + int ancType) { + int ret = 1; + + if ((ancType != MPEGS_ANCTYPE_HEADER_AND_FRAME) && + (ancType != MPEGS_ANCTYPE_FRAME)) { + ret = 0; + } + + if (ret == 0) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + + return (ret); +} + +/** + * \brief Check, if ancStartStop is valid. + **/ +static int isValidAncStartStop(CMpegSurroundDecoder *pMpegSurroundDecoder, + int ancStartStop) { + int ret = 1; + + switch (ancStartStop) { + case MPEGS_START: + /* Sequence start - start and continue - start not allowed */ + if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START) || + (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_CONTINUE)) { + ret = 0; + } + break; + + case MPEGS_STOP: + /* MPS payload of the previous frame must be valid if current type is stop + Sequence startstop - stop and stop - stop not allowed + Sequence startstop - continue and stop - continue are allowed */ + if ((pMpegSurroundDecoder->ancStartStopPrev == MPEGS_STOP) || + (pMpegSurroundDecoder->ancStartStopPrev == MPEGS_START_STOP)) { + ret = 0; + } + break; + + case MPEGS_CONTINUE: + case MPEGS_START_STOP: + /* No error detection possible for this states */ + break; + } + + if (ret == 0) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } else { + pMpegSurroundDecoder->ancStartStopPrev = (MPEGS_ANCSTARTSTOP)ancStartStop; + } + + return (ret); +} + +int mpegSurroundDecoder_Parse(CMpegSurroundDecoder *pMpegSurroundDecoder, + HANDLE_FDK_BITSTREAM hBs, int *pMpsDataBits, + AUDIO_OBJECT_TYPE coreCodec, int sampleRate, + int frameSize, int fGlobalIndependencyFlag) { + SACDEC_ERROR err = MPS_OK; + SPATIAL_SPECIFIC_CONFIG *sscParse; + SPATIAL_BS_FRAME *bsFrame; + HANDLE_FDK_BITSTREAM hMpsBsData = NULL; + FDK_BITSTREAM mpsBsData; + int mpsDataBits = *pMpsDataBits; + int mpsBsBits; + MPEGS_ANCTYPE ancType; + MPEGS_ANCSTARTSTOP ancStartStop; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + mpsBsBits = (INT)FDKgetValidBits(hBs); + + sscParse = &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameParse]; + bsFrame = &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse]; + + /* + Find operation mode of mpeg surround decoder: + - MPEGS_OPMODE_EMM: Mode: Enhanced Matrix Mode (Blind) + - MPEGS_OPMODE_MPS_PAYLOAD: Mode: Normal, Stereo or Binaural + - MPEGS_OPMODE_NO_MPS_PAYLOAD: Mode: No MpegSurround Payload + */ + { + /* Parse ancType and ancStartStop */ + ancType = (MPEGS_ANCTYPE)FDKreadBits(hBs, 2); + ancStartStop = (MPEGS_ANCSTARTSTOP)FDKreadBits(hBs, 2); + mpsDataBits -= 4; + + /* Set valid anc type flag, if ancType signals a payload with either header + * and frame or frame */ + if (isValidAncType(pMpegSurroundDecoder, ancType)) { + /* Set valid anc startstop flag, if transmitted sequence is not illegal */ + if (isValidAncStartStop(pMpegSurroundDecoder, ancStartStop)) { + switch (ancStartStop) { + case MPEGS_START: + /* Assuming that core coder frame size (AAC) is smaller than MPS + coder frame size. Save audio data for next frame. */ + if (mpsDataBits > MPS_DATA_BUFFER_SIZE * 8) { + err = MPS_NOTOK; + goto bail; + } + for (int i = 0; i < mpsDataBits / 8; i++) { + pMpegSurroundDecoder->mpsData[i] = FDKreadBits(hBs, 8); + } + pMpegSurroundDecoder->mpsDataBits = mpsDataBits; + break; + + case MPEGS_CONTINUE: + case MPEGS_STOP: + /* Assuming that core coder frame size (AAC) is smaller than MPS + coder frame size. Save audio data for next frame. */ + if ((pMpegSurroundDecoder->mpsDataBits + mpsDataBits) > + MPS_DATA_BUFFER_SIZE * 8) { + err = MPS_NOTOK; + goto bail; + } + for (int i = 0; i < mpsDataBits / 8; i++) { + pMpegSurroundDecoder + ->mpsData[(pMpegSurroundDecoder->mpsDataBits / 8) + i] = + FDKreadBits(hBs, 8); + } + pMpegSurroundDecoder->mpsDataBits += mpsDataBits; + FDKinitBitStream(&mpsBsData, pMpegSurroundDecoder->mpsData, + MAX_BUFSIZE_BYTES, + pMpegSurroundDecoder->mpsDataBits, BS_READER); + hMpsBsData = &mpsBsData; + break; + + case MPEGS_START_STOP: + pMpegSurroundDecoder->mpsDataBits = mpsDataBits; + hMpsBsData = hBs; + break; + + default: + FDK_ASSERT(0); + } + + if ((ancStartStop == MPEGS_STOP) || + (ancStartStop == MPEGS_START_STOP)) { + switch (ancType) { + case MPEGS_ANCTYPE_HEADER_AND_FRAME: { + int parseResult, bitsRead; + SPATIAL_SPECIFIC_CONFIG spatialSpecificConfigTmp = + pMpegSurroundDecoder->spatialSpecificConfigBackup; + + /* Parse spatial specific config */ + bitsRead = (INT)FDKgetValidBits(hMpsBsData); + + err = SpatialDecParseSpecificConfigHeader( + hMpsBsData, + &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec, + pMpegSurroundDecoder->upmixType); + + bitsRead = (bitsRead - (INT)FDKgetValidBits(hMpsBsData)); + parseResult = ((err == MPS_OK) ? bitsRead : -bitsRead); + + if (parseResult < 0) { + parseResult = -parseResult; + err = MPS_PARSE_ERROR; + } else if (err == MPS_OK) { + /* Check SSC for consistency (e.g. bit errors could cause + * trouble) */ + err = sscCheckInBand( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + frameSize, sampleRate); + } + if (err != MPS_OK) { + pMpegSurroundDecoder->spatialSpecificConfigBackup = + spatialSpecificConfigTmp; + break; + } + + pMpegSurroundDecoder->mpsDataBits -= parseResult; + + /* Initiate re-initialization, if header has changed */ + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sscParse) == MPS_UNEQUAL_SSC) { + pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse] |= + MPEGS_INIT_CHANGE_HEADER; + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + /* We found a valid in-band configuration. Therefore any + * previous config is invalid now. */ + pMpegSurroundDecoder->mpegSurroundSscIsGlobalCfg = 0; + } + } + FDK_FALLTHROUGH; + case MPEGS_ANCTYPE_FRAME: + + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse] & + MPEGS_INIT_ERROR_PAYLOAD) { + err = MPS_PARSE_ERROR; + break; + } + + /* First spatial specific config is parsed into + * spatialSpecificConfigBackup, second spatialSpecificConfigBackup + * is copied into spatialSpecificConfig[bsFrameDecode] */ + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameParse]) { + FDKmemcpy(sscParse, + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + sizeof(SPATIAL_SPECIFIC_CONFIG)); + pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameParse] = + MPEGS_SYNC_FOUND; + } + + if (pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameParse] >= + MPEGS_SYNC_FOUND) { + int nbits = 0, bitsAvail; + + if (err != MPS_OK) { + break; + } + + bitsAvail = FDKgetValidBits(hMpsBsData); + + if (bitsAvail <= 0) { + err = MPS_PARSE_ERROR; + } else { + err = SpatialDecParseFrameData( + pMpegSurroundDecoder->pSpatialDec, bsFrame, hMpsBsData, + sscParse, (UPMIXTYPE)pMpegSurroundDecoder->upmixType, + fGlobalIndependencyFlag); + if (err == MPS_OK) { + bsFrame->newBsData = 1; + } + } + + nbits = bitsAvail - (INT)FDKgetValidBits(hMpsBsData); + + if ((nbits > bitsAvail) || + (nbits > pMpegSurroundDecoder->mpsDataBits) || + (pMpegSurroundDecoder->mpsDataBits > nbits + 7 && + !IS_LOWDELAY(coreCodec))) { + bsFrame->newBsData = 0; + err = MPS_PARSE_ERROR; + break; + } + pMpegSurroundDecoder->mpsDataBits -= nbits; + } + break; + + default: /* added to avoid compiler warning */ + err = MPS_NOTOK; + break; /* added to avoid compiler warning */ + } /* switch (ancType) */ + + if (err == MPS_OK) { + pMpegSurroundDecoder->ancStartStopPrev = ancStartStop; + } else { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, + MPEGS_SYNC_LOST, MPEGS_STOP); + pMpegSurroundDecoder->mpsDataBits = 0; + } + } /* (ancStartStop == MPEGS_STOP) || (ancStartStop == MPEGS_START_STOP) + */ + } /* validAncStartStop */ + } /* validAncType */ + } + +bail: + + *pMpsDataBits -= (mpsBsBits - (INT)FDKgetValidBits(hBs)); + + return err; +} + +int mpegSurroundDecoder_Apply(CMpegSurroundDecoder *pMpegSurroundDecoder, + INT_PCM *input, PCM_MPS *pTimeData, + const int timeDataSize, int timeDataFrameSize, + int *nChannels, int *frameSize, int sampleRate, + AUDIO_OBJECT_TYPE coreCodec, + AUDIO_CHANNEL_TYPE channelType[], + UCHAR channelIndices[], + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + PCM_MPS *pTimeOut = pTimeData; + UINT initControlFlags = 0, controlFlags = 0; + int timeDataRequiredSize = 0; + int newData; + + if (pMpegSurroundDecoder == NULL) { + return MPS_INVALID_HANDLE; + } + + FDK_ASSERT(pMpegSurroundDecoder->pSpatialDec); + + if (!FDK_chMapDescr_isValid(mapDescr)) { + return MPS_INVALID_HANDLE; + } + + if ((*nChannels <= 0) || (*nChannels > 2)) { + return MPS_NOTOK; + } + + pMpegSurroundDecoder->pSpatialDec->pConfigCurrent = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + newData = pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameParse] + .newBsData; + + switch (mpegSurroundOperationMode(pMpegSurroundDecoder, 1000)) { + case MPEGS_OPMODE_MPS_PAYLOAD: + if (pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + } + + if (err == MPS_OK) { + if ((pMpegSurroundDecoder + ->fOnSync[pMpegSurroundDecoder->bsFrameDecode] != + MPEGS_SYNC_COMPLETE) && + (pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode] + .bsIndependencyFlag == 1)) { + /* We got a valid header and independently decodeable frame data. + -> Go to the next sync level and start processing. */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_COMPLETE; + } + } else { + /* We got a valid config header but found an error while parsing the + bitstream. Wait for the next independent frame and apply error + conealment in the meantime. */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_FOUND; + controlFlags |= MPEGS_CONCEAL; + err = MPS_OK; + } + /* + Concealment: + - Bitstream is available, no sync found during bitstream processing + - Bitstream is available, sync lost due to corrupted bitstream + - Bitstream is available, sync found but no independent frame + */ + if (pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] != + MPEGS_SYNC_COMPLETE) { + controlFlags |= MPEGS_CONCEAL; + } + break; + + case MPEGS_OPMODE_NO_MPS_PAYLOAD: + /* Concealment: No bitstream is available */ + controlFlags |= MPEGS_CONCEAL; + break; + + default: + err = MPS_NOTOK; + } + + if (err != MPS_OK) { + goto bail; + } + + /* + * Force BypassMode if choosen by user + */ + if (pMpegSurroundDecoder->mpegSurroundUserParams.bypassMode) { + controlFlags |= MPEGS_BYPASSMODE; + } + + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode]) { + int startWithDfltCfg = 0; + /* + * Init with a default configuration if we came here and are still not + * initialized. + */ + if (pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] & + MPEGS_INIT_ENFORCE_REINIT) { + /* Get default spatial specific config */ + if (FDK_SpatialDecInitDefaultSpatialSpecificConfig( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, coreCodec, + *nChannels, sampleRate, + *frameSize / + mpegSurroundDecoder_GetNrOfQmfBands(NULL, sampleRate), + pMpegSurroundDecoder->mpegSurroundDecoderLevel, + pMpegSurroundDecoder->mpegSurroundUserParams.blindEnable)) { + err = MPS_NOTOK; + goto bail; + } + + /* Initiate re-initialization, if header has changed */ + if (FDK_SpatialDecCompareSpatialSpecificConfigHeader( + &pMpegSurroundDecoder->spatialSpecificConfigBackup, + &pMpegSurroundDecoder->spatialSpecificConfig + [pMpegSurroundDecoder->bsFrameDecode]) == MPS_UNEQUAL_SSC) { + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_HEADER; + SpatialDecInitParserContext(pMpegSurroundDecoder->pSpatialDec); + } + + startWithDfltCfg = 1; + } + + /* First spatial specific config is parsed into spatialSpecificConfigBackup, + * second spatialSpecificConfigBackup is copied into spatialSpecificConfig + */ + err = initMpegSurroundDecoder(pMpegSurroundDecoder); + + if (startWithDfltCfg) { + /* initialized with default config, but no sync found */ + /* maybe use updateMpegSurroundDecoderStatus later on */ + pMpegSurroundDecoder->fOnSync[pMpegSurroundDecoder->bsFrameDecode] = + MPEGS_SYNC_LOST; + } + + /* Since we do not have state MPEGS_SYNC_COMPLETE apply concealment */ + controlFlags |= MPEGS_CONCEAL; + + if (err != MPS_OK) { + goto bail; + } + } + + /* + * Process MPEG Surround Audio + */ + initControlFlags = controlFlags; + + /* Check that provided output buffer is large enough. */ + if (pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis == 0) { + err = MPS_UNSUPPORTED_FORMAT; + goto bail; + } + timeDataRequiredSize = + (timeDataFrameSize * + pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT * + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; + if (timeDataSize < timeDataRequiredSize) { + err = MPS_OUTPUT_BUFFER_TOO_SMALL; + goto bail; + } + + if ((pMpegSurroundDecoder->pSpatialDec->pConfigCurrent->syntaxFlags & + SACDEC_SYNTAX_USAC) && + (pMpegSurroundDecoder->pSpatialDec->stereoConfigIndex > 1)) { + FDK_ASSERT(timeDataRequiredSize >= timeDataFrameSize * *nChannels); + /* Place samples comprising QMF time slots spaced at QMF output Band raster + * to allow slot wise processing */ + int timeDataFrameSizeOut = + (timeDataFrameSize * + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsSynthesis) / + pMpegSurroundDecoder->pQmfDomain->globalConf.nBandsAnalysis; + pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = + pTimeData + timeDataFrameSizeOut - timeDataFrameSize; + for (int i = *nChannels - 1; i >= 0; i--) { + FDKmemmove(pTimeData + (i + 1) * timeDataFrameSizeOut - timeDataFrameSize, + pTimeData + timeDataFrameSize * i, + sizeof(PCM_MPS) * timeDataFrameSize); + FDKmemclear(pTimeData + i * timeDataFrameSizeOut, + sizeof(PCM_MPS) * (timeDataFrameSizeOut - timeDataFrameSize)); + } + } else { + if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface) { + FDKmemcpy(input, pTimeData, + sizeof(INT_PCM) * (*nChannels) * (*frameSize)); + pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput = input; + } + } + + /* + * Process MPEG Surround Audio + */ + err = SpatialDecApplyFrame( + pMpegSurroundDecoder->pSpatialDec, + &pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode], + pMpegSurroundDecoder->mpegSurroundUseTimeInterface ? INPUTMODE_TIME + : INPUTMODE_QMF_SBR, + pMpegSurroundDecoder->pQmfDomain->globalConf.TDinput, NULL, NULL, + pTimeOut, *frameSize, &controlFlags, *nChannels, mapDescr); + *nChannels = pMpegSurroundDecoder->pSpatialDec->numOutputChannelsAT; + + if (err != + MPS_OK) { /* A fatal error occured. Go back to start and try again: */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ENFORCE_REINIT, MPEGS_SYNC_LOST, + MPEGS_STOP); + *frameSize = + 0; /* Declare that framework can not use the data in pTimeOut. */ + } else { + if (((controlFlags & MPEGS_CONCEAL) && + !(initControlFlags & MPEGS_CONCEAL)) || + (pMpegSurroundDecoder->pSpatialDec->errInt != + MPS_OK)) { /* Account for errors that occured in + SpatialDecApplyFrame(): */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_ERROR_PAYLOAD, MPEGS_SYNC_LOST, + MPEGS_STOP); + } + } + + if ((err == MPS_OK) && !(controlFlags & MPEGS_BYPASSMODE) && + !(pMpegSurroundDecoder->upmixType == UPMIX_TYPE_BYPASS)) { + SpatialDecChannelProperties(pMpegSurroundDecoder->pSpatialDec, channelType, + channelIndices, mapDescr); + } + +bail: + + if (newData) { + /* numParameterSetsPrev shall only be read in the decode process, because of + that we can update this state variable here */ + pMpegSurroundDecoder->pSpatialDec->numParameterSetsPrev = + pMpegSurroundDecoder->bsFrames[pMpegSurroundDecoder->bsFrameDecode] + .numParameterSets; + } + + return (err); +} + +/** + * \brief Free config dependent MPEG Surround memory. + **/ +SACDEC_ERROR mpegSurroundDecoder_FreeMem( + CMpegSurroundDecoder *pMpegSurroundDecoder) { + SACDEC_ERROR err = MPS_OK; + + if (pMpegSurroundDecoder != NULL) { + FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec = NULL; + } + + return err; +} + +/** + * \brief Close MPEG Surround decoder. + **/ +void mpegSurroundDecoder_Close(CMpegSurroundDecoder *pMpegSurroundDecoder) { + if (pMpegSurroundDecoder != NULL) { + FDK_SpatialDecClose(pMpegSurroundDecoder->pSpatialDec); + pMpegSurroundDecoder->pSpatialDec = NULL; + + for (int i = 0; i < 1; i++) { + SpatialDecCloseBsFrame(&pMpegSurroundDecoder->bsFrames[i]); + } + + FDK_FREE_MEMORY_1D(pMpegSurroundDecoder); + } +} + +#define SACDEC_VL0 2 +#define SACDEC_VL1 0 +#define SACDEC_VL2 0 + +int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + + info += i; + + info->module_id = FDK_MPSDEC; +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = "MPEG Surround Decoder"; + info->version = LIB_VERSION(SACDEC_VL0, SACDEC_VL1, SACDEC_VL2); + LIB_VERSION_STRING(info); + info->flags = 0 | CAPF_MPS_LD | CAPF_MPS_USAC | CAPF_MPS_HQ | + CAPF_MPS_1CH_IN | CAPF_MPS_2CH_OUT; /* end flags */ + + return 0; +} + +SACDEC_ERROR mpegSurroundDecoder_SetParam( + CMpegSurroundDecoder *pMpegSurroundDecoder, const SACDEC_PARAM param, + const INT value) { + SACDEC_ERROR err = MPS_OK; + SPATIALDEC_PARAM *pUserParams = NULL; + + /* check decoder handle */ + if (pMpegSurroundDecoder != NULL) { + /* init local shortcuts */ + pUserParams = &pMpegSurroundDecoder->mpegSurroundUserParams; + } else { + err = MPS_INVALID_HANDLE; + /* check the parameter values before exiting. */ + } + + /* apply param value */ + switch (param) { + case SACDEC_OUTPUT_MODE: + switch ((SAC_DEC_OUTPUT_MODE)value) { + case SACDEC_OUT_MODE_NORMAL: + case SACDEC_OUT_MODE_STEREO: + break; + default: + err = MPS_INVALID_PARAMETER; + } + if (err == MPS_OK) { + if (0) { + err = MPS_INVALID_PARAMETER; + } else if (pUserParams->outputMode != (UCHAR)value) { + pUserParams->outputMode = (UCHAR)value; + pMpegSurroundDecoder + ->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_OUTPUT_MODE; + } + } + break; + + case SACDEC_INTERFACE: + if (value < 0 || value > 1) { + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pMpegSurroundDecoder->mpegSurroundUseTimeInterface != (UCHAR)value) { + pMpegSurroundDecoder->mpegSurroundUseTimeInterface = (UCHAR)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_TIME_FREQ_INTERFACE; + } + break; + + case SACDEC_BS_INTERRUPTION: + if ((err == MPS_OK) && (value != 0)) { + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_BS_INTERRUPTION, + MPEGS_SYNC_LOST, MPEGS_STOP); + } + break; + + case SACDEC_CLEAR_HISTORY: + if ((err == MPS_OK) && (value != 0)) { + /* Just reset the states and go on. */ + updateMpegSurroundDecoderStatus(pMpegSurroundDecoder, + MPEGS_INIT_CLEAR_HISTORY, + MPEGS_SYNC_LOST, MPEGS_STOP); + } + break; + + case SACDEC_CONCEAL_NUM_KEEP_FRAMES: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealNumKeepFrames != (UINT)value) { + pUserParams->concealNumKeepFrames = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_FADE_OUT_SLOPE_LENGTH: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealFadeOutSlopeLength != (UINT)value) { + pUserParams->concealFadeOutSlopeLength = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_FADE_IN_SLOPE_LENGTH: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealFadeInSlopeLength != (UINT)value) { + pUserParams->concealFadeInSlopeLength = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + case SACDEC_CONCEAL_NUM_RELEASE_FRAMES: + if (value < 0) { /* Check valid value range */ + err = MPS_INVALID_PARAMETER; + } + if (err != MPS_OK) { + goto bail; + } + if (pUserParams->concealNumReleaseFrames != (UINT)value) { + pUserParams->concealNumReleaseFrames = (UINT)value; + pMpegSurroundDecoder->initFlags[pMpegSurroundDecoder->bsFrameDecode] |= + MPEGS_INIT_CHANGE_CONCEAL_PARAMS; + } + break; + + default: + err = MPS_INVALID_PARAMETER; + break; + } /* switch(param) */ + +bail: + return err; +} + +SACDEC_ERROR mpegSurroundDecoder_IsPseudoLR( + CMpegSurroundDecoder *pMpegSurroundDecoder, int *bsPseudoLr) { + if (pMpegSurroundDecoder != NULL) { + const SPATIAL_SPECIFIC_CONFIG *sscDecode = + &pMpegSurroundDecoder + ->spatialSpecificConfig[pMpegSurroundDecoder->bsFrameDecode]; + *bsPseudoLr = (int)sscDecode->bsPseudoLr; + return MPS_OK; + } else + return MPS_INVALID_HANDLE; +} + +/** + * \brief Get the signal delay caused by the MPEG Surround decoder module. + **/ +UINT mpegSurroundDecoder_GetDelay(const CMpegSurroundDecoder *self) { + INT outputDelay = 0; + + if (self != NULL) { + const SPATIAL_SPECIFIC_CONFIG *sscDecode = + &self->spatialSpecificConfig[self->bsFrameDecode]; + AUDIO_OBJECT_TYPE coreCodec = sscDecode->coreCodec; + + /* See chapter 4.5 (delay and synchronization) of ISO/IEC FDIS 23003-1 and + chapter 5.4.3 of ISO/IEC FDIS 23003-2 for details on the following + figures. */ + + if (coreCodec > AOT_NULL_OBJECT) { + if (IS_LOWDELAY(coreCodec)) { + /* All low delay variants (ER-AAC-(E)LD): */ + outputDelay += 256; + } else if (!IS_USAC(coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) + * branch: */ + outputDelay += 320 + 257; /* cos to exp delay + QMF synthesis */ + if (self->mpegSurroundUseTimeInterface) { + outputDelay += 320 + 384; /* QMF and hybrid analysis */ + } + } + } + } + + return (outputDelay); +} diff --git a/fdk-aac/libSACdec/src/sac_dec_ssc_struct.h b/fdk-aac/libSACdec/src/sac_dec_ssc_struct.h new file mode 100644 index 0000000..b67b465 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_dec_ssc_struct.h @@ -0,0 +1,283 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: interface - spatial specific config struct + +*******************************************************************************/ + +#ifndef SAC_DEC_SSC_STRUCT_H +#define SAC_DEC_SSC_STRUCT_H + +#include "FDK_audio.h" + +#define MAX_NUM_QMF_BANDS (128) +#define MAX_TIME_SLOTS 64 +#define MAX_INPUT_CHANNELS 1 +#define MAX_OUTPUT_CHANNELS \ + 2 /* CAUTION: This does NOT restrict the number of \ + output channels exclusively! In addition it \ + affects the max number of bitstream and residual channels! */ +#define MAX_NUM_OTT (5) +#define MAX_NUM_TTT (0) +#define MAX_NUM_EXT_TYPES (8) +#define MAX_PARAMETER_BANDS (28) +#define MAX_PARAMETER_BANDS_LD (23) + +#define MAX_NUM_XCHANNELS (6) + +#define MAX_ARBITRARY_TREE_LEVELS (0) + +typedef enum { + /* CAUTION: Do not change enum values! */ + SPATIALDEC_FREQ_RES_40 = 40, + SPATIALDEC_FREQ_RES_28 = 28, + SPATIALDEC_FREQ_RES_23 = 23, + SPATIALDEC_FREQ_RES_20 = 20, + SPATIALDEC_FREQ_RES_15 = 15, + SPATIALDEC_FREQ_RES_14 = 14, + SPATIALDEC_FREQ_RES_12 = 12, + SPATIALDEC_FREQ_RES_10 = 10, + SPATIALDEC_FREQ_RES_9 = 9, + SPATIALDEC_FREQ_RES_7 = 7, + SPATIALDEC_FREQ_RES_5 = 5, + SPATIALDEC_FREQ_RES_4 = 4 + +} SPATIALDEC_FREQ_RES; + +typedef enum { + + SPATIALDEC_QUANT_FINE_DEF = 0, + SPATIALDEC_QUANT_EDQ1 = 1, + SPATIALDEC_QUANT_EDQ2 = 2, + SPATIALDEC_QUANT_RSVD3 = 3, + SPATIALDEC_QUANT_RSVD4 = 4, + SPATIALDEC_QUANT_RSVD5 = 5, + SPATIALDEC_QUANT_RSVD6 = 6, + SPATIALDEC_QUANT_RSVD7 = 7 + +} SPATIALDEC_QUANT_MODE; + +typedef enum { SPATIALDEC_MODE_RSVD7 = 7 } SPATIALDEC_TREE_CONFIG; + +typedef enum { + + SPATIALDEC_GAIN_MODE0 = 0, + SPATIALDEC_GAIN_RSVD1 = 1, + SPATIALDEC_GAIN_RSVD2 = 2, + SPATIALDEC_GAIN_RSVD3 = 3, + SPATIALDEC_GAIN_RSVD4 = 4, + SPATIALDEC_GAIN_RSVD5 = 5, + SPATIALDEC_GAIN_RSVD6 = 6, + SPATIALDEC_GAIN_RSVD7 = 7, + SPATIALDEC_GAIN_RSVD8 = 8, + SPATIALDEC_GAIN_RSVD9 = 9, + SPATIALDEC_GAIN_RSVD10 = 10, + SPATIALDEC_GAIN_RSVD11 = 11, + SPATIALDEC_GAIN_RSVD12 = 12, + SPATIALDEC_GAIN_RSVD13 = 13, + SPATIALDEC_GAIN_RSVD14 = 14, + SPATIALDEC_GAIN_RSVD15 = 15 + +} SPATIALDEC_FIXED_GAINS; + +typedef enum { + + SPATIALDEC_TS_TPNOWHITE = 0, + SPATIALDEC_TS_TPWHITE = 1, + SPATIALDEC_TS_TES = 2, + SPATIALDEC_TS_NOTS = 3, + SPATIALDEC_TS_RSVD4 = 4, + SPATIALDEC_TS_RSVD5 = 5, + SPATIALDEC_TS_RSVD6 = 6, + SPATIALDEC_TS_RSVD7 = 7, + SPATIALDEC_TS_RSVD8 = 8, + SPATIALDEC_TS_RSVD9 = 9, + SPATIALDEC_TS_RSVD10 = 10, + SPATIALDEC_TS_RSVD11 = 11, + SPATIALDEC_TS_RSVD12 = 12, + SPATIALDEC_TS_RSVD13 = 13, + SPATIALDEC_TS_RSVD14 = 14, + SPATIALDEC_TS_RSVD15 = 15 + +} SPATIALDEC_TS_CONF; + +typedef enum { + + SPATIALDEC_DECORR_MODE0 = 0, + SPATIALDEC_DECORR_MODE1 = 1, + SPATIALDEC_DECORR_MODE2 = 2, + SPATIALDEC_DECORR_RSVD3 = 3, + SPATIALDEC_DECORR_RSVD4 = 4, + SPATIALDEC_DECORR_RSVD5 = 5, + SPATIALDEC_DECORR_RSVD6 = 6, + SPATIALDEC_DECORR_RSVD7 = 7, + SPATIALDEC_DECORR_RSVD8 = 8, + SPATIALDEC_DECORR_RSVD9 = 9, + SPATIALDEC_DECORR_RSVD10 = 10, + SPATIALDEC_DECORR_RSVD11 = 11, + SPATIALDEC_DECORR_RSVD12 = 12, + SPATIALDEC_DECORR_RSVD13 = 13, + SPATIALDEC_DECORR_RSVD14 = 14, + SPATIALDEC_DECORR_RSVD15 = 15 + +} SPATIALDEC_DECORR_CONF; + +typedef struct T_SPATIALDEC_OTT_CONF { + int nOttBands; + +} SPATIALDEC_OTT_CONF; + +typedef struct T_SPATIALDEC_RESIDUAL_CONF { + int bResidualPresent; + int nResidualBands; + +} SPATIALDEC_RESIDUAL_CONF; + +typedef struct T_SPATIAL_SPECIFIC_CONFIG { + UINT syntaxFlags; + int samplingFreq; + int nTimeSlots; + SPATIALDEC_FREQ_RES freqRes; + SPATIALDEC_TREE_CONFIG treeConfig; + SPATIALDEC_QUANT_MODE quantMode; + int bArbitraryDownmix; + + int bResidualCoding; + SPATIALDEC_FIXED_GAINS bsFixedGainDMX; + + SPATIALDEC_TS_CONF tempShapeConfig; + SPATIALDEC_DECORR_CONF decorrConfig; + + int nInputChannels; /* derived from treeConfig */ + int nOutputChannels; /* derived from treeConfig */ + + /* ott config */ + int nOttBoxes; /* derived from treeConfig */ + SPATIALDEC_OTT_CONF OttConfig[MAX_NUM_OTT]; /* dimension nOttBoxes */ + + /* ttt config */ + int nTttBoxes; /* derived from treeConfig */ + + /* residual config */ + SPATIALDEC_RESIDUAL_CONF + ResidualConfig[MAX_NUM_OTT + + MAX_NUM_TTT]; /* dimension (nOttBoxes + nTttBoxes) */ + + int sacExtCnt; + int sacExtType[MAX_NUM_EXT_TYPES]; + int envQuantMode; + + AUDIO_OBJECT_TYPE coreCodec; + + UCHAR stereoConfigIndex; + UCHAR coreSbrFrameLengthIndex; /* Table 70 in ISO/IEC FDIS 23003-3:2011 */ + UCHAR bsHighRateMode; + UCHAR bsDecorrType; + UCHAR bsPseudoLr; + UCHAR bsPhaseCoding; + UCHAR bsOttBandsPhasePresent; + int bsOttBandsPhase; + + SCHAR ottCLDdefault[MAX_NUM_OTT]; + UCHAR numOttBandsIPD; + UCHAR bitstreamOttBands[MAX_NUM_OTT]; + UCHAR numOttBands[MAX_NUM_OTT]; + +} SPATIAL_SPECIFIC_CONFIG; + +#endif diff --git a/fdk-aac/libSACdec/src/sac_process.cpp b/fdk-aac/libSACdec/src/sac_process.cpp new file mode 100644 index 0000000..56c72ad --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_process.cpp @@ -0,0 +1,1066 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Processing + +*******************************************************************************/ + +/* data structures and interfaces for spatial audio reference software */ +#include "sac_process.h" + +#include "sac_bitdec.h" +#include "sac_calcM1andM2.h" +#include "sac_smoothing.h" +#include "sac_rom.h" + +#include "sac_dec_errorcodes.h" + +#include "FDK_trigFcts.h" +#include "FDK_decorrelate.h" + +/** + * \brief Linear interpolation between two parameter values. + * a*alpha + b*(1-alpha) + * = a*alpha + b - b*alpha + * + * \param alpha Weighting factor. + * \param a Parameter a. + * \param b Parameter b. + * + * \return Interpolated parameter value. + */ +FDK_INLINE FIXP_DBL interpolateParameter(const FIXP_SGL alpha, const FIXP_DBL a, + const FIXP_DBL b) { + return (b - fMult(alpha, b) + fMult(alpha, a)); +} + +/** + * \brief Map MPEG Surround channel indices to MPEG 4 PCE like channel indices. + * \param self Spatial decoder handle. + * \param ch MPEG Surround channel index. + * \return MPEG 4 PCE style channel index, corresponding to the given MPEG + * Surround channel index. + */ +static UINT mapChannel(spatialDec *self, UINT ch) { + static const UCHAR chanelIdx[][8] = { + {0, 1, 2, 3, 4, 5, 6, 7}, /* binaural, TREE_212, arbitrary tree */ + }; + + int idx = 0; + + return (chanelIdx[idx][ch]); +} + +FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale) { + /* init no gain modifier */ + FIXP_DBL gain = 0x80000000; + *scale = 0; + + if ((!isTwoChMode(self->upmixType)) && + (self->upmixType != UPMIXTYPE_BYPASS)) { + if ((ch == 0) || (ch == 1) || (ch == 2)) { + /* no modifier */ + } + } + + return gain; +} + +SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, + const INT ts, const INT bypassMode, + FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const int numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch, offset; + + offset = self->pQmfDomain->globalConf.nBandsSynthesis * + self->pQmfDomain->globalConf.nQmfTimeSlots; + + { + for (ch = 0; ch < numInputChannels; ch++) { + const PCM_MPS *inSamples = + &inData[ts * self->pQmfDomain->globalConf.nBandsAnalysis]; + FIXP_DBL *pQmfRealAnalysis = qmfReal[ch]; /* no delay in blind mode */ + FIXP_DBL *pQmfImagAnalysis = qmfImag[ch]; + + CalculateSpaceAnalysisQmf(&self->pQmfDomain->QmfDomainIn[ch].fb, + inSamples + (ch * offset), pQmfRealAnalysis, + pQmfImagAnalysis); + + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + for (i = 0; i < self->qmfBands; i++) { + qmfReal[ch][i] = fMult(qmfReal[ch][i], self->clipProtectGain__FDK); + qmfImag[ch][i] = fMult(qmfImag[ch][i], self->clipProtectGain__FDK); + } + } + } + } + + self->qmfInputDelayBufPos = + (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; + + return err; +} + +SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, + FIXP_DBL **qmfInDataImag, const INT ts, + const INT bypassMode, FIXP_DBL **qmfReal__FDK, + FIXP_DBL **qmfImag__FDK, + const INT numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch; + + { + for (ch = 0; ch < numInputChannels; ch++) { + FIXP_DBL *pQmfRealAnalysis = + qmfReal__FDK[ch]; /* no delay in blind mode */ + FIXP_DBL *pQmfImagAnalysis = qmfImag__FDK[ch]; + + /* Write Input data to pQmfRealAnalysis. */ + if (self->bShareDelayWithSBR) { + FDK_QmfDomain_GetSlot( + &self->pQmfDomain->QmfDomainIn[ch], ts + HYBRID_FILTER_DELAY, 0, + MAX_QMF_BANDS_TO_HYBRID, pQmfRealAnalysis, pQmfImagAnalysis, 15); + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, + MAX_QMF_BANDS_TO_HYBRID, self->qmfBands, + pQmfRealAnalysis, pQmfImagAnalysis, 15); + } else { + FDK_QmfDomain_GetSlot(&self->pQmfDomain->QmfDomainIn[ch], ts, 0, + self->qmfBands, pQmfRealAnalysis, + pQmfImagAnalysis, 15); + } + if (ts == self->pQmfDomain->globalConf.nQmfTimeSlots - 1) { + /* Is currently also needed in case we dont have any overlap. We need to + * save lb_scale to ov_lb_scale */ + FDK_QmfDomain_SaveOverlap(&self->pQmfDomain->QmfDomainIn[ch], 0); + } + + /* Apply clip protection to output. */ + if (!isTwoChMode(self->upmixType) && !bypassMode) { + int i; + for (i = 0; i < self->qmfBands; i++) { + qmfReal__FDK[ch][i] = + fMult(qmfReal__FDK[ch][i], self->clipProtectGain__FDK); + qmfImag__FDK[ch][i] = + fMult(qmfImag__FDK[ch][i], self->clipProtectGain__FDK); + } + } + + } /* End of loop over numInputChannels */ + } + + self->qmfInputDelayBufPos = + (self->qmfInputDelayBufPos + 1) % self->pc_filterdelay; + + return err; +} + +/******************************************************************************* + Functionname: SpatialDecHybridAnalysis + ******************************************************************************* + + Description: + + Arguments: + + Input: + float** pointers[4] leftReal, leftIm, rightReal, rightIm + + Output: + float self->qmfInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; + float self->qmfInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_QMF_BANDS]; + + float +self->hybInputReal[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; float +self->hybInputImag[MAX_INPUT_CHANNELS][MAX_TIME_SLOTS][MAX_HYBRID_BANDS]; + + +*******************************************************************************/ +SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal, + FIXP_DBL **qmfInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, const INT ts, + const INT numInputChannels) { + SACDEC_ERROR err = MPS_OK; + int ch; + + for (ch = 0; ch < numInputChannels; + ch++) /* hybrid filtering for down-mix signals */ + { + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + int k; + /* No hybrid filtering. Just copy the QMF data. */ + for (k = 0; k < self->hybridBands; k += 1) { + hybOutputReal[ch][k] = qmfInputReal[ch][k]; + hybOutputImag[ch][k] = qmfInputImag[ch][k]; + } + } else { + self->hybridAnalysis[ch].hfMode = self->bShareDelayWithSBR; + + if (self->stereoConfigIndex == 3) + FDK_ASSERT(self->hybridAnalysis[ch].hfMode == 0); + FDKhybridAnalysisApply(&self->hybridAnalysis[ch], qmfInputReal[ch], + qmfInputImag[ch], hybOutputReal[ch], + hybOutputImag[ch]); + } + } + + if ((self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_USAC) && + self->residualCoding) { + self->hybridAnalysis[numInputChannels].hfMode = 0; + FDKhybridAnalysisApply( + &self->hybridAnalysis[numInputChannels], + self->qmfResidualReal__FDK[0][0], self->qmfResidualImag__FDK[0][0], + self->hybResidualReal__FDK[0], self->hybResidualImag__FDK[0]); + } + + return err; +} + +SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, FIXP_DBL **pxReal, + FIXP_DBL **pxImag) { + SACDEC_ERROR err = MPS_OK; + int row; + + /* Creating wDry */ + for (row = 0; row < self->numInputChannels; row++) { + /* pointer to direct signals */ + pxReal[row] = hybInputReal[row]; + pxImag[row] = hybInputImag[row]; + } + + return err; +} + +static void M2ParamToKernelMult(FIXP_SGL *RESTRICT pKernel, + FIXP_DBL *RESTRICT Mparam, + FIXP_DBL *RESTRICT MparamPrev, + int *RESTRICT pWidth, FIXP_SGL alpha__FDK, + int nBands) { + int pb; + + for (pb = 0; pb < nBands; pb++) { + FIXP_SGL tmp = FX_DBL2FX_SGL( + interpolateParameter(alpha__FDK, Mparam[pb], MparamPrev[pb])); + + int i = pWidth[pb]; + if (i & 1) *pKernel++ = tmp; + if (i & 2) { + *pKernel++ = tmp; + *pKernel++ = tmp; + } + for (i >>= 2; i--;) { + *pKernel++ = tmp; + *pKernel++ = tmp; + *pKernel++ = tmp; + *pKernel++ = tmp; + } + } +} + +SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212( + spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal, + FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag) { + SACDEC_ERROR err = MPS_OK; + int res; + FIXP_DBL *decorrInReal = vReal[0]; + FIXP_DBL *decorrInImag = vImag[0]; + + /* M1 does not do anything in 212 mode, so use simplified processing */ + FDK_ASSERT(self->numVChannels == 2); + FDK_ASSERT(self->numDirektSignals == 1); + FDK_ASSERT(self->numDecorSignals == 1); + FDKmemcpy(vReal[0], xReal[0], self->hybridBands * sizeof(FIXP_DBL)); + FDKmemcpy(vImag[0], xImag[0], self->hybridBands * sizeof(FIXP_DBL)); + + if (isTsdActive(frame->TsdData)) { + /* Generate v_{x,nonTr} as input for allpass based decorrelator */ + TsdGenerateNonTr(self->hybridBands, frame->TsdData, self->TsdTs, vReal[0], + vImag[0], vReal[1], vImag[1], &decorrInReal, + &decorrInImag); + } + /* - Decorrelate */ + res = SpatialDecGetResidualIndex(self, 1); + if (FDKdecorrelateApply(&self->apDecor[0], decorrInReal, decorrInImag, + vReal[1], vImag[1], + self->param2hyb[self->residualBands[res]])) { + return MPS_NOTOK; + } + if (isTsdActive(frame->TsdData)) { + /* Generate v_{x,Tr}, apply transient decorrelator and add to allpass based + * decorrelator output */ + TsdApply(self->hybridBands, frame->TsdData, &self->TsdTs, + vReal[0], /* input: v_x */ + vImag[0], + vReal[1], /* input: d_{x,nonTr}; output: d_{x,nonTr} + d_{x,Tr} */ + vImag[1]); + } + + /* Write residual signal in approriate parameter bands */ + if (self->residualBands[res] > 0) { + int stopBand = self->param2hyb[self->residualBands[res]]; + FDKmemcpy(vReal[1], self->hybResidualReal__FDK[res], + fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); + FDKmemcpy(vImag[1], self->hybResidualImag__FDK[res], + fixMin(stopBand, self->hybridBands) * sizeof(FIXP_DBL)); + } /* (self->residualBands[res]>0) */ + + return err; +} + +SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps, + const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry) { + SACDEC_ERROR err = MPS_OK; + INT row; + + INT *pWidth = self->kernels_width; + /* for stereoConfigIndex == 3 case hybridBands is < 71 */ + INT pb_max = self->kernels[self->hybridBands - 1] + 1; + INT max_row = self->numOutputChannels; + + INT M2_exp = 0; + if (self->residualCoding) M2_exp = 3; + + for (row = 0; row < max_row; row++) // 2 times + { + FIXP_DBL *Mparam0 = self->M2Real__FDK[row][0]; + FIXP_DBL *Mparam1 = self->M2Real__FDK[row][1]; + FIXP_DBL *MparamPrev0 = self->M2RealPrev__FDK[row][0]; + FIXP_DBL *MparamPrev1 = self->M2RealPrev__FDK[row][1]; + + FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; + FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; + + FIXP_DBL *RESTRICT pWReal0 = wReal[0]; + FIXP_DBL *RESTRICT pWReal1 = wReal[1]; + FIXP_DBL *RESTRICT pWImag0 = wImag[0]; + FIXP_DBL *RESTRICT pWImag1 = wImag[1]; + for (INT pb = 0; pb < pb_max; pb++) { + FIXP_DBL tmp0, tmp1; + + tmp0 = interpolateParameter(alpha, Mparam0[pb], MparamPrev0[pb]); + tmp1 = interpolateParameter(alpha, Mparam1[pb], MparamPrev1[pb]); + + INT i = pWidth[pb]; + + do // about 3-4 times + { + FIXP_DBL var0, var1, real, imag; + + var0 = *pWReal0++; + var1 = *pWReal1++; + real = fMultDiv2(var0, tmp0); + var0 = *pWImag0++; + real = fMultAddDiv2(real, var1, tmp1); + var1 = *pWImag1++; + imag = fMultDiv2(var0, tmp0); + *pHybOutRealDry++ = real << (1 + M2_exp); + imag = fMultAddDiv2(imag, var1, tmp1); + *pHybOutImagDry++ = imag << (1 + M2_exp); + } while (--i != 0); + } + } + return err; +} + +SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry) { + SACDEC_ERROR err = MPS_OK; + INT row; + INT scale_param_m2; + INT *pWidth = self->kernels_width; + INT pb_max = self->kernels[self->hybridBands - 1] + 1; + + scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2; + + for (row = 0; row < self->numM2rows; row++) { + INT qs, pb; + + FIXP_DBL *RESTRICT pWReal0 = wReal[0]; + FIXP_DBL *RESTRICT pWImag0 = wImag[0]; + FIXP_DBL *RESTRICT pWReal1 = wReal[1]; + FIXP_DBL *RESTRICT pWImag1 = wImag[1]; + + FIXP_DBL *MReal0 = self->M2Real__FDK[row][0]; + FIXP_DBL *MImag0 = self->M2Imag__FDK[row][0]; + FIXP_DBL *MReal1 = self->M2Real__FDK[row][1]; + FIXP_DBL *MRealPrev0 = self->M2RealPrev__FDK[row][0]; + FIXP_DBL *MImagPrev0 = self->M2ImagPrev__FDK[row][0]; + FIXP_DBL *MRealPrev1 = self->M2RealPrev__FDK[row][1]; + + FIXP_DBL *RESTRICT pHybOutRealDry = hybOutputRealDry[row]; + FIXP_DBL *RESTRICT pHybOutImagDry = hybOutputImagDry[row]; + + FDK_ASSERT(!(self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD)); + FDK_ASSERT((pWidth[0] + pWidth[1]) >= 3); + + for (pb = 0, qs = 3; pb < 2; pb++) { + INT s; + FIXP_DBL maxVal; + FIXP_SGL mReal1; + FIXP_SGL mReal0, mImag0; + FIXP_DBL iReal0, iImag0, iReal1; + + iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); + iImag0 = -interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); + iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); + + maxVal = fAbs(iReal0) | fAbs(iImag0); + maxVal |= fAbs(iReal1); + + s = fMax(CntLeadingZeros(maxVal) - 1, 0); + s = fMin(s, scale_param_m2); + + mReal0 = FX_DBL2FX_SGL(iReal0 << s); + mImag0 = FX_DBL2FX_SGL(iImag0 << s); + mReal1 = FX_DBL2FX_SGL(iReal1 << s); + + s = scale_param_m2 - s; + + INT i = pWidth[pb]; + + do { + FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; + + wReal0 = *pWReal0++; + wImag0 = *pWImag0++; + wReal1 = *pWReal1++; + wImag1 = *pWImag1++; + + cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); + + *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; + *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; + + if (qs > 0) { + mImag0 = -mImag0; + qs--; + } + } while (--i != 0); + } + + for (; pb < pb_max; pb++) { + INT s; + FIXP_DBL maxVal; + FIXP_SGL mReal1; + FIXP_SGL mReal0, mImag0; + FIXP_DBL iReal0, iImag0, iReal1; + + iReal0 = interpolateParameter(alpha, MReal0[pb], MRealPrev0[pb]); + iImag0 = interpolateParameter(alpha, MImag0[pb], MImagPrev0[pb]); + iReal1 = interpolateParameter(alpha, MReal1[pb], MRealPrev1[pb]); + + maxVal = fAbs(iReal0) | fAbs(iImag0); + maxVal |= fAbs(iReal1); + + s = fMax(CntLeadingZeros(maxVal) - 1, 0); + s = fMin(s, scale_param_m2); + + mReal0 = FX_DBL2FX_SGL(iReal0 << s); + mImag0 = FX_DBL2FX_SGL(iImag0 << s); + mReal1 = FX_DBL2FX_SGL(iReal1 << s); + + s = scale_param_m2 - s; + + INT i = pWidth[pb]; + + do { + FIXP_DBL real, imag, wReal0, wImag0, wReal1, wImag1; + + wReal0 = *pWReal0++; + wImag0 = *pWImag0++; + wReal1 = *pWReal1++; + wImag1 = *pWImag1++; + + cplxMultDiv2(&real, &imag, wReal0, wImag0, mReal0, mImag0); + + *pHybOutRealDry++ = fMultAddDiv2(real, wReal1, mReal1) << s; + *pHybOutImagDry++ = fMultAddDiv2(imag, wImag1, mReal1) << s; + } while (--i != 0); + } + } + + return err; +} + +SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha, + FIXP_DBL **wReal, FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry, + FIXP_DBL **hybOutputRealWet, + FIXP_DBL **hybOutputImagWet) { + SACDEC_ERROR err = MPS_OK; + + { + int qs, row, col; + int complexHybBands; + int complexParBands; + int scale_param_m2 = 0; + int toolsDisabled; + + UCHAR activParamBands; + FIXP_DBL *RESTRICT pWReal, *RESTRICT pWImag, *RESTRICT pHybOutRealDry, + *RESTRICT pHybOutImagDry, *RESTRICT pHybOutRealWet, + *RESTRICT pHybOutImagWet; + C_ALLOC_SCRATCH_START(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); + + /* The wet signal is added to the dry signal directly in applyM2 if GES and + * STP are disabled */ + toolsDisabled = + ((self->tempShapeConfig == 1) || (self->tempShapeConfig == 2)) ? 0 : 1; + + { + complexHybBands = self->hybridBands; + complexParBands = self->numParameterBands; + } + + FDKmemclear(hybOutputImagDry[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumCmplxHybBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputRealDry[0], self->createParams.maxNumOutputChannels * + self->createParams.maxNumHybridBands * + sizeof(FIXP_DBL)); + + if (!toolsDisabled) { + FDKmemclear(hybOutputRealWet[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumHybridBands * sizeof(FIXP_DBL)); + FDKmemclear(hybOutputImagWet[0], + self->createParams.maxNumOutputChannels * + self->createParams.maxNumCmplxHybBands * + sizeof(FIXP_DBL)); + } + + if (self->phaseCoding == 3) { + /* + SCALE_DATA_APPLY_M2 to compensate for Div2 below ?! */ + scale_param_m2 = SCALE_PARAM_M2_212_PRED + SCALE_DATA_APPLY_M2; + } + + for (row = 0; row < self->numM2rows; row++) { + pHybOutRealDry = hybOutputRealDry[row]; + pHybOutImagDry = hybOutputImagDry[row]; + + if (toolsDisabled) { + pHybOutRealWet = hybOutputRealDry[row]; + pHybOutImagWet = hybOutputImagDry[row]; + } else { + pHybOutRealWet = hybOutputRealWet[row]; + pHybOutImagWet = hybOutputImagWet[row]; + } + + for (col = 0; col < self->numDirektSignals; col++) { + if (self->pActivM2ParamBands == + 0) { /* default setting, calculate all rows and columns */ + activParamBands = 1; + } else { + if (self->pActivM2ParamBands[MAX_M2_INPUT * row + + col]) /* table with activ and inactiv + bands exists for current + configuration */ + activParamBands = 1; + else + activParamBands = 0; + } + if (activParamBands) { + pWReal = wReal[col]; + pWImag = wImag[col]; + + M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], + self->M2RealPrev__FDK[row][col], + self->kernels_width, alpha, + self->numParameterBands); + + if (1 && (self->phaseCoding != 3)) { + /* direct signals */ + { + /* only one sample will be assigned to each row, hence + * accumulation is not neccessary; that is valid for all + * configurations */ + for (qs = 0; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] = fMult(pWReal[qs], pKernel[qs]); + pHybOutImagDry[qs] = fMult(pWImag[qs], pKernel[qs]); + } + } + } else { /* isBinauralMode(self->upmixType) */ + + for (qs = 0; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + } + + M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], + self->M2ImagPrev__FDK[row][col], + self->kernels_width, alpha, complexParBands); + + /* direct signals sign is -1 for qs = 0,2 */ + pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0]) + << (scale_param_m2); + pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0]) + << (scale_param_m2); + + pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2]) + << (scale_param_m2); + pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2]) + << (scale_param_m2); + + /* direct signals sign is +1 for qs = 1,3,4,5,...,complexHybBands */ + pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1]) + << (scale_param_m2); + pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1]) + << (scale_param_m2); + + for (qs = 3; qs < complexHybBands; qs++) { + pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + } + } /* self->upmixType */ + } /* if (activParamBands) */ + } /* self->numDirektSignals */ + + for (; col < self->numVChannels; col++) { + if (self->pActivM2ParamBands == + 0) { /* default setting, calculate all rows and columns */ + activParamBands = 1; + } else { + if (self->pActivM2ParamBands[MAX_M2_INPUT * row + + col]) /* table with activ and inactiv + bands exists for current + configuration */ + activParamBands = 1; + else + activParamBands = 0; + } + + if (activParamBands) { + int resBandIndex; + int resHybIndex; + + resBandIndex = + self->residualBands[SpatialDecGetResidualIndex(self, col)]; + resHybIndex = self->param2hyb[resBandIndex]; + + pWReal = wReal[col]; + pWImag = wImag[col]; + + M2ParamToKernelMult(pKernel, self->M2Real__FDK[row][col], + self->M2RealPrev__FDK[row][col], + self->kernels_width, alpha, + self->numParameterBands); + + if (1 && (self->phaseCoding != 3)) { + /* residual signals */ + for (qs = 0; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] += fMult(pWReal[qs], pKernel[qs]); + pHybOutImagDry[qs] += fMult(pWImag[qs], pKernel[qs]); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] += fMult(pWReal[qs], pKernel[qs]); + pHybOutImagWet[qs] += fMult(pWImag[qs], pKernel[qs]); + } + } else { /* self->upmixType */ + /* residual signals */ + FIXP_DBL *RESTRICT pHybOutReal; + FIXP_DBL *RESTRICT pHybOutImag; + + for (qs = 0; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagDry[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagWet[qs] += fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + } + + M2ParamToKernelMult(pKernel, self->M2Imag__FDK[row][col], + self->M2ImagPrev__FDK[row][col], + self->kernels_width, alpha, complexParBands); + + /* direct signals sign is -1 for qs = 0,2 */ + /* direct signals sign is +1 for qs = 1,3.. */ + if (toolsDisabled) { + pHybOutRealDry[0] += fMultDiv2(pWImag[0], pKernel[0]) + << (scale_param_m2); + pHybOutImagDry[0] -= fMultDiv2(pWReal[0], pKernel[0]) + << (scale_param_m2); + + pHybOutRealDry[1] -= fMultDiv2(pWImag[1], pKernel[1]) + << (scale_param_m2); + pHybOutImagDry[1] += fMultDiv2(pWReal[1], pKernel[1]) + << (scale_param_m2); + + pHybOutRealDry[2] += fMultDiv2(pWImag[2], pKernel[2]) + << (scale_param_m2); + pHybOutImagDry[2] -= fMultDiv2(pWReal[2], pKernel[2]) + << (scale_param_m2); + } else { + pHybOutReal = &pHybOutRealDry[0]; + pHybOutImag = &pHybOutImagDry[0]; + if (0 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[0] += fMultDiv2(pWImag[0], pKernel[0]) + << (scale_param_m2); + pHybOutImag[0] -= fMultDiv2(pWReal[0], pKernel[0]) + << (scale_param_m2); + + if (1 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[1] -= fMultDiv2(pWImag[1], pKernel[1]) + << (scale_param_m2); + pHybOutImag[1] += fMultDiv2(pWReal[1], pKernel[1]) + << (scale_param_m2); + + if (2 == resHybIndex) { + pHybOutReal = &pHybOutRealWet[0]; + pHybOutImag = &pHybOutImagWet[0]; + } + pHybOutReal[2] += fMultDiv2(pWImag[2], pKernel[2]) + << (scale_param_m2); + pHybOutImag[2] -= fMultDiv2(pWReal[2], pKernel[2]) + << (scale_param_m2); + } + + for (qs = 3; qs < resHybIndex; qs++) { + pHybOutRealDry[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagDry[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + } + /* decor signals */ + for (; qs < complexHybBands; qs++) { + pHybOutRealWet[qs] -= fMultDiv2(pWImag[qs], pKernel[qs]) + << (scale_param_m2); + pHybOutImagWet[qs] += fMultDiv2(pWReal[qs], pKernel[qs]) + << (scale_param_m2); + } + } /* self->upmixType */ + } /* if (activParamBands) { */ + } /* self->numVChannels */ + } + + C_ALLOC_SCRATCH_END(pKernel, FIXP_SGL, MAX_HYBRID_BANDS); + } + + return err; +} + +SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, PCM_MPS *timeOut, + const INT numInputChannels, + const FDK_channelMapDescr *const mapDescr) { + SACDEC_ERROR err = MPS_OK; + + int ch; + int stride, offset; + + stride = self->numOutputChannelsAT; + offset = 1; + + PCM_MPS *pTimeOut__FDK = + &timeOut[stride * self->pQmfDomain->globalConf.nBandsSynthesis * ts]; + C_ALLOC_SCRATCH_START(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + C_ALLOC_SCRATCH_START(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + + for (ch = 0; ch < self->numOutputChannelsAT; ch++) { + if (self->pConfigCurrent->syntaxFlags & SACDEC_SYNTAX_LD) { + int k; + /* No hybrid filtering. Just copy the QMF data. */ + for (k = 0; k < self->hybridBands; k += 1) { + pQmfReal[k] = hybOutputReal[ch][k]; + pQmfImag[k] = hybOutputImag[ch][k]; + } + } else { + FDKhybridSynthesisApply(&self->hybridSynthesis[ch], hybOutputReal[ch], + hybOutputImag[ch], pQmfReal, pQmfImag); + } + + /* Map channel indices from MPEG Surround -> PCE style -> channelMapping[] + */ + FDK_ASSERT(self->numOutputChannelsAT <= 6); + int outCh = FDK_chMapDescr_getMapValue(mapDescr, mapChannel(self, ch), + self->numOutputChannelsAT); + + { + if (self->stereoConfigIndex == 3) { + /* MPS -> SBR */ + int i; + FIXP_DBL *pWorkBufReal, *pWorkBufImag; + FDK_ASSERT((self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_m == + (FIXP_DBL)0x80000000) && + (self->pQmfDomain->QmfDomainOut[outCh].fb.outGain_e == 0)); + FDK_QmfDomain_GetWorkBuffer(&self->pQmfDomain->QmfDomainIn[outCh], ts, + &pWorkBufReal, &pWorkBufImag); + FDK_ASSERT(self->qmfBands <= + self->pQmfDomain->QmfDomainIn[outCh].workBuf_nBands); + for (i = 0; i < self->qmfBands; i++) { + pWorkBufReal[i] = pQmfReal[i]; + pWorkBufImag[i] = pQmfImag[i]; + } + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale = + -7; /*-ALGORITHMIC_SCALING_IN_ANALYSIS_FILTERBANK;*/ + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= + self->pQmfDomain->QmfDomainIn[outCh].fb.filterScale; + self->pQmfDomain->QmfDomainIn[outCh].scaling.lb_scale -= + self->clipProtectGainSF__FDK; + + } else { + /* Call the QMF synthesis for dry. */ + err = CalculateSpaceSynthesisQmf(&self->pQmfDomain->QmfDomainOut[outCh], + pQmfReal, pQmfImag, stride, + pTimeOut__FDK + (offset * outCh)); + } + if (err != MPS_OK) goto bail; + } + } /* ch loop */ + +bail: + C_ALLOC_SCRATCH_END(pQmfImag, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + C_ALLOC_SCRATCH_END(pQmfReal, FIXP_DBL, QMF_MAX_SYNTHESIS_BANDS); + + return err; +} + +void SpatialDecBufferMatrices(spatialDec *self) { + int row, col; + int complexParBands; + complexParBands = self->numParameterBands; + + /* + buffer matrices M2 + */ + for (row = 0; row < self->numM2rows; row++) { + for (col = 0; col < self->numVChannels; col++) { + FDKmemcpy(self->M2RealPrev__FDK[row][col], self->M2Real__FDK[row][col], + self->numParameterBands * sizeof(FIXP_DBL)); + if (0 || (self->phaseCoding == 3)) { + FDKmemcpy(self->M2ImagPrev__FDK[row][col], self->M2Imag__FDK[row][col], + complexParBands * sizeof(FIXP_DBL)); + } + } + } + + /* buffer phase */ + FDKmemcpy(self->PhasePrevLeft__FDK, self->PhaseLeft__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + FDKmemcpy(self->PhasePrevRight__FDK, self->PhaseRight__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); +} + +#define PHASE_SCALE 2 + +#ifndef P_PI +#define P_PI 3.1415926535897932 +#endif + +/* For better precision, PI (pi_x2) is already doubled */ +static FIXP_DBL interp_angle__FDK(FIXP_DBL angle1, FIXP_DBL angle2, + FIXP_SGL alpha, FIXP_DBL pi_x2) { + if (angle2 - angle1 > (pi_x2 >> 1)) angle2 -= pi_x2; + + if (angle1 - angle2 > (pi_x2 >> 1)) angle1 -= pi_x2; + + return interpolateParameter(alpha, angle2, angle1); +} + +/* + * + */ +void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha__FDK, + int lastSlotOfParamSet) { + int pb, qs; + FIXP_DBL ppb[MAX_PARAMETER_BANDS * + 4]; /* left real, imag - right real, imag interleaved */ + + const FIXP_DBL pi_x2 = PIx2__IPD; + for (pb = 0; pb < self->numParameterBands; pb++) { + FIXP_DBL pl, pr; + + pl = interp_angle__FDK(self->PhasePrevLeft__FDK[pb], + self->PhaseLeft__FDK[pb], alpha__FDK, pi_x2); + pr = interp_angle__FDK(self->PhasePrevRight__FDK[pb], + self->PhaseRight__FDK[pb], alpha__FDK, pi_x2); + + inline_fixp_cos_sin(pl, pr, IPD_SCALE, &ppb[4 * pb]); + } + + /* sign is -1 for qs = 0,2 and +1 for qs = 1 */ + + const SCHAR *kernels = &self->kernels[0]; + + FIXP_DBL *Dry_real0 = &self->hybOutputRealDry__FDK[0][0]; + FIXP_DBL *Dry_imag0 = &self->hybOutputImagDry__FDK[0][0]; + FIXP_DBL *Dry_real1 = &self->hybOutputRealDry__FDK[1][0]; + FIXP_DBL *Dry_imag1 = &self->hybOutputImagDry__FDK[1][0]; + + for (qs = 2; qs >= 0; qs--) { + FIXP_DBL out_re, out_im; + + pb = *kernels++; + if (qs == 1) /* sign[qs] >= 0 */ + { + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } else { + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + -ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + -ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } + } + + /* sign is +1 for qs >=3 */ + for (qs = self->hybridBands - 3; qs--;) { + FIXP_DBL out_re, out_im; + + pb = *kernels++; + cplxMultDiv2(&out_re, &out_im, *Dry_real0, *Dry_imag0, ppb[4 * pb + 0], + ppb[4 * pb + 1]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real0++ = out_re; + *Dry_imag0++ = out_im; + + cplxMultDiv2(&out_re, &out_im, *Dry_real1, *Dry_imag1, ppb[4 * pb + 2], + ppb[4 * pb + 3]); + out_re <<= PHASE_SCALE - 1; + out_im <<= PHASE_SCALE - 1; + *Dry_real1++ = out_re; + *Dry_imag1++ = out_im; + } +} diff --git a/fdk-aac/libSACdec/src/sac_process.h b/fdk-aac/libSACdec/src/sac_process.h new file mode 100644 index 0000000..ee2f2fe --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_process.h @@ -0,0 +1,297 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Processing + +*******************************************************************************/ + +/*! + \file + \brief Polyphase Filterbank +*/ + +#ifndef SAC_PROCESS_H +#define SAC_PROCESS_H + +#include "sac_dec.h" + +void SpatialDecApplyPhase(spatialDec *self, FIXP_SGL alpha, + int lastSlotOfParamSet); + +/** + * \brief Apply QMF Analysis Filterbank. + * + * Calculates qmf data on downmix input time data. + * Delaylines will be applied if necessaray. + * + * \param self A spatial decoder handle. + * \param inData Downmix channel time data as input. + * \param ts Signals time slot offset for input buffer. + * \param qmfReal Downmix channel qmf output data. + * \param qmfImag Downmix channel qmf output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecQMFAnalysis(spatialDec *self, const PCM_MPS *inData, + const INT ts, const INT bypassMode, + FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const int numInputChannels); + +/** + * \brief Feed spatial decoder with external qmf data. + * + * \param self A spatial decoder handle. + * \param qmfInDataReal External qmf downmix data as input. + * \param qmfInDataImag External qmf downmix data as input. + * \param ts Signals time slot in input buffer to process. + * \param qmfReal Downmix channel qmf output data. + * \param qmfImag Downmix channel qmf output data. + * \param numInputChannels Number of input channels. Might differ from + * self->numInputChannels. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecFeedQMF(spatialDec *self, FIXP_DBL **qmfInDataReal, + FIXP_DBL **qmfInDataImag, const INT ts, + const INT bypassMode, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, const INT numInputChannels); + +/** + * \brief Apply Hybrdid Analysis Filterbank. + * + * Calculates hybrid data on downmix input data. + * Residual hybrid signals will also be calculated on current slot if available. + * + * \param self A spatial decoder handle. + * \param qmfInputReal Downmix channel qmf data as input. + * \param qmfInputImag Downmix channel qmf data as input. + * \param hybOutputReal Downmix channel hybrid output data. + * \param hybOutputImag Downmix channel hybrid output data. + * \param ts Signals time slot in spatial frame to process. + * \param numInputChannels Number of input channels. Might differ from + * self->numInputChannels. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecHybridAnalysis(spatialDec *self, FIXP_DBL **qmfInputReal, + FIXP_DBL **qmfInputImag, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, const INT ts, + const INT numInputChannels); + +/** + * \brief Create X data. + * + * Returns a pointer list over Xchannels pointing to downmix input channels + * and to residual channels when provided. + * + * \param self A spatial decoder handle. + * \param hybInputReal Downmix channel hybrid data as input. + * \param hybInputImag Downmix channel hybrid data as input. + * \param pxReal Pointer to hybrid and residual data as output. + * \param pxImag Pointer to hybrid and residual data as output. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecCreateX(spatialDec *self, FIXP_DBL **hybInputReal, + FIXP_DBL **hybInputImag, FIXP_DBL **pxReal, + FIXP_DBL **pxImag); + +/** + * \brief MPS212 combined version of apply M1 parameters and create wet signal + * + * \param self A spatial decoder handle. + * \param xReal Downmix and residual X data as input. + * \param xImag Downmix and residual X data as input. + * \param vReal output data: [0] direct signal (V); [1] wet signal + * (W). + * \param vImag output data: [0] direct signal (V); [1] wet signal + * (W). + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecApplyM1_CreateW_Mode212( + spatialDec *self, const SPATIAL_BS_FRAME *frame, FIXP_DBL **xReal, + FIXP_DBL **xImag, FIXP_DBL **vReal, FIXP_DBL **vImag); + +/** + * \brief Apply M2 parameters. + * + * \param self A spatial decoder handle. + * \param ps Signals parameter band from where M2 parameter to + * use. + * \param alpha Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal Wet input data. + * \param wImag Wet input data. + * \param hybOutputRealDry Dry output data. + * \param hybOutputImagDry Dry output data. + * \param hybOutputRealWet Wet output data. + * \param hybOutputImagWet Wet output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecApplyM2(spatialDec *self, INT ps, const FIXP_SGL alpha, + FIXP_DBL **wReal, FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry, + FIXP_DBL **hybOutputRealWet, + FIXP_DBL **hybOutputImagWet); + +/** + * \brief Apply M2 parameter for 212 mode with residualCoding and phaseCoding. + * + * \param self [i] A spatial decoder handle. + * \param ps [i] Signals parameter band from where M2 parameter + * to use. + * \param alpha [i] Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal [i] Wet input data. + * \param wImag [i] Wet input data. + * \param hybOutputRealDry [o] Dry output data. + * \param hybOutputImagDry [o] Dry output data. + * + * \return error + */ +SACDEC_ERROR SpatialDecApplyM2_Mode212_ResidualsPlusPhaseCoding( + spatialDec *self, INT ps, const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, FIXP_DBL **hybOutputRealDry, FIXP_DBL **hybOutputImagDry); + +/** + * \brief Apply M2 parameter for 212 mode, upmix from mono to stereo. + * + * \param self [i] A spatial decoder handle. + * \param ps [i] Signals parameter band from where M2 parameter + * to use. + * \param alpha [i] Smoothing factor between current and previous + * parameter band. Rangeability between 0.f and 1.f. + * \param wReal [i] Wet input data. + * \param wImag [i] Wet input data. + * \param hybOutputRealDry [o] Dry output data. + * \param hybOutputImagDry [o] Dry output data. + * + * \return error + */ +SACDEC_ERROR SpatialDecApplyM2_Mode212(spatialDec *self, INT ps, + const FIXP_SGL alpha, FIXP_DBL **wReal, + FIXP_DBL **wImag, + FIXP_DBL **hybOutputRealDry, + FIXP_DBL **hybOutputImagDry); + +/** + * \brief Convert Hybrid input to output audio data. + * + * \param hSpaceSynthesisQmf A spatial decoder handle. + * \param ts Signals time slot in spatial frame to process. + * \param hybOutputReal Hybrid data as input. + * \param hybOutputImag Hybrid data as input. + * \param timeOut audio output data. + * + * \return Error status. + */ +SACDEC_ERROR SpatialDecSynthesis(spatialDec *self, const INT ts, + FIXP_DBL **hybOutputReal, + FIXP_DBL **hybOutputImag, PCM_MPS *timeOut, + const INT numInputChannels, + const FDK_channelMapDescr *const mapDescr); + +void SpatialDecBufferMatrices(spatialDec *self); + +FIXP_DBL getChGain(spatialDec *self, UINT ch, INT *scale); + +#endif diff --git a/fdk-aac/libSACdec/src/sac_qmf.cpp b/fdk-aac/libSACdec/src/sac_qmf.cpp new file mode 100644 index 0000000..a075490 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_qmf.cpp @@ -0,0 +1,156 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec QMF processing + +*******************************************************************************/ + +#include "sac_qmf.h" + +#include "FDK_matrixCalloc.h" +#include "sac_dec_interface.h" +#include "sac_rom.h" + +#include "qmf.h" + +SACDEC_ERROR CalculateSpaceSynthesisQmf( + const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, + const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig) { + SACDEC_ERROR err = MPS_OK; + + if (hQmfDomainOutCh == NULL) { + err = MPS_INVALID_HANDLE; + } else { + HANDLE_SPACE_SYNTHESIS_QMF hSpaceSynthesisQmf = &hQmfDomainOutCh->fb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + (QMF_MAX_SYNTHESIS_BANDS << 1)); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#endif + + qmfSynthesisFilteringSlot(hSpaceSynthesisQmf, Sr, Si, 0, 0, timeSig, stride, + pWorkBuffer); + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, (QMF_MAX_SYNTHESIS_BANDS << 1)); +#endif + } + + return err; +} + +SACDEC_ERROR CalculateSpaceAnalysisQmf( + HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig, + FIXP_DBL *Sr, FIXP_DBL *Si) { + SACDEC_ERROR err = MPS_OK; + + if (hSpaceAnalysisQmf == NULL) { + err = MPS_INVALID_HANDLE; + } else { + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (64 << 1)); + + qmfAnalysisFilteringSlot(hSpaceAnalysisQmf, Sr, Si, timeSig, 1, + pWorkBuffer); + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (64 << 1)); + } + + return err; +} diff --git a/fdk-aac/libSACdec/src/sac_qmf.h b/fdk-aac/libSACdec/src/sac_qmf.h new file mode 100644 index 0000000..d1dc837 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_qmf.h @@ -0,0 +1,143 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec QMF processing + +*******************************************************************************/ + +#ifndef SAC_QMF_H +#define SAC_QMF_H + +#include "common_fix.h" + +#include "sac_dec_interface.h" + +#include "FDK_qmf_domain.h" +#define HANDLE_SPACE_ANALYSIS_QMF HANDLE_QMF_FILTER_BANK +#define HANDLE_SPACE_SYNTHESIS_QMF HANDLE_QMF_FILTER_BANK + +/** + * \brief Convert Qmf input to output audio data. + * + * \param hSpaceSynthesisQmf A Qmf Synthesis Filterbank handle. + * \param Sr Pointer to Qmf input buffer. + * \param Si Pointer to Qmf input buffer. + * \param stride Stride factor for output data, 1 if none. + * \param timeSig (None-)Interleaved audio output data. + * + * \return Error status. + */ +SACDEC_ERROR CalculateSpaceSynthesisQmf( + const HANDLE_FDK_QMF_DOMAIN_OUT hQmfDomainOutCh, const FIXP_DBL *Sr, + const FIXP_DBL *Si, const INT stride, INT_PCM *timeSig); + +/** + * \brief Convert audio input data to qmf representation. + * + * \param hSpaceAnalysisQmf A Qmf Analysis Filterbank handle. + * \param timeSig (None-)Interleavd audio input data. + * \param Sr Pointer to Qmf output buffer. + * \param Si Pointer to Qmf output buffer. + * + * \return Error status. + */ +SACDEC_ERROR CalculateSpaceAnalysisQmf( + HANDLE_SPACE_ANALYSIS_QMF hSpaceAnalysisQmf, const PCM_MPS *timeSig, + FIXP_DBL *Sr, FIXP_DBL *Si); + +#endif /* SAC_QMF_H */ diff --git a/fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp b/fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp new file mode 100644 index 0000000..87c0ac6 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_reshapeBBEnv.cpp @@ -0,0 +1,680 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec guided envelope shaping + +*******************************************************************************/ + +#include "sac_reshapeBBEnv.h" + +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "sac_calcM1andM2.h" +#include "sac_reshapeBBEnv.h" +#include "sac_rom.h" + +#define INP_DRY_WET 0 +#define INP_DMX 1 + +#define SF_SHAPE 1 +#define SF_DIV32 6 +#define SF_FACTOR_SLOT 5 + +#define START_BB_ENV 0 /* 10 */ +#define END_BB_ENV 9 /* 18 */ + +#define SF_ALPHA1 8 +#define SF_BETA1 4 + +void initBBEnv(spatialDec *self, int initStatesFlag) { + INT ch, k; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + k = row2channelGES[self->treeConfig][ch]; + self->row2channelDmxGES[ch] = k; + if (k == -1) continue; + + switch (self->treeConfig) { + case TREE_212: + self->row2channelDmxGES[ch] = 0; + break; + default:; + } + } + + if (initStatesFlag) { + for (k = 0; k < 2 * MAX_OUTPUT_CHANNELS + MAX_INPUT_CHANNELS; k++) { + self->reshapeBBEnvState->normNrgPrev__FDK[k] = + FL2FXCONST_DBL(0.5f); /* 32768.f*32768.f */ + self->reshapeBBEnvState->normNrgPrevSF[k] = DFRACT_BITS - 1; + self->reshapeBBEnvState->partNrgPrevSF[k] = 0; + self->reshapeBBEnvState->partNrgPrev2SF[k] = 0; + self->reshapeBBEnvState->frameNrgPrevSF[k] = 0; + } + } + + self->reshapeBBEnvState->alpha__FDK = + FL2FXCONST_DBL(0.99637845575f); /* FDKexp(-64 / (0.4f * 44100)) */ + self->reshapeBBEnvState->beta__FDK = + FL2FXCONST_DBL(0.96436909488f); /* FDKexp(-64 / (0.04f * 44100)) */ +} + +static inline void getSlotNrgHQ(FIXP_DBL *RESTRICT pReal, + FIXP_DBL *RESTRICT pImag, + FIXP_DBL *RESTRICT slotNrg, INT maxValSF, + INT hybBands) { + INT qs; + FIXP_DBL nrg; + + /* qs = 12, 13, 14 */ + slotNrg[0] = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[1] = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[2] = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 15 */ + slotNrg[3] = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 16, 17 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[4] = nrg + ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 18, 19, 20 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + nrg += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[5] = nrg + ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 21, 22 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[6] = nrg + ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 23, 24 */ + if (hybBands > 23) { + slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[6] += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 25, 26, 29, 28, 29 */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + nrg += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + nrg += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + nrg += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + slotNrg[7] = nrg + ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + /* qs = 30 ... min(41,hybBands-1) */ + nrg = ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + for (qs = 31; qs < hybBands; qs++) { + nrg += ((fPow2Div2((*pReal++) << maxValSF) + + fPow2Div2((*pImag++) << maxValSF)) >> + (SF_FACTOR_SLOT - 1)); + } + slotNrg[8] = nrg; + } else { + slotNrg[7] = (FIXP_DBL)0; + slotNrg[8] = (FIXP_DBL)0; + } +} + +static inline INT getMaxValDmx(FIXP_DBL *RESTRICT pReal, + FIXP_DBL *RESTRICT pImag, INT cplxBands, + INT hybBands) { + INT qs, clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + for (qs = 12; qs < cplxBands; qs++) { + maxVal |= fAbs(pReal[qs]); + maxVal |= fAbs(pImag[qs]); + } + for (; qs < hybBands; qs++) { + maxVal |= fAbs(pReal[qs]); + } + + clz = fixMax(0, CntLeadingZeros(maxVal) - 1); + + return (clz); +} + +static inline INT getMaxValDryWet(FIXP_DBL *RESTRICT pReal, + FIXP_DBL *RESTRICT pImag, + FIXP_DBL *RESTRICT pHybOutputRealDry, + FIXP_DBL *RESTRICT pHybOutputImagDry, + FIXP_DBL *RESTRICT pHybOutputRealWet, + FIXP_DBL *RESTRICT pHybOutputImagWet, + INT cplxBands, INT hybBands) { + INT qs, clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + for (qs = 12; qs < cplxBands; qs++) { + pReal[qs] = pHybOutputRealDry[qs] + pHybOutputRealWet[qs]; + maxVal |= fAbs(pReal[qs]); + pImag[qs] = pHybOutputImagDry[qs] + pHybOutputImagWet[qs]; + maxVal |= fAbs(pImag[qs]); + } + for (; qs < hybBands; qs++) { + pReal[qs] = pHybOutputRealDry[qs] + pHybOutputRealWet[qs]; + maxVal |= fAbs(pReal[qs]); + } + + clz = fixMax(0, CntLeadingZeros(maxVal) - 1); + + return (clz); +} + +static inline void slotAmp(FIXP_DBL *RESTRICT slotAmp_dry, + FIXP_DBL *RESTRICT slotAmp_wet, + FIXP_DBL *RESTRICT pHybOutputRealDry, + FIXP_DBL *RESTRICT pHybOutputImagDry, + FIXP_DBL *RESTRICT pHybOutputRealWet, + FIXP_DBL *RESTRICT pHybOutputImagWet, INT cplxBands, + INT hybBands) { + INT qs; + FIXP_DBL dry, wet; + + dry = wet = FL2FXCONST_DBL(0.0f); + for (qs = 0; qs < cplxBands; qs++) { + dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs]) + + fPow2Div2(pHybOutputImagDry[qs])); + wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs]) + + fPow2Div2(pHybOutputImagWet[qs])); + } + for (; qs < hybBands; qs++) { + dry = fAddSaturate(dry, fPow2Div2(pHybOutputRealDry[qs])); + wet = fAddSaturate(wet, fPow2Div2(pHybOutputRealWet[qs])); + } + *slotAmp_dry = dry; + *slotAmp_wet = wet; +} + +#if defined(__aarch64__) +__attribute__((noinline)) +#endif +static void +shapeBBEnv(FIXP_DBL *pHybOutputRealDry, FIXP_DBL *pHybOutputImagDry, + FIXP_DBL dryFac, INT scale, INT cplxBands, INT hybBands) { + INT qs; + + if (scale == 0) { + for (qs = 0; qs < cplxBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac); + pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac); + } + for (; qs < hybBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac); + } + } else { + for (qs = 0; qs < cplxBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac) << scale; + pHybOutputImagDry[qs] = fMultDiv2(pHybOutputImagDry[qs], dryFac) << scale; + } + for (; qs < hybBands; qs++) { + pHybOutputRealDry[qs] = fMultDiv2(pHybOutputRealDry[qs], dryFac) << scale; + } + } +} + +static void extractBBEnv(spatialDec *self, INT inp, INT start, INT channels, + FIXP_DBL *pEnv, const SPATIAL_BS_FRAME *frame) { + INT ch, pb, prevChOffs; + INT clz, scale, scale_min, envSF; + INT scaleCur, scalePrev, commonScale; + INT slotNrgSF, partNrgSF, frameNrgSF; + INT *pPartNrgPrevSF, *pFrameNrgPrevSF; + INT *pNormNrgPrevSF, *pPartNrgPrev2SF; + + FIXP_DBL maxVal, env, frameNrg, normNrg; + FIXP_DBL *pReal, *pImag; + FIXP_DBL *partNrg, *partNrgPrev; + + C_ALLOC_SCRATCH_START(pScratchBuffer, FIXP_DBL, + (2 * 42 + MAX_PARAMETER_BANDS)); + C_ALLOC_SCRATCH_START(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_START(resPbSF, INT, (END_BB_ENV - START_BB_ENV)); + + FIXP_DBL *slotNrg = pScratchBuffer + (2 * 42); + + RESHAPE_BBENV_STATE *pBBEnvState = self->reshapeBBEnvState; + + FIXP_DBL alpha = pBBEnvState->alpha__FDK; + /*FIXP_DBL alpha1 = (FL2FXCONST_DBL(1.0f) - alpha) << SF_ALPHA1;*/ + FIXP_DBL alpha1 = ((FIXP_DBL)MAXVAL_DBL - alpha) << SF_ALPHA1; + FIXP_DBL beta = pBBEnvState->beta__FDK; + /*FIXP_DBL beta1 = (FL2FXCONST_DBL(1.0f) - beta) << SF_BETA1;*/ + FIXP_DBL beta1 = ((FIXP_DBL)MAXVAL_DBL - beta) << SF_BETA1; + + INT shapeActiv = 1; + INT hybBands = fixMin(42, self->hybridBands); + INT staticScale = self->staticDecScale; + INT cplxBands; + cplxBands = fixMin(42, self->hybridBands); + + for (ch = start; ch < channels; ch++) { + if (inp == INP_DRY_WET) { + INT ch2 = row2channelGES[self->treeConfig][ch]; + if (ch2 == -1) { + continue; + } else { + if (frame->tempShapeEnableChannelGES[ch2]) { + shapeActiv = 1; + } else { + shapeActiv = 0; + } + } + prevChOffs = ch; + pReal = pScratchBuffer; + pImag = pScratchBuffer + 42; + clz = getMaxValDryWet( + pReal, pImag, self->hybOutputRealDry__FDK[ch], + self->hybOutputImagDry__FDK[ch], self->hybOutputRealWet__FDK[ch], + self->hybOutputImagWet__FDK[ch], cplxBands, hybBands); + } else { + prevChOffs = ch + self->numOutputChannels; + pReal = self->hybInputReal__FDK[ch]; + pImag = self->hybInputImag__FDK[ch]; + clz = getMaxValDmx(pReal, pImag, cplxBands, hybBands); + } + + partNrg = partNrgPrev = pBBEnvState->partNrgPrev__FDK[prevChOffs]; + pPartNrgPrevSF = &pBBEnvState->partNrgPrevSF[prevChOffs]; + pFrameNrgPrevSF = &pBBEnvState->frameNrgPrevSF[prevChOffs]; + pNormNrgPrevSF = &pBBEnvState->normNrgPrevSF[prevChOffs]; + pPartNrgPrev2SF = &pBBEnvState->partNrgPrev2SF[prevChOffs]; + + /* calculate slot energy */ + { + getSlotNrgHQ(&pReal[12], &pImag[12], slotNrg, clz, + fixMin(42, self->hybridBands)); /* scale slotNrg: + 2*(staticScale-clz) + + SF_FACTOR_SLOT */ + } + + slotNrgSF = 2 * (staticScale - clz) + SF_FACTOR_SLOT; + frameNrgSF = 2 * (staticScale - clz) + SF_FACTOR_SLOT; + + partNrgSF = fixMax(slotNrgSF - SF_ALPHA1 + 1, + pPartNrgPrevSF[0] - pPartNrgPrev2SF[0] + 1); + scalePrev = fixMax(fixMin(partNrgSF - pPartNrgPrevSF[0], DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + scaleCur = + fixMax(fixMin(partNrgSF - slotNrgSF + SF_ALPHA1, DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + + maxVal = FL2FXCONST_DBL(0.0f); + frameNrg = FL2FXCONST_DBL(0.0f); + if ((scaleCur < 0) && (scalePrev < 0)) { + scaleCur = -scaleCur; + scalePrev = -scalePrev; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else if ((scaleCur >= 0) && (scalePrev >= 0)) { + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else if ((scaleCur < 0) && (scalePrev >= 0)) { + scaleCur = -scaleCur; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) << scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) >> scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } else { /* if ( (scaleCur >= 0) && (scalePrev < 0) ) */ + scalePrev = -scalePrev; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + partNrg[pb] = ((fMultDiv2(alpha1, slotNrg[pb]) >> scaleCur) + + (fMultDiv2(alpha, partNrgPrev[pb]) << scalePrev)) + << 1; + maxVal |= partNrg[pb]; + frameNrg += slotNrg[pb] >> 3; + } + } + + /* frameNrg /= (END_BB_ENV - START_BB_ENV); 0.88888888888f = + * (1/(END_BB_ENV-START_BB_ENV)<<3; shift with 3 is compensated in loop + * above */ + frameNrg = fMult(frameNrg, FL2FXCONST_DBL(0.88888888888f)); + + /* store scalefactor and headroom for part nrg prev */ + pPartNrgPrevSF[0] = partNrgSF; + pPartNrgPrev2SF[0] = fixMax(0, CntLeadingZeros(maxVal) - 1); + + commonScale = fixMax(frameNrgSF - SF_ALPHA1 + 1, pFrameNrgPrevSF[0] + 1); + scalePrev = fixMin(commonScale - pFrameNrgPrevSF[0], DFRACT_BITS - 1); + scaleCur = fixMin(commonScale - frameNrgSF + SF_ALPHA1, DFRACT_BITS - 1); + frameNrgSF = commonScale; + + frameNrg = ((fMultDiv2(alpha1, frameNrg) >> scaleCur) + + (fMultDiv2(alpha, pBBEnvState->frameNrgPrev__FDK[prevChOffs]) >> + scalePrev)) + << 1; + + clz = fixMax(0, CntLeadingZeros(frameNrg) - 1); + pBBEnvState->frameNrgPrev__FDK[prevChOffs] = frameNrg << clz; + pFrameNrgPrevSF[0] = frameNrgSF - clz; + + env = FL2FXCONST_DBL(0.0f); + scale = clz + partNrgSF - frameNrgSF; + scale_min = DFRACT_BITS - 1; + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + if ((partNrg[pb] | slotNrg[pb]) != FL2FXCONST_DBL(0.0f)) { + INT s; + INT sc = 0; + INT sn = fixMax(0, CntLeadingZeros(slotNrg[pb]) - 1); + FIXP_DBL inv_sqrt = invSqrtNorm2(partNrg[pb], &sc); + FIXP_DBL res = fMult(slotNrg[pb] << sn, fPow2(inv_sqrt)); + + s = fixMax(0, CntLeadingZeros(res) - 1); + res = res << s; + + sc = scale - (2 * sc - sn - s); + scale_min = fixMin(scale_min, sc); + + resPb[pb] = res; + resPbSF[pb] = sc; + } else { + resPb[pb] = (FIXP_DBL)0; + resPbSF[pb] = 0; + } + } + + scale_min = 4 - scale_min; + + for (pb = START_BB_ENV; pb < END_BB_ENV; pb++) { + INT sc = fixMax(fixMin(resPbSF[pb] + scale_min, DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + + if (sc < 0) { + env += resPb[pb] << (-sc); + } else { + env += resPb[pb] >> (sc); + } + } + + env = fMultDiv2(env, pBBEnvState->frameNrgPrev__FDK[prevChOffs]); + envSF = slotNrgSF + scale_min + 1; + + commonScale = fixMax(envSF - SF_BETA1 + 1, pNormNrgPrevSF[0] + 1); + scalePrev = fixMin(commonScale - pNormNrgPrevSF[0], DFRACT_BITS - 1); + scaleCur = fixMin(commonScale - envSF + SF_BETA1, DFRACT_BITS - 1); + + normNrg = ((fMultDiv2(beta1, env) >> scaleCur) + + (fMultDiv2(beta, pBBEnvState->normNrgPrev__FDK[prevChOffs]) >> + scalePrev)) + << 1; + + clz = fixMax(0, CntLeadingZeros(normNrg) - 1); + pBBEnvState->normNrgPrev__FDK[prevChOffs] = normNrg << clz; + pNormNrgPrevSF[0] = commonScale - clz; + + if (shapeActiv) { + if ((env | normNrg) != FL2FXCONST_DBL(0.0f)) { + INT sc, se, sn; + se = fixMax(0, CntLeadingZeros(env) - 1); + sc = commonScale + SF_DIV32 - envSF + se; + env = fMult(sqrtFixp((env << se) >> (sc & 0x1)), + invSqrtNorm2(normNrg, &sn)); + + sc = fixMin((sc >> 1) - sn, DFRACT_BITS - 1); + if (sc < 0) { + env <<= (-sc); + } else { + env >>= (sc); + } + } + /* env is scaled by SF_DIV32/2 bits */ + } + pEnv[ch] = env; + } + + C_ALLOC_SCRATCH_END(resPbSF, INT, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_END(resPb, FIXP_DBL, (END_BB_ENV - START_BB_ENV)); + C_ALLOC_SCRATCH_END(pScratchBuffer, FIXP_DBL, (2 * 42 + MAX_PARAMETER_BANDS)); +} + +void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame, + INT ts) { + INT ch, scale; + INT dryFacSF, slotAmpSF; + FIXP_DBL tmp, dryFac, envShape; + FIXP_DBL slotAmp_dry, slotAmp_wet, slotAmp_ratio; + FIXP_DBL envDry[MAX_OUTPUT_CHANNELS], envDmx[2]; + + INT cplxBands; + INT hybBands = self->hybridBands - 6; + + cplxBands = self->hybridBands - 6; + + /* extract downmix envelope(s) */ + switch (self->treeConfig) { + default: + extractBBEnv(self, INP_DMX, 0, fMin(self->numInputChannels, 2), envDmx, + frame); + } + + /* extract dry and wet envelopes */ + extractBBEnv(self, INP_DRY_WET, 0, self->numOutputChannels, envDry, frame); + + for (ch = 0; ch < self->numOutputChannels; ch++) { + INT ch2; + + ch2 = row2channelGES[self->treeConfig][ch]; + + if (ch2 == -1) continue; + + if (frame->tempShapeEnableChannelGES[ch2]) { + INT sc; + + /* reshape dry and wet signals according to transmitted envelope */ + + /* De-quantize GES data */ + FDK_ASSERT((frame->bsEnvShapeData[ch2][ts] >= 0) && + (frame->bsEnvShapeData[ch2][ts] <= 4)); + FDK_ASSERT((self->envQuantMode == 0) || (self->envQuantMode == 1)); + envShape = + FX_CFG2FX_DBL(envShapeDataTable__FDK[frame->bsEnvShapeData[ch2][ts]] + [self->envQuantMode]); + + /* get downmix channel */ + ch2 = self->row2channelDmxGES[ch]; + + /* multiply ratio with dmx envelope; tmp is scaled by SF_DIV32/2+SF_SHAPE + * bits */ + if (ch2 == 2) { + tmp = fMultDiv2(envShape, envDmx[0]) + fMultDiv2(envShape, envDmx[1]); + } else { + tmp = fMult(envShape, envDmx[ch2]); + } + + /* weighting factors */ + dryFacSF = slotAmpSF = 0; + dryFac = slotAmp_ratio = FL2FXCONST_DBL(0.0f); + + /* dryFac will be scaled by dryFacSF bits */ + if (envDry[ch] != FL2FXCONST_DBL(0.0f)) { + envDry[ch] = invSqrtNorm2(envDry[ch], &dryFacSF); + dryFac = fMultDiv2(tmp, fPow2Div2(envDry[ch])) << 2; + dryFacSF = SF_SHAPE + 2 * dryFacSF; + } + + /* calculate slotAmp_dry and slotAmp_wet */ + slotAmp(&slotAmp_dry, &slotAmp_wet, &self->hybOutputRealDry__FDK[ch][6], + &self->hybOutputImagDry__FDK[ch][6], + &self->hybOutputRealWet__FDK[ch][6], + &self->hybOutputImagWet__FDK[ch][6], cplxBands, hybBands); + + /* slotAmp_ratio will be scaled by slotAmpSF bits */ + if (slotAmp_dry != FL2FXCONST_DBL(0.0f)) { + sc = fixMax(0, CntLeadingZeros(slotAmp_wet) - 1); + sc = sc - (sc & 1); + + slotAmp_wet = sqrtFixp(slotAmp_wet << sc); + slotAmp_dry = invSqrtNorm2(slotAmp_dry, &slotAmpSF); + + slotAmp_ratio = fMult(slotAmp_wet, slotAmp_dry); + slotAmpSF = slotAmpSF - (sc >> 1); + } + + /* calculate common scale factor */ + scale = + fixMax(3, fixMax(dryFacSF, slotAmpSF)); /* scale is at least with 3 + bits to avoid overflows + when calculating dryFac */ + dryFac = dryFac >> (scale - dryFacSF); + slotAmp_ratio = slotAmp_ratio >> (scale - slotAmpSF); + + /* limit dryFac */ + dryFac = fixMax( + FL2FXCONST_DBL(0.25f) >> (INT)fixMin(2 * scale, DFRACT_BITS - 1), + fMult(dryFac, slotAmp_ratio) - (slotAmp_ratio >> scale) + + (dryFac >> scale)); + dryFac = fixMin( + FL2FXCONST_DBL(0.50f) >> (INT)fixMin(2 * scale - 3, DFRACT_BITS - 1), + dryFac); /* reduce shift bits by 3, because upper + limit 4.0 is scaled with 3 bits */ + scale = 2 * scale + 1; + + /* improve precision for dryFac */ + sc = fixMax(0, CntLeadingZeros(dryFac) - 1); + dryFac = dryFac << (INT)fixMin(scale, sc); + scale = scale - fixMin(scale, sc); + + /* shaping */ + shapeBBEnv(&self->hybOutputRealDry__FDK[ch][6], + &self->hybOutputImagDry__FDK[ch][6], dryFac, scale, cplxBands, + hybBands); + } + } +} diff --git a/fdk-aac/libSACdec/src/sac_reshapeBBEnv.h b/fdk-aac/libSACdec/src/sac_reshapeBBEnv.h new file mode 100644 index 0000000..1658530 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_reshapeBBEnv.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec guided envelope shaping + +*******************************************************************************/ + +#ifndef SAC_RESHAPEBBENV_H +#define SAC_RESHAPEBBENV_H + +#include "sac_dec_interface.h" + +#define BB_ENV_SIZE 9 /* END_BB_ENV - START_BB_ENV */ + +void initBBEnv(spatialDec *self, int initStatesFlag); +void SpatialDecReshapeBBEnv(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ts); + +#endif diff --git a/fdk-aac/libSACdec/src/sac_rom.cpp b/fdk-aac/libSACdec/src/sac_rom.cpp new file mode 100644 index 0000000..4285b65 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_rom.cpp @@ -0,0 +1,709 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec tables + +*******************************************************************************/ + +#include "sac_rom.h" +#include "sac_calcM1andM2.h" + +#define SCALE_CPC(a) (FL2FXCONST_CFG(a / (float)(1 << SCALE_PARAM_M1))) +const FIXP_CFG dequantCPC__FDK[] = { + SCALE_CPC(-2.0f), SCALE_CPC(-1.9f), SCALE_CPC(-1.8f), SCALE_CPC(-1.7f), + SCALE_CPC(-1.6f), SCALE_CPC(-1.5f), SCALE_CPC(-1.4f), SCALE_CPC(-1.3f), + SCALE_CPC(-1.2f), SCALE_CPC(-1.1f), SCALE_CPC(-1.0f), SCALE_CPC(-0.9f), + SCALE_CPC(-0.8f), SCALE_CPC(-0.7f), SCALE_CPC(-0.6f), SCALE_CPC(-0.5f), + SCALE_CPC(-0.4f), SCALE_CPC(-0.3f), SCALE_CPC(-0.2f), SCALE_CPC(-0.1f), + SCALE_CPC(0.0f), SCALE_CPC(0.1f), SCALE_CPC(0.2f), SCALE_CPC(0.3f), + SCALE_CPC(0.4f), SCALE_CPC(0.5f), SCALE_CPC(0.6f), SCALE_CPC(0.7f), + SCALE_CPC(0.8f), SCALE_CPC(0.9f), SCALE_CPC(1.0f), SCALE_CPC(1.1f), + SCALE_CPC(1.2f), SCALE_CPC(1.3f), SCALE_CPC(1.4f), SCALE_CPC(1.5f), + SCALE_CPC(1.6f), SCALE_CPC(1.7f), SCALE_CPC(1.8f), SCALE_CPC(1.9f), + SCALE_CPC(2.0f), SCALE_CPC(2.1f), SCALE_CPC(2.2f), SCALE_CPC(2.3f), + SCALE_CPC(2.4f), SCALE_CPC(2.5f), SCALE_CPC(2.6f), SCALE_CPC(2.7f), + SCALE_CPC(2.8f), SCALE_CPC(2.9f), SCALE_CPC(3.0f)}; + +#define SCALE_ICC(a) (FL2FXCONST_CFG(a)) +const FIXP_CFG dequantICC__FDK[8] = { + /*SCALE_ICC(1.00000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + SCALE_ICC(0.9370f), + SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), + SCALE_ICC(0.36764f), + SCALE_ICC(0.0000f), + SCALE_ICC(-0.58900f), + SCALE_ICC(-0.9900f)}; + +#define SCALE_CLD2(a) (FL2FXCONST_CFG(a / (float)(1 << 8))) +const FIXP_CFG dequantCLD__FDK[31] = { + SCALE_CLD2(-150.0f), SCALE_CLD2(-45.0f), SCALE_CLD2(-40.0f), + SCALE_CLD2(-35.0f), SCALE_CLD2(-30.0f), SCALE_CLD2(-25.0f), + SCALE_CLD2(-22.0f), SCALE_CLD2(-19.0f), SCALE_CLD2(-16.0f), + SCALE_CLD2(-13.0f), SCALE_CLD2(-10.0f), SCALE_CLD2(-8.0f), + SCALE_CLD2(-6.0f), SCALE_CLD2(-4.0f), SCALE_CLD2(-2.0f), + SCALE_CLD2(0.0f), SCALE_CLD2(2.0f), SCALE_CLD2(4.0f), + SCALE_CLD2(6.0f), SCALE_CLD2(8.0f), SCALE_CLD2(10.0f), + SCALE_CLD2(13.0f), SCALE_CLD2(16.0f), SCALE_CLD2(19.0f), + SCALE_CLD2(22.0f), SCALE_CLD2(25.0f), SCALE_CLD2(30.0f), + SCALE_CLD2(35.0f), SCALE_CLD2(40.0f), SCALE_CLD2(45.0f), + SCALE_CLD2(150.0f)}; + +#define SCALE_IPD(a) (FL2FXCONST_CFG(a / (float)(1 << IPD_SCALE))) +const FIXP_CFG dequantIPD__FDK[16] = { + /* SCALE_IPD(0.000000000f), SCALE_IPD(0.392699082f), + SCALE_IPD(0.785398163f), SCALE_IPD(1.178097245f), + SCALE_IPD(1.570796327f), SCALE_IPD(1.963495408f), + SCALE_IPD(2.356194490f), SCALE_IPD(2.748893572f), + SCALE_IPD(3.141592654f), SCALE_IPD(3.534291735f), + SCALE_IPD(3.926990817f), SCALE_IPD(4.319689899f), + SCALE_IPD(4.712388980f), SCALE_IPD(5.105088062f), + SCALE_IPD(5.497787144f), SCALE_IPD(5.890486225f) */ + SCALE_IPD(0.00000000000000f), SCALE_IPD(0.392699082f), + SCALE_IPD(0.78539816339745f), SCALE_IPD(1.178097245f), + SCALE_IPD(1.57079632679490f), SCALE_IPD(1.963495408f), + SCALE_IPD(2.35619449019234f), SCALE_IPD(2.748893572f), + SCALE_IPD(3.14159265358979f), SCALE_IPD(3.534291735f), + SCALE_IPD(3.92699081698724f), SCALE_IPD(4.319689899f), + SCALE_IPD(4.71238898038469f), SCALE_IPD(5.105088062f), + SCALE_IPD(5.49778714378214f), SCALE_IPD(5.890486225f)}; + +#define SCALE_SPLIT_ANGLE(a) (FL2FXCONST_CFG(a / (float)(1 << IPD_SCALE))) +/* + Generate table dequantIPD_CLD_ICC_splitAngle__FDK[16][31][8]: + + #define ABS_THR ( 1e-9f * 32768 * 32768 ) + + float dequantICC[] = + {1.0000f,0.9370f,0.84118f,0.60092f,0.36764f,0.0f,-0.5890f,-0.9900f}; float + dequantCLD[] = + {-150.0,-45.0,-40.0,-35.0,-30.0,-25.0,-22.0,-19.0,-16.0,-13.0,-10.0, -8.0, + -6.0, -4.0, -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, + 10.0, 13.0, 16.0, 19.0, 22.0, 25.0, 30.0, 35.0, 40.0, 45.0, 150.0 }; float + dequantIPD[] = + {0.f,0.392699082f,0.785398163f,1.178097245f,1.570796327f,1.963495408f, + 2.35619449f,2.748893572f,3.141592654f,3.534291735f,3.926990817f, + 4.319689899f,4.71238898f,5.105088062f,5.497787144f,5.890486225f}; + + for (ipdIdx=0; ipdIdx<16; ipdIdx++) + for (cldIdx=0; cldIdx<31; cldIdx++) + for (iccIdx=0; iccIdx<8; iccIdx++) { + ipd = dequantIPD[ipdIdx]; + cld = dequantCLD[cldIdx]; + icc = dequantICC[iccIdx]; + iidLin = (float) pow(10.0f, cld / 20.0f); + iidLin2 = iidLin * iidLin; + iidLin21 = iidLin2 + 1.0f; + sinIpd = (float) sin(ipd); + cosIpd = (float) cos(ipd); + temp1 = 2.0f * icc * iidLin; + temp1c = temp1 * cosIpd; + ratio = (iidLin21 + temp1c) / (iidLin21 + temp1) + ABS_THR; + w2 = (float) pow(ratio, 0.25f); + w1 = 2.0f - w2; + dequantIPD_CLD_ICC_splitAngle__FDK[ipdIdx][cldIdx][iccIdx] = (float) + atan2(w2 * sinIpd, w1 * iidLin + w2 * cosIpd); + } +*/ + +#define SCALE_CLD(a) (FL2FXCONST_CFG(a)) + +const FIXP_CFG dequantCLD_c_l[31] = { + SCALE_CLD(0.0000000316f), + SCALE_CLD(0.0056233243f), + SCALE_CLD(0.0099994997f), + SCALE_CLD(0.0177799836f), + SCALE_CLD(0.0316069759f), + SCALE_CLD(0.0561454296f), + SCALE_CLD(0.0791834071f), + SCALE_CLD(0.1115021780f), + SCALE_CLD(0.1565355062f), + SCALE_CLD(0.2184644639f), + SCALE_CLD(0.3015113473f), + SCALE_CLD(0.3698741496f), + SCALE_CLD(0.4480624795f), + SCALE_CLD(0.5336171389f), + SCALE_CLD(0.6219832301f), + SCALE_CLD(0.7071067691f), + SCALE_CLD(0.7830305696f), + SCALE_CLD(0.8457261920f), + SCALE_CLD(0.8940021992f), + SCALE_CLD(0.9290818572f), + SCALE_CLD(0.9534626007f), + SCALE_CLD(0.9758449197f), + SCALE_CLD(0.9876723289f), + SCALE_CLD(0.9937641621f), + SCALE_CLD(0.9968600869f), + SCALE_CLD(0.9984226227f), + SCALE_CLD(0.9995003939f), + SCALE_CLD(0.9998419285f), + SCALE_CLD(0.9999499917f), + SCALE_CLD(0.9999842048f), + /*SCALE_CLD(1.0000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)}; + +#define SC_H(a) (FL2FXCONST_CFG(a)) +#define DATA_TYPE_H FIXP_CFG + +/* not correlated tables */ +const DATA_TYPE_H H11_nc[31][8] = { + {SC_H(0.0000000316f), SC_H(0.0000000296f), SC_H(0.0000000266f), + SC_H(0.0000000190f), SC_H(0.0000000116f), SC_H(0.0000000000f), + SC_H(-0.0000000186f), SC_H(-0.0000000313f)}, + {SC_H(0.0056233243f), SC_H(0.0052728835f), SC_H(0.0047394098f), + SC_H(0.0033992692f), SC_H(0.0020946222f), SC_H(0.0000316215f), + SC_H(-0.0032913829f), SC_H(-0.0055664564f)}, + {SC_H(0.0099994997f), SC_H(0.0093815643f), SC_H(0.0084402543f), + SC_H(0.0060722125f), SC_H(0.0037622179f), SC_H(0.0000999898f), + SC_H(-0.0058238208f), SC_H(-0.0098974844f)}, + {SC_H(0.0177799836f), SC_H(0.0166974831f), SC_H(0.0150465844f), + SC_H(0.0108831404f), SC_H(0.0068073822f), SC_H(0.0003161267f), + SC_H(-0.0102626514f), SC_H(-0.0175957214f)}, + {SC_H(0.0316069759f), SC_H(0.0297324844f), SC_H(0.0268681273f), + SC_H(0.0196138974f), SC_H(0.0124691967f), SC_H(0.0009989988f), + SC_H(-0.0179452803f), SC_H(-0.0312700421f)}, + {SC_H(0.0561454296f), SC_H(0.0529650487f), SC_H(0.0480896905f), + SC_H(0.0356564634f), SC_H(0.0232860073f), SC_H(0.0031523081f), + SC_H(-0.0309029408f), SC_H(-0.0555154830f)}, + {SC_H(0.0791834071f), SC_H(0.0748842582f), SC_H(0.0682762116f), + SC_H(0.0513241664f), SC_H(0.0343080349f), SC_H(0.0062700072f), + SC_H(-0.0422340371f), SC_H(-0.0782499388f)}, + {SC_H(0.1115021780f), SC_H(0.1057924852f), SC_H(0.0969873071f), + SC_H(0.0742305145f), SC_H(0.0511277616f), SC_H(0.0124327289f), + SC_H(-0.0566596612f), SC_H(-0.1100896299f)}, + {SC_H(0.1565355062f), SC_H(0.1491366178f), SC_H(0.1376826316f), + SC_H(0.1078186408f), SC_H(0.0770794004f), SC_H(0.0245033558f), + SC_H(-0.0735980421f), SC_H(-0.1543303132f)}, + {SC_H(0.2184644639f), SC_H(0.2091979682f), SC_H(0.1947948188f), + SC_H(0.1568822265f), SC_H(0.1172478944f), SC_H(0.0477267131f), + SC_H(-0.0899507254f), SC_H(-0.2148526460f)}, + {SC_H(0.3015113473f), SC_H(0.2904391289f), SC_H(0.2731673419f), + SC_H(0.2273024023f), SC_H(0.1786239147f), SC_H(0.0909090787f), + SC_H(-0.0964255333f), SC_H(-0.2951124907f)}, + {SC_H(0.3698741496f), SC_H(0.3578284085f), SC_H(0.3390066922f), + SC_H(0.2888108492f), SC_H(0.2351117432f), SC_H(0.1368068755f), + SC_H(-0.0850296095f), SC_H(-0.3597966135f)}, + {SC_H(0.4480624795f), SC_H(0.4354025424f), SC_H(0.4156077504f), + SC_H(0.3627120256f), SC_H(0.3058823943f), SC_H(0.2007599771f), + SC_H(-0.0484020934f), SC_H(-0.4304940701f)}, + {SC_H(0.5336171389f), SC_H(0.5208471417f), SC_H(0.5008935928f), + SC_H(0.4476420581f), SC_H(0.3905044496f), SC_H(0.2847472429f), + SC_H(0.0276676007f), SC_H(-0.4966579080f)}, + {SC_H(0.6219832301f), SC_H(0.6096963882f), SC_H(0.5905415416f), + SC_H(0.5396950245f), SC_H(0.4856070578f), SC_H(0.3868631124f), + SC_H(0.1531652957f), SC_H(-0.5045361519f)}, + {SC_H(0.7071067691f), SC_H(0.6958807111f), SC_H(0.6784504056f), + SC_H(0.6326373219f), SC_H(0.5847306848f), SC_H(0.4999999702f), + SC_H(0.3205464482f), SC_H(0.0500000045f)}, + {SC_H(0.7830305696f), SC_H(0.7733067870f), SC_H(0.7582961321f), + SC_H(0.7194055915f), SC_H(0.6797705293f), SC_H(0.6131368876f), + SC_H(0.4997332692f), SC_H(0.6934193969f)}, + {SC_H(0.8457261920f), SC_H(0.8377274871f), SC_H(0.8254694939f), + SC_H(0.7942851782f), SC_H(0.7635439038f), SC_H(0.7152527571f), + SC_H(0.6567122936f), SC_H(0.8229061961f)}, + {SC_H(0.8940021992f), SC_H(0.8877248168f), SC_H(0.8781855106f), + SC_H(0.8544237614f), SC_H(0.8318918347f), SC_H(0.7992399335f), + SC_H(0.7751275301f), SC_H(0.8853276968f)}, + {SC_H(0.9290818572f), SC_H(0.9243524075f), SC_H(0.9172304869f), + SC_H(0.8998877406f), SC_H(0.8841174841f), SC_H(0.8631930947f), + SC_H(0.8565139771f), SC_H(0.9251161218f)}, + {SC_H(0.9534626007f), SC_H(0.9500193000f), SC_H(0.9448821545f), + SC_H(0.9326565266f), SC_H(0.9220023751f), SC_H(0.9090909362f), + SC_H(0.9096591473f), SC_H(0.9514584541f)}, + {SC_H(0.9758449197f), SC_H(0.9738122821f), SC_H(0.9708200693f), + SC_H(0.9639287591f), SC_H(0.9582763910f), SC_H(0.9522733092f), + SC_H(0.9553207159f), SC_H(0.9750427008f)}, + {SC_H(0.9876723289f), SC_H(0.9865267277f), SC_H(0.9848603010f), + SC_H(0.9811310172f), SC_H(0.9782302976f), SC_H(0.9754966497f), + SC_H(0.9779621363f), SC_H(0.9873252511f)}, + {SC_H(0.9937641621f), SC_H(0.9931397438f), SC_H(0.9922404289f), + SC_H(0.9902750254f), SC_H(0.9888116717f), SC_H(0.9875672460f), + SC_H(0.9891131520f), SC_H(0.9936066866f)}, + {SC_H(0.9968600869f), SC_H(0.9965277910f), SC_H(0.9960530400f), + SC_H(0.9950347543f), SC_H(0.9943022728f), SC_H(0.9937300086f), + SC_H(0.9946073294f), SC_H(0.9967863560f)}, + {SC_H(0.9984226227f), SC_H(0.9982488155f), SC_H(0.9980020523f), + SC_H(0.9974802136f), SC_H(0.9971146584f), SC_H(0.9968476892f), + SC_H(0.9973216057f), SC_H(0.9983873963f)}, + {SC_H(0.9995003939f), SC_H(0.9994428754f), SC_H(0.9993617535f), + SC_H(0.9991930723f), SC_H(0.9990783334f), SC_H(0.9990010262f), + SC_H(0.9991616607f), SC_H(0.9994897842f)}, + {SC_H(0.9998419285f), SC_H(0.9998232722f), SC_H(0.9997970462f), + SC_H(0.9997430444f), SC_H(0.9997069836f), SC_H(0.9996838570f), + SC_H(0.9997364879f), SC_H(0.9998386502f)}, + {SC_H(0.9999499917f), SC_H(0.9999440312f), SC_H(0.9999356270f), + SC_H(0.9999184012f), SC_H(0.9999070764f), SC_H(0.9998999834f), + SC_H(0.9999169707f), SC_H(0.9999489784f)}, + {SC_H(0.9999842048f), SC_H(0.9999822974f), SC_H(0.9999796152f), + SC_H(0.9999741912f), SC_H(0.9999706149f), SC_H(0.9999684095f), + SC_H(0.9999738336f), SC_H(0.9999839067f)}, + /* { SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f), + SC_H( 1.0000000000f), SC_H( 1.0000000000f), SC_H( 1.0000000000f), + SC_H( 1.0000000000f), SC_H( 1.0000000000f)} */ + {FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL), + FX_DBL2FX_CFG(MAXVAL_DBL), FX_DBL2FX_CFG(MAXVAL_DBL)}}; +const DATA_TYPE_H H12_nc[31][8] = { + {SC_H(0.0000000000f), SC_H(0.0000000110f), SC_H(0.0000000171f), + SC_H(0.0000000253f), SC_H(0.0000000294f), SC_H(0.0000000316f), + SC_H(0.0000000256f), SC_H(0.0000000045f)}, + {SC_H(0.0000000000f), SC_H(0.0019540924f), SC_H(0.0030265113f), + SC_H(0.0044795922f), SC_H(0.0052186525f), SC_H(0.0056232354f), + SC_H(0.0045594489f), SC_H(0.0007977085f)}, + {SC_H(0.0000000000f), SC_H(0.0034606720f), SC_H(0.0053620986f), + SC_H(0.0079446984f), SC_H(0.0092647560f), SC_H(0.0099989995f), + SC_H(0.0081285369f), SC_H(0.0014247064f)}, + {SC_H(0.0000000000f), SC_H(0.0061091618f), SC_H(0.0094724922f), + SC_H(0.0140600521f), SC_H(0.0164252054f), SC_H(0.0177771728f), + SC_H(0.0145191532f), SC_H(0.0025531140f)}, + {SC_H(0.0000000000f), SC_H(0.0107228858f), SC_H(0.0166464616f), + SC_H(0.0247849934f), SC_H(0.0290434174f), SC_H(0.0315911844f), + SC_H(0.0260186065f), SC_H(0.0046027615f)}, + {SC_H(0.0000000000f), SC_H(0.0186282862f), SC_H(0.0289774220f), + SC_H(0.0433696397f), SC_H(0.0510888547f), SC_H(0.0560568646f), + SC_H(0.0468755551f), SC_H(0.0083869267f)}, + {SC_H(0.0000000000f), SC_H(0.0257363543f), SC_H(0.0401044972f), + SC_H(0.0602979437f), SC_H(0.0713650510f), SC_H(0.0789347738f), + SC_H(0.0669798329f), SC_H(0.0121226767f)}, + {SC_H(0.0000000000f), SC_H(0.0352233723f), SC_H(0.0550108925f), + SC_H(0.0832019597f), SC_H(0.0990892947f), SC_H(0.1108068749f), + SC_H(0.0960334241f), SC_H(0.0176920593f)}, + {SC_H(0.0000000000f), SC_H(0.0475566536f), SC_H(0.0744772255f), + SC_H(0.1134835035f), SC_H(0.1362429112f), SC_H(0.1546057910f), + SC_H(0.1381545961f), SC_H(0.0261824392f)}, + {SC_H(0.0000000000f), SC_H(0.0629518181f), SC_H(0.0989024863f), + SC_H(0.1520351619f), SC_H(0.1843357086f), SC_H(0.2131874412f), + SC_H(0.1990868896f), SC_H(0.0395608991f)}, + {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f), + SC_H(0.1980977356f), SC_H(0.2429044843f), SC_H(0.2874797881f), + SC_H(0.2856767476f), SC_H(0.0617875643f)}, + {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f), + SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f), + SC_H(0.3599678576f), SC_H(0.0857512727f)}, + {SC_H(0.0000000000f), SC_H(0.1057573780f), SC_H(0.1674221754f), + SC_H(0.2630588412f), SC_H(0.3274079263f), SC_H(0.4005688727f), + SC_H(0.4454404712f), SC_H(0.1242370531f)}, + {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915067f), + SC_H(0.2904545665f), SC_H(0.3636667728f), SC_H(0.4512939751f), + SC_H(0.5328993797f), SC_H(0.1951362640f)}, + {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952532977f), + SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870318770f), + SC_H(0.6028295755f), SC_H(0.3637395203f)}, + {SC_H(0.0000000000f), SC_H(0.1254990250f), SC_H(0.1992611140f), + SC_H(0.3158638775f), SC_H(0.3976053298f), SC_H(0.5000000000f), + SC_H(0.6302776933f), SC_H(0.7053368092f)}, + {SC_H(0.0000000000f), SC_H(0.1230182052f), SC_H(0.1952533126f), + SC_H(0.3091802597f), SC_H(0.3886501491f), SC_H(0.4870319068f), + SC_H(0.6028295755f), SC_H(0.3637394905f)}, + {SC_H(0.0000000000f), SC_H(0.1160409302f), SC_H(0.1839915216f), + SC_H(0.2904545665f), SC_H(0.3636668026f), SC_H(0.4512939751f), + SC_H(0.5328993797f), SC_H(0.1951362044f)}, + {SC_H(0.0000000000f), SC_H(0.1057573855f), SC_H(0.1674221754f), + SC_H(0.2630588710f), SC_H(0.3274079263f), SC_H(0.4005688727f), + SC_H(0.4454405010f), SC_H(0.1242370382f)}, + {SC_H(0.0000000000f), SC_H(0.0936254337f), SC_H(0.1479234397f), + SC_H(0.2310739607f), SC_H(0.2855334580f), SC_H(0.3436433673f), + SC_H(0.3599678576f), SC_H(0.0857512653f)}, + {SC_H(0.0000000000f), SC_H(0.0809580907f), SC_H(0.1276271492f), + SC_H(0.1980977207f), SC_H(0.2429044843f), SC_H(0.2874797881f), + SC_H(0.2856767476f), SC_H(0.0617875606f)}, + {SC_H(0.0000000000f), SC_H(0.0629518107f), SC_H(0.0989024863f), + SC_H(0.1520351619f), SC_H(0.1843357235f), SC_H(0.2131874412f), + SC_H(0.1990868896f), SC_H(0.0395609401f)}, + {SC_H(0.0000000000f), SC_H(0.0475566462f), SC_H(0.0744772255f), + SC_H(0.1134835184f), SC_H(0.1362429112f), SC_H(0.1546057761f), + SC_H(0.1381545961f), SC_H(0.0261824802f)}, + {SC_H(0.0000000000f), SC_H(0.0352233797f), SC_H(0.0550108962f), + SC_H(0.0832019448f), SC_H(0.0990892798f), SC_H(0.1108068526f), + SC_H(0.0960334465f), SC_H(0.0176920686f)}, + {SC_H(0.0000000000f), SC_H(0.0257363524f), SC_H(0.0401044935f), + SC_H(0.0602979474f), SC_H(0.0713650808f), SC_H(0.0789347589f), + SC_H(0.0669797957f), SC_H(0.0121226516f)}, + {SC_H(0.0000000000f), SC_H(0.0186282881f), SC_H(0.0289774258f), + SC_H(0.0433696248f), SC_H(0.0510888547f), SC_H(0.0560568906f), + SC_H(0.0468755886f), SC_H(0.0083869714f)}, + {SC_H(0.0000000000f), SC_H(0.0107228830f), SC_H(0.0166464727f), + SC_H(0.0247849822f), SC_H(0.0290434249f), SC_H(0.0315911621f), + SC_H(0.0260186475f), SC_H(0.0046027377f)}, + {SC_H(0.0000000000f), SC_H(0.0061091576f), SC_H(0.0094724894f), + SC_H(0.0140600465f), SC_H(0.0164251942f), SC_H(0.0177771524f), + SC_H(0.0145191504f), SC_H(0.0025530567f)}, + {SC_H(0.0000000000f), SC_H(0.0034606743f), SC_H(0.0053620976f), + SC_H(0.0079446994f), SC_H(0.0092647672f), SC_H(0.0099990256f), + SC_H(0.0081285043f), SC_H(0.0014247177f)}, + {SC_H(0.0000000000f), SC_H(0.0019540912f), SC_H(0.0030265225f), + SC_H(0.0044795908f), SC_H(0.0052186381f), SC_H(0.0056232223f), + SC_H(0.0045594289f), SC_H(0.0007977359f)}, + {SC_H(0.0000000000f), SC_H(0.0000000149f), SC_H(0.0000000298f), + SC_H(0.0000000298f), SC_H(0.0000000000f), SC_H(0.0000000596f), + SC_H(0.0000000000f), SC_H(0.0000000000f)}}; + +/* + for (i=0; i<31; i++) { + cld = dequantCLD[i]; + val = (float)(FDKexp(cld/dbe)/(1+FDKexp(cld/dbe))); + val = (float)(dbe*FDKlog(val)); + } +*/ +#define SCALE_CLD_C1C2(a) (FL2FXCONST_DBL(a / (float)(1 << SF_CLD_C1C2))) +const FIXP_DBL dequantCLD_c1[31] = {SCALE_CLD_C1C2(-1.5000000000000000e+002f), + SCALE_CLD_C1C2(-4.5000137329101563e+001f), + SCALE_CLD_C1C2(-4.0000434875488281e+001f), + SCALE_CLD_C1C2(-3.5001373291015625e+001f), + SCALE_CLD_C1C2(-3.0004341125488281e+001f), + SCALE_CLD_C1C2(-2.5013711929321289e+001f), + SCALE_CLD_C1C2(-2.2027315139770508e+001f), + SCALE_CLD_C1C2(-1.9054332733154297e+001f), + SCALE_CLD_C1C2(-1.6107742309570313e+001f), + SCALE_CLD_C1C2(-1.3212384223937988e+001f), + SCALE_CLD_C1C2(-1.0413927078247070e+001f), + SCALE_CLD_C1C2(-8.6389207839965820e+000f), + SCALE_CLD_C1C2(-6.9732279777526855e+000f), + SCALE_CLD_C1C2(-5.4554042816162109e+000f), + SCALE_CLD_C1C2(-4.1244258880615234e+000f), + SCALE_CLD_C1C2(-3.0102999210357666e+000f), + SCALE_CLD_C1C2(-2.1244258880615234e+000f), + SCALE_CLD_C1C2(-1.4554045200347900e+000f), + SCALE_CLD_C1C2(-9.7322785854339600e-001f), + SCALE_CLD_C1C2(-6.3892036676406860e-001f), + SCALE_CLD_C1C2(-4.1392669081687927e-001f), + SCALE_CLD_C1C2(-2.1238386631011963e-001f), + SCALE_CLD_C1C2(-1.0774217545986176e-001f), + SCALE_CLD_C1C2(-5.4333221167325974e-002f), + SCALE_CLD_C1C2(-2.7315950021147728e-002f), + SCALE_CLD_C1C2(-1.3711934909224510e-002f), + SCALE_CLD_C1C2(-4.3406565673649311e-003f), + SCALE_CLD_C1C2(-1.3732088264077902e-003f), + SCALE_CLD_C1C2(-4.3438826105557382e-004f), + SCALE_CLD_C1C2(-1.3745666365139186e-004f), + SCALE_CLD_C1C2(0.0000000000000000e+000f)}; + +/* sac_stp */ +/* none scaled */ +const FIXP_CFG BP__FDK[] = {FL2FXCONST_CFG(0.73919999599457), + FL2FXCONST_CFG(0.97909998893738), + FL2FXCONST_CFG(0.99930000305176)}; + +/* scaled with 26 bits */ +const FIXP_CFG BP_GF__FDK[] = { + FL2FXCONST_CFG(0.00000000643330), FL2FXCONST_CFG(0.00004396850232), + FL2FXCONST_CFG(0.00087456948552), FL2FXCONST_CFG(0.00474648220243), + FL2FXCONST_CFG(0.01717987244800), FL2FXCONST_CFG(0.04906742491073), + FL2FXCONST_CFG(0.10569518656729), FL2FXCONST_CFG(0.21165767592653), + FL2FXCONST_CFG(0.36036762478024), FL2FXCONST_CFG(0.59894182766948), + FL2FXCONST_CFG(0.81641678929129), FL2FXCONST_CFG(0.97418481133397), + FL2FXCONST_CFG(0.99575411610845), FL2FXCONST_CFG(0.88842666281361), + FL2FXCONST_CFG(0.79222317063736), FL2FXCONST_CFG(0.70828604318604), + FL2FXCONST_CFG(0.66395054816338), FL2FXCONST_CFG(0.64633739516952), + FL2FXCONST_CFG(0.66098278185255)}; + +/* sac_bitdec */ +const INT samplingFreqTable[16] = {96000, 88200, 64000, 48000, 44100, 32000, + 24000, 22050, 16000, 12000, 11025, 8000, + 7350, 0, 0, 0}; + +const UCHAR freqResTable[] = {0, 28, 20, 14, 10, 7, 5, 4}; + +const UCHAR freqResTable_LD[] = {0, 23, 15, 12, 9, 7, 5, 4}; + +const UCHAR tempShapeChanTable[][8] = {{5, 5, 4, 6, 6, 4, 4, 2}, + {5, 5, 5, 7, 7, 4, 4, 2}}; + +const TREEPROPERTIES treePropertyTable[] = { + {1, 6, 5, 0, {0, 0, 0, 0, 1}}, {1, 6, 5, 0, {0, 0, 1, 0, 0}}, + {2, 6, 3, 1, {1, 0, 0, 0, 0}}, {2, 8, 5, 1, {1, 0, 0, 0, 0}}, + {2, 8, 5, 1, {1, 0, 0, 0, 0}}, {6, 8, 2, 0, {0, 0, 0, 0, 0}}, + {6, 8, 2, 0, {0, 0, 0, 0, 0}}, {1, 2, 1, 0, {0, 0, 0, 0, 0}}}; + +const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}; + +const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 0, 0, 1, 1, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 8, + 8, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 11, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13}; + +const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, + 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19}; + +const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 21, 22, 22, 22, 23, + 23, 23, 23, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 26, 26, 26, + 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27}; + +const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 9, + 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, 11, 11, 12, + 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + +const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 14, 15, + 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 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, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22}; + +const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 14}; + +const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 10, 11, 11, 11}; + +const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8}; + +const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6}; + +const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4}; + +const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3}; + +const FIXP_CFG clipGainTable__FDK[] = { + /*CLIP_PROTECT_GAIN_0(1.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + CLIP_PROTECT_GAIN_1(1.189207f), + CLIP_PROTECT_GAIN_1(1.414213f), + CLIP_PROTECT_GAIN_1(1.681792f), + /*CLIP_PROTECT_GAIN_1(2.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + CLIP_PROTECT_GAIN_2(2.378414f), + CLIP_PROTECT_GAIN_2(2.828427f), + /*CLIP_PROTECT_GAIN_2(4.000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL)}; + +const UCHAR clipGainSFTable__FDK[] = {0, 1, 1, 1, 1, 2, 2, 2}; + +const UCHAR pbStrideTable[] = {1, 2, 5, 28}; + +const int smgTimeTable[] = {64, 128, 256, 512}; + +/* table is scaled by factor 0.5 */ +const FIXP_CFG envShapeDataTable__FDK[5][2] = { + {FL2FXCONST_CFG(0.25000000000000f), FL2FXCONST_CFG(0.25000000000000f)}, + {FL2FXCONST_CFG(0.35355339059327f), FL2FXCONST_CFG(0.31498026247372f)}, + {FL2FXCONST_CFG(0.50000000000000f), FL2FXCONST_CFG(0.39685026299205f)}, + {FL2FXCONST_CFG(0.70710678118655f), FL2FXCONST_CFG(0.50000000000000f)}, + {/*FL2FXCONST_CFG( 1.00000000000000f)*/ FX_DBL2FX_CFG(MAXVAL_DBL), + FL2FXCONST_CFG(0.62996052494744f)}}; + +/* sac_calcM1andM2 */ +const SCHAR row2channelSTP[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 2}, {0, 4}, + {0, 4}, {0, 2}, {-1, 2}, {0, 1}}; + +const SCHAR row2channelGES[][MAX_M2_INPUT] = {{0, 1}, {0, 3}, {0, 3}, {0, 5}, + {0, 5}, {0, 2}, {-1, 2}, {0, 1}}; + +const SCHAR row2residual[][MAX_M2_INPUT] = {{-1, 0}, {-1, 0}, {-1, -1}, + {-1, -1}, {-1, -1}, {-1, -1}, + {-1, -1}, {-1, 0}}; + +/******************************************************************************* + Functionname: sac_getCLDValues + ******************************************************************************* + + Description: Get CLD values from table index. + + Arguments: + index: Table index + *cu, *cl : Pointer to locations where resulting values will be written to. + + Return: nothing + +*******************************************************************************/ +void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl) { + *cu = FX_CFG2FX_DBL(dequantCLD_c_l[index]); + *cl = FX_CFG2FX_DBL(dequantCLD_c_l[31 - 1 - index]); +} + +void SpatialDequantGetCLD2Values(int idx, FIXP_DBL* x) { + *x = FX_CFG2FX_DBL(dequantCLD__FDK[idx]); +} diff --git a/fdk-aac/libSACdec/src/sac_rom.h b/fdk-aac/libSACdec/src/sac_rom.h new file mode 100644 index 0000000..d366fb6 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_rom.h @@ -0,0 +1,230 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec tables + +*******************************************************************************/ + +#ifndef SAC_ROM_H +#define SAC_ROM_H + +#include "FDK_archdef.h" +#include "sac_dec_interface.h" + +#include "huff_nodes.h" +#include "sac_bitdec.h" +#include "machine_type.h" + +/* Global ROM table data type: */ +#ifndef ARCH_PREFER_MULT_32x32 +#define FIXP_CFG FIXP_SGL +#define FX_CFG2FX_DBL FX_SGL2FX_DBL +#define FX_CFG2FX_SGL +#define CFG(a) (FX_DBL2FXCONST_SGL(a)) +#define FL2FXCONST_CFG FL2FXCONST_SGL +#define FX_DBL2FX_CFG(x) FX_DBL2FX_SGL((FIXP_DBL)(x)) +#else +#define FIXP_CFG FIXP_DBL +#define FX_CFG2FX_DBL +#define FX_CFG2FX_SGL FX_DBL2FX_SGL +#define CFG(a) FIXP_DBL(a) +#define FL2FXCONST_CFG FL2FXCONST_DBL +#define FX_DBL2FX_CFG(x) ((FIXP_DBL)(x)) +#endif + +/* others */ +#define SCALE_INV_ICC (2) +#define G_dd_SCALE (2) + +#define QCC_SCALE 1 +#define M1M2_DATA FIXP_DBL +#ifndef ARCH_PREFER_MULT_32x32 +#define M1M2_CDATA FIXP_SGL +#define M1M2_CDATA2FX_DBL(a) FX_SGL2FX_DBL(a) +#define FX_DBL2M1M2_CDATA(a) FX_DBL2FX_SGL(a) +#else +#define M1M2_CDATA FIXP_DBL +#define M1M2_CDATA2FX_DBL(a) (a) +#define FX_DBL2M1M2_CDATA(a) (a) +#endif + +#define CLIP_PROTECT_GAIN_0(x) FL2FXCONST_CFG(((x) / (float)(1 << 0))) +#define CLIP_PROTECT_GAIN_1(x) FL2FXCONST_CFG(((x) / (float)(1 << 1))) +#define CLIP_PROTECT_GAIN_2(x) FL2FXCONST_CFG(((x) / (float)(1 << 2))) + +#define SF_CLD_C1C2 (8) + +extern const FIXP_CFG dequantCPC__FDK[]; +extern const FIXP_CFG dequantICC__FDK[8]; +extern const FIXP_CFG dequantCLD__FDK[31]; + +#define IPD_SCALE (5) +#define PI__IPD (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << IPD_SCALE))) +/* Define for PI*2 for better precision in SpatialDecApplyPhase() */ +#define PIx2__IPD \ + (FL2FXCONST_DBL(3.1415926535897932f / (float)(1 << (IPD_SCALE - 1)))) + +extern const FIXP_CFG dequantIPD__FDK[16]; + +extern const FIXP_CFG H11_nc[31][8]; +extern const FIXP_CFG H12_nc[31][8]; + +extern const FIXP_DBL dequantCLD_c1[31]; + +extern const FIXP_CFG BP__FDK[]; +extern const FIXP_CFG BP_GF__FDK[]; +extern const SCHAR row2channelSTP[][MAX_M2_INPUT]; + +/* sac_bitdec */ +extern const INT samplingFreqTable[16]; +extern const UCHAR freqResTable[]; +extern const UCHAR freqResTable_LD[]; +extern const UCHAR tempShapeChanTable[2][8]; +extern const TREEPROPERTIES treePropertyTable[]; + +extern const SCHAR kernels_4_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_5_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_7_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_10_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_14_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_20_to_71[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_28_to_71[MAX_HYBRID_BANDS]; + +extern const UCHAR mapping_4_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_5_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_7_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_10_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_14_to_28[MAX_PARAMETER_BANDS]; +extern const UCHAR mapping_20_to_28[MAX_PARAMETER_BANDS]; +extern const SCHAR kernels_4_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_5_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_7_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_9_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_12_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_15_to_64[MAX_HYBRID_BANDS]; +extern const SCHAR kernels_23_to_64[MAX_HYBRID_BANDS]; + +extern const UCHAR mapping_15_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_12_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_9_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_7_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_5_to_23[MAX_PARAMETER_BANDS_LD]; +extern const UCHAR mapping_4_to_23[MAX_PARAMETER_BANDS_LD]; + +extern const FIXP_CFG clipGainTable__FDK[]; +extern const UCHAR clipGainSFTable__FDK[]; + +extern const UCHAR pbStrideTable[]; +extern const int smgTimeTable[]; + +extern const FIXP_CFG envShapeDataTable__FDK[5][2]; +extern const SCHAR row2channelGES[][MAX_M2_INPUT]; + +/* sac_calcM1andM2 */ +extern const SCHAR row2residual[][MAX_M2_INPUT]; + +void SpatialDequantGetCLDValues(int index, FIXP_DBL* cu, FIXP_DBL* cl); + +void SpatialDequantGetCLD2Values(int index, FIXP_DBL* x); + +/* External helper functions */ +static inline int SacGetHybridSubbands(int qmfSubbands) { + return qmfSubbands - MAX_QMF_BANDS_TO_HYBRID + 10; +} + +#endif /* SAC_ROM_H */ diff --git a/fdk-aac/libSACdec/src/sac_smoothing.cpp b/fdk-aac/libSACdec/src/sac_smoothing.cpp new file mode 100644 index 0000000..bee6551 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_smoothing.cpp @@ -0,0 +1,295 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec parameter smoothing + +*******************************************************************************/ + +#include "sac_dec.h" +#include "sac_bitdec.h" +#include "sac_smoothing.h" +#include "sac_rom.h" + +/******************************************************************************* + Functionname: calcFilterCoeff + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + + +*******************************************************************************/ +static FIXP_DBL calcFilterCoeff__FDK(spatialDec *self, int ps, + const SPATIAL_BS_FRAME *frame) { + int dSlots; + FIXP_DBL delta; + + dSlots = frame->paramSlot[ps] - self->smoothState->prevParamSlot; + + if (dSlots <= 0) { + dSlots += self->timeSlots; + } + + delta = fDivNorm(dSlots, self->smgTime[ps]); + + return delta; +} + +/******************************************************************************* + Functionname: getSmoothOnOff + ******************************************************************************* + + Description: + + Arguments: + + Input: + + Output: + + +*******************************************************************************/ +static int getSmoothOnOff(spatialDec *self, int ps, int pb) { + int smoothBand = 0; + + smoothBand = self->smgData[ps][pb]; + + return smoothBand; +} + +void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps) { + FIXP_DBL delta__FDK; + FIXP_DBL one_minus_delta__FDK; + + int pb, row, col; + int residualBands = 0; + + if (self->residualCoding) { + int i; + int boxes = self->numOttBoxes; + for (i = 0; i < boxes; i++) { + if (self->residualBands[i] > residualBands) { + residualBands = self->residualBands[i]; + } + } + } + + delta__FDK = calcFilterCoeff__FDK(self, ps, frame); + if (delta__FDK == /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL) + one_minus_delta__FDK = FL2FXCONST_DBL(0.0f); + else if (delta__FDK == FL2FXCONST_DBL(0.0f)) + one_minus_delta__FDK = /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL; + else + one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1; + + for (pb = 0; pb < self->numParameterBands; pb++) { + int smoothBand; + + smoothBand = getSmoothOnOff(self, ps, pb); + + if (smoothBand && (pb >= residualBands)) { + for (row = 0; row < self->numM2rows; row++) { + for (col = 0; col < self->numVChannels; col++) { + self->M2Real__FDK[row][col][pb] = + ((fMultDiv2(delta__FDK, self->M2Real__FDK[row][col][pb]) + + fMultDiv2(one_minus_delta__FDK, + self->M2RealPrev__FDK[row][col][pb])) + << 1); + if (0 || (self->phaseCoding == 3)) { + self->M2Imag__FDK[row][col][pb] = + ((fMultDiv2(delta__FDK, self->M2Imag__FDK[row][col][pb]) + + fMultDiv2(one_minus_delta__FDK, + self->M2ImagPrev__FDK[row][col][pb])) + << 1); + } + } + } + } + } + self->smoothState->prevParamSlot = frame->paramSlot[ps]; +} + +/* init states */ +void initParameterSmoothing(spatialDec *self) { + self->smoothState->prevParamSlot = 0; +} + +void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps) { + int pb; + int dSlots; + FIXP_DBL delta__FDK; + FIXP_DBL one_minus_delta__FDK; + FIXP_DBL *phaseLeftSmooth__FDK = self->smoothState->opdLeftState__FDK; + FIXP_DBL *phaseRightSmooth__FDK = self->smoothState->opdRightState__FDK; + int quantCoarse; + + quantCoarse = frame->IPDLosslessData[0].bsQuantCoarseXXX[ps]; + + if (frame->OpdSmoothingMode == 0) { + FDKmemcpy(phaseLeftSmooth__FDK, self->PhaseLeft__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + FDKmemcpy(phaseRightSmooth__FDK, self->PhaseRight__FDK, + self->numParameterBands * sizeof(FIXP_DBL)); + } else { + if (ps == 0) { + dSlots = frame->paramSlot[ps] + 1; + } else { + dSlots = frame->paramSlot[ps] - frame->paramSlot[ps - 1]; + } + + delta__FDK = (FIXP_DBL)((INT)(FL2FXCONST_DBL(0.0078125f)) * dSlots); + + if (delta__FDK == (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/) + one_minus_delta__FDK = FL2FXCONST_DBL(0.0f); + else if (delta__FDK == FL2FXCONST_DBL(0.0f)) + one_minus_delta__FDK = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + else + one_minus_delta__FDK = (FL2FXCONST_DBL(0.5f) - (delta__FDK >> 1)) << 1; + + for (pb = 0; pb < self->numParameterBands; pb++) { + FIXP_DBL tmpL, tmpR, tmp; + + tmpL = self->PhaseLeft__FDK[pb]; + tmpR = self->PhaseRight__FDK[pb]; + + while (tmpL > phaseLeftSmooth__FDK[pb] + PI__IPD) tmpL -= PI__IPD << 1; + while (tmpL < phaseLeftSmooth__FDK[pb] - PI__IPD) tmpL += PI__IPD << 1; + while (tmpR > phaseRightSmooth__FDK[pb] + PI__IPD) tmpR -= PI__IPD << 1; + while (tmpR < phaseRightSmooth__FDK[pb] - PI__IPD) tmpR += PI__IPD << 1; + + phaseLeftSmooth__FDK[pb] = + fMult(delta__FDK, tmpL) + + fMult(one_minus_delta__FDK, phaseLeftSmooth__FDK[pb]); + phaseRightSmooth__FDK[pb] = + fMult(delta__FDK, tmpR) + + fMult(one_minus_delta__FDK, phaseRightSmooth__FDK[pb]); + + tmp = (((tmpL >> 1) - (tmpR >> 1)) - ((phaseLeftSmooth__FDK[pb] >> 1) - + (phaseRightSmooth__FDK[pb] >> 1))) + << 1; + while (tmp > PI__IPD) tmp -= PI__IPD << 1; + while (tmp < -PI__IPD) tmp += PI__IPD << 1; + if (fixp_abs(tmp) > fMult((quantCoarse ? FL2FXCONST_DBL(50.f / 180.f) + : FL2FXCONST_DBL(25.f / 180.f)), + PI__IPD)) { + phaseLeftSmooth__FDK[pb] = tmpL; + phaseRightSmooth__FDK[pb] = tmpR; + } + + while (phaseLeftSmooth__FDK[pb] > PI__IPD << 1) + phaseLeftSmooth__FDK[pb] -= PI__IPD << 1; + while (phaseLeftSmooth__FDK[pb] < (FIXP_DBL)0) + phaseLeftSmooth__FDK[pb] += PI__IPD << 1; + while (phaseRightSmooth__FDK[pb] > PI__IPD << 1) + phaseRightSmooth__FDK[pb] -= PI__IPD << 1; + while (phaseRightSmooth__FDK[pb] < (FIXP_DBL)0) + phaseRightSmooth__FDK[pb] += PI__IPD << 1; + + self->PhaseLeft__FDK[pb] = phaseLeftSmooth__FDK[pb]; + self->PhaseRight__FDK[pb] = phaseRightSmooth__FDK[pb]; + } + } + return; +} diff --git a/fdk-aac/libSACdec/src/sac_smoothing.h b/fdk-aac/libSACdec/src/sac_smoothing.h new file mode 100644 index 0000000..fdf3f5b --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_smoothing.h @@ -0,0 +1,114 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec parameter smoothing + +*******************************************************************************/ + +#ifndef SAC_SMOOTHING_H +#define SAC_SMOOTHING_H + +#include "sac_dec.h" + +void initParameterSmoothing(spatialDec *self); +void SpatialDecSmoothM1andM2(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps); +void SpatialDecSmoothOPD(spatialDec *self, const SPATIAL_BS_FRAME *frame, + int ps); + +#endif diff --git a/fdk-aac/libSACdec/src/sac_stp.cpp b/fdk-aac/libSACdec/src/sac_stp.cpp new file mode 100644 index 0000000..818e9df --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_stp.cpp @@ -0,0 +1,548 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec subband processing + +*******************************************************************************/ + +#include "sac_stp.h" +#include "sac_calcM1andM2.h" +#include "sac_bitdec.h" +#include "FDK_matrixCalloc.h" +#include "sac_rom.h" + +#define BP_GF_START 6 +#define BP_GF_SIZE 25 +#define HP_SIZE 9 +#define STP_UPDATE_ENERGY_RATE 32 + +#define SF_WET 5 +#define SF_DRY \ + 3 /* SF_DRY == 2 would produce good conformance test results as well */ +#define SF_PRODUCT_BP_GF 13 +#define SF_PRODUCT_BP_GF_GF 26 +#define SF_SCALE 2 + +#define SF_SCALE_LD64 FL2FXCONST_DBL(0.03125) /* LD64((1<= scale2 >= 1/STP_SCALE_LIMIT + => STP_SCALE_LIMIT >= (0.1 + 0.9 * scale) >= 1/STP_SCALE_LIMIT + => (STP_SCALE_LIMIT-0.1)/0.9 >= scale >= + (1/STP_SCALE_LIMIT-0.1)/0.9 + + 3. Limiting of scale factor before sqrt calculation + ((STP_SCALE_LIMIT-0.1)/0.9)^2 >= (scale^2) >= + ((1/STP_SCALE_LIMIT-0.1)/0.9)^2 (STP_SCALE_LIMIT_HI)^2 >= (scale^2) >= + (STP_SCALE_LIMIT_LO)^2 + + 4. Thresholds for limiting of scale factor + STP_SCALE_LIMIT_HI = ((2.82-0.1)/0.9) + STP_SCALE_LIMIT_LO = (((1.0/2.82)-0.1)/0.9) + STP_SCALE_LIMIT_HI_LD64 = LD64(STP_SCALE_LIMIT_HI*STP_SCALE_LIMIT_HI) + STP_SCALE_LIMIT_LO_LD64 = LD64(STP_SCALE_LIMIT_LO*STP_SCALE_LIMIT_LO) +*/ + +#define DRY_ENER_WEIGHT(DryEner) DryEner = DryEner >> dry_scale_dmx + +#define WET_ENER_WEIGHT(WetEner) WetEner = WetEner << wet_scale_dmx + +#define DRY_ENER_SUM_REAL(DryEner, dmxReal, n) \ + DryEner += \ + fMultDiv2(fPow2Div2(dmxReal << SF_DRY), pBP[n]) >> ((2 * SF_DRY) - 2) + +#define DRY_ENER_SUM_CPLX(DryEner, dmxReal, dmxImag, n) \ + DryEner += fMultDiv2( \ + fPow2Div2(dmxReal << SF_DRY) + fPow2Div2(dmxImag << SF_DRY), pBP[n]) + +#define CALC_WET_SCALE(dryIdx, wetIdx) \ + if ((DryEnerLD64[dryIdx] - STP_SCALE_LIMIT_HI_LD64) > WetEnerLD64[wetIdx]) { \ + scale[wetIdx] = STP_SCALE_LIMIT_HI; \ + } else if (DryEnerLD64[dryIdx] < \ + (WetEnerLD64[wetIdx] - STP_SCALE_LIMIT_LO_LD64)) { \ + scale[wetIdx] = STP_SCALE_LIMIT_LO; \ + } else { \ + tmp = ((DryEnerLD64[dryIdx] - WetEnerLD64[wetIdx]) >> 1) - SF_SCALE_LD64; \ + scale[wetIdx] = CalcInvLdData(tmp); \ + } + +struct STP_DEC { + FIXP_DBL runDryEner[MAX_INPUT_CHANNELS]; + FIXP_DBL runWetEner[MAX_OUTPUT_CHANNELS]; + FIXP_DBL oldDryEnerLD64[MAX_INPUT_CHANNELS]; + FIXP_DBL oldWetEnerLD64[MAX_OUTPUT_CHANNELS]; + FIXP_DBL prev_tp_scale[MAX_OUTPUT_CHANNELS]; + const FIXP_CFG *BP; + const FIXP_CFG *BP_GF; + int update_old_ener; +}; + +inline void combineSignalReal(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputRealWet, int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet; + hybOutputRealDry++, hybOutputRealWet++; + } +} + +inline void combineSignalRealScale1(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputRealWet, FIXP_DBL scaleX, + int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = + *hybOutputRealDry + + (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1)); + hybOutputRealDry++, hybOutputRealWet++; + } +} + +inline void combineSignalCplx(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = *hybOutputRealDry + *hybOutputRealWet; + *hybOutputImagDry = *hybOutputImagDry + *hybOutputImagWet; + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + } +} + +inline void combineSignalCplxScale1(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, + const FIXP_CFG *pBP, FIXP_DBL scaleX, + int bands) { + int n; + FIXP_DBL scaleY; + for (n = bands - 1; n >= 0; n--) { + scaleY = fMultDiv2(scaleX, *pBP); + *hybOutputRealDry = + *hybOutputRealDry + + (fMultDiv2(*hybOutputRealWet, scaleY) << (SF_SCALE + 2)); + *hybOutputImagDry = + *hybOutputImagDry + + (fMultDiv2(*hybOutputImagWet, scaleY) << (SF_SCALE + 2)); + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + pBP++; + } +} + +inline void combineSignalCplxScale2(FIXP_DBL *hybOutputRealDry, + FIXP_DBL *hybOutputImagDry, + FIXP_DBL *hybOutputRealWet, + FIXP_DBL *hybOutputImagWet, FIXP_DBL scaleX, + int bands) { + int n; + + for (n = bands - 1; n >= 0; n--) { + *hybOutputRealDry = + *hybOutputRealDry + + (fMultDiv2(*hybOutputRealWet, scaleX) << (SF_SCALE + 1)); + *hybOutputImagDry = + *hybOutputImagDry + + (fMultDiv2(*hybOutputImagWet, scaleX) << (SF_SCALE + 1)); + hybOutputRealDry++, hybOutputRealWet++; + hybOutputImagDry++, hybOutputImagWet++; + } +} + +/******************************************************************************* + Functionname: subbandTPCreate + ******************************************************************************/ +SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec) { + HANDLE_STP_DEC self = NULL; + FDK_ALLOCATE_MEMORY_1D(self, 1, struct STP_DEC) + if (hStpDec != NULL) { + *hStpDec = self; + } + + return MPS_OK; +bail: + return MPS_OUTOFMEMORY; +} + +SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self) { + SACDEC_ERROR err = MPS_OK; + int ch; + + for (ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++) { + self->prev_tp_scale[ch] = FL2FXCONST_DBL(1.0f / (1 << SF_SCALE)); + self->oldWetEnerLD64[ch] = + FL2FXCONST_DBL(0.34375f); /* 32768.0*32768.0/2^(44-26-10) */ + } + for (ch = 0; ch < MAX_INPUT_CHANNELS; ch++) { + self->oldDryEnerLD64[ch] = + FL2FXCONST_DBL(0.1875f); /* 32768.0*32768.0/2^(44-26) */ + } + + self->BP = BP__FDK; + self->BP_GF = BP_GF__FDK; + + self->update_old_ener = 0; + + return err; +} + +/******************************************************************************* + Functionname: subbandTPDestroy + ******************************************************************************/ +void subbandTPDestroy(HANDLE_STP_DEC *hStpDec) { + if (hStpDec != NULL) { + FDK_FREE_MEMORY_1D(*hStpDec); + } +} + +/******************************************************************************* + Functionname: subbandTPApply + ******************************************************************************/ +SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame) { + FIXP_DBL *qmfOutputRealDry[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputImagDry[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputRealWet[MAX_OUTPUT_CHANNELS]; + FIXP_DBL *qmfOutputImagWet[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEner[MAX_INPUT_CHANNELS]; + FIXP_DBL scale[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEnerLD64[MAX_INPUT_CHANNELS]; + FIXP_DBL WetEnerLD64[MAX_OUTPUT_CHANNELS]; + + FIXP_DBL DryEner0 = FL2FXCONST_DBL(0.0f); + FIXP_DBL WetEnerX, damp, tmp; + FIXP_DBL dmxReal0, dmxImag0; + int skipChannels[MAX_OUTPUT_CHANNELS]; + int n, ch, cplxBands, cplxHybBands; + int dry_scale_dmx, wet_scale_dmx; + int i_LF, i_RF; + HANDLE_STP_DEC hStpDec; + const FIXP_CFG *pBP; + + int nrgScale = (2 * self->clipProtectGainSF__FDK); + + hStpDec = self->hStpDec; + + /* set scalefactor and loop counter */ + FDK_ASSERT(SF_DRY >= 1); + { + cplxBands = BP_GF_SIZE; + cplxHybBands = self->hybridBands; + dry_scale_dmx = (2 * SF_DRY) - 2; + wet_scale_dmx = 2; + } + + /* setup pointer for forming the direct downmix signal */ + for (ch = 0; ch < self->numOutputChannels; ch++) { + qmfOutputRealDry[ch] = &self->hybOutputRealDry__FDK[ch][7]; + qmfOutputRealWet[ch] = &self->hybOutputRealWet__FDK[ch][7]; + qmfOutputImagDry[ch] = &self->hybOutputImagDry__FDK[ch][7]; + qmfOutputImagWet[ch] = &self->hybOutputImagWet__FDK[ch][7]; + } + + /* clear skipping flag for all output channels */ + FDKmemset(skipChannels, 0, self->numOutputChannels * sizeof(int)); + + /* set scale values to zero */ + FDKmemset(scale, 0, self->numOutputChannels * sizeof(FIXP_DBL)); + + /* update normalisation energy with latest smoothed energy */ + if (hStpDec->update_old_ener == STP_UPDATE_ENERGY_RATE) { + hStpDec->update_old_ener = 1; + for (ch = 0; ch < self->numInputChannels; ch++) { + hStpDec->oldDryEnerLD64[ch] = + CalcLdData(hStpDec->runDryEner[ch] + ABS_THR__FDK); + } + for (ch = 0; ch < self->numOutputChannels; ch++) { + hStpDec->oldWetEnerLD64[ch] = + CalcLdData(hStpDec->runWetEner[ch] + ABS_THR2__FDK); + } + } else { + hStpDec->update_old_ener++; + } + + /* get channel configuration */ + switch (self->treeConfig) { + case TREE_212: + i_LF = 0; + i_RF = 1; + break; + default: + return MPS_WRONG_TREECONFIG; + } + + /* form the 'direct' downmix signal */ + pBP = hStpDec->BP_GF - BP_GF_START; + switch (self->treeConfig) { + case TREE_212: + for (n = BP_GF_START; n < cplxBands; n++) { + dmxReal0 = qmfOutputRealDry[i_LF][n] + qmfOutputRealDry[i_RF][n]; + dmxImag0 = qmfOutputImagDry[i_LF][n] + qmfOutputImagDry[i_RF][n]; + DRY_ENER_SUM_CPLX(DryEner0, dmxReal0, dmxImag0, n); + } + DRY_ENER_WEIGHT(DryEner0); + break; + default:; + } + DryEner[0] = DryEner0; + + /* normalise the 'direct' signals */ + for (ch = 0; ch < self->numInputChannels; ch++) { + DryEner[ch] = DryEner[ch] << (nrgScale); + hStpDec->runDryEner[ch] = + fMult(STP_LPF_COEFF1__FDK, hStpDec->runDryEner[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, DryEner[ch]); + if (DryEner[ch] != FL2FXCONST_DBL(0.0f)) { + DryEnerLD64[ch] = + fixMax((CalcLdData(DryEner[ch]) - hStpDec->oldDryEnerLD64[ch]), + FL2FXCONST_DBL(-0.484375f)); + } else { + DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } + } + if (self->treeConfig == TREE_212) { + for (; ch < MAX_INPUT_CHANNELS; ch++) { + DryEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } + } + + /* normalise the 'diffuse' signals */ + pBP = hStpDec->BP_GF - BP_GF_START; + for (ch = 0; ch < self->numOutputChannels; ch++) { + if (skipChannels[ch]) { + continue; + } + + WetEnerX = FL2FXCONST_DBL(0.0f); + for (n = BP_GF_START; n < cplxBands; n++) { + tmp = fPow2Div2(qmfOutputRealWet[ch][n] << SF_WET); + tmp += fPow2Div2(qmfOutputImagWet[ch][n] << SF_WET); + WetEnerX += fMultDiv2(tmp, pBP[n]); + } + WET_ENER_WEIGHT(WetEnerX); + + WetEnerX = WetEnerX << (nrgScale); + hStpDec->runWetEner[ch] = + fMult(STP_LPF_COEFF1__FDK, hStpDec->runWetEner[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF1__FDK, WetEnerX); + + if (WetEnerX == FL2FXCONST_DBL(0.0f)) { + WetEnerLD64[ch] = FL2FXCONST_DBL(-0.484375f); + } else { + WetEnerLD64[ch] = + fixMax((CalcLdData(WetEnerX) - hStpDec->oldWetEnerLD64[ch]), + FL2FXCONST_DBL(-0.484375f)); + } + } + + /* compute scale factor for the 'diffuse' signals */ + switch (self->treeConfig) { + case TREE_212: + if (DryEner[0] != FL2FXCONST_DBL(0.0f)) { + CALC_WET_SCALE(0, i_LF); + CALC_WET_SCALE(0, i_RF); + } + break; + default:; + } + + damp = FL2FXCONST_DBL(0.1f / (1 << SF_SCALE)); + for (ch = 0; ch < self->numOutputChannels; ch++) { + /* damp the scaling factor */ + scale[ch] = damp + fMult(FL2FXCONST_DBL(0.9f), scale[ch]); + + /* limiting the scale factor */ + if (scale[ch] > STP_SCALE_LIMIT__FDK) { + scale[ch] = STP_SCALE_LIMIT__FDK; + } + if (scale[ch] < ONE_DIV_STP_SCALE_LIMIT__FDK) { + scale[ch] = ONE_DIV_STP_SCALE_LIMIT__FDK; + } + + /* low pass filter the scaling factor */ + scale[ch] = + fMult(STP_LPF_COEFF2__FDK, scale[ch]) + + fMult(ONE_MINUS_STP_LPF_COEFF2__FDK, hStpDec->prev_tp_scale[ch]); + hStpDec->prev_tp_scale[ch] = scale[ch]; + } + + /* combine 'direct' and scaled 'diffuse' signal */ + FDK_ASSERT((HP_SIZE - 3 + 10 - 1) == PC_NUM_HYB_BANDS); + const SCHAR *channlIndex = row2channelSTP[self->treeConfig]; + + for (ch = 0; ch < self->numOutputChannels; ch++) { + int no_scaling; + + no_scaling = !frame->tempShapeEnableChannelSTP[channlIndex[ch]]; + if (no_scaling) { + combineSignalCplx( + &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], + cplxHybBands - self->tp_hybBandBorder); + + } else { + FIXP_DBL scaleX; + scaleX = scale[ch]; + pBP = hStpDec->BP - self->tp_hybBandBorder; + /* Band[HP_SIZE-3+10-1] needs not to be processed in + combineSignalCplxScale1(), because pB[HP_SIZE-3+10-1] would be 1.0 */ + combineSignalCplxScale1( + &self->hybOutputRealDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagDry__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputRealWet__FDK[ch][self->tp_hybBandBorder], + &self->hybOutputImagWet__FDK[ch][self->tp_hybBandBorder], + &pBP[self->tp_hybBandBorder], scaleX, + (HP_SIZE - 3 + 10 - 1) - self->tp_hybBandBorder); + + { + combineSignalCplxScale2( + &self->hybOutputRealDry__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputImagDry__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputRealWet__FDK[ch][HP_SIZE - 3 + 10 - 1], + &self->hybOutputImagWet__FDK[ch][HP_SIZE - 3 + 10 - 1], scaleX, + cplxHybBands - (HP_SIZE - 3 + 10 - 1)); + } + } + } + + return (SACDEC_ERROR)MPS_OK; + ; +} diff --git a/fdk-aac/libSACdec/src/sac_stp.h b/fdk-aac/libSACdec/src/sac_stp.h new file mode 100644 index 0000000..18471bd --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_stp.h @@ -0,0 +1,115 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): + + Description: SAC Dec subband processing + +*******************************************************************************/ + +#ifndef SAC_STP_H +#define SAC_STP_H + +#include "sac_dec.h" + +SACDEC_ERROR subbandTPCreate(HANDLE_STP_DEC *hStpDec); + +SACDEC_ERROR subbandTPInit(HANDLE_STP_DEC self); + +SACDEC_ERROR subbandTPApply(spatialDec *self, const SPATIAL_BS_FRAME *frame); +void subbandTPDestroy(HANDLE_STP_DEC *hStpDec); + +#endif diff --git a/fdk-aac/libSACdec/src/sac_tsd.cpp b/fdk-aac/libSACdec/src/sac_tsd.cpp new file mode 100644 index 0000000..30acca8 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_tsd.cpp @@ -0,0 +1,353 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Matthias Hildenbrand + + Description: USAC MPS212 Transient Steering Decorrelator (TSD) + +*******************************************************************************/ + +#include "sac_tsd.h" + +#define TSD_START_BAND (7) +#define SIZE_S (4) +#define SIZE_C (5) + +/*** Tables ***/ +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const UCHAR nBitsTsdCW_32slots[32] = { + 5, 9, 13, 16, 18, 20, 22, 24, 25, 26, 27, 28, 29, 29, 30, 30, + 30, 29, 29, 28, 27, 26, 25, 24, 22, 20, 18, 16, 13, 9, 5, 0}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const UCHAR nBitsTsdCW_64slots[64] = { + 6, 11, 16, 20, 23, 27, 30, 33, 35, 38, 40, 42, 44, 46, 48, 49, + 51, 52, 53, 55, 56, 57, 58, 58, 59, 60, 60, 60, 61, 61, 61, 61, + 61, 61, 61, 60, 60, 60, 59, 58, 58, 57, 56, 55, 53, 52, 51, 49, + 48, 46, 44, 42, 40, 38, 35, 33, 30, 27, 23, 20, 16, 11, 6, 0}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_STP phiTsd[8] = { + STCP(0x7fffffff, 0x00000000), STCP(0x5a82799a, 0x5a82799a), + STCP(0x00000000, 0x7fffffff), STCP(0xa57d8666, 0x5a82799a), + STCP(0x80000000, 0x00000000), STCP(0xa57d8666, 0xa57d8666), + STCP(0x00000000, 0x80000000), STCP(0x5a82799a, 0xa57d8666), +}; + +/*** Static Functions ***/ +static void longmult1(USHORT a[], USHORT b, USHORT d[], int len) { + int k; + ULONG tmp; + ULONG b0 = (ULONG)b; + + tmp = ((ULONG)a[0]) * b0; + d[0] = (USHORT)tmp; + + for (k = 1; k < len; k++) { + tmp = (tmp >> 16) + ((ULONG)a[k]) * b0; + d[k] = (USHORT)tmp; + } +} + +static void longdiv(USHORT b[], USHORT a, USHORT d[], USHORT *pr, int len) { + ULONG r; + ULONG tmp; + int k; + + FDK_ASSERT(a != 0); + + r = 0; + + for (k = len - 1; k >= 0; k--) { + tmp = ((ULONG)b[k]) + (r << 16); + + if (tmp) { + d[k] = (USHORT)(tmp / a); + r = tmp - d[k] * a; + } else { + d[k] = 0; + } + } + *pr = (USHORT)r; +} + +static void longsub(USHORT a[], USHORT b[], int lena, int lenb) { + int h; + LONG carry = 0; + + FDK_ASSERT(lena >= lenb); + for (h = 0; h < lenb; h++) { + carry += ((LONG)a[h]) - ((LONG)b[h]); + a[h] = (USHORT)carry; + carry = carry >> 16; + } + + for (; h < lena; h++) { + carry = ((LONG)a[h]) + carry; + a[h] = (USHORT)carry; + carry = carry >> 16; + } + + FDK_ASSERT(carry == + 0); /* carry != 0 indicates subtraction underflow, e.g. b > a */ + return; +} + +static int longcompare(USHORT a[], USHORT b[], int len) { + int i; + + for (i = len - 1; i > 0; i--) { + if (a[i] != b[i]) break; + } + return (a[i] >= b[i]) ? 1 : 0; +} + +FDK_INLINE int isTrSlot(const TSD_DATA *pTsdData, const int ts) { + return (pTsdData->bsTsdTrPhaseData[ts] >= 0); +} + +/*** Public Functions ***/ +int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData) { + int nBitsTrSlots = 0; + int bsTsdNumTrSlots; + const UCHAR *nBitsTsdCW_tab = NULL; + + switch (numSlots) { + case 32: + nBitsTrSlots = 4; + nBitsTsdCW_tab = nBitsTsdCW_32slots; + break; + case 64: + nBitsTrSlots = 5; + nBitsTsdCW_tab = nBitsTsdCW_64slots; + break; + default: + return 1; + } + + /*** Read TempShapeData for bsTempShapeConfig == 3 ***/ + pTsdData->bsTsdEnable = FDKreadBit(hBs); + if (!pTsdData->bsTsdEnable) { + return 0; + } + + /*** Parse/Decode TsdData() ***/ + pTsdData->numSlots = numSlots; + + bsTsdNumTrSlots = FDKreadBits(hBs, nBitsTrSlots); + + /* Decode transient slot positions */ + { + int nBitsTsdCW = (int)nBitsTsdCW_tab[bsTsdNumTrSlots]; + SCHAR *phaseData = pTsdData->bsTsdTrPhaseData; + int p = bsTsdNumTrSlots + 1; + int k, h; + USHORT s[SIZE_S] = {0}; + USHORT c[SIZE_C] = {0}; + USHORT r[1]; + + /* Init with TsdSepData[k] = 0 */ + for (k = 0; k < numSlots; k++) { + phaseData[k] = -1; /* means TsdSepData[] = 0 */ + } + + for (h = (SIZE_S - 1); h >= 0; h--) { + if (nBitsTsdCW > h * 16) { + s[h] = (USHORT)FDKreadBits(hBs, nBitsTsdCW - h * 16); + nBitsTsdCW = h * 16; + } + } + + /* c = prod_{h=1}^{p} (k-p+h)/h */ + k = numSlots - 1; + c[0] = k - p + 1; + for (h = 2; h <= p; h++) { + longmult1(c, (k - p + h), c, 5); /* c *= k - p + h; */ + longdiv(c, h, c, r, 5); /* c /= h; */ + FDK_ASSERT(*r == 0); + } + + /* go through all slots */ + for (; k >= 0; k--) { + if (p > k) { + for (; k >= 0; k--) { + phaseData[k] = 1; /* means TsdSepData[] = 1 */ + } + break; + } + if (longcompare(s, c, 4)) { /* (s >= c) */ + longsub(s, c, 4, 4); /* s -= c; */ + phaseData[k] = 1; /* means TsdSepData[] = 1 */ + if (p == 1) { + break; + } + /* Update c for next iteration: c_new = c_old * p / k */ + longmult1(c, p, c, 5); + p--; + } else { + /* Update c for next iteration: c_new = c_old * (k-p) / k */ + longmult1(c, (k - p), c, 5); + } + longdiv(c, k, c, r, 5); + FDK_ASSERT(*r == 0); + } + + /* Read phase data */ + for (k = 0; k < numSlots; k++) { + if (phaseData[k] == 1) { + phaseData[k] = FDKreadBits(hBs, 3); + } + } + } + + return 0; +} + +void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData, + const int ts, FIXP_DBL *pVdirectReal, + FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal, + FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal, + FIXP_DBL **ppDecorrInImag) { + int k = 0; + + if (!isTrSlot(pTsdData, ts)) { + /* Let allpass based decorrelator read from direct input. */ + *ppDecorrInReal = pVdirectReal; + *ppDecorrInImag = pVdirectImag; + return; + } + + /* Generate nonTr input signal for allpass based decorrelator */ + for (; k < TSD_START_BAND; k++) { + pVnonTrReal[k] = pVdirectReal[k]; + pVnonTrImag[k] = pVdirectImag[k]; + } + for (; k < numHybridBands; k++) { + pVnonTrReal[k] = (FIXP_DBL)0; + pVnonTrImag[k] = (FIXP_DBL)0; + } + *ppDecorrInReal = pVnonTrReal; + *ppDecorrInImag = pVnonTrImag; +} + +void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs, + const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag, + FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag) { + const int ts = *pTsdTs; + + if (isTrSlot(pTsdData, ts)) { + int k; + const FIXP_STP *phi = &phiTsd[pTsdData->bsTsdTrPhaseData[ts]]; + FDK_ASSERT((pTsdData->bsTsdTrPhaseData[ts] >= 0) && + (pTsdData->bsTsdTrPhaseData[ts] < 8)); + + /* d = d_nonTr + v_direct * exp(j * bsTsdTrPhaseData[ts]/4 * pi ) */ + for (k = TSD_START_BAND; k < numHybridBands; k++) { + FIXP_DBL tempReal, tempImag; + cplxMult(&tempReal, &tempImag, pVdirectReal[k], pVdirectImag[k], *phi); + pDnonTrReal[k] += tempReal; + pDnonTrImag[k] += tempImag; + } + } + + /* The modulo MAX_TSD_TIME_SLOTS operation is to avoid illegal memory accesses + * in case of errors. */ + *pTsdTs = (ts + 1) & (MAX_TSD_TIME_SLOTS - 1); + return; +} diff --git a/fdk-aac/libSACdec/src/sac_tsd.h b/fdk-aac/libSACdec/src/sac_tsd.h new file mode 100644 index 0000000..2521e27 --- /dev/null +++ b/fdk-aac/libSACdec/src/sac_tsd.h @@ -0,0 +1,167 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround decoder library ************************* + + Author(s): Matthias Hildenbrand + + Description: USAC MPS212 Transient Steering Decorrelator (TSD) + +*******************************************************************************/ + +#ifndef SAC_TSD_H +#define SAC_TSD_H + +#include "FDK_bitstream.h" +#include "common_fix.h" + +#define MAX_TSD_TIME_SLOTS (64) + +/** Structure which holds the data needed to apply TSD to current frame. */ +typedef struct { + UCHAR bsTsdEnable; /**< for current frame TSD is (0:disabled, 1:enabled) */ + UCHAR numSlots; /**< total number of QMF slots per frame */ + SCHAR + bsTsdTrPhaseData[MAX_TSD_TIME_SLOTS]; /**< -1 => TsdSepData[ts]=0; 0-7: + values of bsTsdTrPhaseData[ts] + and TsdSepData[ts]=1 */ +} TSD_DATA; + +FDK_INLINE int isTsdActive(const TSD_DATA *pTsdData) { + return (int)pTsdData->bsTsdEnable; +} + +/** + * \brief Parse and Decode TSD data. + * \param[in] hBs bitstream handle to read data from. + * \param[in] numSlots number of QMF slots per frame. + * \param[out] pTsdData pointer to TSD data structure. + * \return 0 on succes, 1 on error. + */ +int TsdRead(HANDLE_FDK_BITSTREAM hBs, const int numSlots, TSD_DATA *pTsdData); + +/** + * \brief Perform transient seperation (v_{x,nonTr} signal). + * \param[in] numHybridBands number of hybrid bands. + * \param[in] pTsdData pointer to TSD data structure. + * \param[in] pVdirectReal pointer to array with direct signal. + * \param[in] pVdirectImag pointer to array with direct signal. + * \param[out] pVnonTrReal pointer to array with nonTr signal. + * \param[out] pVnonTrImag pointer to array with nonTr signal. + * \param[out] ppDecorrInReal handle to array where allpass based decorrelator + * should read from (modified by this function). + * \param[out] ppDecorrInImag handle to array where allpass based decorrelator + * should read from (modified by this function). + */ +void TsdGenerateNonTr(const int numHybridBands, const TSD_DATA *pTsdData, + const int ts, FIXP_DBL *pVdirectReal, + FIXP_DBL *pVdirectImag, FIXP_DBL *pVnonTrReal, + FIXP_DBL *pVnonTrImag, FIXP_DBL **ppDecorrInReal, + FIXP_DBL **ppDecorrInImag); + +/** + * \brief Generate d_{x,Tr} signal and add to d_{x,nonTr} signal + * \param[in] numHybridBands + * \param[in,out] pTsdData + * \param pTsdTs pointer to persistent time slot counter + * \param[in] pVdirectReal + * \param[in] pVdirectImag + * \param[out] pDnonTrReal + * \param[out] pDnonTrImag + */ +void TsdApply(const int numHybridBands, const TSD_DATA *pTsdData, int *pTsdTs, + const FIXP_DBL *pVdirectReal, const FIXP_DBL *pVdirectImag, + FIXP_DBL *pDnonTrReal, FIXP_DBL *pDnonTrImag); + +#endif /* #ifndef SAC_TSD_H */ diff --git a/fdk-aac/libSACenc/include/sacenc_lib.h b/fdk-aac/libSACenc/include/sacenc_lib.h new file mode 100644 index 0000000..758cc0f --- /dev/null +++ b/fdk-aac/libSACenc/include/sacenc_lib.h @@ -0,0 +1,405 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Encoder API + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ + +#ifndef SACENC_LIB_H +#define SACENC_LIB_H + +/* Includes ******************************************************************/ +#include "machine_type.h" +#include "FDK_audio.h" + +#ifdef __cplusplus +extern "C" { +#endif +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/** + * Space encoder error codes. + */ +typedef enum { + SACENC_OK = 0x00000000, /*!< No error happened. All fine. */ + SACENC_INVALID_HANDLE = + 0x00000080, /*!< Handle passed to function call was invalid. */ + SACENC_MEMORY_ERROR = 0x00000800, /*!< Memory allocation failed. */ + SACENC_INIT_ERROR = 0x00008000, /*!< General initialization error. */ + SACENC_ENCODE_ERROR = + 0x00080000, /*!< The encoding process was interrupted by an unexpected + error. */ + SACENC_PARAM_ERROR = 0x00800000, /*!< Invalid runtime parameter. */ + SACENC_UNSUPPORTED_PARAMETER = 0x00800001, /*!< Parameter not available. */ + SACENC_INVALID_CONFIG = 0x00800002, /*!< Configuration not provided. */ + SACENC_UNKNOWN_ERROR = 0x08000000 /*!< Unknown error. */ + +} FDK_SACENC_ERROR; + +typedef enum { + SACENC_INVALID_MODE = 0, + SACENC_212 = 8, + SACENC_ESCAPE = 15 + +} MP4SPACEENC_MODE; + +typedef enum { + SACENC_BANDS_INVALID = 0, + SACENC_BANDS_4 = 4, + SACENC_BANDS_5 = 5, + SACENC_BANDS_7 = 7, + SACENC_BANDS_9 = 9, + SACENC_BANDS_12 = 12, + SACENC_BANDS_15 = 15, + SACENC_BANDS_23 = 23 + +} MP4SPACEENC_BANDS_CONFIG; + +typedef enum { + SACENC_QUANTMODE_INVALID = -1, + SACENC_QUANTMODE_FINE = 0, + SACENC_QUANTMODE_EBQ1 = 1, + SACENC_QUANTMODE_EBQ2 = 2, + SACENC_QUANTMODE_RSVD3 = 3 + +} MP4SPACEENC_QUANTMODE; + +typedef enum { + SACENC_DMXGAIN_INVALID = -1, + SACENC_DMXGAIN_0_dB = 0, + SACENC_DMXGAIN_1_5_dB = 1, + SACENC_DMXGAIN_3_dB = 2, + SACENC_DMXGAIN_4_5_dB = 3, + SACENC_DMXGAIN_6_dB = 4, + SACENC_DMXGAIN_7_5_dB = 5, + SACENC_DMXGAIN_9_dB = 6, + SACENC_DMXGAIN_12_dB = 7 + +} MP4SPACEENC_DMX_GAIN; + +/** + * \brief Space Encoder setting parameters. + * + * Use FDK_sacenc_setParam() function to configure the internal status of the + * following parameters. + */ +typedef enum { + SACENC_LOWDELAY, /*!< Configure lowdelay MPEG Surround. + - 0: Disable Lowdelay. (default) + - 1: Enable Lowdelay. + - 2: Enable Lowdelay including keep frame. */ + + SACENC_ENC_MODE, /*!< Configure encoder tree mode. See ::MP4SPACEENC_MODE for + available values. */ + + SACENC_SAMPLERATE, /*!< Configure encoder sampling rate. */ + + SACENC_FRAME_TIME_SLOTS, /*!< Configure number of slots per spatial frame. */ + + SACENC_PARAM_BANDS, /*!< Configure number of parameter bands. See + ::MP4SPACEENC_BANDS_CONFIG for available values. */ + + SACENC_TIME_DOM_DMX, /*!< Configure time domain downmix. + - 0: No time domain downmix. (default) + - 1: Static time domain downmix. + - 2: Enhanced time domain downmix, stereo to mono + only. */ + + SACENC_DMX_GAIN, /*!< Configure downmix gain. See ::MP4SPACEENC_DMX_GAIN for + available values. */ + + SACENC_COARSE_QUANT, /*!< Use coarse parameter quantization. + - 0: No (default) + - 1: Yes */ + + SACENC_QUANT_MODE, /*!< Configure quanitzation mode. See + ::MP4SPACEENC_QUANTMODE for available values. */ + + SACENC_TIME_ALIGNMENT, /*!< Configure time alignment in samples. */ + + SACENC_INDEPENDENCY_COUNT, /*!< Configure the independency count. (count == 0 + means independencyFlag == 1) */ + + SACENC_INDEPENDENCY_FACTOR, /*!< How often should we set the independency flag + */ + + SACENC_NONE /*!< ------ */ + +} SPACEENC_PARAM; + +/** + * Describes Spatial Specific Config. + */ +typedef struct { + INT nSscSizeBits; /*!< Number of valid bits in pSsc buffer. */ + UCHAR *pSsc; /*!< SpatialSpecificConfig buffer in binary format. */ + +} MPEG4SPACEENC_SSCBUF; + +/** + * Provides some info about the encoder configuration. + */ +typedef struct { + INT nSampleRate; /*!< Configured sampling rate.*/ + INT nSamplesFrame; /*!< Frame length in samples. */ + INT nTotalInputChannels; /*!< Number of expected audio input channels. */ + INT nDmxDelay; /*!< Delay of the downmixed signal. */ + INT nCodecDelay; /*!< Delay of the whole en-/decoded signal, including + core-coder delay. */ + INT nDecoderDelay; /*!< Delay added by the MP4SPACE decoder. */ + INT nPayloadDelay; /*!< Delay of the payload. */ + INT nDiscardOutFrames; /*!< Number of dmx frames to discard for alignment with + bitstream. */ + + MPEG4SPACEENC_SSCBUF + *pSscBuf; /*!< Pointer to Spatial Specific Config structure. */ + +} MP4SPACEENC_INFO; + +/** + * MPEG Surround encoder handle. + */ +typedef struct MP4SPACE_ENCODER *HANDLE_MP4SPACE_ENCODER; + +/** + * Defines the input arguments for a FDK_sacenc_encode() call. + */ +typedef struct { + INT nInputSamples; /*!< Number of valid input audio samples (multiple of input + channels). */ + UINT inputBufferSizePerChannel; /*!< Size of input buffer (input audio + samples) per channel. */ + UINT isInputInterleaved; /*!< Indicates if input audio samples are represented + in blocks or interleaved: + - 0 : in blocks. + - 1 : interleaved. */ + +} SACENC_InArgs; + +/** + * Defines the output arguments for a FDK_sacenc_encode() call. + */ +typedef struct { + INT nOutputBits; /*!< Number of valid payload bits generated during + FDK_sacenc_encode(). */ + INT nOutputSamples; /*!< Number of valid output audio samples generated during + FDK_sacenc_encode(). */ + UINT nSamplesConsumed; /*!< Number of input audio samples consumed in + FDK_sacenc_encode(). */ + +} SACENC_OutArgs; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Opens a new instace of the MPEG Surround encoder. + * + * \param phMp4SpaceEnc Pointer to the encoder handle to be deallocated. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_MEMORY_ERROR, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +/** + * \brief Finalizes opening process of MPEG Surround encoder. + * + * Shows, how many samples are needed as input + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param dmxDelay Downmix delay. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_INIT_ERROR, SACENC_INVALID_CONFIG, + * on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const INT dmxDelay); + +/** + * \brief Close the MPEG Surround encoder instance. + * + * Deallocate encoder instance and free whole memory. + * + * \param phMp4SpaceEnc Pointer to the encoder handle to be deallocated. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +/** + * \brief MPEG surround parameter extraction, framwise. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const FDK_bufDescr *inBufDesc, + const FDK_bufDescr *outBufDesc, + const SACENC_InArgs *inargs, + SACENC_OutArgs *outargs); + +/** + * \brief Provides information on produced bitstream. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param pInfo Pointer to an encoder info struct, filled on + * return. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + MP4SPACEENC_INFO *const pInfo); + +/** + * \brief Set one single MPEG Surround encoder parameter. + * + * This function allows configuration of all encoder parameters specified in + * ::SPACEENC_PARAM. Each parameter must be set with a separate function call. + * An internal validation of the configuration value range will be done. + * + * \param hMp4SpaceEnc A valid MPEG Surround encoder handle. + * \param param Parameter to be set. See ::SPACEENC_PARAM. + * \param value Parameter value. See parameter description in + * ::SPACEENC_PARAM. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_UNSUPPORTED_PARAMETER, + * SACENC_INVALID_CONFIG, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const SPACEENC_PARAM param, + const UINT value); + +/** + * \brief Get information about MPEG Surround encoder library build. + * + * Fill a given LIB_INFO structure with library version information. + * + * \param info Pointer to an allocated LIB_INFO struct. + * + * \return + * - SACENC_OK, on success. + * - SACENC_INVALID_HANDLE, SACENC_INIT_ERROR, on failure. + */ +FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info); + +#ifdef __cplusplus +} +#endif + +#endif /* SACENC_LIB_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_bitstream.cpp b/fdk-aac/libSACenc/src/sacenc_bitstream.cpp new file mode 100644 index 0000000..dacfc27 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_bitstream.cpp @@ -0,0 +1,826 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_bitstream.h" +#include "sacenc_const.h" + +#include "genericStds.h" +#include "common_fix.h" + +#include "FDK_matrixCalloc.h" +#include "sacenc_nlc_enc.h" + +/* Defines *******************************************************************/ +#define MAX_FREQ_RES_INDEX 8 +#define MAX_SAMPLING_FREQUENCY_INDEX 13 +#define SAMPLING_FREQUENCY_INDEX_ESCAPE 15 + +/* Data Types ****************************************************************/ +typedef struct { + SCHAR cld_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + SCHAR icc_old[SACENC_MAX_NUM_BOXES][MAX_NUM_BINS]; + UCHAR quantCoarseCldPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR quantCoarseIccPrev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} PREV_OTTDATA; + +typedef struct { + PREV_OTTDATA prevOttData; + +} STATIC_SPATIALFRAME; + +typedef struct BSF_INSTANCE { + SPATIALSPECIFICCONFIG spatialSpecificConfig; + SPATIALFRAME frame; + STATIC_SPATIALFRAME prevFrameData; + +} BSF_INSTANCE; + +/* Constants *****************************************************************/ +static const INT SampleRateTable[MAX_SAMPLING_FREQUENCY_INDEX] = { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, + 22050, 16000, 12000, 11025, 8000, 7350}; + +static const UCHAR FreqResBinTable_LD[MAX_FREQ_RES_INDEX] = {0, 23, 15, 12, + 9, 7, 5, 4}; +static const UCHAR FreqResStrideTable_LD[] = {1, 2, 5, 23}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR DuplicateLosslessData( + const INT startBox, const INT stopBox, + const LOSSLESSDATA *const hLosslessDataFrom, const INT setFrom, + LOSSLESSDATA *const hLosslessDataTo, const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hLosslessDataFrom) || (NULL == hLosslessDataTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + + for (i = startBox; i < stopBox; i++) { + hLosslessDataTo->bsXXXDataMode[i][setTo] = + hLosslessDataFrom->bsXXXDataMode[i][setFrom]; + hLosslessDataTo->bsDataPair[i][setTo] = + hLosslessDataFrom->bsDataPair[i][setFrom]; + hLosslessDataTo->bsQuantCoarseXXX[i][setTo] = + hLosslessDataFrom->bsQuantCoarseXXX[i][setFrom]; + hLosslessDataTo->bsFreqResStrideXXX[i][setTo] = + hLosslessDataFrom->bsFreqResStrideXXX[i][setFrom]; + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hFrom) || (NULL == hTo)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + /* Only Copy Parameter Set selective stuff */ + + /* OTT-Data */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + FDKmemcpy(hTo->ottData.cld[box][setTo], hFrom->ottData.cld[box][setFrom], + sizeof(hFrom->ottData.cld[0][0])); + FDKmemcpy(hTo->ottData.icc[box][setTo], hFrom->ottData.icc[box][setFrom], + sizeof(hFrom->ottData.icc[0][0])); + } + + /* LOSSLESSDATA */ + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->CLDLosslessData, + setFrom, &hTo->CLDLosslessData, setTo); + DuplicateLosslessData(0, SACENC_MAX_NUM_BOXES, &hFrom->ICCLosslessData, + setFrom, &hTo->ICCLosslessData, setTo); + + } /* valid handle */ + + return error; +} + +/* set frame defaults */ +static void clearFrame(SPATIALFRAME *const pFrame) { + FDKmemclear(pFrame, sizeof(SPATIALFRAME)); + + pFrame->bsIndependencyFlag = 1; + pFrame->framingInfo.numParamSets = 1; +} + +static void fine2coarse(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + data[i] /= 2; + } + } else { + for (i = startBand; i < startBand + numBands; i++) { + data[i] >>= 1; + } + } +} + +static void coarse2fine(SCHAR *const data, const DATA_TYPE dataType, + const INT startBand, const INT numBands) { + int i; + + for (i = startBand; i < startBand + numBands; i++) { + data[i] <<= 1; + } + + if (dataType == t_CLD) { + for (i = startBand; i < startBand + numBands; i++) { + if (data[i] == -14) { + data[i] = -15; + } else if (data[i] == 14) { + data[i] = 15; + } + } + } /* (dataType == t_CLD) */ +} + +static UCHAR getBsFreqResStride(const INT index) { + const UCHAR *pFreqResStrideTable = NULL; + int freqResStrideTableSize = 0; + + pFreqResStrideTable = FreqResStrideTable_LD; + freqResStrideTableSize = + sizeof(FreqResStrideTable_LD) / sizeof(*FreqResStrideTable_LD); + + return (((NULL != pFreqResStrideTable) && (index >= 0) && + (index < freqResStrideTableSize)) + ? pFreqResStrideTable[index] + : 1); +} + +/* write data to bitstream */ +static void ecData(HANDLE_FDK_BITSTREAM bitstream, + SCHAR data[MAX_NUM_PARAMS][MAX_NUM_BINS], + SCHAR oldData[MAX_NUM_BINS], + UCHAR quantCoarseXXXprev[MAX_NUM_PARAMS], + LOSSLESSDATA *const losslessData, const DATA_TYPE dataType, + const INT paramIdx, const INT numParamSets, + const INT independencyFlag, const INT startBand, + const INT stopBand, const INT defaultValue) { + int ps, pb, strOffset, pbStride, dataBands, i; + int aStrides[MAX_NUM_BINS + 1] = {0}; + SHORT cmpIdxData[2][MAX_NUM_BINS] = {{0}}; + SHORT cmpOldData[MAX_NUM_BINS] = {0}; + + /* bsXXXDataMode */ + if (independencyFlag || (losslessData->bsQuantCoarseXXX[paramIdx][0] != + quantCoarseXXXprev[paramIdx])) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][0] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[0][i] != oldData[i]) { + losslessData->bsXXXDataMode[paramIdx][0] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][0], 2); + + for (ps = 1; ps < numParamSets; ps++) { + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + losslessData->bsQuantCoarseXXX[paramIdx][ps - 1]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + } else { + losslessData->bsXXXDataMode[paramIdx][ps] = KEEP; + for (i = startBand; i < stopBand; i++) { + if (data[ps][i] != data[ps - 1][i]) { + losslessData->bsXXXDataMode[paramIdx][ps] = FINECOARSE; + break; + } + } + } + + FDKwriteBits(bitstream, losslessData->bsXXXDataMode[paramIdx][ps], 2); + } /* for ps */ + + /* Create data pairs if possible */ + for (ps = 0; ps < (numParamSets - 1); ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + /* Check if next parameter set is FINCOARSE */ + if (losslessData->bsXXXDataMode[paramIdx][ps + 1] == FINECOARSE) { + /* We have to check if ps and ps+1 use the same bsXXXQuantMode */ + /* and also have the same stride */ + if ((losslessData->bsQuantCoarseXXX[paramIdx][ps + 1] == + losslessData->bsQuantCoarseXXX[paramIdx][ps]) && + (losslessData->bsFreqResStrideXXX[paramIdx][ps + 1] == + losslessData->bsFreqResStrideXXX[paramIdx][ps])) { + losslessData->bsDataPair[paramIdx][ps] = 1; + losslessData->bsDataPair[paramIdx][ps + 1] = 1; + + /* We have a data pair -> Jump to the ps after next ps*/ + ps++; + continue; + } + } + /* dataMode of next ps is not FINECOARSE or does not use the same + * bsXXXQuantMode/stride */ + /* -> no dataPair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } else { + /* No FINECOARSE -> no data pair possible */ + losslessData->bsDataPair[paramIdx][ps] = 0; + + /* Initialize ps after next ps to Zero (only important for the last + * parameter set) */ + losslessData->bsDataPair[paramIdx][ps + 1] = 0; + } + } /* for ps */ + + for (ps = 0; ps < numParamSets; ps++) { + if (losslessData->bsXXXDataMode[paramIdx][ps] == DEFAULT) { + /* Prepare old data */ + for (i = startBand; i < stopBand; i++) { + oldData[i] = defaultValue; + } + quantCoarseXXXprev[paramIdx] = 0; /* Default data are always fine */ + } + + if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE) { + FDKwriteBits(bitstream, losslessData->bsDataPair[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsQuantCoarseXXX[paramIdx][ps], 1); + FDKwriteBits(bitstream, losslessData->bsFreqResStrideXXX[paramIdx][ps], + 2); + + if (losslessData->bsQuantCoarseXXX[paramIdx][ps] != + quantCoarseXXXprev[paramIdx]) { + if (quantCoarseXXXprev[paramIdx]) { + coarse2fine(oldData, dataType, startBand, stopBand - startBand); + } else { + fine2coarse(oldData, dataType, startBand, stopBand - startBand); + } + } + + /* Handle strides */ + pbStride = + getBsFreqResStride(losslessData->bsFreqResStrideXXX[paramIdx][ps]); + dataBands = (stopBand - startBand - 1) / pbStride + 1; + + aStrides[0] = startBand; + for (pb = 1; pb <= dataBands; pb++) { + aStrides[pb] = aStrides[pb - 1] + pbStride; + } + + strOffset = 0; + while (aStrides[dataBands] > stopBand) { + if (strOffset < dataBands) { + strOffset++; + } + for (i = strOffset; i <= dataBands; i++) { + aStrides[i]--; + } + } /* while */ + + for (pb = 0; pb < dataBands; pb++) { + cmpOldData[startBand + pb] = oldData[aStrides[pb]]; + cmpIdxData[0][startBand + pb] = data[ps][aStrides[pb]]; + + if (losslessData->bsDataPair[paramIdx][ps]) { + cmpIdxData[1][startBand + pb] = data[ps + 1][aStrides[pb]]; + } + } /* for pb*/ + + /* Finally encode */ + if (losslessData->bsDataPair[paramIdx][ps]) { + fdk_sacenc_ecDataPairEnc(bitstream, cmpIdxData, cmpOldData, dataType, 0, + startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } else { + fdk_sacenc_ecDataSingleEnc(bitstream, cmpIdxData, cmpOldData, dataType, + 0, startBand, dataBands, + losslessData->bsQuantCoarseXXX[paramIdx][ps], + independencyFlag && (ps == 0)); + } + + /* Overwrite old data */ + for (i = startBand; i < stopBand; i++) { + if (losslessData->bsDataPair[paramIdx][ps]) { + oldData[i] = data[ps + 1][i]; + } else { + oldData[i] = data[ps][i]; + } + } + + quantCoarseXXXprev[paramIdx] = + losslessData->bsQuantCoarseXXX[paramIdx][ps]; + + /* Jump forward if we have encoded a data pair */ + if (losslessData->bsDataPair[paramIdx][ps]) { + ps++; + } + + } /* if (losslessData->bsXXXDataMode[paramIdx][ps] == FINECOARSE ) */ + } /* for ps */ +} + +/****************************************************************************/ +/* Bitstream formatter interface functions */ +/****************************************************************************/ +static FDK_SACENC_ERROR getBsFreqResIndex(const INT numBands, + INT *const pbsFreqResIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsFreqResIndex) { + error = SACENC_INVALID_HANDLE; + } else { + const UCHAR *pFreqResBinTable = FreqResBinTable_LD; + int i; + *pbsFreqResIndex = -1; + + for (i = 0; i < MAX_FREQ_RES_INDEX; i++) { + if (numBands == pFreqResBinTable[i]) { + *pbsFreqResIndex = i; + break; + } + } + if (*pbsFreqResIndex < 0 || *pbsFreqResIndex >= MAX_FREQ_RES_INDEX) { + error = SACENC_INVALID_CONFIG; + } + } + return error; +} + +static FDK_SACENC_ERROR getSamplingFrequencyIndex( + const INT bsSamplingFrequency, INT *const pbsSamplingFrequencyIndex) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pbsSamplingFrequencyIndex) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + *pbsSamplingFrequencyIndex = SAMPLING_FREQUENCY_INDEX_ESCAPE; + + for (i = 0; i < MAX_SAMPLING_FREQUENCY_INDEX; i++) { + if (bsSamplingFrequency == SampleRateTable[i]) { /*spatial sampling rate*/ + *pbsSamplingFrequencyIndex = i; + break; + } + } + } + return error; +} + +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((selfPtr == NULL) || (*selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if (*selfPtr != NULL) { + FDK_FREE_MEMORY_1D(*selfPtr); + } + } + return error; +} + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == selfPtr) { + error = SACENC_INVALID_HANDLE; + } else { + /* allocate encoder struct */ + FDK_ALLOCATE_MEMORY_1D(*selfPtr, 1, BSF_INSTANCE); + } + return error; + +bail: + fdk_sacenc_destroySpatialBitstreamEncoder(selfPtr); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/* init encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (selfPtr == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + /* init/clear */ + clearFrame(&selfPtr->frame); + + } /* valid handle */ + return error; +} + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr) { + return ((selfPtr == NULL) ? NULL : &(selfPtr->spatialSpecificConfig)); +} + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits) { + FDK_SACENC_ERROR error = SACENC_OK; + INT bsSamplingFrequencyIndex = 0; + INT bsFreqRes = 0; + + if ((spatialSpecificConfig == NULL) || (pOutputBuffer == NULL) || + (pnOutputBits == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_BITSTREAM bitstream; + + /* Find FreqRes */ + if (SACENC_OK != (error = getBsFreqResIndex(spatialSpecificConfig->numBands, + &bsFreqRes))) + goto bail; + + /* Find SamplingFrequencyIndex */ + if (SACENC_OK != (error = getSamplingFrequencyIndex( + spatialSpecificConfig->bsSamplingFrequency, + &bsSamplingFrequencyIndex))) + goto bail; + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + /****************************************************************************/ + /* write to bitstream */ + + FDKwriteBits(&bitstream, bsSamplingFrequencyIndex, 4); + + if (bsSamplingFrequencyIndex == 15) { + FDKwriteBits(&bitstream, spatialSpecificConfig->bsSamplingFrequency, 24); + } + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFrameLength, 5); + + FDKwriteBits(&bitstream, bsFreqRes, 3); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsTreeConfig, 4); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsQuantMode, 2); + + FDKwriteBits(&bitstream, 0, 1); /* bsArbitraryDownmix */ + + FDKwriteBits(&bitstream, spatialSpecificConfig->bsFixedGainDMX, 3); + + FDKwriteBits(&bitstream, TEMPSHAPE_OFF, 2); + FDKwriteBits(&bitstream, spatialSpecificConfig->bsDecorrConfig, 2); + + FDKbyteAlign(&bitstream, 0); /* byte alignment */ + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType) { + int idx = -1; + + switch (frameType) { + case READ_SPATIALFRAME: + case WRITE_SPATIALFRAME: + idx = 0; + break; + default: + idx = -1; /* invalid configuration */ + } /* switch frameType */ + + return (((selfPtr == NULL) || (idx == -1)) ? NULL : &selfPtr->frame); +} + +static FDK_SACENC_ERROR writeFramingInfo(HANDLE_FDK_BITSTREAM hBitstream, + const FRAMINGINFO *const pFramingInfo, + const INT frameLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pFramingInfo == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKwriteBits(hBitstream, pFramingInfo->bsFramingType, 1); + FDKwriteBits(hBitstream, pFramingInfo->numParamSets - 1, 1); + + if (pFramingInfo->bsFramingType) { + int ps = 0; + int numParamSets = pFramingInfo->numParamSets; + + { + for (ps = 0; ps < numParamSets; ps++) { + int bitsParamSlot = 0; + while ((1 << bitsParamSlot) < (frameLength + 1)) bitsParamSlot++; + if (bitsParamSlot > 0) + FDKwriteBits(hBitstream, pFramingInfo->bsParamSlots[ps], + bitsParamSlot); + } + } + } /* pFramingInfo->bsFramingType */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeSmgData(HANDLE_FDK_BITSTREAM hBitstream, + const SMGDATA *const pSmgData, + const INT numParamSets, + const INT dataBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pSmgData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, j; + + for (i = 0; i < numParamSets; i++) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothMode[i], 2); + + if (pSmgData->bsSmoothMode[i] >= 2) { + FDKwriteBits(hBitstream, pSmgData->bsSmoothTime[i], 2); + } + if (pSmgData->bsSmoothMode[i] == 3) { + const int stride = getBsFreqResStride(pSmgData->bsFreqResStride[i]); + FDKwriteBits(hBitstream, pSmgData->bsFreqResStride[i], 2); + for (j = 0; j < dataBands; j += stride) { + FDKwriteBits(hBitstream, pSmgData->bsSmgData[i][j], 1); + } + } + } /* for i */ + } /* valid handle */ + + return error; +} + +static FDK_SACENC_ERROR writeOttData( + HANDLE_FDK_BITSTREAM hBitstream, PREV_OTTDATA *const pPrevOttData, + OTTDATA *const pOttData, const OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES], + LOSSLESSDATA *const pCLDLosslessData, LOSSLESSDATA *const pICCLosslessData, + const INT numOttBoxes, const INT numBands, const INT numParamSets, + const INT bsIndependencyFlag) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hBitstream == NULL) || (pPrevOttData == NULL) || (pOttData == NULL) || + (ottConfig == NULL) || (pCLDLosslessData == NULL) || + (pICCLosslessData == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < numOttBoxes; i++) { + ecData(hBitstream, pOttData->cld[i], pPrevOttData->cld_old[i], + pPrevOttData->quantCoarseCldPrev[i], pCLDLosslessData, t_CLD, i, + numParamSets, bsIndependencyFlag, 0, ottConfig[i].bsOttBands, 15); + } + { + for (i = 0; i < numOttBoxes; i++) { + { + ecData(hBitstream, pOttData->icc[i], pPrevOttData->icc_old[i], + pPrevOttData->quantCoarseIccPrev[i], pICCLosslessData, t_ICC, + i, numParamSets, bsIndependencyFlag, 0, numBands, 0); + } + } /* for i */ + } + } /* valid handle */ + + return error; +} + +/* write extension frame data to stream */ +static FDK_SACENC_ERROR WriteSpatialExtensionFrame( + HANDLE_FDK_BITSTREAM bitstream, HANDLE_BSF_INSTANCE self) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((bitstream == NULL) || (self == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKbyteAlign(bitstream, 0); + } /* valid handle */ + + return error; +} + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pOutputBuffer == NULL) || (pnOutputBits == NULL) || (selfPtr == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + SPATIALFRAME *frame = NULL; + SPATIALSPECIFICCONFIG *config = NULL; + FDK_BITSTREAM bitstream; + + int i, j, numParamSets, numOttBoxes; + + if ((NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, READ_SPATIALFRAME))) || + (NULL == (config = &(selfPtr->spatialSpecificConfig)))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + numOttBoxes = selfPtr->spatialSpecificConfig.treeDescription.numOttBoxes; + + numParamSets = frame->framingInfo.numParamSets; + + if (frame->bUseBBCues) { + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + /* If a transient was detected, force only the second ps broad band */ + if (numParamSets == 1) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][0] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][0] = 3; + } else { + for (j = 1; j < MAX_NUM_PARAMS; j++) { + frame->CLDLosslessData.bsFreqResStrideXXX[i][j] = 3; + frame->ICCLosslessData.bsFreqResStrideXXX[i][j] = 3; + } + } + } + } /* frame->bUseBBCues */ + + /* bind extern buffer to bitstream handle */ + FDKinitBitStream(&bitstream, pOutputBuffer, outputBufferSize, 0, BS_WRITER); + + if (SACENC_OK != (error = writeFramingInfo( + &bitstream, &(frame->framingInfo), + selfPtr->spatialSpecificConfig.bsFrameLength))) { + goto bail; + } + + /* write bsIndependencyFlag */ + FDKwriteBits(&bitstream, frame->bsIndependencyFlag, 1); + + /* write spatial data to bitstream */ + if (SACENC_OK != + (error = writeOttData(&bitstream, &selfPtr->prevFrameData.prevOttData, + &frame->ottData, config->ottConfig, + &frame->CLDLosslessData, &frame->ICCLosslessData, + numOttBoxes, config->numBands, numParamSets, + frame->bsIndependencyFlag))) { + goto bail; + } + if (SACENC_OK != (error = writeSmgData(&bitstream, &frame->smgData, + numParamSets, config->numBands))) { + goto bail; + } + + /* byte alignment */ + FDKbyteAlign(&bitstream, 0); + + /* Write SpatialExtensionFrame */ + if (SACENC_OK != + (error = WriteSpatialExtensionFrame(&bitstream, selfPtr))) { + goto bail; + } + + if (NULL == + (frame = fdk_sacenc_getSpatialFrame(selfPtr, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + clearFrame(frame); + + /* return number of valid bits in bitstream */ + if ((*pnOutputBits = FDKgetValidBits(&bitstream)) > + (outputBufferSize * 8)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* terminate buffer with alignment */ + FDKbyteAlign(&bitstream, 0); + + } /* valid handle */ + +bail: + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_bitstream.h b/fdk-aac/libSACenc/src/sacenc_bitstream.h new file mode 100644 index 0000000..67b7b5a --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_bitstream.h @@ -0,0 +1,296 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): + + Description: Encoder Library Interface + Bitstream Writer + +*******************************************************************************/ + +#ifndef SACENC_BITSTREAM_H +#define SACENC_BITSTREAM_H + +/* Includes ******************************************************************/ +#include "FDK_bitstream.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" + +/* Defines *******************************************************************/ +#define MAX_NUM_BINS 23 +#define MAX_NUM_PARAMS 2 +#define MAX_NUM_OUTPUTCHANNELS SACENC_MAX_OUTPUT_CHANNELS +#define MAX_TIME_SLOTS 32 + +typedef enum { + TREE_212 = 7, + TREE_ESCAPE = 15 + +} TREECONFIG; + +typedef enum { + FREQ_RES_40 = 0, + FREQ_RES_20 = 1, + FREQ_RES_10 = 2, + FREQ_RES_5 = 3 + +} FREQ; + +typedef enum { + QUANTMODE_INVALID = -1, + QUANTMODE_FINE = 0, + QUANTMODE_EBQ1 = 1, + QUANTMODE_EBQ2 = 2 + +} QUANTMODE; + +typedef enum { + TEMPSHAPE_OFF = 0 + +} TEMPSHAPECONFIG; + +typedef enum { + FIXEDGAINDMX_INVALID = -1, + FIXEDGAINDMX_0 = 0, + FIXEDGAINDMX_1 = 1, + FIXEDGAINDMX_2 = 2, + FIXEDGAINDMX_3 = 3, + FIXEDGAINDMX_4 = 4, + FIXEDGAINDMX_5 = 5, + FIXEDGAINDMX_6 = 6, + FIXEDGAINDMX_7 = 7 + +} FIXEDGAINDMXCONFIG; + +typedef enum { + DECORR_INVALID = -1, + DECORR_QMFSPLIT0 = 0, /* QMF splitfreq: 3, 15, 24, 65 */ + DECORR_QMFSPLIT1 = 1, /* QMF splitfreq: 3, 50, 65, 65 */ + DECORR_QMFSPLIT2 = 2 /* QMF splitfreq: 0, 15, 65, 65 */ + +} DECORRCONFIG; + +typedef enum { + DEFAULT = 0, + KEEP = 1, + INTERPOLATE = 2, + FINECOARSE = 3 + +} DATA_MODE; + +typedef enum { + READ_SPATIALFRAME = 0, + WRITE_SPATIALFRAME = 1 + +} SPATIALFRAME_TYPE; + +/* Data Types ****************************************************************/ +typedef struct { + INT numOttBoxes; + INT numInChan; + INT numOutChan; + +} TREEDESCRIPTION; + +typedef struct { + INT bsOttBands; + +} OTTCONFIG; + +typedef struct { + INT bsSamplingFrequency; /* for bsSamplingFrequencyIndex */ + INT bsFrameLength; + INT numBands; /* for bsFreqRes */ + TREECONFIG bsTreeConfig; + QUANTMODE bsQuantMode; + FIXEDGAINDMXCONFIG bsFixedGainDMX; + int bsEnvQuantMode; + DECORRCONFIG bsDecorrConfig; + TREEDESCRIPTION treeDescription; + OTTCONFIG ottConfig[SACENC_MAX_NUM_BOXES]; + +} SPATIALSPECIFICCONFIG; + +typedef struct { + UCHAR bsFramingType; + UCHAR numParamSets; + UCHAR bsParamSlots[MAX_NUM_PARAMS]; + +} FRAMINGINFO; + +typedef struct { + SCHAR cld[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + SCHAR icc[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} OTTDATA; + +typedef struct { + UCHAR bsSmoothMode[MAX_NUM_PARAMS]; + UCHAR bsSmoothTime[MAX_NUM_PARAMS]; + UCHAR bsFreqResStride[MAX_NUM_PARAMS]; + UCHAR bsSmgData[MAX_NUM_PARAMS][MAX_NUM_BINS]; + +} SMGDATA; + +typedef struct { + UCHAR bsEnvShapeChannel[MAX_NUM_OUTPUTCHANNELS]; + UCHAR bsEnvShapeData[MAX_NUM_OUTPUTCHANNELS][MAX_TIME_SLOTS]; + +} TEMPSHAPEDATA; + +typedef struct { + UCHAR bsXXXDataMode[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsDataPair[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsQuantCoarseXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + UCHAR bsFreqResStrideXXX[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAMS]; + +} LOSSLESSDATA; + +typedef struct { + FRAMINGINFO framingInfo; + UCHAR bsIndependencyFlag; + OTTDATA ottData; + SMGDATA smgData; + TEMPSHAPEDATA tempShapeData; + LOSSLESSDATA CLDLosslessData; + LOSSLESSDATA ICCLosslessData; + UCHAR bUseBBCues; + +} SPATIALFRAME; + +typedef struct BSF_INSTANCE *HANDLE_BSF_INSTANCE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +/* destroy encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_destroySpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +/* create encoder instance */ +FDK_SACENC_ERROR fdk_sacenc_createSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE *selfPtr); + +FDK_SACENC_ERROR fdk_sacenc_initSpatialBitstreamEncoder( + HANDLE_BSF_INSTANCE selfPtr); + +/* get SpatialSpecificConfig struct */ +SPATIALSPECIFICCONFIG *fdk_sacenc_getSpatialSpecificConfig( + HANDLE_BSF_INSTANCE selfPtr); + +/* write SpatialSpecificConfig to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialSpecificConfig( + SPATIALSPECIFICCONFIG *const spatialSpecificConfig, + UCHAR *const pOutputBuffer, const INT outputBufferSize, + INT *const pnOutputBits); + +/* get SpatialFrame struct */ +SPATIALFRAME *fdk_sacenc_getSpatialFrame(HANDLE_BSF_INSTANCE selfPtr, + const SPATIALFRAME_TYPE frameType); + +/* write frame data to stream */ +FDK_SACENC_ERROR fdk_sacenc_writeSpatialFrame(UCHAR *const pOutputBuffer, + const INT outputBufferSize, + INT *const pnOutputBits, + HANDLE_BSF_INSTANCE selfPtr); + +/* Copy/Save spatial frame data for one parameter set */ +FDK_SACENC_ERROR fdk_sacenc_duplicateParameterSet( + const SPATIALFRAME *const hFrom, const INT setFrom, SPATIALFRAME *const hTo, + const INT setTo); + +#endif /* SACENC_BITSTREAM_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_const.h b/fdk-aac/libSACenc/src/sacenc_const.h new file mode 100644 index 0000000..c86e765 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_const.h @@ -0,0 +1,126 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Multrus + + Description: Encoder Library Interface + constants to MPEG-4 spatial encoder lib + +*******************************************************************************/ + +#ifndef SACENC_CONST_H +#define SACENC_CONST_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define NUM_QMF_BANDS 64 +#define MAX_QMF_BANDS 128 + +#define SACENC_MAX_NUM_BOXES 1 +#define SACENC_MAX_INPUT_CHANNELS 2 +#define SACENC_MAX_OUTPUT_CHANNELS 1 + +#define SACENC_FLOAT_EPSILON (1e-9f) + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_CONST_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_delay.cpp b/fdk-aac/libSACenc/src/sacenc_delay.cpp new file mode 100644 index 0000000..f2ed6b0 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_delay.cpp @@ -0,0 +1,472 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + This file contains all delay infrastructure + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_delay.h" +#include "sacenc_const.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +struct DELAY { + struct DELAY_CONFIG { + /* Routing Config Switches*/ + INT bDmxAlign; + INT bTimeDomDmx; + INT bMinimizeDelay; + INT bSacTimeAlignmentDynamicOut; + + /* Needed Input Variables*/ + INT nQmfLen; + INT nFrameLen; + INT nSurroundDelay; + INT nArbDmxDelay; + INT nLimiterDelay; + INT nCoreCoderDelay; + INT nSacStreamMuxDelay; + INT nSacTimeAlignment; /* Overwritten, if bSacTimeAlignmentDynamicOut */ + } config; + + /* Variable Delaybuffers -> Delays */ + INT nDmxAlignBuffer; + INT nSurroundAnalysisBuffer; + INT nArbDmxAnalysisBuffer; + INT nOutputAudioBuffer; + INT nBitstreamFrameBuffer; + INT nOutputAudioQmfFrameBuffer; + INT nDiscardOutFrames; + + /* Variable Delaybuffers Computation Variables */ + INT nBitstreamFrameBufferSize; + + /* Output: Infos */ + INT nInfoDmxDelay; /* Delay of the downmixed signal after the space encoder */ + INT nInfoCodecDelay; /* Delay of the whole en-/decoder including CoreCoder */ + INT nInfoDecoderDelay; /* Delay of the Mpeg Surround decoder */ +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Open() +description: initializes Delays +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*phDelay, 1, struct DELAY); + } + return error; + +bail: + fdk_sacenc_delay_Close(phDelay); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_Close() +description: destructs Delay +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phDelay) { + error = SACENC_INVALID_HANDLE; + } else { + if (NULL != *phDelay) { + FDK_FREE_MEMORY_1D(*phDelay); + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDelay) { + error = SACENC_INVALID_HANDLE; + } else { + /* Fill structure before calculation */ + FDKmemclear(&hDelay->config, sizeof(hDelay->config)); + + hDelay->config.nQmfLen = nQmfLen; + hDelay->config.nFrameLen = nFrameLen; + hDelay->config.nCoreCoderDelay = nCoreCoderDelay; + hDelay->config.nSacStreamMuxDelay = nSacStreamMuxDelay; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_delay_SubCalulateBufferDelays() +description: Calculates the Delays of the buffers +returns: Error Code +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDel) { + error = SACENC_INVALID_HANDLE; + } else { + int nEncoderAnDelay, nEncoderSynDelay, nEncoderWinDelay, nDecoderAnDelay, + nDecoderSynDelay, nResidualCoderFrameDelay, + nArbDmxResidualCoderFrameDelay; + + if (hDel->config.bSacTimeAlignmentDynamicOut > 0) { + hDel->config.nSacTimeAlignment = 0; + } + + { + nEncoderAnDelay = + 2 * hDel->config.nQmfLen + + hDel->config.nQmfLen / 2; /* Only Ld-QMF Delay, no hybrid */ + nEncoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderAnDelay = 2 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nDecoderSynDelay = 1 * hDel->config.nQmfLen + hDel->config.nQmfLen / 2; + nEncoderWinDelay = + hDel->config.nFrameLen / 2; /* WindowLookahead is just half a frame */ + } + + { nResidualCoderFrameDelay = 0; } + + { nArbDmxResidualCoderFrameDelay = 0; } + + /* Calculate variable Buffer-Delays */ + if (hDel->config.bTimeDomDmx == 0) { + /* ArbitraryDmx and TdDmx off */ + int tempDelay; + + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = 0; + tempDelay = nEncoderSynDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay; + tempDelay = (nResidualCoderFrameDelay * hDel->config.nFrameLen) + + hDel->config.nSacStreamMuxDelay - tempDelay; + + if (tempDelay > 0) { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay; + } else { + tempDelay = -tempDelay; + hDel->nBitstreamFrameBuffer = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen) - tempDelay; + } + + hDel->nOutputAudioQmfFrameBuffer = + (hDel->nOutputAudioBuffer + (hDel->config.nQmfLen / 2) - 1) / + hDel->config.nQmfLen; + + if (hDel->config.bDmxAlign > 0) { + tempDelay = nEncoderWinDelay + nEncoderAnDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->nSurroundAnalysisBuffer + nEncoderAnDelay + + nEncoderWinDelay + nEncoderSynDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + + } else { + /* ArbitraryDmx or TdDmx on */ + int tempDelay1, tempDelay2, tempDelay12, tempDelay3; + + tempDelay1 = hDel->config.nArbDmxDelay - hDel->config.nSurroundDelay; + + if (tempDelay1 >= 0) { + hDel->nSurroundAnalysisBuffer = tempDelay1; + hDel->nArbDmxAnalysisBuffer = 0; + } else { + hDel->nSurroundAnalysisBuffer = 0; + hDel->nArbDmxAnalysisBuffer = -tempDelay1; + } + + tempDelay1 = nEncoderWinDelay + hDel->config.nSurroundDelay + + hDel->nSurroundAnalysisBuffer + + nEncoderAnDelay; /*Surround Path*/ + tempDelay2 = nEncoderWinDelay + hDel->config.nArbDmxDelay + + hDel->nArbDmxAnalysisBuffer + + nEncoderAnDelay; /* ArbDmx Compare Path */ + tempDelay3 = hDel->config.nArbDmxDelay + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + + nDecoderAnDelay; /* ArbDmx Passthrough*/ + + tempDelay12 = + FDKmax(nResidualCoderFrameDelay, nArbDmxResidualCoderFrameDelay) * + hDel->config.nFrameLen; + tempDelay12 += hDel->config.nSacStreamMuxDelay; + + if (tempDelay1 > tempDelay2) { + tempDelay12 += tempDelay1; + } else { + tempDelay12 += tempDelay2; + } + + if (tempDelay3 > tempDelay12) { + if (hDel->config.bMinimizeDelay > 0) { + hDel->nBitstreamFrameBuffer = + (tempDelay3 - tempDelay12) / hDel->config.nFrameLen; /*floor*/ + hDel->nOutputAudioBuffer = 0; + hDel->nSurroundAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + hDel->nArbDmxAnalysisBuffer += + (tempDelay3 - tempDelay12 - + (hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen)); + } else { + hDel->nBitstreamFrameBuffer = + ((tempDelay3 - tempDelay12) + hDel->config.nFrameLen - 1) / + hDel->config.nFrameLen; + hDel->nOutputAudioBuffer = + hDel->nBitstreamFrameBuffer * hDel->config.nFrameLen + + tempDelay12 - tempDelay3; + } + } else { + hDel->nBitstreamFrameBuffer = 0; + hDel->nOutputAudioBuffer = tempDelay12 - tempDelay3; + } + + if (hDel->config.bDmxAlign > 0) { + int tempDelay = hDel->config.nArbDmxDelay + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay + + hDel->config.nCoreCoderDelay; + hDel->nDiscardOutFrames = + (tempDelay + hDel->config.nFrameLen - 1) / hDel->config.nFrameLen; + hDel->nDmxAlignBuffer = + hDel->nDiscardOutFrames * hDel->config.nFrameLen - tempDelay; + } else { + hDel->nDiscardOutFrames = 0; + hDel->nDmxAlignBuffer = 0; + } + + /* Output: Info-Variables */ + hDel->nInfoDmxDelay = hDel->config.nArbDmxDelay + + hDel->nOutputAudioBuffer + + hDel->config.nLimiterDelay; + hDel->nInfoCodecDelay = + hDel->nInfoDmxDelay + hDel->config.nCoreCoderDelay + + hDel->config.nSacTimeAlignment + nDecoderAnDelay + nDecoderSynDelay; + hDel->nInfoDecoderDelay = nDecoderAnDelay + nDecoderSynDelay; + + } /* ArbitraryDmx or TdDmx on */ + + /* Additonal Variables needed for Computation Issues */ + hDel->nBitstreamFrameBufferSize = hDel->nBitstreamFrameBuffer + 1; + } + + return error; +} + +static FDK_SACENC_ERROR assignParameterInRange( + const INT startRange, /* including startRange */ + const INT stopRange, /* including stopRange */ + const INT value, /* value to write*/ + INT *const ptr /* destination pointer*/ +) { + FDK_SACENC_ERROR error = SACENC_INVALID_CONFIG; + + if ((startRange <= value) && (value <= stopRange)) { + *ptr = value; + error = SACENC_OK; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn) { + return (assignParameterInRange(0, 1, bDmxAlignIn, &hDelay->config.bDmxAlign)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn) { + return ( + assignParameterInRange(0, 1, bTimeDomDmxIn, &hDelay->config.bTimeDomDmx)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn) { + return (assignParameterInRange(0, 1, bSacTimeAlignmentDynamicOutIn, + &hDelay->config.bSacTimeAlignmentDynamicOut)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn) { + return (assignParameterInRange(-32768, 32767, nSacTimeAlignmentIn, + &hDelay->config.nSacTimeAlignment)); +} + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay) { + return (assignParameterInRange(0, 1, bMinimizeDelay, + &hDelay->config.bMinimizeDelay)); +} + +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nOutputAudioBuffer); +} + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nSurroundAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nArbDmxAnalysisBuffer); +} + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay) { + return (hDelay->nBitstreamFrameBufferSize); +} + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay) { + return (hDelay->nDmxAlignBuffer); +} + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay) { + return (hDelay->nDiscardOutFrames); +} + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDmxDelay); +} + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoCodecDelay); +} + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay) { + return (hDelay->nInfoDecoderDelay); +} diff --git a/fdk-aac/libSACenc/src/sacenc_delay.h b/fdk-aac/libSACenc/src/sacenc_delay.h new file mode 100644 index 0000000..38bfbc5 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_delay.h @@ -0,0 +1,175 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + delay management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ +#ifndef SACENC_DELAY_H +#define SACENC_DELAY_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "machine_type.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define MAX_DELAY_INPUT 1024 +#define MAX_DELAY_OUTPUT 4096 +/* bumped from 0 to 5. this should be equal or larger to the dualrate sbr + * resampler filter length */ +#define MAX_DELAY_SURROUND_ANALYSIS 5 +#define MAX_BITSTREAM_DELAY 1 + +/* Data Types ****************************************************************/ +typedef struct DELAY *HANDLE_DELAY; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_delay_Open(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Close(HANDLE_DELAY *phDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_Init(HANDLE_DELAY hDelay, const INT nQmfLen, + const INT nFrameLen, + const INT nCoreCoderDelay, + const INT nSacStreamMuxDelay); + +FDK_SACENC_ERROR fdk_sacenc_delay_SubCalulateBufferDelays(HANDLE_DELAY hDel); + +/* Set Expert Config Parameters */ +FDK_SACENC_ERROR fdk_sacenc_delay_SetDmxAlign(HANDLE_DELAY hDelay, + const INT bDmxAlignIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetTimeDomDmx(HANDLE_DELAY hDelay, + const INT bTimeDomDmxIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetSacTimeAlignmentDynamicOut( + HANDLE_DELAY hDelay, const INT bSacTimeAlignmentDynamicOutIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetNSacTimeAlignment( + HANDLE_DELAY hDelay, const INT nSacTimeAlignmentIn); + +FDK_SACENC_ERROR fdk_sacenc_delay_SetMinimizeDelay(HANDLE_DELAY hDelay, + const INT bMinimizeDelay); + +/* Get Internal Variables */ +INT fdk_sacenc_delay_GetOutputAudioBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetArbDmxAnalysisBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetBitstreamFrameBufferSize(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDmxAlignBufferDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetDiscardOutFrames(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDmxDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoCodecDelay(HANDLE_DELAY hDelay); + +INT fdk_sacenc_delay_GetInfoDecoderDelay(HANDLE_DELAY hDelay); + +#endif /* SACENC_DELAY_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.cpp b/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.cpp new file mode 100644 index 0000000..be66c83 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.cpp @@ -0,0 +1,639 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_dmx_tdom_enh.h" + +#include "FDK_matrixCalloc.h" +#include "FDK_trigFcts.h" +#include "fixpoint_math.h" + +/* Defines *******************************************************************/ +#define PI_FLT 3.1415926535897931f +#define ALPHA_FLT 0.0001f + +#define PI_E (2) +#define PI_M (FL2FXCONST_DBL(PI_FLT / (1 << PI_E))) + +#define ALPHA_E (13) +#define ALPHA_M (FL2FXCONST_DBL(ALPHA_FLT * (1 << ALPHA_E))) + +enum { L = 0, R = 1 }; + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX { + int maxFramelength; + + int framelength; + + FIXP_DBL prev_gain_m[2]; + INT prev_gain_e; + FIXP_DBL prev_H1_m[2]; + INT prev_H1_e; + + FIXP_DBL *sinusWindow_m; + SCHAR sinusWindow_e; + + FIXP_DBL prev_Left_m; + INT prev_Left_e; + FIXP_DBL prev_Right_m; + INT prev_Right_e; + FIXP_DBL prev_XNrg_m; + INT prev_XNrg_e; + + FIXP_DBL lin_bbCld_weight_m; + INT lin_bbCld_weight_e; + FIXP_DBL gain_weight_m[2]; + INT gain_weight_e; + +} ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e); + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e); + +/* Function / Class Definition ***********************************************/ +static FIXP_DBL invSqrtNorm2(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + src_m = invSqrtNorm2(src_m, result_e); + *result_e = (*result_e) - (src_e >> 1); + + return src_m; +} + +static FIXP_DBL sqrtFixp(const FIXP_DBL op_m, const INT op_e, + INT *const result_e) { + FIXP_DBL src_m = op_m; + int src_e = op_e; + + if (src_e & 1) { + src_m >>= 1; + src_e += 1; + } + + *result_e = (src_e >> 1); + return sqrtFixp(src_m); +} + +static FIXP_DBL fixpAdd(const FIXP_DBL src1_m, const INT src1_e, + const FIXP_DBL src2_m, const INT src2_e, + INT *const dst_e) { + FIXP_DBL dst_m; + + if (src1_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src2_e; + dst_m = src2_m; + } else if (src2_m == FL2FXCONST_DBL(0.f)) { + *dst_e = src1_e; + dst_m = src1_m; + } else { + *dst_e = fixMax(src1_e, src2_e) + 1; + dst_m = + scaleValue(src1_m, fixMax((src1_e - (*dst_e)), -(DFRACT_BITS - 1))) + + scaleValue(src2_m, fixMax((src2_e - (*dst_e)), -(DFRACT_BITS - 1))); + } + return dst_m; +} + +/** + * \brief Sum up fixpoint values with best possible accuracy. + * + * \param value1 First input value. + * \param q1 Scaling factor of first input value. + * \param pValue2 Pointer to second input value, will be modified on + * return. + * \param pQ2 Pointer to second scaling factor, will be modified on + * return. + * + * \return void + */ +static void fixpAddNorm(const FIXP_DBL value1, const INT q1, + FIXP_DBL *const pValue2, INT *const pQ2) { + const int headroom1 = fNormz(fixp_abs(value1)) - 1; + const int headroom2 = fNormz(fixp_abs(*pValue2)) - 1; + int resultScale = fixMax(q1 - headroom1, (*pQ2) - headroom2); + + if ((value1 != FL2FXCONST_DBL(0.f)) && (*pValue2 != FL2FXCONST_DBL(0.f))) { + resultScale++; + } + + *pValue2 = + scaleValue(value1, q1 - resultScale) + + scaleValue(*pValue2, fixMax(-(DFRACT_BITS - 1), ((*pQ2) - resultScale))); + *pQ2 = (*pValue2 != (FIXP_DBL)0) ? resultScale : DFRACT_BITS - 1; +} + +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx, const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx = NULL; + + if (NULL == phEnhancedTimeDmx) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx, 1, ENHANCED_TIME_DOMAIN_DMX); + FDK_ALLOCATE_MEMORY_1D(hEnhancedTimeDmx->sinusWindow_m, 1 + framelength, + FIXP_DBL); + hEnhancedTimeDmx->maxFramelength = framelength; + *phEnhancedTimeDmx = hEnhancedTimeDmx; + } + return error; + +bail: + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnhancedTimeDmx); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, + const INT framelength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (hEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + if (framelength > hEnhancedTimeDmx->maxFramelength) { + error = SACENC_INIT_ERROR; + goto bail; + } + + hEnhancedTimeDmx->framelength = framelength; + + INT deltax_e; + FIXP_DBL deltax_m; + + deltax_m = fDivNormHighPrec( + PI_M, (FIXP_DBL)(2 * hEnhancedTimeDmx->framelength), &deltax_e); + deltax_m = scaleValue(deltax_m, PI_E + deltax_e - (DFRACT_BITS - 1) - 1); + deltax_e = 1; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength + 1; smp++) { + hEnhancedTimeDmx->sinusWindow_m[smp] = + fMult(ALPHA_M, fPow2(fixp_sin(smp * deltax_m, deltax_e))); + } + hEnhancedTimeDmx->sinusWindow_e = -ALPHA_E; + + hEnhancedTimeDmx->prev_Left_m = hEnhancedTimeDmx->prev_Right_m = + hEnhancedTimeDmx->prev_XNrg_m = FL2FXCONST_DBL(0.f); + hEnhancedTimeDmx->prev_Left_e = hEnhancedTimeDmx->prev_Right_e = + hEnhancedTimeDmx->prev_XNrg_e = DFRACT_BITS - 1; + + hEnhancedTimeDmx->lin_bbCld_weight_m = + fDivNormHighPrec(fPow2(pInputGain_m[L]), fPow2(pInputGain_m[R]), + &hEnhancedTimeDmx->lin_bbCld_weight_e); + + hEnhancedTimeDmx->gain_weight_m[L] = fMult(pInputGain_m[L], outputGain_m); + hEnhancedTimeDmx->gain_weight_m[R] = fMult(pInputGain_m[R], outputGain_m); + hEnhancedTimeDmx->gain_weight_e = + -fNorm(fixMax(hEnhancedTimeDmx->gain_weight_m[L], + hEnhancedTimeDmx->gain_weight_m[R])); + + hEnhancedTimeDmx->gain_weight_m[L] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[L], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_m[R] = scaleValue( + hEnhancedTimeDmx->gain_weight_m[R], -hEnhancedTimeDmx->gain_weight_e); + hEnhancedTimeDmx->gain_weight_e += inputGain_e + outputGain_e; + + hEnhancedTimeDmx->prev_gain_m[L] = hEnhancedTimeDmx->gain_weight_m[L] >> 1; + hEnhancedTimeDmx->prev_gain_m[R] = hEnhancedTimeDmx->gain_weight_m[R] >> 1; + hEnhancedTimeDmx->prev_gain_e = hEnhancedTimeDmx->gain_weight_e + 1; + + hEnhancedTimeDmx->prev_H1_m[L] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[L], -4); + hEnhancedTimeDmx->prev_H1_m[R] = + scaleValue(hEnhancedTimeDmx->gain_weight_m[R], -4); + hEnhancedTimeDmx->prev_H1_e = 2 + 2 + hEnhancedTimeDmx->gain_weight_e; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnhancedTimeDmx) || (NULL == inputTime) || + (NULL == inputTime[L]) || (NULL == inputTime[R]) || + (NULL == outputTimeDmx)) { + error = SACENC_INVALID_HANDLE; + } else { + int smp; + FIXP_DBL lin_bbCld_m, lin_Cld_m, bbCorr_m, sqrt_linCld_m, G_m[2], H1_m[2], + gainLeft_m, gainRight_m; + FIXP_DBL bbNrgLeft_m, bbNrgRight_m, bbXNrg_m, nrgLeft_m, nrgRight_m, nrgX_m; + INT lin_bbCld_e, lin_Cld_e, bbCorr_e, sqrt_linCld_e, G_e, H1_e; + INT bbNrgLeft_e, bbNrgRight_e, bbXNrg_e, nrgLeft_e, nrgRight_e, nrgX_e; + + /* Increase energy time resolution with shorter processing blocks. 128 is an + * empiric value. */ + const int granuleLength = fixMin(128, hEnhancedTimeDmx->framelength); + int granuleShift = + (granuleLength > 1) + ? ((DFRACT_BITS - 1) - fNorm((FIXP_DBL)(granuleLength - 1))) + : 0; + granuleShift = fixMax( + 3, granuleShift + + 1); /* one bit more headroom for worst case accumulation */ + + smp = 0; + + /* Prevent division by zero. */ + bbNrgLeft_m = bbNrgRight_m = bbXNrg_m = (FIXP_DBL)(1); + bbNrgLeft_e = bbNrgRight_e = bbXNrg_e = 0; + + do { + const int offset = smp; + FIXP_DBL partialL, partialR, partialX; + partialL = partialR = partialX = FL2FXCONST_DBL(0.f); + + int in_margin = FDKmin( + getScalefactorPCM( + &inputTime[L][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1), + getScalefactorPCM( + &inputTime[R][offset], + fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength) - + offset, + 1)); + + /* partial energy */ + for (smp = offset; + smp < fixMin(offset + granuleLength, hEnhancedTimeDmx->framelength); + smp++) { + FIXP_PCM inputL = + scaleValue((FIXP_PCM)inputTime[L][smp], in_margin - 1); + FIXP_PCM inputR = + scaleValue((FIXP_PCM)inputTime[R][smp], in_margin - 1); + + partialL += fPow2Div2(inputL) >> (granuleShift - 3); + partialR += fPow2Div2(inputR) >> (granuleShift - 3); + partialX += fMultDiv2(inputL, inputR) >> (granuleShift - 3); + } + + fixpAddNorm(partialL, granuleShift - 2 * in_margin, &bbNrgLeft_m, + &bbNrgLeft_e); + fixpAddNorm(partialR, granuleShift - 2 * in_margin, &bbNrgRight_m, + &bbNrgRight_e); + fixpAddNorm(partialX, granuleShift - 2 * in_margin, &bbXNrg_m, &bbXNrg_e); + } while (smp < hEnhancedTimeDmx->framelength); + + nrgLeft_m = + fixpAdd(hEnhancedTimeDmx->prev_Left_m, hEnhancedTimeDmx->prev_Left_e, + bbNrgLeft_m, bbNrgLeft_e, &nrgLeft_e); + nrgRight_m = + fixpAdd(hEnhancedTimeDmx->prev_Right_m, hEnhancedTimeDmx->prev_Right_e, + bbNrgRight_m, bbNrgRight_e, &nrgRight_e); + nrgX_m = + fixpAdd(hEnhancedTimeDmx->prev_XNrg_m, hEnhancedTimeDmx->prev_XNrg_e, + bbXNrg_m, bbXNrg_e, &nrgX_e); + + lin_bbCld_m = fMult(hEnhancedTimeDmx->lin_bbCld_weight_m, + fDivNorm(nrgLeft_m, nrgRight_m, &lin_bbCld_e)); + lin_bbCld_e += + hEnhancedTimeDmx->lin_bbCld_weight_e + nrgLeft_e - nrgRight_e; + + bbCorr_m = fMult(nrgX_m, invSqrtNorm2(fMult(nrgLeft_m, nrgRight_m), + nrgLeft_e + nrgRight_e, &bbCorr_e)); + bbCorr_e += nrgX_e; + + hEnhancedTimeDmx->prev_Left_m = bbNrgLeft_m; + hEnhancedTimeDmx->prev_Left_e = bbNrgLeft_e; + hEnhancedTimeDmx->prev_Right_m = bbNrgRight_m; + hEnhancedTimeDmx->prev_Right_e = bbNrgRight_e; + hEnhancedTimeDmx->prev_XNrg_m = bbXNrg_m; + hEnhancedTimeDmx->prev_XNrg_e = bbXNrg_e; + + /* + bbCld = 10.f*log10(lin_bbCld) + + lin_Cld = pow(10,bbCld/20) + = pow(10,10.f*log10(lin_bbCld)/20.f) + = sqrt(lin_bbCld) + + lin_Cld2 = lin_Cld*lin_Cld + = sqrt(lin_bbCld)*sqrt(lin_bbCld) + = lin_bbCld + */ + lin_Cld_m = sqrtFixp(lin_bbCld_m, lin_bbCld_e, &lin_Cld_e); + sqrt_linCld_m = sqrtFixp(lin_Cld_m, lin_Cld_e, &sqrt_linCld_e); + + /*calculate how much right and how much left signal, to avoid signal + * cancellations*/ + calculateRatio(sqrt_linCld_m, sqrt_linCld_e, lin_Cld_m, lin_Cld_e, bbCorr_m, + bbCorr_e, G_m, &G_e); + + /*calculate downmix gains*/ + calculateDmxGains(lin_Cld_m, lin_Cld_e, lin_bbCld_m, lin_bbCld_e, bbCorr_m, + bbCorr_e, G_m, G_e, H1_m, &H1_e); + + /*adapt output gains*/ + H1_m[L] = fMult(H1_m[L], hEnhancedTimeDmx->gain_weight_m[L]); + H1_m[R] = fMult(H1_m[R], hEnhancedTimeDmx->gain_weight_m[R]); + H1_e += hEnhancedTimeDmx->gain_weight_e; + + gainLeft_m = hEnhancedTimeDmx->prev_gain_m[L]; + gainRight_m = hEnhancedTimeDmx->prev_gain_m[R]; + + INT intermediate_gain_e = + +hEnhancedTimeDmx->sinusWindow_e + H1_e - hEnhancedTimeDmx->prev_gain_e; + + for (smp = 0; smp < hEnhancedTimeDmx->framelength; smp++) { + const INT N = hEnhancedTimeDmx->framelength; + FIXP_DBL intermediate_gainLeft_m, intermediate_gainRight_m, tmp; + + intermediate_gainLeft_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[L]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[L])), + intermediate_gain_e); + intermediate_gainRight_m = + scaleValue((fMult(hEnhancedTimeDmx->sinusWindow_m[smp], H1_m[R]) + + fMult(hEnhancedTimeDmx->sinusWindow_m[N - smp], + hEnhancedTimeDmx->prev_H1_m[R])), + intermediate_gain_e); + + gainLeft_m = intermediate_gainLeft_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainLeft_m); + gainRight_m = intermediate_gainRight_m + + fMult(FL2FXCONST_DBL(1.f - ALPHA_FLT), gainRight_m); + + tmp = fMultDiv2(gainLeft_m, (FIXP_PCM)inputTime[L][smp + InputDelay]) + + fMultDiv2(gainRight_m, (FIXP_PCM)inputTime[R][smp + InputDelay]); + outputTimeDmx[smp] = (INT_PCM)SATURATE_SHIFT( + tmp, + -(hEnhancedTimeDmx->prev_gain_e + 1 - (DFRACT_BITS - SAMPLE_BITS)), + SAMPLE_BITS); + } + + hEnhancedTimeDmx->prev_gain_m[L] = gainLeft_m; + hEnhancedTimeDmx->prev_gain_m[R] = gainRight_m; + + hEnhancedTimeDmx->prev_H1_m[L] = H1_m[L]; + hEnhancedTimeDmx->prev_H1_m[R] = H1_m[R]; + hEnhancedTimeDmx->prev_H1_e = H1_e; + } + + return error; +} + +static void calculateRatio(const FIXP_DBL sqrt_linCld_m, + const INT sqrt_linCld_e, const FIXP_DBL lin_Cld_m, + const INT lin_Cld_e, const FIXP_DBL Icc_m, + const INT Icc_e, FIXP_DBL G_m[2], INT *G_e) { +#define G_SCALE_FACTOR (2) + + if (Icc_m >= FL2FXCONST_DBL(0.f)) { + G_m[0] = G_m[1] = FL2FXCONST_DBL(1.f / (float)(1 << G_SCALE_FACTOR)); + G_e[0] = G_SCALE_FACTOR; + } else { + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << G_SCALE_FACTOR)); + FIXP_DBL tmp1_m, tmp2_m, numerator_m, denominator_m, r_m, r4_m, q; + INT tmp1_e, tmp2_e, numerator_e, denominator_e, r_e, r4_e; + + /* r = (lin_Cld + 1 + 2*Icc*sqrt_linCld) / (lin_Cld + 1 - + * 2*Icc*sqrt_linCld) = (tmp1 + tmp2) / (tmp1 - tmp2) + */ + tmp1_m = + fixpAdd(lin_Cld_m, lin_Cld_e, FL2FXCONST_DBL(1.f / 2.f), 1, &tmp1_e); + + tmp2_m = fMult(Icc_m, sqrt_linCld_m); + tmp2_e = 1 + Icc_e + sqrt_linCld_e; + numerator_m = fixpAdd(tmp1_m, tmp1_e, tmp2_m, tmp2_e, &numerator_e); + denominator_m = fixpAdd(tmp1_m, tmp1_e, -tmp2_m, tmp2_e, &denominator_e); + + if ((numerator_m > FL2FXCONST_DBL(0.f)) && + (denominator_m > FL2FXCONST_DBL(0.f))) { + r_m = fDivNorm(numerator_m, denominator_m, &r_e); + r_e += numerator_e - denominator_e; + + /* r_4 = sqrt( sqrt( r ) ) */ + r4_m = sqrtFixp(r_m, r_e, &r4_e); + r4_m = sqrtFixp(r4_m, r4_e, &r4_e); + + r4_e -= G_SCALE_FACTOR; + + /* q = min(r4_m, max_gain_factor) */ + q = ((r4_e >= 0) && (r4_m >= (max_gain_factor >> r4_e))) + ? max_gain_factor + : scaleValue(r4_m, r4_e); + } else { + q = FL2FXCONST_DBL(0.f); + } + + G_m[0] = max_gain_factor - q; + G_m[1] = q; + + *G_e = G_SCALE_FACTOR; + } +} + +static void calculateDmxGains(const FIXP_DBL lin_Cld_m, const INT lin_Cld_e, + const FIXP_DBL lin_Cld2_m, const INT lin_Cld2_e, + const FIXP_DBL Icc_m, const INT Icc_e, + const FIXP_DBL G_m[2], const INT G_e, + FIXP_DBL H1_m[2], INT *pH1_e) { +#define H1_SCALE_FACTOR (2) + const FIXP_DBL max_gain_factor = + FL2FXCONST_DBL(2.f / (float)(1 << H1_SCALE_FACTOR)); + + FIXP_DBL nrgRight_m, nrgLeft_m, crossNrg_m, inv_weight_num_m, + inv_weight_denom_m, inverse_weight_m, inverse_weight_limited; + INT nrgRight_e, nrgLeft_e, crossNrg_e, inv_weight_num_e, inv_weight_denom_e, + inverse_weight_e; + + /* nrgRight = sqrt(1/(lin_Cld2 + 1) */ + nrgRight_m = fixpAdd(lin_Cld2_m, lin_Cld2_e, FL2FXCONST_DBL(1.f / 2.f), 1, + &nrgRight_e); + nrgRight_m = invSqrtNorm2(nrgRight_m, nrgRight_e, &nrgRight_e); + + /* nrgLeft = lin_Cld * nrgRight */ + nrgLeft_m = fMult(lin_Cld_m, nrgRight_m); + nrgLeft_e = lin_Cld_e + nrgRight_e; + + /* crossNrg = sqrt(nrgLeft*nrgRight) */ + crossNrg_m = sqrtFixp(fMult(nrgLeft_m, nrgRight_m), nrgLeft_e + nrgRight_e, + &crossNrg_e); + + /* inverse_weight = sqrt((nrgLeft + nrgRight) / ( (G[0]*G[0]*nrgLeft) + + * (G[1]*G[1]*nrgRight) + 2*G[0]*G[1]*Icc*crossNrg)) = sqrt(inv_weight_num / + * inv_weight_denom) + */ + inv_weight_num_m = + fixpAdd(nrgRight_m, nrgRight_e, nrgLeft_m, nrgLeft_e, &inv_weight_num_e); + + inv_weight_denom_m = + fixpAdd(fMult(fPow2(G_m[0]), nrgLeft_m), 2 * G_e + nrgLeft_e, + fMult(fPow2(G_m[1]), nrgRight_m), 2 * G_e + nrgRight_e, + &inv_weight_denom_e); + + inv_weight_denom_m = + fixpAdd(fMult(fMult(fMult(G_m[0], G_m[1]), crossNrg_m), Icc_m), + 1 + 2 * G_e + crossNrg_e + Icc_e, inv_weight_denom_m, + inv_weight_denom_e, &inv_weight_denom_e); + + if (inv_weight_denom_m > FL2FXCONST_DBL(0.f)) { + inverse_weight_m = + fDivNorm(inv_weight_num_m, inv_weight_denom_m, &inverse_weight_e); + inverse_weight_m = + sqrtFixp(inverse_weight_m, + inverse_weight_e + inv_weight_num_e - inv_weight_denom_e, + &inverse_weight_e); + inverse_weight_e -= H1_SCALE_FACTOR; + + /* inverse_weight_limited = min(max_gain_factor, inverse_weight) */ + inverse_weight_limited = + ((inverse_weight_e >= 0) && + (inverse_weight_m >= (max_gain_factor >> inverse_weight_e))) + ? max_gain_factor + : scaleValue(inverse_weight_m, inverse_weight_e); + } else { + inverse_weight_limited = max_gain_factor; + } + + H1_m[0] = fMult(G_m[0], inverse_weight_limited); + H1_m[1] = fMult(G_m[1], inverse_weight_limited); + + *pH1_e = G_e + H1_SCALE_FACTOR; +} + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *phEnhancedTimeDmx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (phEnhancedTimeDmx == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + if (*phEnhancedTimeDmx != NULL) { + if ((*phEnhancedTimeDmx)->sinusWindow_m != NULL) { + FDK_FREE_MEMORY_1D((*phEnhancedTimeDmx)->sinusWindow_m); + } + FDK_FREE_MEMORY_1D(*phEnhancedTimeDmx); + } + } + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.h b/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.h new file mode 100644 index 0000000..0b39911 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_dmx_tdom_enh.h @@ -0,0 +1,134 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Luis Valero + + Description: Enhanced Time Domain Downmix + +*******************************************************************************/ + +#ifndef SACENC_DMX_TDOM_ENH_H +#define SACENC_DMX_TDOM_ENH_H + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "common_fix.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_ENHANCED_TIME_DOMAIN_DMX *HANDLE_ENHANCED_TIME_DOMAIN_DMX; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_open_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_init_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const FIXP_DBL *const pInputGain_m, const INT inputGain_e, + const FIXP_DBL outputGain_m, const INT outputGain_e, const INT framelength); + +FDK_SACENC_ERROR fdk_sacenc_apply_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx, + const INT_PCM *const *const inputTime, INT_PCM *const outputTimeDmx, + const INT InputDelay); + +FDK_SACENC_ERROR fdk_sacenc_close_enhancedTimeDomainDmx( + HANDLE_ENHANCED_TIME_DOMAIN_DMX *hEnhancedTimeDmx); + +#endif /* SACENC_DMX_TDOM_ENH_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_filter.cpp b/fdk-aac/libSACenc/src/sacenc_filter.cpp new file mode 100644 index 0000000..79f0797 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_filter.cpp @@ -0,0 +1,207 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library + Filter functions + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_filter.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER { + FIXP_DBL c__FDK; + FIXP_DBL state__FDK; + +} DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hDCFilter) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hDCFilter, 1, DC_FILTER); + } + return error; + +bail: + fdk_sacenc_destroyDCFilter(hDCFilter); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate) { + FDK_SACENC_ERROR error = SACENC_OK; + + FIXP_DBL expC; + int s; + + /* Conversion for use of CalcInvLdData: e^x = 2^(x*log10(e)/log10(2) = + CalcInvLdData(x*log10(e)/log10(2)/64.0) 1.44269504089 = log10(e)/log10(2) + 0.5 = scale constant value with 1 Bits + */ + expC = fDivNormHighPrec((FIXP_DBL)20, (FIXP_DBL)sampleRate, &s); + expC = fMultDiv2(FL2FXCONST_DBL(-1.44269504089 * 0.5), expC) >> + (LD_DATA_SHIFT - 1 - 1); + + if (s < 0) + expC = expC >> (-s); + else + expC = expC << (s); + + expC = CalcInvLdData(expC); + + hDCFilter->c__FDK = expC; + hDCFilter->state__FDK = FL2FXCONST_DBL(0.0f); + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter != NULL) && (*hDCFilter != NULL)) { + FDKfree(*hDCFilter); + + *hDCFilter = NULL; + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hDCFilter == NULL) || (signalIn == NULL) || (signalOut == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const INT_PCM *const x = signalIn; + INT_PCM *const y = signalOut; + const FIXP_DBL c = hDCFilter->c__FDK; + FIXP_DBL *const state = &hDCFilter->state__FDK; + int i; + FIXP_DBL x0, x1, y1; + + x1 = x0 = FX_PCM2FX_DBL(x[0]) >> DC_FILTER_SF; + y1 = x0 + (*state); + + for (i = 1; i < signalLength; i++) { + x0 = FX_PCM2FX_DBL(x[i]) >> DC_FILTER_SF; + y[i - 1] = FX_DBL2FX_PCM(y1); + y1 = x0 - x1 + fMult(c, y1); + x1 = x0; + } + + *state = fMult(c, y1) - x1; + y[i - 1] = FX_DBL2FX_PCM(y1); + } + + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_filter.h b/fdk-aac/libSACenc/src/sacenc_filter.h new file mode 100644 index 0000000..10e3abd --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_filter.h @@ -0,0 +1,133 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Encoder Library Interface + Filter functions + +*******************************************************************************/ + +#ifndef SACENC_FILTER_H +#define SACENC_FILTER_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +#define DC_FILTER_SF 1 + +/* Data Types ****************************************************************/ +typedef struct T_DC_FILTER *HANDLE_DC_FILTER; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_initDCFilter(HANDLE_DC_FILTER hDCFilter, + const UINT sampleRate); + +FDK_SACENC_ERROR fdk_sacenc_destroyDCFilter(HANDLE_DC_FILTER *hDCFilter); + +FDK_SACENC_ERROR fdk_sacenc_applyDCFilter(HANDLE_DC_FILTER hDCFilter, + const INT_PCM *const signalIn, + INT_PCM *const signalOut, + const INT signalLength); + +#endif /* SACENC_FILTER_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_framewindowing.cpp b/fdk-aac/libSACenc/src/sacenc_framewindowing.cpp new file mode 100644 index 0000000..15f0f0a --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_framewindowing.cpp @@ -0,0 +1,568 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW { + INT nTimeSlotsMax; + INT bFrameKeep; + INT startSlope; + INT stopSlope; + INT startRect; + INT stopRect; + + INT taperAnaLen; + INT taperSynLen; + FIXP_WIN pTaperAna__FDK[MAX_TIME_SLOTS]; + FIXP_WIN pTaperSyn__FDK[MAX_TIME_SLOTS]; + +} FRAMEWINDOW; + +typedef enum { + FIX_INVALID = -1, + FIX_RECT_SMOOTH = 0, + FIX_SMOOTH_RECT = 1, + FIX_LARGE_SMOOTH = 2, + FIX_RECT_TRIANG = 3 + +} FIX_TYPE; + +typedef enum { + VAR_INVALID = -1, + VAR_HOLD = 0, + VAR_ISOLATE = 1 + +} VAR_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void calcTaperWin(FIXP_WIN *pTaperWin, INT timeSlots) { + FIXP_DBL x; + int i, scale; + + for (i = 0; i < timeSlots; i++) { + x = fDivNormHighPrec((FIXP_DBL)i, (FIXP_DBL)timeSlots, &scale); + + if (scale < 0) { + pTaperWin[i] = FX_DBL2FX_WIN(x >> (-scale)); + } else { + pTaperWin[i] = FX_DBL2FX_WIN(x << (scale)); + } + } + pTaperWin[timeSlots] = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phFrameWindow) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(*phFrameWindow, 1, FRAMEWINDOW); + } + return error; + +bail: + fdk_sacenc_frameWindow_Destroy(phFrameWindow); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (pFrameWindowConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (pFrameWindowConfig->nTimeSlotsMax < 0) { + error = SACENC_INIT_ERROR; + } else { + int ts; + hFrameWindow->bFrameKeep = pFrameWindowConfig->bFrameKeep; + hFrameWindow->nTimeSlotsMax = pFrameWindowConfig->nTimeSlotsMax; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + int timeSlots = pFrameWindowConfig->nTimeSlotsMax; + { + hFrameWindow->startSlope = 0; + hFrameWindow->stopSlope = ((3 * timeSlots) >> 1) - 1; + hFrameWindow->startRect = timeSlots >> 1; + hFrameWindow->stopRect = timeSlots; + calcTaperWin(hFrameWindow->pTaperSyn__FDK, timeSlots >> 1); + hFrameWindow->taperSynLen = timeSlots >> 1; + } + + /* Calculate Taper for non-rect. ana. windows */ + hFrameWindow->taperAnaLen = + hFrameWindow->startRect - hFrameWindow->startSlope; + for (ts = 0; ts < hFrameWindow->taperAnaLen; ts++) { + { hFrameWindow->pTaperAna__FDK[ts] = winMaxVal; } + } + } + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phFrameWindow) && (NULL != *phFrameWindow)) { + FDKfree(*phFrameWindow); + *phFrameWindow = NULL; + } + return error; +} + +static FDK_SACENC_ERROR FrameWinList_Reset(FRAMEWIN_LIST *const pFrameWinList) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < MAX_NUM_PARAMS; k++) { + pFrameWinList->dat[k].slot = -1; + pFrameWinList->dat[k].hold = FW_INTP; + } + pFrameWinList->n = 0; + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Add(FRAMEWIN_LIST *const pFrameWinList, + const INT slot, + const FW_SLOTTYPE hold) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + if (pFrameWinList->n >= MAX_NUM_PARAMS) { /* Place left in List ?*/ + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0 && + pFrameWinList->dat[pFrameWinList->n - 1].slot - slot > 0) { + error = SACENC_PARAM_ERROR; + } else { + pFrameWinList->dat[pFrameWinList->n].slot = slot; + pFrameWinList->dat[pFrameWinList->n].hold = hold; + pFrameWinList->n++; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Remove( + FRAMEWIN_LIST *const pFrameWinList, const INT idx) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + if (idx < 0 || idx >= MAX_NUM_PARAMS) { + error = SACENC_PARAM_ERROR; + } else if (pFrameWinList->n > 0) { + if (idx == MAX_NUM_PARAMS - 1) { + pFrameWinList->dat[idx].slot = -1; + pFrameWinList->dat[idx].hold = FW_INTP; + } else { + for (k = idx; k < MAX_NUM_PARAMS - 1; k++) { + pFrameWinList->dat[k] = pFrameWinList->dat[k + 1]; + } + } + pFrameWinList->n--; + } + } + return error; +} + +static FDK_SACENC_ERROR FrameWindowList_Limit( + FRAMEWIN_LIST *const pFrameWinList, const INT ll /*lower limit*/, + const INT ul /*upper limit*/ +) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == pFrameWinList) { + error = SACENC_INVALID_HANDLE; + } else { + int k = 0; + for (k = 0; k < pFrameWinList->n; k++) { + if (pFrameWinList->dat[k].slot < ll || pFrameWinList->dat[k].slot > ul) { + FrameWindowList_Remove(pFrameWinList, k); + --k; + } + } + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hFrameWindow == NULL) || (tr_pos == NULL) || (pFramingInfo == NULL) || + (pFrameWinList == NULL) || (pWindowAna__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + const VAR_TYPE varType = VAR_HOLD; + const int tranL = 4; + int winCnt = 0; + int w, ps; + + int startSlope = hFrameWindow->startSlope; + int stopSlope = hFrameWindow->stopSlope; + int startRect = hFrameWindow->startRect; + int stopRect = hFrameWindow->stopRect; + int taperAnaLen = hFrameWindow->taperAnaLen; + + FIXP_WIN winMaxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + FIXP_WIN applyRightWindowGain__FDK[MAX_NUM_PARAMS]; + FIXP_WIN *pTaperAna__FDK = hFrameWindow->pTaperAna__FDK; + + /* sanity check */ + for (ps = 0; ps < MAX_NUM_PARAMS; ps++) { + if (pWindowAna__FDK[ps] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + } + + if ((timeSlots > hFrameWindow->nTimeSlotsMax) || (timeSlots < 0)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Reset */ + if (SACENC_OK != (error = FrameWinList_Reset(pFrameWinList))) goto bail; + + FDKmemclear(applyRightWindowGain__FDK, sizeof(applyRightWindowGain__FDK)); + + if (tr_pos[0] > -1) { /* Transients in first (left) half? */ + int p_l = tr_pos[0]; + winCnt = 0; + + /* Create Parameter Positions */ + switch (varType) { + case VAR_HOLD: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + break; + case VAR_ISOLATE: + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l - 1, FW_HOLD))) + goto bail; + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, p_l, FW_INTP))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add(pFrameWinList, + p_l + tranL, FW_HOLD))) + goto bail; + if (SACENC_OK != (error = FrameWindowList_Add( + pFrameWinList, p_l + tranL + 1, FW_INTP))) + goto bail; + break; + default: + error = SACENC_INVALID_CONFIG; + break; + } + + /* Outside of frame? => Kick Out */ + if (SACENC_OK != + (error = FrameWindowList_Limit(pFrameWinList, 0, timeSlots - 1))) + goto bail; + + /* Add timeSlots as temporary border for window creation */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_HOLD))) + goto bail; + + /* Create Windows */ + for (ps = 0; ps < pFrameWinList->n - 1; ps++) { + if (FW_HOLD != pFrameWinList->dat[ps].hold) { + int const start = pFrameWinList->dat[ps].slot; + int const stop = pFrameWinList->dat[ps + 1].slot; + + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + start); + FDKmemset_flex(&pWindowAna__FDK[winCnt][start], winMaxVal, + stop - start + 1); + FDKmemset_flex(&pWindowAna__FDK[winCnt][stop + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots - stop - 1); + + applyRightWindowGain__FDK[winCnt] = + pWindowAna__FDK[winCnt][timeSlots - 1]; + winCnt++; + } + } /* ps */ + + /* Pop temporary frame border */ + if (SACENC_OK != + (error = FrameWindowList_Remove(pFrameWinList, pFrameWinList->n - 1))) + goto bail; + } else { /* No transient in left half of ana. window */ + winCnt = 0; + + /* Add paramter set at end of frame */ + if (SACENC_OK != + (error = FrameWindowList_Add(pFrameWinList, timeSlots - 1, FW_INTP))) + goto bail; + /* Analysis Window */ + FDKmemset_flex(pWindowAna__FDK[winCnt], FX_DBL2FX_WIN((FIXP_DBL)0), + startSlope); + FDKmemcpy_flex(&pWindowAna__FDK[winCnt][startSlope], 1, pTaperAna__FDK, 1, + taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[winCnt][startRect], winMaxVal, + timeSlots - startRect); + + applyRightWindowGain__FDK[winCnt] = winMaxVal; + winCnt++; + } /* if (tr_pos[0] > -1) */ + + for (w = 0; w < winCnt; w++) { + if (applyRightWindowGain__FDK[w] > (FIXP_WIN)0) { + if (tr_pos[1] > -1) { /* Transients in second (right) half? */ + int p_r = tr_pos[1]; + + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + p_r - timeSlots); + FDKmemset_flex(&pWindowAna__FDK[w][p_r], FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - p_r); + + } else { /* No transient in right half of ana. window */ + /* Analysis Window */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], winMaxVal, + stopRect - timeSlots + 1); + FDKmemcpy_flex(&pWindowAna__FDK[w][stopRect], 1, + &pTaperAna__FDK[taperAnaLen - 1], -1, taperAnaLen); + FDKmemset_flex(&pWindowAna__FDK[w][stopSlope + 1], + FX_DBL2FX_WIN((FIXP_DBL)0), + 2 * timeSlots - stopSlope - 1); + + } /* if (tr_pos[1] > -1) */ + + /* Weight */ + if (applyRightWindowGain__FDK[w] < winMaxVal) { + int ts; + for (ts = 0; ts < timeSlots; ts++) { + pWindowAna__FDK[w][timeSlots + ts] = + FX_DBL2FX_WIN(fMult(pWindowAna__FDK[w][timeSlots + ts], + applyRightWindowGain__FDK[w])); + } + } + } /* if (applyRightWindowGain[w] > 0.0f) */ + else { + /* All Zero */ + FDKmemset_flex(&pWindowAna__FDK[w][timeSlots], + FX_DBL2FX_WIN((FIXP_DBL)0), timeSlots); + } + } /* loop over windows */ + + if (hFrameWindow->bFrameKeep == 1) { + FDKmemcpy_flex(&pWindowAna__FDK[0][2 * timeSlots], 1, + &pWindowAna__FDK[0][timeSlots], 1, timeSlots); + FDKmemcpy_flex(&pWindowAna__FDK[0][timeSlots], 1, pWindowAna__FDK[0], 1, + timeSlots); + + if (avoid_keep != 0) { + FDKmemset_flex(pWindowAna__FDK[0], FX_DBL2FX_WIN((FIXP_DBL)0), + timeSlots); + } else { + FDKmemset_flex(pWindowAna__FDK[0], winMaxVal, timeSlots); + } + } /* if (hFrameWindow->bFrameKeep==1) */ + + /* Feed Info to Bitstream Formatter */ + pFramingInfo->numParamSets = pFrameWinList->n; + pFramingInfo->bsFramingType = 1; /* variable framing */ + for (ps = 0; ps < pFramingInfo->numParamSets; ps++) { + pFramingInfo->bsParamSlots[ps] = pFrameWinList->dat[ps].slot; + } + + /* if there is just one param set at last slot, + use fixed framing to save some bits */ + if ((pFramingInfo->numParamSets == 1) && + (pFramingInfo->bsParamSlots[0] == timeSlots - 1)) { + pFramingInfo->bsFramingType = 0; + } + + } /* valid handle */ + +bail: + + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pFrameWindowAna__FDK == NULL) || (ppDataIn__FDK == NULL) || + (ppDataOut__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts; + FIXP_WIN maxVal = FX_DBL2FX_WIN((FIXP_DBL)MAXVAL_DBL); + + if (dim == FW_CHANGE_DIM) { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[i][ts].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[i][ts].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[i][ts].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } else { + for (ts = startTimeSlot; ts < nTimeSlots; ts++) { + FIXP_WIN win = pFrameWindowAna__FDK[ts]; + if (win == maxVal) { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = ppDataIn__FDK[ts][i].v.re; + ppDataOut__FDK[ts][i].v.im = ppDataIn__FDK[ts][i].v.im; + } + } else { + for (i = 0; i < nHybridBands; i++) { + ppDataOut__FDK[ts][i].v.re = fMult(win, ppDataIn__FDK[ts][i].v.re); + ppDataOut__FDK[ts][i].v.im = fMult(win, ppDataIn__FDK[ts][i].v.im); + } + } + } /* ts */ + } + } + + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_framewindowing.h b/fdk-aac/libSACenc/src/sacenc_framewindowing.h new file mode 100644 index 0000000..6b22dc9 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_framewindowing.h @@ -0,0 +1,181 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Get windows for framing + +*******************************************************************************/ + +#ifndef SACENC_FRAMEWINDOWING_H +#define SACENC_FRAMEWINDOWING_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "genericStds.h" +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_WIN FIXP_DBL +#define FX_DBL2FX_WIN(x) (x) +#define DALDATATYPE_WIN DALDATATYPE_DFRACT + +typedef enum { + FW_INTP = 0, + FW_HOLD = 1 + +} FW_SLOTTYPE; + +typedef enum { + FW_LEAVE_DIM = 0, + FW_CHANGE_DIM = 1 + +} FW_DIMENSION; + +/* Data Types ****************************************************************/ +typedef struct T_FRAMEWINDOW *HANDLE_FRAMEWINDOW; + +typedef struct T_FRAMEWINDOW_CONFIG { + INT nTimeSlotsMax; + INT bFrameKeep; + +} FRAMEWINDOW_CONFIG; + +typedef struct { + INT slot; + FW_SLOTTYPE hold; + +} FRAMEWIN_DATA; + +typedef struct { + FRAMEWIN_DATA dat[MAX_NUM_PARAMS]; + INT n; + +} FRAMEWIN_LIST; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Create( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Init( + HANDLE_FRAMEWINDOW hFrameWindow, + const FRAMEWINDOW_CONFIG *const pFrameWindowConfig); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_Destroy( + HANDLE_FRAMEWINDOW *phFrameWindow); + +FDK_SACENC_ERROR fdk_sacenc_frameWindow_GetWindow( + HANDLE_FRAMEWINDOW hFrameWindow, INT tr_pos[MAX_NUM_PARAMS], + const INT timeSlots, FRAMINGINFO *const pFramingInfo, + FIXP_WIN *pWindowAna__FDK[MAX_NUM_PARAMS], + FRAMEWIN_LIST *const pFrameWinList, const INT avoid_keep); + +FDK_SACENC_ERROR fdk_sacenc_analysisWindowing( + const INT nTimeSlots, const INT startTimeSlot, + FIXP_WIN *pFrameWindowAna__FDK, const FIXP_DPK *const *const ppDataIn__FDK, + FIXP_DPK *const *const ppDataOut__FDK, const INT nHybridBands, + const INT dim); + +#endif /* SACENC_FRAMEWINDOWING_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_huff_tab.cpp b/fdk-aac/libSACenc/src/sacenc_huff_tab.cpp new file mode 100644 index 0000000..7b28ecd --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_huff_tab.cpp @@ -0,0 +1,997 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_huff_tab.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab = { + {/* h1D[2][31] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x00007ffc, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0000fffa, 16), HUFF_PACK(0x0001fffe, 17), + HUFF_PACK(0x0001fff6, 17), HUFF_PACK(0x0003fffe, 18), + HUFF_PACK(0x0003ffff, 18), HUFF_PACK(0x0007ffde, 19), + HUFF_PACK(0x0003ffee, 18), HUFF_PACK(0x000fffbe, 20), + HUFF_PACK(0x001fff7e, 21), HUFF_PACK(0x00fffbfc, 24), + HUFF_PACK(0x00fffbfd, 24), HUFF_PACK(0x00fffbfe, 24), + HUFF_PACK(0x00fffbff, 24), HUFF_PACK(0x007ffdfc, 23), + HUFF_PACK(0x007ffdfd, 23)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000003fa, 10), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x00000ffe, 12), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x00001ffe, 13), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x00003ffe, 14), + HUFF_PACK(0x00003fbe, 14), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x0000fffe, 16), + HUFF_PACK(0x0001fffe, 17), HUFF_PACK(0x0007fffe, 19), + HUFF_PACK(0x0007fffc, 19), HUFF_PACK(0x000ffffa, 20), + HUFF_PACK(0x001ffffc, 21), HUFF_PACK(0x001ffffd, 21), + HUFF_PACK(0x001ffffe, 21), HUFF_PACK(0x001fffff, 21), + HUFF_PACK(0x000ffffb, 20)}}, + { /* HUFF_CLD_TAB_2D */ + { /* HUFF_CLD_TAB_2D[0][] */ + {/* HUFF_CLD_TAB_2D[0][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x00000004, 5), HUFF_PACK(0x0000003e, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x0000000e, 6), HUFF_PACK(0x000000fe, 10)}, + {HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000001e, 7), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000005, 5)}, + {HUFF_PACK(0x000000ff, 10), HUFF_PACK(0x0000000d, 6), + HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000003, 3), + HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00001f7e, 13)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x0000011f, 9), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000004e, 7)}, + {HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x000007de, 11), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x00000037, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x00001f7f, 13), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x0000017a, 9), + HUFF_PACK(0x000000ee, 9), HUFF_PACK(0x000007b6, 11)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000047ce, 15)}, + {HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x00000022, 6), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000003f, 7), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x000008fb, 12)}, + {HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0000003a, 7), + HUFF_PACK(0x000001f6, 9), HUFF_PACK(0x000001de, 10), + HUFF_PACK(0x000003da, 10), HUFF_PACK(0x000007b7, 11)}, + {HUFF_PACK(0x000001df, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000017b, 9), HUFF_PACK(0x000003ef, 10), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000008e, 8), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000001fe, 9)}, + {HUFF_PACK(0x000008f8, 12), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x0000047f, 11), HUFF_PACK(0x00000076, 8), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x000023e6, 14), HUFF_PACK(0x000011f2, 13), + HUFF_PACK(0x000001ff, 9), HUFF_PACK(0x0000003d, 7), + HUFF_PACK(0x0000004f, 7), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000004, 4)}, + {HUFF_PACK(0x000047cf, 15), HUFF_PACK(0x0000011e, 9), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x00000010, 5), + HUFF_PACK(0x0000000d, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000000a, 7), HUFF_PACK(0x0000001e, 8), + HUFF_PACK(0x0000008a, 9), HUFF_PACK(0x0000004e, 10), + HUFF_PACK(0x00000276, 10), HUFF_PACK(0x000002e2, 11)}, + {HUFF_PACK(0x00000000, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x000000f2, 8), + HUFF_PACK(0x00000012, 8), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000008b, 9), HUFF_PACK(0x00002e76, 15)}, + {HUFF_PACK(0x00000012, 6), HUFF_PACK(0x00000007, 5), + HUFF_PACK(0x00000038, 6), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x00000008, 7), HUFF_PACK(0x00000046, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000001ca, 9), + HUFF_PACK(0x0000173a, 14), HUFF_PACK(0x00001738, 14)}, + {HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x0000004a, 7), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000000c, 7), + HUFF_PACK(0x0000004e, 8), HUFF_PACK(0x000000f7, 8), + HUFF_PACK(0x0000013a, 9), HUFF_PACK(0x0000009e, 11), + HUFF_PACK(0x000009fe, 12), HUFF_PACK(0x0000013e, 12)}, + {HUFF_PACK(0x00000026, 9), HUFF_PACK(0x0000001a, 8), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e2, 9), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x000001ce, 9), + HUFF_PACK(0x00000277, 10), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000002e6, 11), HUFF_PACK(0x000004fc, 11)}, + {HUFF_PACK(0x000002e3, 11), HUFF_PACK(0x00000170, 10), + HUFF_PACK(0x00000172, 10), HUFF_PACK(0x000000ba, 9), + HUFF_PACK(0x0000003e, 9), HUFF_PACK(0x000001e3, 9), + HUFF_PACK(0x0000001b, 8), HUFF_PACK(0x0000003f, 9), + HUFF_PACK(0x0000009e, 9), HUFF_PACK(0x0000009f, 9)}, + {HUFF_PACK(0x00000b9e, 13), HUFF_PACK(0x000009ff, 12), + HUFF_PACK(0x000004fd, 11), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000001cf, 9), HUFF_PACK(0x000000ef, 8), + HUFF_PACK(0x00000044, 8), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000000e4, 8), HUFF_PACK(0x000000f0, 8)}, + {HUFF_PACK(0x00002e72, 15), HUFF_PACK(0x0000013f, 12), + HUFF_PACK(0x00000b9f, 13), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000047, 8), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x0000007d, 7), + HUFF_PACK(0x00000010, 6), HUFF_PACK(0x00000024, 6)}, + {HUFF_PACK(0x00002e77, 15), HUFF_PACK(0x00005ce6, 16), + HUFF_PACK(0x000000bb, 9), HUFF_PACK(0x000000e6, 8), + HUFF_PACK(0x00000016, 8), HUFF_PACK(0x000000ff, 8), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000003a, 6), + HUFF_PACK(0x00000017, 5), HUFF_PACK(0x00000002, 4)}, + {HUFF_PACK(0x00005ce7, 16), HUFF_PACK(0x000003cf, 10), + HUFF_PACK(0x00000017, 8), HUFF_PACK(0x000001cb, 9), + HUFF_PACK(0x0000009c, 8), HUFF_PACK(0x0000004b, 7), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[0][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000076e, 11), HUFF_PACK(0x00000ede, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000003f, 6), + HUFF_PACK(0x000003b6, 10), HUFF_PACK(0x0000003a, 6)}, + {HUFF_PACK(0x0000001c, 5), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000001da, 9), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x000000ef, 8), HUFF_PACK(0x00000edf, 12), + HUFF_PACK(0x000000ec, 8), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x00000efc, 12), + HUFF_PACK(0x0000effe, 16), HUFF_PACK(0x0001dffe, 17)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000efe, 12), + HUFF_PACK(0x000077fe, 15), HUFF_PACK(0x00000076, 7)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000efd, 12), + HUFF_PACK(0x000000ee, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000003be, 10), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001e, 5)}, + {HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x00003bfe, 14), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x00000002, 3)}, + {HUFF_PACK(0x000000bf, 8), HUFF_PACK(0x0001dfff, 17), + HUFF_PACK(0x00001dfe, 13), HUFF_PACK(0x000000ff, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000000bc, 8), HUFF_PACK(0x000005fc, 11), + HUFF_PACK(0x00005ffe, 15), HUFF_PACK(0x0002ffde, 18), + HUFF_PACK(0x000bff7e, 20), HUFF_PACK(0x0017feff, 21)}, + {HUFF_PACK(0x00000004, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000000e, 7), HUFF_PACK(0x000002fa, 10), + HUFF_PACK(0x000001fe, 13), HUFF_PACK(0x0000bff2, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x000000ee, 8)}, + {HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000001ff, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x00000000, 5), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x0000000e, 8), HUFF_PACK(0x0000003e, 10), + HUFF_PACK(0x00002ffe, 14), HUFF_PACK(0x000002fb, 10), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x00000006, 6), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000a, 8), HUFF_PACK(0x0000007e, 11), + HUFF_PACK(0x000000fe, 12), HUFF_PACK(0x00000016, 9), + HUFF_PACK(0x00000006, 7), HUFF_PACK(0x00000002, 5)}, + {HUFF_PACK(0x0000000f, 7), HUFF_PACK(0x00000076, 7), + HUFF_PACK(0x00000017, 9), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00000bfe, 12), HUFF_PACK(0x0000001e, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000003, 4)}, + {HUFF_PACK(0x00000004, 7), HUFF_PACK(0x000000bd, 8), + HUFF_PACK(0x0000bff3, 16), HUFF_PACK(0x00005fff, 15), + HUFF_PACK(0x00000bfa, 12), HUFF_PACK(0x0000017c, 9), + HUFF_PACK(0x0000003a, 6), HUFF_PACK(0x00000003, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fefe, 21), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfb, 12), HUFF_PACK(0x000001df, 9), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017feff, 21) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000014, 5), + HUFF_PACK(0x0000008e, 8), HUFF_PACK(0x000004fe, 11), + HUFF_PACK(0x000023fe, 14), HUFF_PACK(0x00008ffe, 16), + HUFF_PACK(0x0005ffbc, 19), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x0017fef7, 21), HUFF_PACK(0x0017fef7, 21)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x00000044, 7), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x000017fc, 13), HUFF_PACK(0x0000bff6, 16), + HUFF_PACK(0x0005ffbe, 19), HUFF_PACK(0x00011ff8, 17), + HUFF_PACK(0x000bff7a, 20), HUFF_PACK(0x000000bc, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x0000001a, 7), HUFF_PACK(0x000000fe, 10), + HUFF_PACK(0x000011f6, 13), HUFF_PACK(0x0000bffe, 16), + HUFF_PACK(0x00011ff9, 17), HUFF_PACK(0x0017fef6, 21), + HUFF_PACK(0x0000011e, 9), HUFF_PACK(0x00000056, 7)}, + {HUFF_PACK(0x00000010, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000009e, 8), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x000011f7, 13), HUFF_PACK(0x00005ff8, 15), + HUFF_PACK(0x00017fee, 17), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x0000001e, 7)}, + {HUFF_PACK(0x00000026, 6), HUFF_PACK(0x0000000e, 6), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x0000047e, 11), + HUFF_PACK(0x00000bfc, 12), HUFF_PACK(0x0000bfff, 16), + HUFF_PACK(0x000008fa, 12), HUFF_PACK(0x0000006e, 9), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x0000007e, 7)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000004e, 7), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x000000de, 10), + HUFF_PACK(0x000011fe, 13), HUFF_PACK(0x00002ffe, 14), + HUFF_PACK(0x000004ff, 11), HUFF_PACK(0x000000ff, 10), + HUFF_PACK(0x000000bd, 8), HUFF_PACK(0x0000002e, 6)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000000af, 8), + HUFF_PACK(0x000001ec, 9), HUFF_PACK(0x000001be, 11), + HUFF_PACK(0x00011ffe, 17), HUFF_PACK(0x00002ffa, 14), + HUFF_PACK(0x000008fe, 12), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000046, 7), HUFF_PACK(0x00000012, 5)}, + {HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x00000045, 7), + HUFF_PACK(0x000002fe, 10), HUFF_PACK(0x000bff7e, 20), + HUFF_PACK(0x00005ff9, 15), HUFF_PACK(0x00005ffa, 15), + HUFF_PACK(0x00000bfd, 12), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000000c, 6), HUFF_PACK(0x00000007, 4)}, + {HUFF_PACK(0x000000be, 8), HUFF_PACK(0x00000036, 8), + HUFF_PACK(0x000bff7f, 20), HUFF_PACK(0x00023ffe, 18), + HUFF_PACK(0x00011ffa, 17), HUFF_PACK(0x00005ffe, 15), + HUFF_PACK(0x000001bf, 11), HUFF_PACK(0x000001ed, 9), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000000, 3)}, + {HUFF_PACK(0x0000017e, 9), HUFF_PACK(0x0017fef7, 21), + HUFF_PACK(0x00047ffe, 19), HUFF_PACK(0x00047fff, 19), + HUFF_PACK(0x00011ffb, 17), HUFF_PACK(0x00002ffb, 14), + HUFF_PACK(0x0000047c, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x00000006, 3)}}, + HUFF_PACK(0x0017fef7, 21) /* escape */ + }}}, + { /* HUFF_CLD_TAB_2D[1][] */ + {/* HUFF_CLD_TAB_2D[1][0] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003be, 10), HUFF_PACK(0x00000efe, 12)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000001c, 5), + HUFF_PACK(0x000001de, 9), HUFF_PACK(0x000000ea, 8)}, + {HUFF_PACK(0x00000074, 7), HUFF_PACK(0x000000ee, 8), + HUFF_PACK(0x000000eb, 8), HUFF_PACK(0x0000001f, 5)}, + {HUFF_PACK(0x0000077e, 11), HUFF_PACK(0x00000eff, 12), + HUFF_PACK(0x00000076, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x00000024, 7), HUFF_PACK(0x0000025e, 11), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079fe, 15)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000007, 4), + HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x00001e7e, 13), HUFF_PACK(0x000000be, 9)}, + {HUFF_PACK(0x00000008, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000026, 7), HUFF_PACK(0x0000012e, 10), + HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x00000027, 7), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x000001e4, 9), HUFF_PACK(0x00000096, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x0000003f, 6)}, + {HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x000001e5, 9), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000079e, 11), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x0000025f, 11), HUFF_PACK(0x0000004a, 8), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x000034fe, 14), HUFF_PACK(0x0001a7fe, 17), + HUFF_PACK(0x00069ff6, 19), HUFF_PACK(0x00069ff7, 19)}, + {HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x00001fde, 13), HUFF_PACK(0x000069fe, 15), + HUFF_PACK(0x0001a7fc, 17), HUFF_PACK(0x00000372, 10)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 6), + HUFF_PACK(0x000000df, 8), HUFF_PACK(0x000001ee, 10), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000069fa, 15), + HUFF_PACK(0x00000373, 10), HUFF_PACK(0x0000007a, 8)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000068, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x00000d3e, 12), HUFF_PACK(0x0000034c, 10), + HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000d2, 8)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000007f, 8), + HUFF_PACK(0x000001f8, 9), HUFF_PACK(0x000006ee, 11), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000001b8, 9), + HUFF_PACK(0x000001fc, 9), HUFF_PACK(0x0000006b, 7)}, + {HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000034d, 10), HUFF_PACK(0x00003fbe, 14), + HUFF_PACK(0x000007f6, 11), HUFF_PACK(0x000003fa, 10), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x0000003d, 6)}, + {HUFF_PACK(0x000003f7, 10), HUFF_PACK(0x00000376, 10), + HUFF_PACK(0x0001a7ff, 17), HUFF_PACK(0x00003fbf, 14), + HUFF_PACK(0x00000ddf, 12), HUFF_PACK(0x000001f9, 9), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x00034ffa, 18), + HUFF_PACK(0x000069fb, 15), HUFF_PACK(0x000034fc, 14), + HUFF_PACK(0x00000fee, 12), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000012, 7), HUFF_PACK(0x000007fe, 11), + HUFF_PACK(0x00001f7e, 13), HUFF_PACK(0x0000fbfe, 16), + HUFF_PACK(0x0001f7fe, 17), HUFF_PACK(0x000b7dfe, 21), + HUFF_PACK(0x000b7dff, 21), HUFF_PACK(0x000b7dff, 21)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000006, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x00000046, 9), + HUFF_PACK(0x000007d0, 12), HUFF_PACK(0x00001f4e, 14), + HUFF_PACK(0x0000b7fe, 17), HUFF_PACK(0x00005bee, 16), + HUFF_PACK(0x00016fbe, 18), HUFF_PACK(0x000003ee, 10)}, + {HUFF_PACK(0x00000006, 5), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000007d2, 12), HUFF_PACK(0x00001f4f, 14), + HUFF_PACK(0x00002dfe, 15), HUFF_PACK(0x0000b7de, 17), + HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x0000002e, 8)}, + {HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000007a, 8), HUFF_PACK(0x000001fa, 10), + HUFF_PACK(0x000007fe, 12), HUFF_PACK(0x00001f7c, 13), + HUFF_PACK(0x000016fa, 14), HUFF_PACK(0x0000009e, 10), + HUFF_PACK(0x00000020, 8), HUFF_PACK(0x00000021, 8)}, + {HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x00000016, 7), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x0000016e, 10), + HUFF_PACK(0x0000009f, 10), HUFF_PACK(0x00000b7c, 13), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000000b6, 9), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x0000007c, 8)}, + {HUFF_PACK(0x0000005a, 8), HUFF_PACK(0x00000078, 8), + HUFF_PACK(0x00000047, 9), HUFF_PACK(0x00000044, 9), + HUFF_PACK(0x000007ff, 12), HUFF_PACK(0x000007d1, 12), + HUFF_PACK(0x000001f6, 10), HUFF_PACK(0x000001f7, 10), + HUFF_PACK(0x0000002f, 8), HUFF_PACK(0x0000002c, 7)}, + {HUFF_PACK(0x000000fc, 9), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000007ff, 11), + HUFF_PACK(0x000016fe, 14), HUFF_PACK(0x000002de, 11), + HUFF_PACK(0x000003ea, 11), HUFF_PACK(0x000000bf, 9), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000000a, 6)}, + {HUFF_PACK(0x0000004e, 9), HUFF_PACK(0x00000026, 8), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00005bfe, 16), + HUFF_PACK(0x00003efe, 14), HUFF_PACK(0x00000b7e, 13), + HUFF_PACK(0x000003eb, 11), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000007b, 7), HUFF_PACK(0x00000007, 5)}, + {HUFF_PACK(0x000001fb, 10), HUFF_PACK(0x00000045, 9), + HUFF_PACK(0x00016ffe, 18), HUFF_PACK(0x0001f7ff, 17), + HUFF_PACK(0x00002df6, 15), HUFF_PACK(0x00001f7d, 13), + HUFF_PACK(0x000003fe, 11), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000003df, 11), HUFF_PACK(0x0005befe, 20), + HUFF_PACK(0x0002df7e, 19), HUFF_PACK(0x00016fff, 18), + HUFF_PACK(0x00007dfe, 15), HUFF_PACK(0x00000fa6, 13), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x00000079, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000b7dff, 21) /* escape */ + }}, + {/* HUFF_CLD_TAB_2D[1][1] */ + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x000007de, 11)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000000ff, 8), HUFF_PACK(0x0000007c, 7), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007df, 11), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x00003efe, 14)}, + {HUFF_PACK(0x00000000, 3), HUFF_PACK(0x00000001, 3), + HUFF_PACK(0x0000003c, 6), HUFF_PACK(0x0000005e, 8), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000007be, 11)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000a, 5), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x0000005f, 8), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000001f6, 9)}, + {HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000f6, 8), HUFF_PACK(0x000000fa, 8), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x000007bf, 11), HUFF_PACK(0x000003de, 10), + HUFF_PACK(0x000003ee, 10), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x00003eff, 14), HUFF_PACK(0x00001f7e, 13), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x0000002e, 7), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 3), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x000006e6, 11), HUFF_PACK(0x0000067a, 12), + HUFF_PACK(0x00000cf2, 13), HUFF_PACK(0x000033de, 15)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x00000372, 10), HUFF_PACK(0x000003d6, 11), + HUFF_PACK(0x00000678, 12), HUFF_PACK(0x00000cf6, 13)}, + {HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003c, 7), + HUFF_PACK(0x000001b8, 9), HUFF_PACK(0x000003d4, 11), + HUFF_PACK(0x0000033e, 11), HUFF_PACK(0x0000033f, 11)}, + {HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x0000004e, 7), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000000ce, 9), + HUFF_PACK(0x000000f6, 9), HUFF_PACK(0x000001ee, 10)}, + {HUFF_PACK(0x000001ef, 10), HUFF_PACK(0x0000013e, 9), + HUFF_PACK(0x0000007f, 8), HUFF_PACK(0x00000066, 8), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x000000d7, 8), HUFF_PACK(0x0000009e, 8)}, + {HUFF_PACK(0x000007ae, 12), HUFF_PACK(0x000001e8, 10), + HUFF_PACK(0x000001e9, 10), HUFF_PACK(0x0000027e, 10), + HUFF_PACK(0x00000032, 7), HUFF_PACK(0x00000018, 6), + HUFF_PACK(0x00000026, 6), HUFF_PACK(0x00000034, 6)}, + {HUFF_PACK(0x00000cf3, 13), HUFF_PACK(0x000007aa, 12), + HUFF_PACK(0x000007ab, 12), HUFF_PACK(0x0000027f, 10), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000b, 4)}, + {HUFF_PACK(0x000033df, 15), HUFF_PACK(0x000019ee, 14), + HUFF_PACK(0x000007af, 12), HUFF_PACK(0x000006e7, 11), + HUFF_PACK(0x000001bb, 9), HUFF_PACK(0x0000007f, 7), + HUFF_PACK(0x00000008, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV9_2D */ + {{HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x000001ba, 10), HUFF_PACK(0x00000dbe, 12), + HUFF_PACK(0x00000d7e, 13), HUFF_PACK(0x00001af6, 14), + HUFF_PACK(0x00007fec, 15), HUFF_PACK(0x0001ffb6, 17)}, + {HUFF_PACK(0x0000000a, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x00000036, 7), + HUFF_PACK(0x000000de, 9), HUFF_PACK(0x000005fe, 11), + HUFF_PACK(0x000006be, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x00007fee, 15), HUFF_PACK(0x00006dfe, 15)}, + {HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00000376, 11), HUFF_PACK(0x00000dfe, 13), + HUFF_PACK(0x00000dff, 13), HUFF_PACK(0x00000d7f, 13)}, + {HUFF_PACK(0x000000b6, 8), HUFF_PACK(0x0000005e, 7), + HUFF_PACK(0x0000007c, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000006a, 8), HUFF_PACK(0x0000016a, 9), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00000ffc, 12), HUFF_PACK(0x00001bfe, 13)}, + {HUFF_PACK(0x0000035e, 10), HUFF_PACK(0x000001b6, 9), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x000000b4, 8), + HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x0000017e, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003ee, 10), + HUFF_PACK(0x0000037e, 11), HUFF_PACK(0x00000377, 11)}, + {HUFF_PACK(0x00000fff, 12), HUFF_PACK(0x000001ae, 10), + HUFF_PACK(0x000001be, 10), HUFF_PACK(0x000001f6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000016b, 9), + HUFF_PACK(0x000000d6, 9), HUFF_PACK(0x0000037e, 10)}, + {HUFF_PACK(0x000017fe, 13), HUFF_PACK(0x00000bfe, 12), + HUFF_PACK(0x000007de, 11), HUFF_PACK(0x000006de, 11), + HUFF_PACK(0x000001b8, 10), HUFF_PACK(0x000000d6, 8), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x00000034, 7), + HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000be, 8)}, + {HUFF_PACK(0x00007fef, 15), HUFF_PACK(0x000006bc, 12), + HUFF_PACK(0x00001bff, 13), HUFF_PACK(0x00001ffa, 13), + HUFF_PACK(0x000001b9, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000000fa, 8), HUFF_PACK(0x0000002e, 6), + HUFF_PACK(0x00000034, 6), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x00006dff, 15), HUFF_PACK(0x00001af7, 14), + HUFF_PACK(0x000036fe, 14), HUFF_PACK(0x000006fe, 12), + HUFF_PACK(0x00000fbe, 12), HUFF_PACK(0x0000035f, 10), + HUFF_PACK(0x000000b7, 8), HUFF_PACK(0x0000002c, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000009, 4)}, + {HUFF_PACK(0x0001ffb7, 17), HUFF_PACK(0x0000ffda, 16), + HUFF_PACK(0x00000d7a, 13), HUFF_PACK(0x000017ff, 13), + HUFF_PACK(0x00000fbf, 12), HUFF_PACK(0x000002fe, 10), + HUFF_PACK(0x0000005f, 8), HUFF_PACK(0x00000016, 6), + HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }}}}}; + +const HUFF_ICC_TABLE fdk_sacenc_huffICCTab = { + {/* h1D[2][8] */ + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}, + {HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000002, 2), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000007f, 7)}}, + { /* HUFF_ICC_TAB_2D */ + { /* HUFF_ICC_TAB_2D[0][] */ + {/* HUFF_ICC_TAB_2D[0][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x000003fe, 11)}, + {HUFF_PACK(0x000001fe, 10), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x0000001e, 6)}, + {HUFF_PACK(0x000003ff, 11), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000000c, 5), HUFF_PACK(0x0000006a, 7), + HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000006ee, 11)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000000d, 5), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000001ae, 9), HUFF_PACK(0x0000ddff, 16)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000001be, 9), + HUFF_PACK(0x00006efe, 15), HUFF_PACK(0x0000ddfe, 16)}, + {HUFF_PACK(0x0000377e, 14), HUFF_PACK(0x00001bbe, 13), + HUFF_PACK(0x00000dde, 12), HUFF_PACK(0x000001bf, 9), + HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000376, 10)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x0000ddff, 16), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000034, 6), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000ddff, 16), HUFF_PACK(0x000001af, 9), + HUFF_PACK(0x0000007f, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x0000ddff, 16) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x0000002e, 6), HUFF_PACK(0x00000044, 7), + HUFF_PACK(0x00000086, 8), HUFF_PACK(0x0000069e, 11), + HUFF_PACK(0x0000043e, 11), HUFF_PACK(0x0000087a, 12)}, + {HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000002a, 6), HUFF_PACK(0x00000046, 7), + HUFF_PACK(0x0000015e, 9), HUFF_PACK(0x00000047, 7), + HUFF_PACK(0x0000034a, 10), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000000d6, 8), HUFF_PACK(0x00000026, 6), + HUFF_PACK(0x0000002f, 6), HUFF_PACK(0x000000d7, 8), + HUFF_PACK(0x0000006a, 7), HUFF_PACK(0x0000034e, 10), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x000002be, 10), HUFF_PACK(0x000001a6, 9), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000012, 5), + HUFF_PACK(0x000001bf, 9), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x000000d0, 8), + HUFF_PACK(0x0000043c, 11), HUFF_PACK(0x0000043f, 11)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000034b, 10), + HUFF_PACK(0x00000027, 6), HUFF_PACK(0x00000020, 6), + HUFF_PACK(0x00000042, 7), HUFF_PACK(0x000000d1, 8)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000087b, 12), + HUFF_PACK(0x000002bf, 10), HUFF_PACK(0x000000de, 8), + HUFF_PACK(0x000000ae, 8), HUFF_PACK(0x00000056, 7), + HUFF_PACK(0x00000016, 5), HUFF_PACK(0x00000014, 5)}, + {HUFF_PACK(0x0000087b, 12), HUFF_PACK(0x0000069f, 11), + HUFF_PACK(0x000001a4, 9), HUFF_PACK(0x0000010e, 9), + HUFF_PACK(0x00000045, 7), HUFF_PACK(0x0000006e, 7), + HUFF_PACK(0x0000001f, 5), HUFF_PACK(0x00000001, 2)}}, + HUFF_PACK(0x0000087b, 12) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[0][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x0000017e, 10), HUFF_PACK(0x000002fe, 11)}, + {HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 5), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00000016, 6)}, + {HUFF_PACK(0x0000000f, 5), HUFF_PACK(0x00000014, 6), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x000002ff, 11), + HUFF_PACK(0x00000015, 6), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000003fc, 10), HUFF_PACK(0x0000fffa, 16), + HUFF_PACK(0x000fff9e, 20), HUFF_PACK(0x000fff9f, 20)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x000000be, 9), HUFF_PACK(0x00007ffe, 15), + HUFF_PACK(0x0007ffce, 19), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x000003fd, 10), HUFF_PACK(0x0000fffb, 16), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000007e, 7), + HUFF_PACK(0x00001ffe, 13), HUFF_PACK(0x00007fff, 15), + HUFF_PACK(0x0000005e, 8), HUFF_PACK(0x0000000e, 5)}, + {HUFF_PACK(0x0000001f, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x0001fff2, 17), HUFF_PACK(0x00000ffc, 12), + HUFF_PACK(0x0000002e, 7), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x000000bf, 9), HUFF_PACK(0x0003ffe6, 18), + HUFF_PACK(0x0000fff8, 16), HUFF_PACK(0x00000ffd, 12), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000001e, 6), + HUFF_PACK(0x00000ffe, 12), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000fffe, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16)}, + {HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000008, 5), + HUFF_PACK(0x000007fe, 11), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000005a, 8)}, + {HUFF_PACK(0x00000006, 4), HUFF_PACK(0x0000007a, 7), + HUFF_PACK(0x00000164, 10), HUFF_PACK(0x00007ffa, 15), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00001fee, 13), HUFF_PACK(0x0000003c, 6)}, + {HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000002ce, 11), HUFF_PACK(0x000002cf, 11), + HUFF_PACK(0x00007ffb, 15), HUFF_PACK(0x00001fec, 13), + HUFF_PACK(0x000000b0, 9), HUFF_PACK(0x0000002e, 7)}, + {HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x00000165, 10), HUFF_PACK(0x00007ffc, 15), + HUFF_PACK(0x00001fef, 13), HUFF_PACK(0x000007fa, 11), + HUFF_PACK(0x000007f8, 11), HUFF_PACK(0x0000001f, 6)}, + {HUFF_PACK(0x0000002f, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x00001fed, 13), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffd, 15), HUFF_PACK(0x00000ff2, 12), + HUFF_PACK(0x000000b1, 9), HUFF_PACK(0x0000000a, 5)}, + {HUFF_PACK(0x00000009, 5), HUFF_PACK(0x00000166, 10), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x00007ffe, 15), HUFF_PACK(0x00003ffc, 14), + HUFF_PACK(0x0000005b, 8), HUFF_PACK(0x0000000e, 4)}, + {HUFF_PACK(0x0000007e, 7), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x0000ffff, 16), + HUFF_PACK(0x0000ffff, 16), HUFF_PACK(0x00000ff3, 12), + HUFF_PACK(0x000000f7, 8), HUFF_PACK(0x00000000, 2)}}, + HUFF_PACK(0x0000ffff, 16) /* escape */ + }}}, + { /* HUFF_ICC_TAB_2D[1][] */ + {/* HUFF_ICC_TAB_2D[1][0] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000037e, 10), HUFF_PACK(0x00000dfe, 12)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000de, 8), HUFF_PACK(0x000000dc, 8), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000006fe, 11), HUFF_PACK(0x00000dff, 12), + HUFF_PACK(0x00000036, 6), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000001b6, 9), HUFF_PACK(0x00001b7c, 13), + HUFF_PACK(0x0000dbfe, 16), HUFF_PACK(0x00036fff, 18)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001e, 5), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x00036ffe, 18), HUFF_PACK(0x0000036e, 10)}, + {HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x000000fe, 8), + HUFF_PACK(0x000000d8, 8), HUFF_PACK(0x000036fe, 14), + HUFF_PACK(0x000006de, 11), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x00001b7e, 13), + HUFF_PACK(0x000000d9, 8), HUFF_PACK(0x000000ff, 8)}, + {HUFF_PACK(0x000003f6, 10), HUFF_PACK(0x000006fe, 11), + HUFF_PACK(0x00006dfe, 15), HUFF_PACK(0x0000037e, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000001a, 5)}, + {HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x0001b7fe, 17), + HUFF_PACK(0x00001b7d, 13), HUFF_PACK(0x000007ef, 11), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00036fff, 18) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x0000000c, 4), + HUFF_PACK(0x000007ee, 11), HUFF_PACK(0x00001e7e, 13), + HUFF_PACK(0x00003cfe, 14), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15)}, + {HUFF_PACK(0x0000000e, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x000001e6, 9), HUFF_PACK(0x00001fbe, 13), + HUFF_PACK(0x000079fe, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000006fc, 11)}, + {HUFF_PACK(0x0000006c, 7), HUFF_PACK(0x000000f6, 8), + HUFF_PACK(0x000001ba, 9), HUFF_PACK(0x00000dfc, 12), + HUFF_PACK(0x00000dfd, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00000f3e, 12), HUFF_PACK(0x000001bb, 9)}, + {HUFF_PACK(0x000000dc, 8), HUFF_PACK(0x000001fe, 9), + HUFF_PACK(0x0000036e, 10), HUFF_PACK(0x000003fe, 10), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x00000fde, 12), + HUFF_PACK(0x000001ee, 9), HUFF_PACK(0x000000f2, 8)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x000001be, 9), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x00001fbf, 13), HUFF_PACK(0x000003ce, 10), + HUFF_PACK(0x000003ff, 10), HUFF_PACK(0x000000de, 8)}, + {HUFF_PACK(0x00000078, 7), HUFF_PACK(0x000000da, 8), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000006fd, 11), HUFF_PACK(0x0000036c, 10), + HUFF_PACK(0x000001ef, 9), HUFF_PACK(0x000000fe, 8)}, + {HUFF_PACK(0x0000036f, 10), HUFF_PACK(0x00000dfe, 12), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000036d, 10), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000dff, 12), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x000079ff, 15), + HUFF_PACK(0x000079ff, 15), HUFF_PACK(0x0000079e, 11), + HUFF_PACK(0x0000007a, 7), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x000079ff, 15) /* escape */ + }}, + {/* HUFF_ICC_TAB_2D[1][1] */ + { + /* LAV1_2D */ + {{HUFF_PACK(0x00000000, 1), HUFF_PACK(0x00000006, 3)}, + {HUFF_PACK(0x00000007, 3), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV3_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x000000fc, 8), HUFF_PACK(0x00000fde, 12)}, + {HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000d, 4), + HUFF_PACK(0x000001fe, 9), HUFF_PACK(0x000007ee, 11)}, + {HUFF_PACK(0x000001fa, 9), HUFF_PACK(0x000001ff, 9), + HUFF_PACK(0x000000fe, 8), HUFF_PACK(0x0000003e, 6)}, + {HUFF_PACK(0x00000fdf, 12), HUFF_PACK(0x000003f6, 10), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x00000000, 1)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV5_2D */ + {{HUFF_PACK(0x00000000, 2), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000003a, 7), HUFF_PACK(0x00000676, 11), + HUFF_PACK(0x000019fe, 13), HUFF_PACK(0x0000cebe, 16)}, + {HUFF_PACK(0x0000000f, 4), HUFF_PACK(0x00000002, 3), + HUFF_PACK(0x0000001e, 6), HUFF_PACK(0x000000fe, 9), + HUFF_PACK(0x000019d6, 13), HUFF_PACK(0x0000675e, 15)}, + {HUFF_PACK(0x0000003e, 7), HUFF_PACK(0x00000032, 6), + HUFF_PACK(0x00000018, 5), HUFF_PACK(0x0000033e, 10), + HUFF_PACK(0x00000cfe, 12), HUFF_PACK(0x00000677, 11)}, + {HUFF_PACK(0x00000674, 11), HUFF_PACK(0x0000019c, 9), + HUFF_PACK(0x000000ff, 9), HUFF_PACK(0x0000003b, 7), + HUFF_PACK(0x0000001c, 6), HUFF_PACK(0x0000007e, 8)}, + {HUFF_PACK(0x000033fe, 14), HUFF_PACK(0x000033ff, 14), + HUFF_PACK(0x00000cea, 12), HUFF_PACK(0x00000066, 7), + HUFF_PACK(0x0000001a, 5), HUFF_PACK(0x00000006, 4)}, + {HUFF_PACK(0x0000cebf, 16), HUFF_PACK(0x000033ae, 14), + HUFF_PACK(0x0000067e, 11), HUFF_PACK(0x0000019e, 9), + HUFF_PACK(0x0000001b, 5), HUFF_PACK(0x00000002, 2)}}, + HUFF_PACK(0x00000000, 0) /* escape */ + }, + { + /* LAV7_2D */ + {{HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000002, 4), + HUFF_PACK(0x000000fe, 9), HUFF_PACK(0x000007be, 12), + HUFF_PACK(0x00000ffc, 13), HUFF_PACK(0x00000ffd, 13), + HUFF_PACK(0x00001efe, 15), HUFF_PACK(0x00003dfe, 16)}, + {HUFF_PACK(0x00000004, 4), HUFF_PACK(0x00000000, 3), + HUFF_PACK(0x0000003c, 7), HUFF_PACK(0x000000f6, 10), + HUFF_PACK(0x000001da, 11), HUFF_PACK(0x000003fe, 12), + HUFF_PACK(0x00003dfe, 15), HUFF_PACK(0x00003dff, 16)}, + {HUFF_PACK(0x0000003c, 8), HUFF_PACK(0x0000003e, 7), + HUFF_PACK(0x0000000a, 5), HUFF_PACK(0x0000003a, 8), + HUFF_PACK(0x000003de, 11), HUFF_PACK(0x000007be, 13), + HUFF_PACK(0x00000f7e, 14), HUFF_PACK(0x00001efe, 14)}, + {HUFF_PACK(0x000001de, 11), HUFF_PACK(0x000000ec, 10), + HUFF_PACK(0x0000007e, 9), HUFF_PACK(0x0000000c, 5), + HUFF_PACK(0x000001ee, 10), HUFF_PACK(0x00000f7e, 13), + HUFF_PACK(0x000007fc, 12), HUFF_PACK(0x00003dff, 15)}, + {HUFF_PACK(0x00007ffe, 16), HUFF_PACK(0x000003be, 12), + HUFF_PACK(0x000000fe, 10), HUFF_PACK(0x000001fe, 10), + HUFF_PACK(0x0000001a, 6), HUFF_PACK(0x0000001c, 7), + HUFF_PACK(0x000007fd, 12), HUFF_PACK(0x00000ffe, 13)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x000003bf, 12), + HUFF_PACK(0x00001ffe, 14), HUFF_PACK(0x000003ff, 12), + HUFF_PACK(0x0000003e, 8), HUFF_PACK(0x0000001b, 6), + HUFF_PACK(0x0000007e, 8), HUFF_PACK(0x000000f6, 9)}, + {HUFF_PACK(0x00007fff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x00003ffe, 15), HUFF_PACK(0x000001db, 11), + HUFF_PACK(0x000000ee, 10), HUFF_PACK(0x0000007a, 8), + HUFF_PACK(0x0000000e, 5), HUFF_PACK(0x0000000b, 5)}, + {HUFF_PACK(0x00003dff, 16), HUFF_PACK(0x00003dff, 16), + HUFF_PACK(0x000003de, 12), HUFF_PACK(0x000001fe, 11), + HUFF_PACK(0x000001ee, 11), HUFF_PACK(0x0000007a, 9), + HUFF_PACK(0x00000006, 5), HUFF_PACK(0x00000003, 2)}}, + HUFF_PACK(0x00003dff, 16) /* escape */ + }}}}}; + +const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab = { + {/* CLD */ + HUFF_PACK(0x00000052, 8), HUFF_PACK(0x000000ae, 9), + HUFF_PACK(0x000000af, 9), HUFF_PACK(0x00000028, 7), + HUFF_PACK(0x0000006e, 7), HUFF_PACK(0x00000036, 6), + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x0000000c, 4), HUFF_PACK(0x0000000a, 4), + HUFF_PACK(0x00000002, 4), HUFF_PACK(0x00000016, 5), + HUFF_PACK(0x00000012, 5), HUFF_PACK(0x00000017, 5), + HUFF_PACK(0x00000000, 4), HUFF_PACK(0x00000004, 4), + HUFF_PACK(0x00000006, 4), HUFF_PACK(0x00000008, 4), + HUFF_PACK(0x00000007, 4), HUFF_PACK(0x00000003, 4), + HUFF_PACK(0x00000001, 4), HUFF_PACK(0x0000001a, 5), + HUFF_PACK(0x00000013, 5), HUFF_PACK(0x0000003e, 6), + HUFF_PACK(0x00000016, 6), HUFF_PACK(0x00000017, 6), + HUFF_PACK(0x0000006f, 7), HUFF_PACK(0x0000002a, 7), + HUFF_PACK(0x00000056, 8), HUFF_PACK(0x00000053, 8), + HUFF_PACK(0x0000003f, 6)}, + {/* ICC */ + HUFF_PACK(0x0000001e, 5), HUFF_PACK(0x0000000e, 4), + HUFF_PACK(0x00000006, 3), HUFF_PACK(0x00000000, 2), + HUFF_PACK(0x00000002, 2), HUFF_PACK(0x00000001, 2), + HUFF_PACK(0x0000003e, 6), HUFF_PACK(0x0000003f, 6)}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ diff --git a/fdk-aac/libSACenc/src/sacenc_huff_tab.h b/fdk-aac/libSACenc/src/sacenc_huff_tab.h new file mode 100644 index 0000000..7d6c331 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_huff_tab.h @@ -0,0 +1,222 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Markus Lohwasser + + Description: SAC-Encoder constant huffman tables + +*******************************************************************************/ + +#ifndef SACENC_HUFF_TAB_H +#define SACENC_HUFF_TAB_H + +/* Includes ******************************************************************/ +#include "machine_type.h" + +/* Defines *******************************************************************/ +#define HUFF_PACK(a, b) \ + { \ + ((((ULONG)a) & 0x00FFFFFF) << 8) | (((ULONG)b) & 0xFF) \ + } /*!< Pack huffman value and length information. */ +#define HUFF_VALUE(a) \ + (((a.packed >> 8) & 0x00FFFFFF)) /*!< Return value from packed table entry. \ + */ +#define HUFF_LENGTH(a) \ + ((a.packed & 0xFF)) /*!< Return length from packed table entry. */ + +/* Data Types ****************************************************************/ +/** + * \brief This struct contains packed huffman entries. + * + * The packed entry consist of hffman value and length information. + * + * |---------------------------------| + * | value | length | + * |---------------------------------| + * |<------- 31...8 ------->|< 7..0 >| + */ +typedef struct { + ULONG packed; /*! Packed huffman entry: + - lower 8 bit are reservoed for length information + - upper 24 bit contains huffman value */ +} HUFF_ENTRY; + +typedef struct { + HUFF_ENTRY entry[2][2]; + HUFF_ENTRY escape; + +} LAV1_2D; + +typedef struct { + HUFF_ENTRY entry[4][4]; + HUFF_ENTRY escape; + +} LAV3_2D; + +typedef struct { + HUFF_ENTRY entry[6][6]; + HUFF_ENTRY escape; + +} LAV5_2D; + +typedef struct { + HUFF_ENTRY entry[7][7]; + HUFF_ENTRY escape; + +} LAV6_2D; + +typedef struct { + HUFF_ENTRY entry[8][8]; + HUFF_ENTRY escape; + +} LAV7_2D; + +typedef struct { + HUFF_ENTRY entry[10][10]; + HUFF_ENTRY escape; + +} LAV9_2D; + +typedef struct { + HUFF_ENTRY entry[13][13]; + HUFF_ENTRY escape; + +} LAV12_2D; + +typedef struct { + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + LAV9_2D lav9; + +} HUFF_CLD_TAB_2D; + +typedef struct { + LAV1_2D lav1; + LAV3_2D lav3; + LAV5_2D lav5; + LAV7_2D lav7; + +} HUFF_ICC_TAB_2D; + +typedef struct { + HUFF_ENTRY h1D[2][31]; + HUFF_CLD_TAB_2D h2D[2][2]; + +} HUFF_CLD_TABLE; + +typedef struct { + HUFF_ENTRY h1D[2][8]; + HUFF_ICC_TAB_2D h2D[2][2]; + +} HUFF_ICC_TABLE; + +typedef struct { + HUFF_ENTRY cld[31]; + HUFF_ENTRY icc[8]; + +} HUFF_PT0_TABLE; + +typedef HUFF_ENTRY HUFF_RES_TABLE[5][8]; + +/* Constants *****************************************************************/ +extern const HUFF_CLD_TABLE fdk_sacenc_huffCLDTab; +extern const HUFF_ICC_TABLE fdk_sacenc_huffICCTab; +extern const HUFF_PT0_TABLE fdk_sacenc_huffPart0Tab; + +/* Function / Class Declarations *********************************************/ + +#endif /* SACENC_HUFF_TAB_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_lib.cpp b/fdk-aac/libSACenc/src/sacenc_lib.cpp new file mode 100644 index 0000000..d6a1658 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_lib.cpp @@ -0,0 +1,2042 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Interface to Spacial Audio Coding Encoder lib + +*******************************************************************************/ + +/**************************************************************************** +\file +Description of file contents +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "genericStds.h" +#include "FDK_core.h" +#include "sacenc_tree.h" +#include "sacenc_bitstream.h" +#include "sacenc_onsetdetect.h" +#include "sacenc_framewindowing.h" +#include "sacenc_filter.h" +#include "sacenc_paramextract.h" +#include "sacenc_staticgain.h" +#include "sacenc_delay.h" +#include "sacenc_dmx_tdom_enh.h" +#include "sacenc_vectorfunctions.h" +#include "qmf.h" + +/* Defines *******************************************************************/ + +/* Encoder library info */ +#define SACENC_LIB_VL0 2 +#define SACENC_LIB_VL1 0 +#define SACENC_LIB_VL2 0 +#define SACENC_LIB_TITLE "MPEG Surround Encoder" +#ifdef __ANDROID__ +#define SACENC_LIB_BUILD_DATE "" +#define SACENC_LIB_BUILD_TIME "" +#else +#define SACENC_LIB_BUILD_DATE __DATE__ +#define SACENC_LIB_BUILD_TIME __TIME__ +#endif + +#define MAX_MPEGS_BYTES (1 << 14) +#define MAX_SSC_BYTES (1 << 6) + +#define MAX_SPACE_TREE_CHANNELS 2 +#define NUM_KEEP_WINDOWS 3 + +/* Data Types ****************************************************************/ +typedef struct { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_BANDS_CONFIG nParamBands; + MP4SPACEENC_QUANTMODE quantMode; + UCHAR bUseCoarseQuant; + UCHAR bLdMode; + UCHAR bTimeDomainDmx; + UINT sampleRate; + UINT frameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UINT independencyFactor; /* how often should we set the independency flag */ + INT timeAlignment; /* additional delay for downmix */ + +} MP4SPACEENC_SETUP, *HANDLE_MP4SPACEENC_SETUP; + +struct ENC_CONFIG_SETUP { + UCHAR bEncMode_212; + UCHAR maxHybridInStaticSlots; + LONG maxSamplingrate; + INT maxAnalysisLengthTimeSlots; + INT maxHybridBands; + INT maxQmfBands; + INT maxChIn; + INT maxFrameTimeSlots; + INT maxFrameLength; + INT maxChOut; + INT maxChTotOut; +}; + +struct MP4SPACE_ENCODER { + MP4SPACEENC_SETUP user; + + ENC_CONFIG_SETUP setup; /* describe allocated instance */ + + HANDLE_FRAMEWINDOW + hFrameWindow; /* Windowing, only created+updated, but not used */ + INT nSamplesValid; /* Input Buffer Handling */ + + /* Routing Sensible Switches/Variables */ + MP4SPACEENC_BANDS_CONFIG nParamBands; + UCHAR useTimeDomDownmix; + + /* not Routing Sensible Switches/Varibles - must be contained in Check */ + MP4SPACEENC_MODE encMode; + UCHAR bEncMode_212_only; + + /* not Routing Sensible Switches/Varibles + lower Classes */ + UCHAR useFrameKeep; + UINT independencyFactor; + UINT nSampleRate; + UCHAR nInputChannels; + UCHAR nOutputChannels; + UCHAR nFrameTimeSlots; /* e.g. 32 when used with HE-AAC */ + UCHAR nQmfBands; + UCHAR nHybridBands; + UINT nFrameLength; /* number of output waveform samples/channel/frame */ + + /* not Routing Sensible Switches/Varibles + lower Classes, secondary computed + */ + INT nSamplesNext; + INT nAnalysisLengthTimeSlots; + INT nAnalysisLookaheadTimeSlots; + INT nUpdateHybridPositionTimeSlots; + INT *pnOutputBits; + INT nInputDelay; + INT nOutputBufferDelay; + INT nSurroundAnalysisBufferDelay; + INT nBitstreamDelayBuffer; + INT nBitstreamBufferRead; + INT nBitstreamBufferWrite; + INT nDiscardOutFrames; + INT avoid_keep; + + /* not Routing Sensible Switches/Varibles -> moved to lower Classes */ + UCHAR useCoarseQuantCld; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantIcc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantCpc; /* Only Used in SpaceTreeSetup */ + UCHAR useCoarseQuantArbDmx; /* ArbitraryDmx,... not available yet */ + MP4SPACEENC_QUANTMODE + quantMode; /* Used for quanitzation and in bitstream writer */ + INT coreCoderDelay; /* Used in delay compensation */ + INT timeAlignment; /* Used in delay compensation */ + + /* Local Processing Variables */ + INT independencyCount; + INT independencyFlag; + INT **ppTrCurrPos; /* belongs somehow to Onset Detection */ + INT trPrevPos[2 * MAX_NUM_TRANS]; /* belongs somehow to Onset Detection */ + + FRAMEWIN_LIST frameWinList; + SPATIALFRAME saveFrame; + + /* Module-Handles */ + SPACE_TREE_SETUP spaceTreeSetup; + MPEG4SPACEENC_SSCBUF sscBuf; + FIXP_WIN *pFrameWindowAna__FDK[MAX_NUM_PARAMS]; + HANDLE_QMF_FILTER_BANK *phQmfFiltIn__FDK; + HANDLE_DC_FILTER phDCFilterSigIn[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_ONSET_DETECT phOnset[SACENC_MAX_INPUT_CHANNELS]; + HANDLE_SPACE_TREE hSpaceTree; + HANDLE_BSF_INSTANCE hBitstreamFormatter; + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig; + HANDLE_STATIC_GAIN hStaticGain; + HANDLE_DELAY hDelay; + + /* enhanced time domain downmix (for stereo input) */ + HANDLE_ENHANCED_TIME_DOMAIN_DMX hEnhancedTimeDmx; + + /* Data Buffers */ + INT_PCM **ppTimeSigIn__FDK; + INT_PCM **ppTimeSigDelayIn__FDK; + INT_PCM **ppTimeSigOut__FDK; + FIXP_DPK ***pppHybridIn__FDK; + FIXP_DPK ***pppHybridInStatic__FDK; + FIXP_DPK ***pppProcDataIn__FDK; + INT_PCM *pOutputDelayBuffer__FDK; + + UCHAR **ppBitstreamDelayBuffer; + + UCHAR *pParameterBand2HybridBandOffset; + INT staticGainScale; + + INT *pEncoderInputChScale; + INT *staticTimeDomainDmxInScale; +}; + +/* Constants *****************************************************************/ +static const UCHAR pValidBands_Ld[8] = {4, 5, 7, 9, 12, 15, 23, 40}; + +static const UCHAR qmf2qmf[] = /* Bypass the HybridAnylyis/Synthesis*/ + {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, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, + 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +/* Function / Class Declarations *********************************************/ +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc); + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc); + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc); + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig(const MP4SPACEENC_MODE encMode); + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands); + +/* Function / Class Definition ***********************************************/ +static UINT mp4SpaceEnc_GetNumQmfBands(const UINT nSampleRate) { + UINT nQmfBands = 0; + + if (nSampleRate < 27713) + nQmfBands = 32; + else if (nSampleRate < 55426) + nQmfBands = 64; + + return nQmfBands; +} + +static UINT updateQmfFlags(const UINT flags, const INT keepStates) { + UINT qmfFlags = flags; + + qmfFlags = (qmfFlags & (~(UINT)QMF_FLAG_LP)); + qmfFlags = (qmfFlags | QMF_FLAG_MPSLDFB); + qmfFlags = (keepStates) ? (qmfFlags | QMF_FLAG_KEEP_STATES) + : (qmfFlags & (~(UINT)QMF_FLAG_KEEP_STATES)); + + return qmfFlags; +} + +static INT freq2HybridBand(const UINT nFrequency, const UINT nSampleRate, + const UINT nQmfBands) { + /* + nQmfSlotWidth = (nSampleRate/2) / nQmfBands; + nQmfBand = nFrequency / nQmfSlotWidth; + */ + int nHybridBand = -1; + int scale = 0; + const FIXP_DBL temp = fDivNorm((FIXP_DBL)(2 * nFrequency * nQmfBands), + (FIXP_DBL)nSampleRate, &scale); + const int nQmfBand = scaleValue(temp, scale - (DFRACT_BITS - 1)); + + if ((nQmfBand > -1) && (nQmfBand < (int)nQmfBands)) { + nHybridBand = qmf2qmf[nQmfBand]; + } + + return nHybridBand; +} + +/* + * Examine buffer descriptor regarding choosen type. + * + * \param pBufDesc Pointer to buffer descriptor + * \param type Buffer type to look for. + + * \return - Buffer descriptor index. + * -1, if there is no entry available. + */ +static INT getBufDescIdx(const FDK_bufDescr *pBufDesc, const UINT type) { + INT i, idx = -1; + + for (i = 0; i < (int)pBufDesc->numBufs; i++) { + if (pBufDesc->pBufType[i] == type) { + idx = i; + break; + } + } + return idx; +} + +FDK_SACENC_ERROR FDK_sacenc_open(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + return mp4SpaceEnc_create(phMp4SpaceEnc); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_create( + HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_MP4SPACE_ENCODER hEnc = NULL; + ENC_CONFIG_SETUP setup; + + if (NULL == phMp4SpaceEnc) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ch; + FDKmemclear(&setup, sizeof(ENC_CONFIG_SETUP)); + + /* Allocate Encoder Instance */ + FDK_ALLOCATE_MEMORY_1D(hEnc, 1, struct MP4SPACE_ENCODER); + + /* Clear everything, also pointers. */ + if (NULL != hEnc) { + FDKmemclear(hEnc, sizeof(struct MP4SPACE_ENCODER)); + } + + setup.maxSamplingrate = 48000; + setup.maxFrameTimeSlots = 16; + + setup.maxAnalysisLengthTimeSlots = 3 * setup.maxFrameTimeSlots; + setup.maxQmfBands = mp4SpaceEnc_GetNumQmfBands(setup.maxSamplingrate); + ; + setup.maxHybridBands = setup.maxQmfBands; + setup.maxFrameLength = setup.maxQmfBands * setup.maxFrameTimeSlots; + + setup.maxChIn = 2; + setup.maxChOut = 1; + setup.maxChTotOut = setup.maxChOut; + setup.bEncMode_212 = 1; + setup.maxHybridInStaticSlots = 24; + + /* Open Static Gain*/ + if (SACENC_OK != + (error = fdk_sacenc_staticGain_OpenConfig(&hEnc->hStaticGainConfig))) { + goto bail; + } + + /* enhanced time domain downmix (for stereo input) */ + if (SACENC_OK != (error = fdk_sacenc_open_enhancedTimeDomainDmx( + &hEnc->hEnhancedTimeDmx, setup.maxFrameLength))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset, + MAX_NUM_PARAM_BANDS, UCHAR); + + /* Create Space Tree first, to get number of in-/output channels */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_Open(&hEnc->hSpaceTree))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->pEncoderInputChScale, setup.maxChIn, INT); + FDK_ALLOCATE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale, setup.maxChIn, + INT); + + FDK_ALLOCATE_MEMORY_1D(hEnc->phQmfFiltIn__FDK, setup.maxChIn, + HANDLE_QMF_FILTER_BANK); + + /* Allocate Analysis Filterbank Structs */ + for (ch = 0; ch < setup.maxChIn; ch++) { + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch], 1, + struct QMF_FILTER_BANK, SECT_DATA_L2) + FDK_ALLOCATE_MEMORY_1D_INT(hEnc->phQmfFiltIn__FDK[ch]->FilterStates, + 2 * 5 * setup.maxQmfBands, FIXP_QAS, + SECT_DATA_L2) + } + + /* Allocate Synthesis Filterbank Structs for arbitrary downmix */ + + /* Allocate DC Filter Struct for normal signal input */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != + (error = fdk_sacenc_createDCFilter(&hEnc->phDCFilterSigIn[ch]))) { + goto bail; + } + } + + /* Open Onset Detection */ + for (ch = 0; ch < setup.maxChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Open( + &hEnc->phOnset[ch], setup.maxFrameTimeSlots))) { + goto bail; + } + } + + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTrCurrPos, setup.maxChIn, MAX_NUM_TRANS, + INT); + + /* Create Windowing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_Create(&hEnc->hFrameWindow))) { + goto bail; + } + + /* Open static gain */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Open(&hEnc->hStaticGain))) { + goto bail; + } + + /* create bitstream encoder */ + if (SACENC_OK != (error = fdk_sacenc_createSpatialBitstreamEncoder( + &hEnc->hBitstreamFormatter))) { + goto bail; + } + + FDK_ALLOCATE_MEMORY_1D(hEnc->sscBuf.pSsc, MAX_SSC_BYTES, UCHAR); + + { + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigIn__FDK, setup.maxChIn, + setup.maxFrameLength + MAX_DELAY_SURROUND_ANALYSIS, + INT_PCM); + } + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK, setup.maxChIn, + MAX_DELAY_SURROUND_ANALYSIS, INT_PCM); + + /* Create new buffers for several signals (including arbitrary downmix) */ + if (setup.bEncMode_212 == 0) { + /* pOutputDelayBuffer__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_1D( + hEnc->pOutputDelayBuffer__FDK, + (setup.maxFrameLength + MAX_DELAY_OUTPUT) * setup.maxChOut, INT_PCM); + } + + /* allocate buffers */ + if (setup.bEncMode_212 == 0) { + /* ppTimeSigOut__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppTimeSigOut__FDK, setup.maxChTotOut, + setup.maxFrameLength, INT_PCM); + } + + if (setup.bEncMode_212 == 1) { + /* pppHybridIn__FDK buffer can be reduced by maxFrameTimeSlots/2 slots for + * SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D( + hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots - (setup.maxFrameTimeSlots >> 1), + setup.maxHybridBands, FIXP_DPK); + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridInStatic__FDK, setup.maxChIn, + setup.maxHybridInStaticSlots, setup.maxHybridBands, + FIXP_DPK); + } else { + FDK_ALLOCATE_MEMORY_3D(hEnc->pppHybridIn__FDK, setup.maxChIn, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + + if (setup.bEncMode_212 == 0) { + /* pppProcDataIn__FDK buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_3D(hEnc->pppProcDataIn__FDK, MAX_SPACE_TREE_CHANNELS, + setup.maxAnalysisLengthTimeSlots, + setup.maxHybridBands, FIXP_DPK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + FDK_ALLOCATE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i], + setup.maxAnalysisLengthTimeSlots, FIXP_WIN); + } /* for i */ + + if (SACENC_OK != (error = fdk_sacenc_delay_Open(&hEnc->hDelay))) { + goto bail; + } + + if (setup.bEncMode_212 == 0) { + /* ppBitstreamDelayBuffer buffer is not needed for SACENC_212 mode */ + FDK_ALLOCATE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer, MAX_BITSTREAM_DELAY, + MAX_MPEGS_BYTES, UCHAR); + } + FDK_ALLOCATE_MEMORY_1D(hEnc->pnOutputBits, MAX_BITSTREAM_DELAY, INT); + + hEnc->setup = setup; /* save configuration used while encoder allocation. */ + mp4SpaceEnc_InitDefault(hEnc); + + if (NULL != phMp4SpaceEnc) { + *phMp4SpaceEnc = hEnc; /* return encoder handle */ + } + + } /* valid handle */ + + return error; + +bail: + if (NULL != hEnc) { + hEnc->setup = setup; + FDK_sacenc_close(&hEnc); + } + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitDefault(HANDLE_MP4SPACE_ENCODER hEnc) { + FDK_SACENC_ERROR err = SACENC_OK; + + /* Get default static gain configuration. */ + if (SACENC_OK != (err = fdk_sacenc_staticGain_InitDefaultConfig( + hEnc->hStaticGainConfig))) { + goto bail; + } + +bail: + return err; +} + +static FDK_SACENC_ERROR FDK_sacenc_configure( + HANDLE_MP4SPACE_ENCODER hEnc, const HANDLE_MP4SPACEENC_SETUP hSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + hEnc->nSampleRate = hSetup->sampleRate; + hEnc->encMode = hSetup->encMode; + hEnc->nQmfBands = mp4SpaceEnc_GetNumQmfBands(hEnc->nSampleRate); + + /* Make sure that we have set time domain downmix for 212 */ + if (hSetup->encMode == SACENC_212 && hSetup->bTimeDomainDmx == 0) { + error = SACENC_INVALID_CONFIG; + } else { + hEnc->useTimeDomDownmix = hSetup->bTimeDomainDmx; + } + + hEnc->timeAlignment = hSetup->timeAlignment; + hEnc->quantMode = hSetup->quantMode; + + hEnc->useCoarseQuantCld = hSetup->bUseCoarseQuant; + hEnc->useCoarseQuantCpc = hSetup->bUseCoarseQuant; + hEnc->useFrameKeep = (hSetup->bLdMode == 2); + hEnc->useCoarseQuantIcc = 0; /* not available */ + hEnc->useCoarseQuantArbDmx = 0; /* not available for user right now */ + hEnc->independencyFactor = hSetup->independencyFactor; + hEnc->independencyCount = 0; + hEnc->independencyFlag = 1; + + /* set number of Hybrid bands */ + hEnc->nHybridBands = hEnc->nQmfBands; + hEnc->nFrameTimeSlots = hSetup->frameTimeSlots; + mp4SpaceEnc_InitNumParamBands(hEnc, hSetup->nParamBands); + + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_init(HANDLE_MP4SPACE_ENCODER hEnc, + const INT dmxDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Checks */ + if (NULL == hEnc) { + error = SACENC_INVALID_HANDLE; + } else { + const int initStatesFlag = 1; + + int ch; /* loop counter */ + int nChInArbDmx; + + if (SACENC_OK != (error = FDK_sacenc_configure(hEnc, &hEnc->user))) { + goto bail; + } + + hEnc->bEncMode_212_only = hEnc->setup.bEncMode_212; + + /* Slots per Frame and Frame Length */ + if (hEnc->nFrameTimeSlots < 1) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + hEnc->nFrameLength = hEnc->nQmfBands * hEnc->nFrameTimeSlots; + + if (hEnc->useFrameKeep == 1) { + hEnc->nAnalysisLengthTimeSlots = 3 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = hEnc->nFrameTimeSlots; + } else { + hEnc->nAnalysisLengthTimeSlots = 2 * hEnc->nFrameTimeSlots; + hEnc->nUpdateHybridPositionTimeSlots = 0; + } + + { + hEnc->nAnalysisLookaheadTimeSlots = + hEnc->nAnalysisLengthTimeSlots - 3 * hEnc->nFrameTimeSlots / 2; + } + + /* init parameterBand2hybridBandOffset table */ + fdk_sacenc_calcParameterBand2HybridBandOffset( + (BOX_SUBBAND_CONFIG)hEnc->nParamBands, hEnc->nHybridBands, + hEnc->pParameterBand2HybridBandOffset); + + /* Fill Setup structure for Space Tree */ + if (SACENC_OK != + (error = mp4SpaceEnc_FillSpaceTreeSetup(hEnc, &hEnc->spaceTreeSetup))) { + goto bail; + } + + /* Init space tree configuration */ + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Init( + hEnc->hSpaceTree, &hEnc->spaceTreeSetup, + hEnc->pParameterBand2HybridBandOffset, hEnc->useFrameKeep))) { + goto bail; + } + + /* Get space tree description and resulting number of input/output channels + */ + { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + hEnc->nInputChannels = + spaceTreeDescription.nOutChannels; /* space tree description + describes decoder + configuration */ + hEnc->nOutputChannels = + spaceTreeDescription.nInChannels; /* space tree description + describes decoder + configuration */ + } + + nChInArbDmx = 0; + + /* INITIALIZATION */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + /* scaling in analysis qmf filterbank (7) */ + hEnc->pEncoderInputChScale[ch] = 7; + + { + /* additional scaling in qmf prototype filter for low delay */ + hEnc->pEncoderInputChScale[ch] += 1; + } + + { hEnc->pEncoderInputChScale[ch] += DC_FILTER_SF; } + } /* nInputChannels */ + + /* Init analysis filterbank */ + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->phQmfFiltIn__FDK[ch]->flags = + updateQmfFlags(hEnc->phQmfFiltIn__FDK[ch]->flags, !initStatesFlag); + + if (0 != qmfInitAnalysisFilterBank( + hEnc->phQmfFiltIn__FDK[ch], + (FIXP_QAS *)hEnc->phQmfFiltIn__FDK[ch]->FilterStates, 1, + hEnc->nQmfBands, hEnc->nQmfBands, hEnc->nQmfBands, + hEnc->phQmfFiltIn__FDK[ch]->flags)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + + /* Initialize DC Filter. */ + { + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_initDCFilter( + hEnc->phDCFilterSigIn[ch], hEnc->nSampleRate))) { + goto bail; + } + } + } + + /* Init onset detect. */ + { + /* init onset detect configuration struct */ + ONSET_DETECT_CONFIG onsetDetectConfig; + onsetDetectConfig.maxTimeSlots = hEnc->nFrameTimeSlots; + onsetDetectConfig.lowerBoundOnsetDetection = + freq2HybridBand(1725, hEnc->nSampleRate, hEnc->nQmfBands); + onsetDetectConfig.upperBoundOnsetDetection = hEnc->nHybridBands; + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Init( + hEnc->phOnset[ch], &onsetDetectConfig, 1))) { + goto bail; + } + } + } + + { + /* init windowing */ + FRAMEWINDOW_CONFIG framewindowConfig; + framewindowConfig.nTimeSlotsMax = hEnc->nFrameTimeSlots; + framewindowConfig.bFrameKeep = hEnc->useFrameKeep; + + if (SACENC_OK != (error = fdk_sacenc_frameWindow_Init( + hEnc->hFrameWindow, &framewindowConfig))) { + goto bail; + } + } + + /* Set encoder mode for static gain initialization. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_SetEncMode( + hEnc->hStaticGainConfig, hEnc->encMode))) { + goto bail; + } + + /* Init static gain. */ + if (SACENC_OK != (error = fdk_sacenc_staticGain_Init( + hEnc->hStaticGain, hEnc->hStaticGainConfig, + &(hEnc->staticGainScale)))) { + goto bail; + } + + for (ch = 0; ch < hEnc->nInputChannels; ch++) { + hEnc->pEncoderInputChScale[ch] += hEnc->staticGainScale; + } + + /* enhanced downmix for stereo input*/ + if (hEnc->useTimeDomDownmix != 0) { + if (SACENC_OK != (error = fdk_sacenc_init_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, + fdk_sacenc_getPreGainPtrFDK(hEnc->hStaticGain), + hEnc->staticGainScale, + fdk_sacenc_getPostGainFDK(hEnc->hStaticGain), + hEnc->staticGainScale, hEnc->nFrameLength))) { + goto bail; + } + } + + /* Create config structure for bitstream formatter including arbitrary + * downmix residual */ + if (SACENC_OK != (error = fdk_sacenc_initSpatialBitstreamEncoder( + hEnc->hBitstreamFormatter))) { + goto bail; + } + + if (SACENC_OK != (error = FillSpatialSpecificConfig( + hEnc, fdk_sacenc_getSpatialSpecificConfig( + hEnc->hBitstreamFormatter)))) { + goto bail; + } + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialSpecificConfig( + fdk_sacenc_getSpatialSpecificConfig(hEnc->hBitstreamFormatter), + hEnc->sscBuf.pSsc, MAX_SSC_BYTES, &hEnc->sscBuf.nSscSizeBits))) { + goto bail; + } + + /* init delay compensation with dmx core coder delay; if no core coder is + * used, many other buffers are initialized nevertheless */ + if (SACENC_OK != + (error = mp4SpaceEnc_InitDelayCompensation(hEnc, dmxDelay))) { + goto bail; + } + + /* How much input do we need? */ + hEnc->nSamplesNext = + hEnc->nFrameLength * (hEnc->nInputChannels + nChInArbDmx); + hEnc->nSamplesValid = 0; + } /* valid handle */ + +bail: + return error; +} + +static INT getAnalysisLengthTimeSlots(FIXP_WIN *pFrameWindowAna, + INT nTimeSlots) { + int i; + for (i = nTimeSlots - 1; i >= 0; i--) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + nTimeSlots = i + 1; + return nTimeSlots; +} + +static INT getAnalysisStartTimeSlot(FIXP_WIN *pFrameWindowAna, INT nTimeSlots) { + int startTimeSlot = 0; + int i; + for (i = 0; i < nTimeSlots; i++) { + if (pFrameWindowAna[i] != (FIXP_WIN)0) { + break; + } + } + startTimeSlot = i; + return startTimeSlot; +} + +static FDK_SACENC_ERROR __FeedDeinterPreScale( + HANDLE_MP4SPACE_ENCODER hEnc, INT_PCM const *const pSamples, + INT_PCM *const pOutputSamples, INT const nSamples, + UINT const isInputInterleaved, UINT const inputBufferSizePerChannel, + UINT *const pnSamplesFed) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hEnc == NULL) || (pSamples == NULL) || (pnSamplesFed == NULL)) { + error = SACENC_INVALID_HANDLE; + } else if (nSamples == 0) { + error = SACENC_INVALID_CONFIG; /* Flushing not implemented */ + } else { + int ch; + const INT nChIn = hEnc->nInputChannels; + const INT nChInWithDmx = nChIn; + const INT samplesToFeed = + FDKmin(nSamples, hEnc->nSamplesNext - hEnc->nSamplesValid); + const INT nSamplesPerChannel = samplesToFeed / nChInWithDmx; + + if ((samplesToFeed < 0) || (samplesToFeed % nChInWithDmx != 0) || + (samplesToFeed > nChInWithDmx * (INT)hEnc->nFrameLength)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + int i; + + const INT_PCM *pInput__FDK; + const INT_PCM *pInput2__FDK; + + { /* no dmx align = default*/ + pInput__FDK = pSamples; + pInput2__FDK = pSamples + (hEnc->nInputDelay * nChInWithDmx); + } + + for (i = 0; i < hEnc->nInputChannels; i++) { + hEnc->staticTimeDomainDmxInScale[i] = hEnc->staticGainScale; + } + + /***** N-channel-input *****/ + for (ch = 0; ch < nChIn; ch++) { + /* Write delayed time signal into time signal buffer */ + FDKmemcpy(&(hEnc->ppTimeSigIn__FDK[ch][0]), + &(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + + if (isInputInterleaved) { + /* Add the new frame de-interleaved. Apply nSurroundAnalysisBufferDelay. + */ + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + 1, pInput__FDK + ch, nChInWithDmx, hEnc->nInputDelay); + FDKmemcpy_flex( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + 1, pInput2__FDK + ch, nChInWithDmx, + nSamplesPerChannel - hEnc->nInputDelay); + } else { + /* Input is already deinterleaved, just copy */ + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay]), + pInput__FDK + ch * inputBufferSizePerChannel, + hEnc->nInputDelay * sizeof(INT_PCM)); + FDKmemcpy( + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nSurroundAnalysisBufferDelay + + hEnc->nInputDelay]), + pInput2__FDK + ch * inputBufferSizePerChannel, + (nSamplesPerChannel - hEnc->nInputDelay) * sizeof(INT_PCM)); + } + + /* Update time signal delay buffer */ + FDKmemcpy(&(hEnc->ppTimeSigDelayIn__FDK[ch][0]), + &(hEnc->ppTimeSigIn__FDK[ch][hEnc->nFrameLength]), + hEnc->nSurroundAnalysisBufferDelay * sizeof(INT_PCM)); + } /* for ch */ + + /***** No Arbitrary Downmix *****/ + /* "Crude TD Dmx": Time DomainDownmix + NO Arbitrary Downmix, Delay Added at + * pOutputBuffer */ + if ((hEnc->useTimeDomDownmix > 0)) { + if ((hEnc->useTimeDomDownmix == 1) || (hEnc->nInputChannels != 2)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } else { + /* enhanced time domain downmix (for stereo input) */ + if (hEnc->encMode == SACENC_212) { + if (pOutputSamples == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, pOutputSamples, + hEnc->nSurroundAnalysisBufferDelay); + } else { + if (&hEnc->ppTimeSigOut__FDK[0][0] == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + fdk_sacenc_apply_enhancedTimeDomainDmx( + hEnc->hEnhancedTimeDmx, hEnc->ppTimeSigIn__FDK, + &hEnc->ppTimeSigOut__FDK[0][0], + hEnc->nSurroundAnalysisBufferDelay); + } + } + } + + /* update number of samples still to process */ + hEnc->nSamplesValid += samplesToFeed; + + /*return number of fed samples */ + *pnSamplesFed = samplesToFeed; + } +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_encode(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const FDK_bufDescr *inBufDesc, + const FDK_bufDescr *outBufDesc, + const SACENC_InArgs *inargs, + SACENC_OutArgs *outargs) { + FDK_SACENC_ERROR error = SACENC_OK; + + const INT_PCM *pInputSamples = + (const INT_PCM *)inBufDesc->ppBase[getBufDescIdx( + inBufDesc, (FDK_BUF_TYPE_INPUT | FDK_BUF_TYPE_PCM_DATA))]; + + INT_PCM *const pOutputSamples = (INT_PCM *)outBufDesc->ppBase[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + const int nOutputSamplesBufferSize = + outBufDesc->pBufSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))] / + outBufDesc->pEleSize[getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_PCM_DATA))]; + + if ((hMp4SpaceEnc == NULL) || (pInputSamples == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int nOutputSamples; + int i, ch, ps, winCnt, ts, slot; + INT currTransPos = -1; + SPATIALFRAME *pFrameData = NULL; + + /* Improve Code Readability */ + const int nChIn = hMp4SpaceEnc->nInputChannels; + const int nChInWithDmx = nChIn; + const int nChOut = hMp4SpaceEnc->nOutputChannels; + const int nSamplesPerChannel = inargs->nInputSamples / nChInWithDmx; + const int nOutputSamplesMax = nSamplesPerChannel * nChOut; + const int nFrameTimeSlots = hMp4SpaceEnc->nFrameTimeSlots; + + INT encoderInputChScale[SACENC_MAX_INPUT_CHANNELS]; + INT nFrameTimeSlotsReduction = 0; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + nFrameTimeSlotsReduction = hMp4SpaceEnc->nFrameTimeSlots >> 1; + } + + for (i = 0; i < nChIn; i++) + encoderInputChScale[i] = hMp4SpaceEnc->pEncoderInputChScale[i]; + + /* Sanity Check */ + if ((0 != inargs->nInputSamples % nChInWithDmx)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* + * Get Frame Data Handle. + */ + + /* get bitstream handle (for storage of cld's, icc's and so on) + * get spatialframe 2 frames in the future; NOTE: this is necessary to + * synchronise spatial data and audio data */ + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, WRITE_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* Independent Frames Counters*/ + if (hMp4SpaceEnc->nDiscardOutFrames > + 0) { /* Independent Frames if they should be discarded, Reset Counter*/ + hMp4SpaceEnc->independencyCount = + 0; /* Reset the counter, first valid frame is an independent one*/ + hMp4SpaceEnc->independencyFlag = 1; + } else { /*hMp4SpaceEnc->nDiscardOutFrames == 0*/ + hMp4SpaceEnc->independencyFlag = + (hMp4SpaceEnc->independencyCount == 0) ? 1 : 0; + if (hMp4SpaceEnc->independencyFactor > 0) { + hMp4SpaceEnc->independencyCount++; + hMp4SpaceEnc->independencyCount = + hMp4SpaceEnc->independencyCount % + ((int)hMp4SpaceEnc->independencyFactor); + } else { /* independencyFactor == 0 */ + hMp4SpaceEnc->independencyCount = -1; + } + } + + /* + * Time signal preprocessing: + * - Feed input buffer + * - Prescale time signal + * - Apply DC filter on input signal + */ + + /* Feed, Deinterleave, Pre-Scale the input time signals */ + if (SACENC_OK != + (error = __FeedDeinterPreScale( + hMp4SpaceEnc, pInputSamples, pOutputSamples, inargs->nInputSamples, + inargs->isInputInterleaved, inargs->inputBufferSizePerChannel, + &outargs->nSamplesConsumed))) { + goto bail; + } + + if (hMp4SpaceEnc->nSamplesNext != hMp4SpaceEnc->nSamplesValid) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Time / Frequency: + * - T/F audio input channels + * - T/F arbitrary downmix input channels + */ + for (ch = 0; ch < nChIn; ch++) { + C_AALLOC_SCRATCH_START(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_START(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + FIXP_GAIN *pPreGain = + fdk_sacenc_getPreGainPtrFDK(hMp4SpaceEnc->hStaticGain); + + for (ts = 0; ts < nFrameTimeSlots; ts++) { + FIXP_DBL *pSpecReal; + FIXP_DBL *pSpecImag; + + INT_PCM *pTimeIn = + &hMp4SpaceEnc->ppTimeSigIn__FDK[ch][(ts * hMp4SpaceEnc->nQmfBands)]; + + { + /* Apply DC filter on input channels */ + if (SACENC_OK != (error = fdk_sacenc_applyDCFilter( + hMp4SpaceEnc->phDCFilterSigIn[ch], pTimeIn, + pTimeIn, hMp4SpaceEnc->nQmfBands))) { + goto bail; + } + } + + /* QMF filterbank */ + C_ALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(hMp4SpaceEnc->phQmfFiltIn__FDK[ch], pQmfInReal, + pQmfInImag, pTimeIn, 1, pWorkBuffer); + + C_ALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (MAX_QMF_BANDS << 1)); + + pSpecReal = pQmfInReal; + pSpecImag = pQmfInImag; + + /* Apply pre-scale after filterbank */ + if (MAXVAL_GAIN != pPreGain[ch]) { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = fMult(pSpecReal[i], pPreGain[ch]); + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = fMult(pSpecImag[i], pPreGain[ch]); + } + } else { + for (i = 0; i < hMp4SpaceEnc->nHybridBands; i++) { + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.re = pSpecReal[i]; + hMp4SpaceEnc + ->pppHybridIn__FDK[ch] + [hMp4SpaceEnc->nAnalysisLookaheadTimeSlots + + ts][i] + .v.im = pSpecImag[i]; + } + } + } /* ts */ + C_AALLOC_SCRATCH_END(pQmfInImag, FIXP_DBL, MAX_QMF_BANDS) + C_AALLOC_SCRATCH_END(pQmfInReal, FIXP_DBL, MAX_QMF_BANDS) + + if (SACENC_OK != error) { + goto bail; + } + } /* ch */ + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec(hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->nHybridBands); + } + } + for (ch = 0; ch < nChIn; ch++) { + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridInStatic__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + } + } + + /* + * Onset Detection: + * - detection of transients + * - build framing + */ + for (ch = 0; ch < nChIn; ch++) { + if (ch != 3) { /* !LFE */ + if (SACENC_OK != + (error = fdk_sacenc_onsetDetect_Apply( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots, + hMp4SpaceEnc->nHybridBands, + &hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nAnalysisLookaheadTimeSlots], + encoderInputChScale[ch], + hMp4SpaceEnc->trPrevPos[1], /* contains previous Transient */ + hMp4SpaceEnc->ppTrCurrPos[ch]))) { + goto bail; + } + + if ((1) && (hMp4SpaceEnc->useFrameKeep == 0)) { + hMp4SpaceEnc->ppTrCurrPos[ch][0] = -1; + } + + /* Find first Transient Position */ + if ((hMp4SpaceEnc->ppTrCurrPos[ch][0] >= 0) && + ((currTransPos < 0) || + (hMp4SpaceEnc->ppTrCurrPos[ch][0] < currTransPos))) { + currTransPos = hMp4SpaceEnc->ppTrCurrPos[ch][0]; + } + } /* !LFE */ + } /* ch */ + + if (hMp4SpaceEnc->useFrameKeep == 1) { + if ((currTransPos != -1) || (hMp4SpaceEnc->independencyFlag == 1)) { + hMp4SpaceEnc->avoid_keep = NUM_KEEP_WINDOWS; + currTransPos = -1; + } + } + + /* Save previous Transient Position */ + hMp4SpaceEnc->trPrevPos[0] = + FDKmax(-1, hMp4SpaceEnc->trPrevPos[1] - (INT)nFrameTimeSlots); + hMp4SpaceEnc->trPrevPos[1] = currTransPos; + + /* Update Onset Detection Energy Buffer */ + for (ch = 0; ch < nChIn; ch++) { + if (SACENC_OK != (error = fdk_sacenc_onsetDetect_Update( + hMp4SpaceEnc->phOnset[ch], nFrameTimeSlots))) { + goto bail; + } + } + + /* Framing */ + if (SACENC_OK != + (error = fdk_sacenc_frameWindow_GetWindow( + hMp4SpaceEnc->hFrameWindow, hMp4SpaceEnc->trPrevPos, + nFrameTimeSlots, &pFrameData->framingInfo, + hMp4SpaceEnc->pFrameWindowAna__FDK, &hMp4SpaceEnc->frameWinList, + hMp4SpaceEnc->avoid_keep))) { + goto bail; + } + + /* + * MPS Processing: + */ + for (ps = 0, winCnt = 0; ps < hMp4SpaceEnc->frameWinList.n; ++ps) { + /* Analysis Windowing */ + if (hMp4SpaceEnc->frameWinList.dat[ps].hold == FW_HOLD) { + /* ************************************** */ + /* ONLY COPY AND HOLD PREVIOUS PARAMETERS */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + &hMp4SpaceEnc->saveFrame, 0, pFrameData, ps))) { + goto bail; + } + + } else { /* !FW_HOLD */ + /* ************************************** */ + /* NEW WINDOW */ + + INT nAnalysisLengthTimeSlots, analysisStartTimeSlot; + + nAnalysisLengthTimeSlots = getAnalysisLengthTimeSlots( + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + analysisStartTimeSlot = + getAnalysisStartTimeSlot(hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt], + hMp4SpaceEnc->nAnalysisLengthTimeSlots); + + /* perform main signal analysis windowing in + * fdk_sacenc_spaceTree_Apply() */ + FIXP_WIN *pFrameWindowAna__FDK = + hMp4SpaceEnc->pFrameWindowAna__FDK[winCnt]; + FIXP_DPK ***pppHybridIn__FDK = hMp4SpaceEnc->pppHybridIn__FDK; + FIXP_DPK ***pppProcDataIn__FDK = hMp4SpaceEnc->pppProcDataIn__FDK; + + if (hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only) { + pppProcDataIn__FDK = pppHybridIn__FDK; + } + + if (SACENC_OK != + (error = fdk_sacenc_spaceTree_Apply( + hMp4SpaceEnc->hSpaceTree, ps, nChIn, nAnalysisLengthTimeSlots, + analysisStartTimeSlot, hMp4SpaceEnc->nHybridBands, + pFrameWindowAna__FDK, pppHybridIn__FDK, + pppProcDataIn__FDK, /* multi-channel input */ + pFrameData, hMp4SpaceEnc->avoid_keep, encoderInputChScale))) { + goto bail; + } + + /* Save spatial frame for potential hold parameter set */ + if (SACENC_OK != (error = fdk_sacenc_duplicateParameterSet( + pFrameData, ps, &hMp4SpaceEnc->saveFrame, 0))) { + goto bail; + } + + ++winCnt; + } + if (hMp4SpaceEnc->avoid_keep > 0) { + hMp4SpaceEnc->avoid_keep--; + } + } /* Loop over Parameter Sets */ + /* ---- End of Processing Loop ---- */ + + /* + * Update hybridInReal/Imag buffer and do the same for arbDmx + * this means to move the hybrid data of the current frame to the beginning + * of the 2*nFrameLength-long buffer + */ + if (!(hMp4SpaceEnc->encMode == SACENC_212 && + hMp4SpaceEnc->bEncMode_212_only)) { + for (ch = 0; ch < nChIn; ch++) { /* for automatic downmix */ + for (slot = 0; + slot < (int)(hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction); + slot++) { + copyCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK[ch][slot], + hMp4SpaceEnc->pppHybridIn__FDK[ch][nFrameTimeSlots + slot], + hMp4SpaceEnc->nHybridBands); + } + for (slot = 0; slot < nFrameTimeSlots; slot++) { + setCplxVec( + hMp4SpaceEnc->pppHybridIn__FDK + [ch][hMp4SpaceEnc->nUpdateHybridPositionTimeSlots + + nFrameTimeSlots - nFrameTimeSlotsReduction + slot], + (FIXP_DBL)0, hMp4SpaceEnc->nHybridBands); + } + } + } + /* + * Spatial Tonality: + */ + { + /* Smooth config off. */ + FDKmemclear(&pFrameData->smgData, sizeof(pFrameData->smgData)); + } + + /* + * Create bitstream + * - control independecy flag + * - write spatial frame + * - return bitstream + */ + UCHAR *pBitstreamDelayBuffer; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* no bitstream delay buffer for SACENC_212 mode, write bitstream directly + * into the sacOutBuffer buffer which is provided by the core routine */ + pBitstreamDelayBuffer = (UCHAR *)outBufDesc->ppBase[1]; + } else { + /* bitstream delay is handled in ppBitstreamDelayBuffer buffer */ + pBitstreamDelayBuffer = + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferWrite]; + } + if (pBitstreamDelayBuffer == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = hMp4SpaceEnc->independencyFlag; + + if (SACENC_OK != + (error = fdk_sacenc_writeSpatialFrame( + pBitstreamDelayBuffer, MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferWrite], + hMp4SpaceEnc->hBitstreamFormatter))) { + goto bail; + } + + /* return bitstream info */ + if ((hMp4SpaceEnc->nDiscardOutFrames == 0) && + (getBufDescIdx(outBufDesc, + (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)) != -1)) { + const INT idx = getBufDescIdx( + outBufDesc, (FDK_BUF_TYPE_OUTPUT | FDK_BUF_TYPE_BS_DATA)); + const INT outBits = + hMp4SpaceEnc->pnOutputBits[hMp4SpaceEnc->nBitstreamBufferRead]; + + if (((outBits + 7) / 8) > + (INT)(outBufDesc->pBufSize[idx] / outBufDesc->pEleSize[idx])) { + outargs->nOutputBits = 0; + error = SACENC_ENCODE_ERROR; + goto bail; + } + + /* return bitstream buffer, copy delayed bitstream for all configurations + * except for the SACENC_212 mode */ + if (hMp4SpaceEnc->encMode != SACENC_212) { + FDKmemcpy( + outBufDesc->ppBase[idx], + hMp4SpaceEnc + ->ppBitstreamDelayBuffer[hMp4SpaceEnc->nBitstreamBufferRead], + (outBits + 7) / 8); + } + + /* return number of valid bits */ + outargs->nOutputBits = outBits; + } else { /* No spatial data should be returned if the current frame is to be + discarded. */ + outargs->nOutputBits = 0; + } + + /* update pointers */ + hMp4SpaceEnc->nBitstreamBufferRead = + (hMp4SpaceEnc->nBitstreamBufferRead + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + hMp4SpaceEnc->nBitstreamBufferWrite = + (hMp4SpaceEnc->nBitstreamBufferWrite + 1) % + hMp4SpaceEnc->nBitstreamDelayBuffer; + + /* Set Output Parameters */ + nOutputSamples = + (hMp4SpaceEnc->nDiscardOutFrames == 0) + ? (nOutputSamplesMax) + : 0; /* don't output samples in case frames to be discarded */ + if (nOutputSamples > nOutputSamplesBufferSize) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + outargs->nOutputSamples = nOutputSamples; + + { /* !bQmfOutput */ + + if (hMp4SpaceEnc->encMode != SACENC_212) { + /* delay output samples and interleave them */ + /* note: in case of arbitrary downmix this will always be processed, + * because nOutputSamples != 0, even if bDMXAlign is switched on */ + /* always run copy-func, so nOutputSamplesMax instead of nOutputSamples + */ + for (ch = 0; ch < nChOut; ch++) { + FDKmemcpy_flex( + &hMp4SpaceEnc->pOutputDelayBuffer__FDK + [ch + (hMp4SpaceEnc->nOutputBufferDelay) * nChOut], + nChOut, hMp4SpaceEnc->ppTimeSigOut__FDK[ch], 1, + nOutputSamplesMax / nChOut); + } + + /* write delayed data in output pcm stream */ + /* always calculate, limiter must have a lookahead!!! */ + FDKmemcpy(pOutputSamples, hMp4SpaceEnc->pOutputDelayBuffer__FDK, + nOutputSamplesMax * sizeof(INT_PCM)); + + /* update delay buffer (move back end to the beginning of the buffer) */ + FDKmemmove( + hMp4SpaceEnc->pOutputDelayBuffer__FDK, + &hMp4SpaceEnc->pOutputDelayBuffer__FDK[nOutputSamplesMax], + nChOut * (hMp4SpaceEnc->nOutputBufferDelay) * sizeof(INT_PCM)); + } + + if (hMp4SpaceEnc->useTimeDomDownmix <= 0) { + if (SACENC_OK != (error = fdk_sacenc_staticPostGain_ApplyFDK( + hMp4SpaceEnc->hStaticGain, pOutputSamples, + nOutputSamplesMax, 0))) { + goto bail; + } + } + + } /* !bQmfOutput */ + + if (hMp4SpaceEnc->nDiscardOutFrames > 0) { + hMp4SpaceEnc->nDiscardOutFrames--; + } + + /* Invalidate Input Buffer */ + hMp4SpaceEnc->nSamplesValid = 0; + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_close(HANDLE_MP4SPACE_ENCODER *phMp4SpaceEnc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL != phMp4SpaceEnc) { + if (NULL != *phMp4SpaceEnc) { + int ch, i; + HANDLE_MP4SPACE_ENCODER const hEnc = *phMp4SpaceEnc; + + if (hEnc->pParameterBand2HybridBandOffset != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pParameterBand2HybridBandOffset); + } + /* Free Analysis Filterbank Structs */ + if (hEnc->pEncoderInputChScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pEncoderInputChScale); + } + if (hEnc->staticTimeDomainDmxInScale != NULL) { + FDK_FREE_MEMORY_1D(hEnc->staticTimeDomainDmxInScale); + } + if (hEnc->phQmfFiltIn__FDK != NULL) { + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (hEnc->phQmfFiltIn__FDK[ch] != NULL) { + if (hEnc->phQmfFiltIn__FDK[ch]->FilterStates != NULL) { + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]->FilterStates); + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK[ch]); + } + } + FDK_FREE_MEMORY_1D(hEnc->phQmfFiltIn__FDK); + } + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phDCFilterSigIn[ch]) { + fdk_sacenc_destroyDCFilter(&hEnc->phDCFilterSigIn[ch]); + } + } + /* Close Onset Detection */ + for (ch = 0; ch < hEnc->setup.maxChIn; ch++) { + if (NULL != hEnc->phOnset[ch]) { + fdk_sacenc_onsetDetect_Close(&hEnc->phOnset[ch]); + } + } + if (hEnc->ppTrCurrPos) { + FDK_FREE_MEMORY_2D(hEnc->ppTrCurrPos); + } + if (hEnc->hFrameWindow) { + fdk_sacenc_frameWindow_Destroy(&hEnc->hFrameWindow); + } + /* Close Space Tree */ + if (NULL != hEnc->hSpaceTree) { + fdk_sacenc_spaceTree_Close(&hEnc->hSpaceTree); + } + if (NULL != hEnc->hEnhancedTimeDmx) { + fdk_sacenc_close_enhancedTimeDomainDmx(&hEnc->hEnhancedTimeDmx); + } + /* Close Static Gain */ + if (NULL != hEnc->hStaticGain) { + fdk_sacenc_staticGain_Close(&hEnc->hStaticGain); + } + if (NULL != hEnc->hStaticGainConfig) { + fdk_sacenc_staticGain_CloseConfig(&hEnc->hStaticGainConfig); + } + /* Close Delay*/ + if (NULL != hEnc->hDelay) { + fdk_sacenc_delay_Close(&hEnc->hDelay); + } + /* Delete Bitstream Stuff */ + if (NULL != hEnc->hBitstreamFormatter) { + fdk_sacenc_destroySpatialBitstreamEncoder(&(hEnc->hBitstreamFormatter)); + } + if (hEnc->pppHybridIn__FDK != NULL) { + if (hEnc->setup.bEncMode_212 == 1) { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + FDK_FREE_MEMORY_3D(hEnc->pppHybridInStatic__FDK); + } else { + FDK_FREE_MEMORY_3D(hEnc->pppHybridIn__FDK); + } + } + if (hEnc->pppProcDataIn__FDK != NULL) { + FDK_FREE_MEMORY_3D(hEnc->pppProcDataIn__FDK); + } + if (hEnc->pOutputDelayBuffer__FDK != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pOutputDelayBuffer__FDK); + } + if (hEnc->ppTimeSigIn__FDK != NULL) { + { FDK_FREE_MEMORY_2D(hEnc->ppTimeSigIn__FDK); } + } + if (hEnc->ppTimeSigDelayIn__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigDelayIn__FDK); + } + if (hEnc->ppTimeSigOut__FDK != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppTimeSigOut__FDK); + } + for (i = 0; i < MAX_NUM_PARAMS; i++) { + if (hEnc->pFrameWindowAna__FDK[i] != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pFrameWindowAna__FDK[i]); + } + } + if (hEnc->pnOutputBits != NULL) { + FDK_FREE_MEMORY_1D(hEnc->pnOutputBits); + } + if (hEnc->ppBitstreamDelayBuffer != NULL) { + FDK_FREE_MEMORY_2D(hEnc->ppBitstreamDelayBuffer); + } + if (hEnc->sscBuf.pSsc != NULL) { + FDK_FREE_MEMORY_1D(hEnc->sscBuf.pSsc); + } + FDK_FREE_MEMORY_1D(*phMp4SpaceEnc); + } + } + + return error; +} + +/*----------------------------------------------------------------------------- + functionname: mp4SpaceEnc_InitDelayCompensation() + description: initialzes delay compensation + returns: noError on success, an apropriate error code else + -----------------------------------------------------------------------------*/ +static FDK_SACENC_ERROR mp4SpaceEnc_InitDelayCompensation( + HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, const INT coreCoderDelay) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + hMp4SpaceEnc->coreCoderDelay = coreCoderDelay; + + if (SACENC_OK != (error = fdk_sacenc_delay_Init( + hMp4SpaceEnc->hDelay, hMp4SpaceEnc->nQmfBands, + hMp4SpaceEnc->nFrameLength, coreCoderDelay, + hMp4SpaceEnc->timeAlignment))) { + goto bail; + } + + fdk_sacenc_delay_SetDmxAlign(hMp4SpaceEnc->hDelay, 0); + fdk_sacenc_delay_SetTimeDomDmx( + hMp4SpaceEnc->hDelay, (hMp4SpaceEnc->useTimeDomDownmix >= 1) ? 1 : 0); + fdk_sacenc_delay_SetMinimizeDelay(hMp4SpaceEnc->hDelay, 1); + + if (SACENC_OK != (error = fdk_sacenc_delay_SubCalulateBufferDelays( + hMp4SpaceEnc->hDelay))) { + goto bail; + } + + /* init output delay compensation */ + hMp4SpaceEnc->nBitstreamDelayBuffer = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nOutputBufferDelay = + fdk_sacenc_delay_GetOutputAudioBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nSurroundAnalysisBufferDelay = + fdk_sacenc_delay_GetSurroundAnalysisBufferDelay(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nBitstreamBufferRead = 0; + hMp4SpaceEnc->nBitstreamBufferWrite = + hMp4SpaceEnc->nBitstreamDelayBuffer - 1; + + if (hMp4SpaceEnc->encMode == SACENC_212) { + /* mode 212 expects no bitstream delay */ + if (hMp4SpaceEnc->nBitstreamBufferWrite != + hMp4SpaceEnc->nBitstreamBufferRead) { + error = SACENC_PARAM_ERROR; + goto bail; + } + + /* mode 212 expects no output buffer delay */ + if (hMp4SpaceEnc->nOutputBufferDelay != 0) { + error = SACENC_PARAM_ERROR; + goto bail; + } + } + + /*** Input delay to obtain a net encoder delay that is a multiple + of the used framelength to ensure synchronization of framing + in artistic down-mix with the corresponding spatial data. ***/ + hMp4SpaceEnc->nDiscardOutFrames = + fdk_sacenc_delay_GetDiscardOutFrames(hMp4SpaceEnc->hDelay); + hMp4SpaceEnc->nInputDelay = + fdk_sacenc_delay_GetDmxAlignBufferDelay(hMp4SpaceEnc->hDelay); + + /* reset independency Flag counter */ + hMp4SpaceEnc->independencyCount = 0; + hMp4SpaceEnc->independencyFlag = 1; + + int i; + + /* write some parameters to bitstream */ + for (i = 0; i < hMp4SpaceEnc->nBitstreamDelayBuffer - 1; i++) { + SPATIALFRAME *pFrameData = NULL; + + if (NULL == (pFrameData = fdk_sacenc_getSpatialFrame( + hMp4SpaceEnc->hBitstreamFormatter, READ_SPATIALFRAME))) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + pFrameData->bsIndependencyFlag = 1; + pFrameData->framingInfo.numParamSets = 1; + pFrameData->framingInfo.bsFramingType = 0; + + fdk_sacenc_writeSpatialFrame( + hMp4SpaceEnc->ppBitstreamDelayBuffer[i], MAX_MPEGS_BYTES, + &hMp4SpaceEnc->pnOutputBits[i], hMp4SpaceEnc->hBitstreamFormatter); + } + + if ((hMp4SpaceEnc->nInputDelay > MAX_DELAY_INPUT) || + (hMp4SpaceEnc->nOutputBufferDelay > MAX_DELAY_OUTPUT) || + (hMp4SpaceEnc->nSurroundAnalysisBufferDelay > + MAX_DELAY_SURROUND_ANALYSIS) || + (hMp4SpaceEnc->nBitstreamDelayBuffer > MAX_BITSTREAM_DELAY)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } + +bail: + + return error; +} + +static QUANTMODE __mapQuantMode(const MP4SPACEENC_QUANTMODE quantMode) { + QUANTMODE bsQuantMode = QUANTMODE_INVALID; + + switch (quantMode) { + case SACENC_QUANTMODE_FINE: + bsQuantMode = QUANTMODE_FINE; + break; + case SACENC_QUANTMODE_EBQ1: + bsQuantMode = QUANTMODE_EBQ1; + break; + case SACENC_QUANTMODE_EBQ2: + bsQuantMode = QUANTMODE_EBQ2; + break; + case SACENC_QUANTMODE_RSVD3: + case SACENC_QUANTMODE_INVALID: + default: + bsQuantMode = QUANTMODE_INVALID; + } /* switch hEnc->quantMode */ + + return bsQuantMode; +} + +static FDK_SACENC_ERROR FillSpatialSpecificConfig( + const HANDLE_MP4SPACE_ENCODER hEnc, SPATIALSPECIFICCONFIG *const hSsc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hEnc) || (NULL == hSsc)) { + error = SACENC_INVALID_HANDLE; + } else { + SPACE_TREE_DESCRIPTION spaceTreeDescription; + int i; + + /* Get tree description */ + if (SACENC_OK != (error = fdk_sacenc_spaceTree_GetDescription( + hEnc->hSpaceTree, &spaceTreeDescription))) { + goto bail; + } + + /* Fill SSC */ + FDKmemclear(hSsc, sizeof(SPATIALSPECIFICCONFIG)); /* reset */ + + hSsc->numBands = hEnc->spaceTreeSetup.nParamBands; /* for bsFreqRes */ + + /* Fill tree configuration */ + hSsc->treeDescription.numOttBoxes = spaceTreeDescription.nOttBoxes; + hSsc->treeDescription.numInChan = spaceTreeDescription.nInChannels; + hSsc->treeDescription.numOutChan = spaceTreeDescription.nOutChannels; + + for (i = 0; i < SACENC_MAX_NUM_BOXES; i++) { + hSsc->ottConfig[i].bsOttBands = hSsc->numBands; + } + + switch (hEnc->encMode) { + case SACENC_212: + hSsc->bsTreeConfig = TREE_212; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSsc->bsSamplingFrequency = + hEnc->nSampleRate; /* for bsSamplingFrequencyIndex */ + hSsc->bsFrameLength = hEnc->nFrameTimeSlots - 1; + + /* map decorr type */ + if (DECORR_INVALID == + (hSsc->bsDecorrConfig = mp4SpaceEnc_GetDecorrConfig(hEnc->encMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* map quantMode */ + if (QUANTMODE_INVALID == + (hSsc->bsQuantMode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Configure Gains*/ + hSsc->bsFixedGainDMX = fdk_sacenc_staticGain_GetDmxGain(hEnc->hStaticGain); + hSsc->bsEnvQuantMode = 0; + + } /* valid handle */ + +bail: + return error; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_FillSpaceTreeSetup( + const HANDLE_MP4SPACE_ENCODER hEnc, + SPACE_TREE_SETUP *const hSpaceTreeSetup) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Sanity Check */ + if (NULL == hEnc || NULL == hSpaceTreeSetup) { + error = SACENC_INVALID_HANDLE; + } else { + QUANTMODE tmpQuantmode = QUANTMODE_INVALID; + + /* map quantMode */ + if (QUANTMODE_INVALID == (tmpQuantmode = __mapQuantMode(hEnc->quantMode))) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hSpaceTreeSetup->nParamBands = hEnc->nParamBands; + hSpaceTreeSetup->bUseCoarseQuantTtoCld = hEnc->useCoarseQuantCld; + hSpaceTreeSetup->bUseCoarseQuantTtoIcc = hEnc->useCoarseQuantIcc; + hSpaceTreeSetup->quantMode = tmpQuantmode; + hSpaceTreeSetup->nHybridBandsMax = hEnc->nHybridBands; + + switch (hEnc->encMode) { + case SACENC_212: + hSpaceTreeSetup->mode = SPACETREE_212; + hSpaceTreeSetup->nChannelsInMax = 2; + break; + case SACENC_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + goto bail; + } /* switch hEnc->encMode */ + + } /* valid handle */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getInfo(const HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + MP4SPACEENC_INFO *const pInfo) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hMp4SpaceEnc) || (NULL == pInfo)) { + error = SACENC_INVALID_HANDLE; + } else { + pInfo->nSampleRate = hMp4SpaceEnc->nSampleRate; + pInfo->nSamplesFrame = hMp4SpaceEnc->nFrameLength; + pInfo->nTotalInputChannels = hMp4SpaceEnc->nInputChannels; + pInfo->nDmxDelay = fdk_sacenc_delay_GetInfoDmxDelay(hMp4SpaceEnc->hDelay); + pInfo->nCodecDelay = + fdk_sacenc_delay_GetInfoCodecDelay(hMp4SpaceEnc->hDelay); + pInfo->nDecoderDelay = + fdk_sacenc_delay_GetInfoDecoderDelay(hMp4SpaceEnc->hDelay); + pInfo->nPayloadDelay = + fdk_sacenc_delay_GetBitstreamFrameBufferSize(hMp4SpaceEnc->hDelay) - 1; + pInfo->nDiscardOutFrames = hMp4SpaceEnc->nDiscardOutFrames; + + pInfo->pSscBuf = &hMp4SpaceEnc->sscBuf; + } + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_setParam(HANDLE_MP4SPACE_ENCODER hMp4SpaceEnc, + const SPACEENC_PARAM param, + const UINT value) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* check encoder handle */ + if (hMp4SpaceEnc == NULL) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + /* apply param value */ + switch (param) { + case SACENC_LOWDELAY: + if (!((value == 0) || (value == 1) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bLdMode = value; + break; + + case SACENC_ENC_MODE: + switch ((MP4SPACEENC_MODE)value) { + case SACENC_212: + hMp4SpaceEnc->user.encMode = (MP4SPACEENC_MODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_SAMPLERATE: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxSamplingrate)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.sampleRate = value; + break; + + case SACENC_FRAME_TIME_SLOTS: + if (((int)value < 0) || + ((int)value > hMp4SpaceEnc->setup.maxFrameTimeSlots)) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.frameTimeSlots = value; + break; + + case SACENC_PARAM_BANDS: + switch ((MP4SPACEENC_BANDS_CONFIG)value) { + case SACENC_BANDS_4: + case SACENC_BANDS_5: + case SACENC_BANDS_7: + case SACENC_BANDS_9: + case SACENC_BANDS_12: + case SACENC_BANDS_15: + case SACENC_BANDS_23: + hMp4SpaceEnc->user.nParamBands = (MP4SPACEENC_BANDS_CONFIG)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_DOM_DMX: + if (!((value == 0) || (value == 2))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bTimeDomainDmx = value; + break; + + case SACENC_DMX_GAIN: + if (!((value == 0) || (value == 1) || (value == 2) || (value == 3) || + (value == 4) || (value == 5) || (value == 6) || (value == 7))) { + error = SACENC_INVALID_CONFIG; + break; + } + error = fdk_sacenc_staticGain_SetDmxGain(hMp4SpaceEnc->hStaticGainConfig, + (MP4SPACEENC_DMX_GAIN)value); + break; + + case SACENC_COARSE_QUANT: + if (!((value == 0) || (value == 1))) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.bUseCoarseQuant = value; + break; + + case SACENC_QUANT_MODE: + switch ((MP4SPACEENC_QUANTMODE)value) { + case SACENC_QUANTMODE_FINE: + case SACENC_QUANTMODE_EBQ1: + case SACENC_QUANTMODE_EBQ2: + hMp4SpaceEnc->user.quantMode = (MP4SPACEENC_QUANTMODE)value; + break; + default: + error = SACENC_INVALID_CONFIG; + } + break; + + case SACENC_TIME_ALIGNMENT: + if ((INT)value < -32768 || (INT)value > 32767) { + error = SACENC_INVALID_CONFIG; + break; + } + hMp4SpaceEnc->user.timeAlignment = value; + break; + + case SACENC_INDEPENDENCY_COUNT: + hMp4SpaceEnc->independencyCount = value; + break; + + case SACENC_INDEPENDENCY_FACTOR: + hMp4SpaceEnc->user.independencyFactor = value; + break; + + default: + error = SACENC_UNSUPPORTED_PARAMETER; + break; + } /* switch(param) */ +bail: + return error; +} + +FDK_SACENC_ERROR FDK_sacenc_getLibInfo(LIB_INFO *info) { + int i = 0; + + if (info == NULL) { + return SACENC_INVALID_HANDLE; + } + + FDK_toolsGetLibInfo(info); + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return SACENC_INIT_ERROR; + } + + info[i].module_id = FDK_MPSENC; + info[i].build_date = SACENC_LIB_BUILD_DATE; + info[i].build_time = SACENC_LIB_BUILD_TIME; + info[i].title = SACENC_LIB_TITLE; + info[i].version = LIB_VERSION(SACENC_LIB_VL0, SACENC_LIB_VL1, SACENC_LIB_VL2); + LIB_VERSION_STRING(&info[i]); + + /* Capability flags */ + info[i].flags = 0; + /* End of flags */ + + return SACENC_OK; +} + +static DECORRCONFIG mp4SpaceEnc_GetDecorrConfig( + const MP4SPACEENC_MODE encMode) { + DECORRCONFIG decorrConfig = DECORR_INVALID; + + /* set decorrConfig dependent on tree mode */ + switch (encMode) { + case SACENC_212: + decorrConfig = DECORR_QMFSPLIT0; + break; + case SACENC_INVALID_MODE: + default: + decorrConfig = DECORR_INVALID; + } + return decorrConfig; +} + +static FDK_SACENC_ERROR mp4SpaceEnc_InitNumParamBands( + HANDLE_MP4SPACE_ENCODER hEnc, const MP4SPACEENC_BANDS_CONFIG nParamBands) { + FDK_SACENC_ERROR error = SACENC_OK; + + /* Set/Check nParamBands */ + int k = 0; + const int n = sizeof(pValidBands_Ld) / sizeof(UCHAR); + const UCHAR *pBands = pValidBands_Ld; + + while (k < n && pBands[k] != (UCHAR)nParamBands) ++k; + if (k == n) { + hEnc->nParamBands = SACENC_BANDS_INVALID; + } else { + hEnc->nParamBands = nParamBands; + } + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_nlc_enc.cpp b/fdk-aac/libSACenc/src/sacenc_nlc_enc.cpp new file mode 100644 index 0000000..0ba6cc9 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_nlc_enc.cpp @@ -0,0 +1,1442 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_nlc_enc.h" + +#include "genericStds.h" +#include "fixpoint_math.h" + +#include "sacenc_const.h" +#include "sacenc_huff_tab.h" +#include "sacenc_paramextract.h" + +/* Defines *******************************************************************/ +#define PAIR_SHIFT 4 +#define PAIR_MASK 0xf + +#define PBC_MIN_BANDS 5 + +typedef enum { + BACKWARDS = 0x0, + FORWARDS = 0x1 + +} DIRECTION; + +typedef enum { + DIFF_FREQ = 0x0, + DIFF_TIME = 0x1 + +} DIFF_TYPE; + +typedef enum { + HUFF_1D = 0x0, + HUFF_2D = 0x1 + +} CODING_SCHEME; + +typedef enum { + FREQ_PAIR = 0x0, + TIME_PAIR = 0x1 + +} PAIRING; + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ +static const UCHAR lavHuffVal[4] = {0, 2, 6, 7}; +static const UCHAR lavHuffLen[4] = {1, 2, 3, 3}; + +static const UCHAR lav_step_CLD[] = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3}; +static const UCHAR lav_step_ICC[] = {0, 0, 1, 1, 2, 2, 3, 3}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static void split_lsb(const SHORT *const in_data, SHORT offset, + const INT num_val, SHORT *const out_data_lsb, + SHORT *const out_data_msb) { + int i; + + for (i = 0; i < num_val; i++) { + SHORT val = in_data[i] + offset; + if (out_data_lsb != NULL) out_data_lsb[i] = val & 0x0001; + if (out_data_msb != NULL) out_data_msb[i] = val >> 1; + } +} + +static void apply_lsb_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_lsb, const UINT num_lsb, + const INT num_val) { + int i; + + for (i = 0; i < num_val; i++) { + FDKwriteBits(strm, in_data_lsb[i], num_lsb); + } +} + +static void calc_diff_freq(const SHORT *const in_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + + for (i = 1; i < num_val; i++) { + out_data[i] = in_data[i] - in_data[i - 1]; + } +} + +static void calc_diff_time(const SHORT *const in_data, + const SHORT *const prev_data, SHORT *const out_data, + const INT num_val) { + int i; + out_data[0] = in_data[0]; + out_data[1] = prev_data[0]; + + for (i = 0; i < num_val; i++) { + out_data[i + 2] = in_data[i] - prev_data[i]; + } +} + +static INT sym_check(SHORT data[2], const INT lav, SHORT *const pSym_bits) { + UCHAR symBits = 0; + int sum_val = data[0] + data[1]; + int diff_val = data[0] - data[1]; + int num_sbits = 0; + + if (sum_val != 0) { + int sum_neg = (sum_val < 0) ? 1 : 0; + if (sum_neg) { + sum_val = -sum_val; + diff_val = -diff_val; + } + symBits = (symBits << 1) | sum_neg; + num_sbits++; + } + + if (diff_val != 0) { + int diff_neg = (diff_val < 0) ? 1 : 0; + if (diff_neg) { + diff_val = -diff_val; + } + symBits = (symBits << 1) | diff_neg; + num_sbits++; + } + + if (pSym_bits != NULL) { + *pSym_bits = symBits; + } + + if (sum_val % 2) { + data[0] = lav - sum_val / 2; + data[1] = lav - diff_val / 2; + } else { + data[0] = sum_val / 2; + data[1] = diff_val / 2; + } + + return num_sbits; +} + +static INT ilog2(UINT i) { + int l = 0; + + if (i) i--; + while (i > 0) { + i >>= 1; + l++; + } + + return l; +} + +static SHORT calc_pcm_bits(const SHORT num_val, const SHORT num_levels) { + SHORT num_complete_chunks = 0, rest_chunk_size = 0; + SHORT max_grp_len = 0, bits_pcm = 0; + int chunk_levels, i; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + num_complete_chunks = num_val / max_grp_len; + rest_chunk_size = num_val % max_grp_len; + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + } + + bits_pcm = (SHORT)(ilog2(chunk_levels) * num_complete_chunks); + bits_pcm += (SHORT)(ilog2(num_levels) * rest_chunk_size); + + return bits_pcm; +} + +static void apply_pcm_coding(HANDLE_FDK_BITSTREAM strm, + const SHORT *const in_data_1, + const SHORT *const in_data_2, const SHORT offset, + const SHORT num_val, const SHORT num_levels) { + SHORT i = 0, j = 0, idx = 0; + SHORT max_grp_len = 0, grp_len = 0, next_val = 0; + int grp_val = 0, chunk_levels = 0; + + SHORT pcm_chunk_size[7] = {0}; + + switch (num_levels) { + case 3: + max_grp_len = 5; + break; + case 5: + max_grp_len = 3; + break; + case 6: + max_grp_len = 5; + break; + case 7: + max_grp_len = 6; + break; + case 9: + max_grp_len = 5; + break; + case 11: + max_grp_len = 2; + break; + case 13: + max_grp_len = 4; + break; + case 19: + max_grp_len = 4; + break; + case 25: + max_grp_len = 3; + break; + case 51: + max_grp_len = 4; + break; + default: + max_grp_len = 1; + } + + chunk_levels = 1; + for (i = 1; i <= max_grp_len; i++) { + chunk_levels *= num_levels; + pcm_chunk_size[i] = ilog2(chunk_levels); + } + + for (i = 0; i < num_val; i += max_grp_len) { + grp_len = FDKmin(max_grp_len, num_val - i); + grp_val = 0; + for (j = 0; j < grp_len; j++) { + idx = i + j; + if (in_data_2 == NULL) { + next_val = in_data_1[idx]; + } else if (in_data_1 == NULL) { + next_val = in_data_2[idx]; + } else { + next_val = ((idx % 2) ? in_data_2[idx / 2] : in_data_1[idx / 2]); + } + next_val += offset; + grp_val = grp_val * num_levels + next_val; + } + + FDKwriteBits(strm, grp_val, pcm_chunk_size[grp_len]); + } +} + +static UINT huff_enc_1D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + const INT dim1, SHORT *const in_data, + const SHORT num_val, const SHORT p0_flag) { + int i, offset = 0; + UINT huffBits = 0; + + HUFF_ENTRY part0 = {0}; + const HUFF_ENTRY *pHuffTab = NULL; + + switch (data_type) { + case t_CLD: + pHuffTab = fdk_sacenc_huffCLDTab.h1D[dim1]; + break; + case t_ICC: + pHuffTab = fdk_sacenc_huffICCTab.h1D[dim1]; + break; + } + + if (p0_flag) { + switch (data_type) { + case t_CLD: + part0 = fdk_sacenc_huffPart0Tab.cld[in_data[0]]; + break; + case t_ICC: + part0 = fdk_sacenc_huffPart0Tab.icc[in_data[0]]; + break; + } + huffBits += FDKwriteBits(strm, HUFF_VALUE(part0), HUFF_LENGTH(part0)); + offset = 1; + } + + for (i = offset; i < num_val; i++) { + int id_sign = 0; + int id = in_data[i]; + + if (id != 0) { + id_sign = 0; + if (id < 0) { + id = -id; + id_sign = 1; + } + } + + huffBits += + FDKwriteBits(strm, HUFF_VALUE(pHuffTab[id]), HUFF_LENGTH(pHuffTab[id])); + + if (id != 0) { + huffBits += FDKwriteBits(strm, id_sign, 1); + } + } /* for i */ + + return huffBits; +} + +static void getHuffEntry(const INT lav, const DATA_TYPE data_type, const INT i, + const SHORT tab_idx_2D[2], const SHORT in_data[][2], + HUFF_ENTRY *const pEntry, HUFF_ENTRY *const pEscape) { + const HUFF_CLD_TAB_2D *pCLD2dTab = + &fdk_sacenc_huffCLDTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + const HUFF_ICC_TAB_2D *pICC2dTab = + &fdk_sacenc_huffICCTab.h2D[tab_idx_2D[0]][tab_idx_2D[1]]; + + switch (lav) { + case 1: { + const LAV1_2D *pLav1 = NULL; + switch (data_type) { + case t_CLD: + pLav1 = NULL; + break; + case t_ICC: + pLav1 = &pICC2dTab->lav1; + break; + } + if (pLav1 != NULL) { + *pEntry = pLav1->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav1->escape; + } + } break; + case 3: { + const LAV3_2D *pLav3 = NULL; + switch (data_type) { + case t_CLD: + pLav3 = &pCLD2dTab->lav3; + break; + case t_ICC: + pLav3 = &pICC2dTab->lav3; + break; + } + if (pLav3 != NULL) { + *pEntry = pLav3->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav3->escape; + } + } break; + case 5: { + const LAV5_2D *pLav5 = NULL; + switch (data_type) { + case t_CLD: + pLav5 = &pCLD2dTab->lav5; + break; + case t_ICC: + pLav5 = &pICC2dTab->lav5; + break; + } + if (pLav5 != NULL) { + *pEntry = pLav5->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav5->escape; + } + } break; + case 7: { + const LAV7_2D *pLav7 = NULL; + switch (data_type) { + case t_CLD: + pLav7 = &pCLD2dTab->lav7; + break; + case t_ICC: + pLav7 = &pICC2dTab->lav7; + break; + } + if (pLav7 != NULL) { + *pEntry = pLav7->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav7->escape; + } + } break; + case 9: { + const LAV9_2D *pLav9 = NULL; + switch (data_type) { + case t_CLD: + pLav9 = &pCLD2dTab->lav9; + break; + case t_ICC: + pLav9 = NULL; + break; + } + if (pLav9 != NULL) { + *pEntry = pLav9->entry[in_data[i][0]][in_data[i][1]]; + *pEscape = pLav9->escape; + } + } break; + } +} + +static UINT huff_enc_2D(HANDLE_FDK_BITSTREAM strm, const DATA_TYPE data_type, + SHORT tab_idx_2D[2], SHORT lav_idx, SHORT in_data[][2], + SHORT num_val, SHORT stride, SHORT *p0_data[2]) { + SHORT i = 0, lav = 0, num_sbits = 0, sym_bits = 0, escIdx = 0; + SHORT esc_data[2][MAXBANDS] = {{0}}; + + UINT huffBits = 0; + + const HUFF_ENTRY *pHuffEntry = NULL; + + switch (data_type) { + case t_CLD: + lav = 2 * lav_idx + 3; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.cld; + break; + case t_ICC: + lav = 2 * lav_idx + 1; /* LAV */ + pHuffEntry = fdk_sacenc_huffPart0Tab.icc; + break; + } + + /* Partition 0 */ + if (p0_data[0] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[0]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + if (p0_data[1] != NULL) { + HUFF_ENTRY entry = pHuffEntry[*p0_data[1]]; + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + } + + for (i = 0; i < num_val; i += stride) { + HUFF_ENTRY entry = {0}; + HUFF_ENTRY escape = {0}; + + esc_data[0][escIdx] = in_data[i][0] + lav; + esc_data[1][escIdx] = in_data[i][1] + lav; + + num_sbits = sym_check(in_data[i], lav, &sym_bits); + + getHuffEntry(lav, data_type, i, tab_idx_2D, in_data, &entry, &escape); + + huffBits += FDKwriteBits(strm, HUFF_VALUE(entry), HUFF_LENGTH(entry)); + + if ((HUFF_VALUE(entry) == HUFF_VALUE(escape)) && + (HUFF_LENGTH(entry) == HUFF_LENGTH(escape))) { + escIdx++; + } else { + huffBits += FDKwriteBits(strm, sym_bits, num_sbits); + } + } /* for i */ + + if (escIdx > 0) { + huffBits += calc_pcm_bits(2 * escIdx, (2 * lav + 1)); + if (strm != NULL) { + apply_pcm_coding(strm, esc_data[0], esc_data[1], 0 /*offset*/, 2 * escIdx, + (2 * lav + 1)); + } + } + + return huffBits; +} + +static SCHAR get_next_lav_step(const INT lav, const DATA_TYPE data_type) { + SCHAR lav_step = 0; + + switch (data_type) { + case t_CLD: + lav_step = (lav > 9) ? -1 : lav_step_CLD[lav]; + break; + case t_ICC: + lav_step = (lav > 7) ? -1 : lav_step_ICC[lav]; + break; + } + + return lav_step; +} + +static INT diff_type_offset(const DIFF_TYPE diff_type) { + int offset = 0; + switch (diff_type) { + case DIFF_FREQ: + offset = 0; + break; + case DIFF_TIME: + offset = 2; + break; + } + return offset; +} + +static SHORT calc_huff_bits(SHORT *in_data_1, SHORT *in_data_2, + const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + SHORT *const lav_idx, SHORT *const cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + SHORT lav_fp[2] = {0}; + + SHORT bit_count_1D = 0; + SHORT bit_count_2D_freq = 0; + SHORT bit_count_min = 0; + + SHORT num_val_1_short = 0; + SHORT num_val_2_short = 0; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* 1D Huffman coding */ + bit_count_1D = 1; /* HUFF_1D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + bit_count_1D += huff_enc_1D(NULL, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + + bit_count_min = bit_count_1D; + *cdg_scheme = HUFF_1D << PAIR_SHIFT; + lav_idx[0] = lav_idx[1] = -1; + + /* Huffman 2D frequency pairs */ + bit_count_2D_freq = 1; /* HUFF_2D */ + + num_val_1_short = num_val; + num_val_2_short = num_val; + + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + lav_fp[0] = lav_fp[1] = 0; + + p0_data_1[0] = NULL; + p0_data_1[1] = NULL; + p0_data_2[0] = NULL; + p0_data_2[1] = NULL; + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][0])); + lav_fp[0] = FDKmax(lav_fp[0], fAbs(pair_vec[i][1])); + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + + lav_fp[0] = get_next_lav_step(lav_fp[0], data_type); + + if (lav_fp[0] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[0]]; + } + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][0])); + lav_fp[1] = FDKmax(lav_fp[1], fAbs(pair_vec[i + 1][1])); + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + lav_fp[1] = get_next_lav_step(lav_fp[1], data_type); + + if (lav_fp[1] != -1) bit_count_2D_freq += lavHuffLen[lav_fp[1]]; + } + + if ((lav_fp[0] != -1) && (lav_fp[1] != -1)) { + if (in_data_1 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[0], lav_fp[0], pair_vec, + num_val_1_short, 2, p0_data_1); + } + if (in_data_2 != NULL) { + bit_count_2D_freq += + huff_enc_2D(NULL, data_type, tab_idx_2D[1], lav_fp[1], pair_vec + 1, + num_val_2_short, 2, p0_data_2); + } + if (in_data_1 != NULL) { + if (df_rest_flag[0]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + if (in_data_2 != NULL) { + if (df_rest_flag[1]) + bit_count_2D_freq += + huff_enc_1D(NULL, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + + if (bit_count_2D_freq < bit_count_min) { + bit_count_min = bit_count_2D_freq; + *cdg_scheme = HUFF_2D << PAIR_SHIFT | FREQ_PAIR; + lav_idx[0] = lav_fp[0]; + lav_idx[1] = lav_fp[1]; + } + } + + return bit_count_min; +} + +static void apply_huff_coding(HANDLE_FDK_BITSTREAM strm, SHORT *const in_data_1, + SHORT *const in_data_2, const DATA_TYPE data_type, + const DIFF_TYPE diff_type_1, + const DIFF_TYPE diff_type_2, const SHORT num_val, + const SHORT *const lav_idx, + const SHORT cdg_scheme) { + SHORT tab_idx_2D[2][2] = {{0}}; + SHORT tab_idx_1D[2] = {0}; + SHORT df_rest_flag[2] = {0}; + SHORT p0_flag[2] = {0}; + + SHORT pair_vec[MAXBANDS][2] = {{0}}; + + SHORT *p0_data_1[2] = {NULL}; + SHORT *p0_data_2[2] = {NULL}; + + SHORT i = 0; + + SHORT num_val_1_short = num_val; + SHORT num_val_2_short = num_val; + + SHORT *in_data_1_short = NULL; + SHORT *in_data_2_short = NULL; + + /* Offset */ + if (in_data_1 != NULL) { + in_data_1_short = in_data_1 + diff_type_offset(diff_type_1); + } + if (in_data_2 != NULL) { + in_data_2_short = in_data_2 + diff_type_offset(diff_type_2); + } + + /* Signalize coding scheme */ + FDKwriteBits(strm, cdg_scheme >> PAIR_SHIFT, 1); + + switch (cdg_scheme >> PAIR_SHIFT) { + case HUFF_1D: + + p0_flag[0] = (diff_type_1 == DIFF_FREQ); + p0_flag[1] = (diff_type_2 == DIFF_FREQ); + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + + if (in_data_1 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], in_data_1_short, + num_val_1_short, p0_flag[0]); + } + if (in_data_2 != NULL) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], in_data_2_short, + num_val_2_short, p0_flag[1]); + } + break; /* HUFF_1D */ + + case HUFF_2D: + + switch (cdg_scheme & PAIR_MASK) { + case FREQ_PAIR: + + if (in_data_1 != NULL) { + if (diff_type_1 == DIFF_FREQ) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = NULL; + + num_val_1_short -= 1; + in_data_1_short += 1; + } + + df_rest_flag[0] = num_val_1_short % 2; + + if (df_rest_flag[0]) num_val_1_short -= 1; + + for (i = 0; i < num_val_1_short - 1; i += 2) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_1_short[i + 1]; + } + + tab_idx_2D[0][0] = (diff_type_1 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[0][1] = 0; + + tab_idx_1D[0] = (diff_type_1 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_1 != NULL ) */ + + if (in_data_2 != NULL) { + if (diff_type_2 == DIFF_FREQ) { + p0_data_2[0] = NULL; + p0_data_2[1] = &in_data_2[0]; + + num_val_2_short -= 1; + in_data_2_short += 1; + } + + df_rest_flag[1] = num_val_2_short % 2; + + if (df_rest_flag[1]) num_val_2_short -= 1; + + for (i = 0; i < num_val_2_short - 1; i += 2) { + pair_vec[i + 1][0] = in_data_2_short[i]; + pair_vec[i + 1][1] = in_data_2_short[i + 1]; + } + + tab_idx_2D[1][0] = (diff_type_2 == DIFF_TIME) ? 1 : 0; + tab_idx_2D[1][1] = 0; + + tab_idx_1D[1] = (diff_type_2 == DIFF_FREQ) ? 0 : 1; + } /* if( in_data_2 != NULL ) */ + + if (in_data_1 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 2, p0_data_1); + if (df_rest_flag[0]) { + huff_enc_1D(strm, data_type, tab_idx_1D[0], + in_data_1_short + num_val_1_short, 1, 0); + } + } + if (in_data_2 != NULL) { + FDKwriteBits(strm, lavHuffVal[lav_idx[1]], lavHuffLen[lav_idx[1]]); + huff_enc_2D(strm, data_type, tab_idx_2D[1], lav_idx[1], + pair_vec + 1, num_val_2_short, 2, p0_data_2); + if (df_rest_flag[1]) { + huff_enc_1D(strm, data_type, tab_idx_1D[1], + in_data_2_short + num_val_2_short, 1, 0); + } + } + break; /* FREQ_PAIR */ + + case TIME_PAIR: + + if ((diff_type_1 == DIFF_FREQ) || (diff_type_2 == DIFF_FREQ)) { + p0_data_1[0] = &in_data_1[0]; + p0_data_1[1] = &in_data_2[0]; + + in_data_1_short += 1; + in_data_2_short += 1; + + num_val_1_short -= 1; + } + + for (i = 0; i < num_val_1_short; i++) { + pair_vec[i][0] = in_data_1_short[i]; + pair_vec[i][1] = in_data_2_short[i]; + } + + tab_idx_2D[0][0] = + ((diff_type_1 == DIFF_TIME) || (diff_type_2 == DIFF_TIME)) ? 1 + : 0; + tab_idx_2D[0][1] = 1; + + FDKwriteBits(strm, lavHuffVal[lav_idx[0]], lavHuffLen[lav_idx[0]]); + + huff_enc_2D(strm, data_type, tab_idx_2D[0], lav_idx[0], pair_vec, + num_val_1_short, 1, p0_data_1); + + break; /* TIME_PAIR */ + } /* switch( cdg_scheme & PAIR_MASK ) */ + + break; /* HUFF_2D */ + + default: + break; + } /* switch( cdg_scheme >> PAIR_SHIFT ) */ +} + +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[2][MAXBANDS]; + SHORT quant_data_msb[2][MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[2][MAXBANDS]; + SHORT data_diff_time[2][MAXBANDS + 2]; + + SHORT *p_quant_data_msb[2]; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df_df = -1; + SHORT min_bits_df_dt = -1; + SHORT min_bits_dtbw_df = -1; + SHORT min_bits_dt_dt = -1; + + SHORT lav_df_df[2] = {-1, -1}; + SHORT lav_df_dt[2] = {-1, -1}; + SHORT lav_dtbw_df[2] = {-1, -1}; + SHORT lav_dt_dt[2] = {-1, -1}; + + SHORT coding_scheme_df_df = 0; + SHORT coding_scheme_df_dt = 0; + SHORT coding_scheme_dtbw_df = 0; + SHORT coding_scheme_dt_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb[0], quant_data_msb[0]); + + split_lsb(aaInData[setIdx + 1] + startBand, quant_offset, dataBands, + quant_data_lsb[1], quant_data_msb[1]); + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 2 * dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[0][pb] = aaInData[setIdx][startBand + pb] + quant_offset; + quant_data_msb[1][pb] = + aaInData[setIdx + 1][startBand + pb] + quant_offset; + } + + p_quant_data_msb[0] = quant_data_msb[0]; + p_quant_data_msb[1] = quant_data_msb[1]; + + num_lsb_bits = 0; + } else { + p_quant_data_msb[0] = aaInData[setIdx] + startBand; + p_quant_data_msb[1] = aaInData[setIdx + 1] + startBand; + + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb[0], data_diff_freq[0], dataBands); + + calc_diff_freq(p_quant_data_msb[1], data_diff_freq[1], dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb[0], p_quant_data_hist_msb, + data_diff_time[0], dataBands); + } + + calc_diff_time(p_quant_data_msb[1], p_quant_data_msb[0], data_diff_time[1], + dataBands); + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(2 * dataBands, quant_levels); + num_pcm_val = 2 * dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df_df = + calc_huff_bits(data_diff_freq[0], data_diff_freq[1], data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df_df, &coding_scheme_df_df); + + min_bits_df_df += 2; + + min_bits_df_df += num_lsb_bits; + + if (min_bits_df_df < min_bits_all) { + min_bits_all = min_bits_df_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_df_dt = + calc_huff_bits(data_diff_freq[0], data_diff_time[1], data_type, DIFF_FREQ, + DIFF_TIME, dataBands, lav_df_dt, &coding_scheme_df_dt); + + min_bits_df_dt += 2; + + min_bits_df_dt += num_lsb_bits; + + if (min_bits_df_dt < min_bits_all) { + min_bits_all = min_bits_df_dt; + } + /**********************************************************/ + + /**********************************************************/ + /**********************************************************/ + + if (allowDiffTimeBack_flag) { + /**********************************************************/ + min_bits_dtbw_df = calc_huff_bits( + data_diff_time[0], data_diff_freq[1], data_type, DIFF_TIME, DIFF_FREQ, + dataBands, lav_dtbw_df, &coding_scheme_dtbw_df); + + min_bits_dtbw_df += 2; + + min_bits_dtbw_df += num_lsb_bits; + + if (min_bits_dtbw_df < min_bits_all) { + min_bits_all = min_bits_dtbw_df; + } + /**********************************************************/ + + /**********************************************************/ + min_bits_dt_dt = calc_huff_bits(data_diff_time[0], data_diff_time[1], + data_type, DIFF_TIME, DIFF_TIME, dataBands, + lav_dt_dt, &coding_scheme_dt_dt); + + min_bits_dt_dt += 2; + + min_bits_dt_dt += num_lsb_bits; + + if (min_bits_dt_dt < min_bits_all) { + min_bits_all = min_bits_dt_dt; + } + /**********************************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, + aaInData[setIdx + 1] + startBand, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df_df) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_freq[1], data_type, + DIFF_FREQ, DIFF_FREQ, dataBands, lav_df_df, + coding_scheme_df_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_df_dt)) { + FDKwriteBits(strm, DIFF_FREQ, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_freq[0], data_diff_time[1], data_type, + DIFF_FREQ, DIFF_TIME, dataBands, lav_df_dt, + coding_scheme_df_dt); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + /*******************************************/ + + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dtbw_df)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_FREQ, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_freq[1], data_type, + DIFF_TIME, DIFF_FREQ, dataBands, lav_dtbw_df, + coding_scheme_dtbw_df); + + min_found = 1; + } + /*******************************************/ + + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time[0], data_diff_time[1], data_type, + DIFF_TIME, DIFF_TIME, dataBands, lav_dt_dt, + coding_scheme_dt_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb[0], 1, dataBands); + + apply_lsb_coding(strm, quant_data_lsb[1], 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag) { + SHORT reset = 0, pb = 0; + SHORT quant_levels = 0, quant_offset = 0, num_pcm_val = 0; + + SHORT splitLsb_flag = 0; + SHORT pcmCoding_flag = 0; + + SHORT allowDiffTimeBack_flag = !independency_flag || (setIdx > 0); + + SHORT num_lsb_bits = -1; + SHORT num_pcm_bits = -1; + + SHORT quant_data_lsb[MAXBANDS]; + SHORT quant_data_msb[MAXBANDS]; + + SHORT quant_data_hist_lsb[MAXBANDS]; + SHORT quant_data_hist_msb[MAXBANDS]; + + SHORT data_diff_freq[MAXBANDS]; + SHORT data_diff_time[MAXBANDS + 2]; + + SHORT *p_quant_data_msb; + SHORT *p_quant_data_hist_msb = NULL; + + SHORT min_bits_all = 0; + SHORT min_found = 0; + + SHORT min_bits_df = -1; + SHORT min_bits_dt = -1; + + SHORT lav_df[2] = {-1, -1}; + SHORT lav_dt[2] = {-1, -1}; + + SHORT coding_scheme_df = 0; + SHORT coding_scheme_dt = 0; + + switch (data_type) { + case t_CLD: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 15; + quant_offset = 7; + } else { + splitLsb_flag = 0; + quant_levels = 31; + quant_offset = 15; + } + break; + case t_ICC: + if (coarse_flag) { + splitLsb_flag = 0; + quant_levels = 4; + quant_offset = 0; + } else { + splitLsb_flag = 0; + quant_levels = 8; + quant_offset = 0; + } + break; + } /* switch( data_type ) */ + + /* Split off LSB */ + if (splitLsb_flag) { + split_lsb(aaInData[setIdx] + startBand, quant_offset, dataBands, + quant_data_lsb, quant_data_msb); + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = dataBands; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_msb[pb] = aaInData[setIdx][startBand + pb] + quant_offset; + } + + p_quant_data_msb = quant_data_msb; + num_lsb_bits = 0; + } else { + p_quant_data_msb = aaInData[setIdx] + startBand; + num_lsb_bits = 0; + } + + if (allowDiffTimeBack_flag) { + if (splitLsb_flag) { + split_lsb(aHistory + startBand, quant_offset, dataBands, + quant_data_hist_lsb, quant_data_hist_msb); + + p_quant_data_hist_msb = quant_data_hist_msb; + } else if (quant_offset != 0) { + for (pb = 0; pb < dataBands; pb++) { + quant_data_hist_msb[pb] = aHistory[startBand + pb] + quant_offset; + } + p_quant_data_hist_msb = quant_data_hist_msb; + } else { + p_quant_data_hist_msb = aHistory + startBand; + } + } + + /* Calculate frequency differences */ + calc_diff_freq(p_quant_data_msb, data_diff_freq, dataBands); + + /* Calculate time differences */ + if (allowDiffTimeBack_flag) { + calc_diff_time(p_quant_data_msb, p_quant_data_hist_msb, data_diff_time, + dataBands); + } + + /* Calculate coding scheme with minumum bit consumption */ + + /**********************************************************/ + num_pcm_bits = calc_pcm_bits(dataBands, quant_levels); + num_pcm_val = dataBands; + + /**********************************************************/ + + min_bits_all = num_pcm_bits; + + /**********************************************************/ + /**********************************************************/ + + /**********************************************************/ + min_bits_df = calc_huff_bits(data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, &coding_scheme_df); + + if (allowDiffTimeBack_flag) min_bits_df += 1; + + min_bits_df += num_lsb_bits; + + if (min_bits_df < min_bits_all) { + min_bits_all = min_bits_df; + } + /**********************************************************/ + + /**********************************************************/ + if (allowDiffTimeBack_flag) { + min_bits_dt = + calc_huff_bits(data_diff_time, NULL, data_type, DIFF_TIME, DIFF_TIME, + dataBands, lav_dt, &coding_scheme_dt); + + min_bits_dt += 1; + min_bits_dt += num_lsb_bits; + + if (min_bits_dt < min_bits_all) { + min_bits_all = min_bits_dt; + } + } /* if( allowDiffTimeBack_flag ) */ + + /***************************/ + /* Start actual coding now */ + /***************************/ + + /* PCM or Diff/Huff Coding? */ + pcmCoding_flag = (min_bits_all == num_pcm_bits); + + FDKwriteBits(strm, pcmCoding_flag, 1); + + if (pcmCoding_flag) { + /* Grouped PCM Coding */ + apply_pcm_coding(strm, aaInData[setIdx] + startBand, NULL, quant_offset, + num_pcm_val, quant_levels); + } else { + /* Diff/Huff Coding */ + + min_found = 0; + + /*******************************************/ + if (min_bits_all == min_bits_df) { + if (allowDiffTimeBack_flag) { + FDKwriteBits(strm, DIFF_FREQ, 1); + } + + apply_huff_coding(strm, data_diff_freq, NULL, data_type, DIFF_FREQ, + DIFF_FREQ, dataBands, lav_df, coding_scheme_df); + + min_found = 1; + } /* if( min_bits_all == min_bits_df ) */ + /*******************************************/ + + /*******************************************/ + if (allowDiffTimeBack_flag) { + /*******************************************/ + if (!min_found && (min_bits_all == min_bits_dt)) { + FDKwriteBits(strm, DIFF_TIME, 1); + + apply_huff_coding(strm, data_diff_time, NULL, data_type, DIFF_TIME, + DIFF_TIME, dataBands, lav_dt, coding_scheme_dt); + } + /*******************************************/ + + } /* if( allowDiffTimeBack_flag ) */ + + /* LSB coding */ + if (splitLsb_flag) { + apply_lsb_coding(strm, quant_data_lsb, 1, dataBands); + } + + } /* Diff/Huff/LSB coding */ + + return reset; +} diff --git a/fdk-aac/libSACenc/src/sacenc_nlc_enc.h b/fdk-aac/libSACenc/src/sacenc_nlc_enc.h new file mode 100644 index 0000000..506b308 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_nlc_enc.h @@ -0,0 +1,141 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Karsten Linzmeier + + Description: Noiseless Coding + Huffman encoder + +*******************************************************************************/ + +#ifndef SACENC_NLC_ENC_H +#define SACENC_NLC_ENC_H + +/* Includes ******************************************************************/ +#include "sacenc_const.h" +#include "FDK_bitstream.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAXBANDS MAX_NUM_BINS /* maximum number of frequency bands */ + +/* Data Types ****************************************************************/ +typedef enum { + t_CLD, + t_ICC + +} DATA_TYPE; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +INT fdk_sacenc_ecDataPairEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +INT fdk_sacenc_ecDataSingleEnc(HANDLE_FDK_BITSTREAM strm, + SHORT aaInData[][MAXBANDS], + SHORT aHistory[MAXBANDS], + const DATA_TYPE data_type, const INT setIdx, + const INT startBand, const INT dataBands, + const INT coarse_flag, + const INT independency_flag); + +#endif /* SACENC_NLC_ENC_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_onsetdetect.cpp b/fdk-aac/libSACenc/src/sacenc_onsetdetect.cpp new file mode 100644 index 0000000..7e9aee1 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_onsetdetect.cpp @@ -0,0 +1,381 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Detect Onset in current frame + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_onsetdetect.h" +#include "genericStds.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define SPACE_ONSET_THRESHOLD (3.0) +#define SPACE_ONSET_THRESHOLD_SF (3) +#define SPACE_ONSET_THRESHOLD_SQUARE \ + (FL2FXCONST_DBL((1.0 / (SPACE_ONSET_THRESHOLD * SPACE_ONSET_THRESHOLD)) * \ + (float)(1 << SPACE_ONSET_THRESHOLD_SF))) + +/* Data Types ****************************************************************/ +struct ONSET_DETECT { + INT maxTimeSlots; + INT minTransientDistance; + INT avgEnergyDistance; + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + FIXP_DBL *pEnergyHist__FDK; + SCHAR *pEnergyHistScale; + SCHAR avgEnergyDistanceScale; +}; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_ONSET_DETECT hOnset = NULL; + + if (NULL == phOnset) { + error = SACENC_INVALID_HANDLE; + } else { + /* Memory Allocation */ + FDK_ALLOCATE_MEMORY_1D(hOnset, 1, struct ONSET_DETECT); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHist__FDK, 16 + maxTimeSlots, + FIXP_DBL); + FDK_ALLOCATE_MEMORY_1D(hOnset->pEnergyHistScale, 16 + maxTimeSlots, SCHAR); + + hOnset->maxTimeSlots = maxTimeSlots; + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + *phOnset = hOnset; + } + return error; + +bail: + fdk_sacenc_onsetDetect_Close(&hOnset); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL == hOnset) || (pOnsetDetectConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + if ((pOnsetDetectConfig->maxTimeSlots > hOnset->maxTimeSlots) || + (pOnsetDetectConfig->upperBoundOnsetDetection < + hOnset->lowerBoundOnsetDetection)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + hOnset->maxTimeSlots = pOnsetDetectConfig->maxTimeSlots; + hOnset->lowerBoundOnsetDetection = + pOnsetDetectConfig->lowerBoundOnsetDetection; + hOnset->upperBoundOnsetDetection = + pOnsetDetectConfig->upperBoundOnsetDetection; + + hOnset->minTransientDistance = + 8; /* minimum distance between detected transients */ + hOnset->avgEnergyDistance = 16; /* average energy distance */ + + hOnset->avgEnergyDistanceScale = 4; + + /* Init / Reset */ + if (initFlags) { + int i; + for (i = 0; i < hOnset->avgEnergyDistance + hOnset->maxTimeSlots; i++) + hOnset->pEnergyHistScale[i] = -(DFRACT_BITS - 3); + + FDKmemset_flex( + hOnset->pEnergyHist__FDK, + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON * (1 << (DFRACT_BITS - 3))), + hOnset->avgEnergyDistance + hOnset->maxTimeSlots); + } + } + +bail: + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((NULL != phOnset) && (NULL != *phOnset)) { + if (NULL != (*phOnset)->pEnergyHist__FDK) { + FDKfree((*phOnset)->pEnergyHist__FDK); + } + (*phOnset)->pEnergyHist__FDK = NULL; + + if (NULL != (*phOnset)->pEnergyHistScale) { + FDKfree((*phOnset)->pEnergyHistScale); + } + (*phOnset)->pEnergyHistScale = NULL; + FDKfree(*phOnset); + *phOnset = NULL; + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hOnset) { + error = SACENC_INVALID_HANDLE; + } else { + if (timeSlots > hOnset->maxTimeSlots) { + error = SACENC_INVALID_CONFIG; + } else { + int i; + /* Shift old data */ + for (i = 0; i < hOnset->avgEnergyDistance; i++) { + hOnset->pEnergyHist__FDK[i] = hOnset->pEnergyHist__FDK[i + timeSlots]; + hOnset->pEnergyHistScale[i] = hOnset->pEnergyHistScale[i + timeSlots]; + } + + /* Clear for new data */ + FDKmemset_flex(&hOnset->pEnergyHist__FDK[hOnset->avgEnergyDistance], + FL2FXCONST_DBL(SACENC_FLOAT_EPSILON), timeSlots); + } + } + return error; +} + +/**************************************************************************/ + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + FDKmemclear(envs, (16 + MAX_TIME_SLOTS) * sizeof(FIXP_DBL)); + + if ((hOnset == NULL) || (pTransientPos == NULL) || + (ppHybridData__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int i, ts, trCnt, currPos; + + if ((nTimeSlots < 0) || (nTimeSlots > hOnset->maxTimeSlots) || + (hOnset->lowerBoundOnsetDetection < -1) || + (hOnset->upperBoundOnsetDetection > nHybridBands)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + const int lowerBoundOnsetDetection = hOnset->lowerBoundOnsetDetection; + const int upperBoundOnsetDetection = hOnset->upperBoundOnsetDetection; + const int M = hOnset->avgEnergyDistance; + + { + SCHAR *envScale = hOnset->pEnergyHistScale; + FIXP_DBL *env = hOnset->pEnergyHist__FDK; + const FIXP_DBL threshold_square = SPACE_ONSET_THRESHOLD_SQUARE; + + trCnt = 0; + + /* reset transient array */ + FDKmemset_flex(pTransientPos, -1, MAX_NUM_TRANS); + + /* minimum transient distance of minTransDist QMF samples */ + if (prevPos > 0) { + currPos = FDKmax(nTimeSlots, + prevPos - nTimeSlots + hOnset->minTransientDistance); + } else { + currPos = nTimeSlots; + } + + /* get energy and scalefactor for each time slot */ + int outScale; + int inScale = 3; /* scale factor determined empirically */ + for (ts = 0; ts < nTimeSlots; ts++) { + env[M + ts] = sumUpCplxPow2( + &ppHybridData__FDK[ts][lowerBoundOnsetDetection + 1], + SUM_UP_DYNAMIC_SCALE, inScale, &outScale, + upperBoundOnsetDetection - lowerBoundOnsetDetection - 1); + envScale[M + ts] = outScale + (hybridDataScale << 1); + } + + /* calculate common scale for all time slots */ + SCHAR maxScale = -(DFRACT_BITS - 1); + for (i = 0; i < (nTimeSlots + M); i++) { + maxScale = fixMax(maxScale, envScale[i]); + } + + /* apply common scale and store energy in temporary buffer */ + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = env[i] >> fixMin((maxScale - envScale[i]), (DFRACT_BITS - 1)); + } + + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < (nTimeSlots + M); i++) { + maxVal |= fAbs(envs[i]); + } + + int s = fixMax(0, CntLeadingZeros(maxVal) - 1); + + for (i = 0; i < (nTimeSlots + M); i++) { + envs[i] = envs[i] << s; + } + + int currPosPrev = currPos; + FIXP_DBL p1, p2; + p2 = FL2FXCONST_DBL(0.0f); + for (; (currPos < (nTimeSlots << 1)) && (trCnt < MAX_NUM_TRANS); + currPos++) { + p1 = fMultDiv2(envs[currPos - nTimeSlots + M], threshold_square) >> + (SPACE_ONSET_THRESHOLD_SF - 1); + + /* Calculate average of past M energy values */ + if (currPosPrev == (currPos - 1)) { + /* remove last and add new element */ + p2 -= (envs[currPosPrev - nTimeSlots] >> + (int)hOnset->avgEnergyDistanceScale); + p2 += (envs[currPos - nTimeSlots + M - 1] >> + (int)hOnset->avgEnergyDistanceScale); + } else { + /* calculate complete vector */ + p2 = FL2FXCONST_DBL(0.0f); + for (ts = 0; ts < M; ts++) { + p2 += (envs[currPos - nTimeSlots + ts] >> + (int)hOnset->avgEnergyDistanceScale); + } + } + currPosPrev = currPos; + + { + /* save position if transient found */ + if (p1 > p2) { + pTransientPos[trCnt++] = currPos; + currPos += hOnset->minTransientDistance; + } + } + } /* for currPos */ + } + + } /* valid handle*/ +bail: + + C_ALLOC_SCRATCH_END(envs, FIXP_DBL, (16 + MAX_TIME_SLOTS)) + + return error; +} + +/**************************************************************************/ diff --git a/fdk-aac/libSACenc/src/sacenc_onsetdetect.h b/fdk-aac/libSACenc/src/sacenc_onsetdetect.h new file mode 100644 index 0000000..5f3f0bd --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_onsetdetect.h @@ -0,0 +1,154 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Determine TES flags + +*******************************************************************************/ + +#ifndef SACENC_ONSETDETECT_H +#define SACENC_ONSETDETECT_H + +/**************************************************************************/ /** + \file + Description of file contents + ******************************************************************************/ + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "FDK_matrixCalloc.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" /* for def. of MAX_NUM_PARAMS */ + +/* Defines *******************************************************************/ +#define MAX_NUM_TRANS (MAX_NUM_PARAMS / 2) + +/* Data Types ****************************************************************/ +typedef struct T_ONSET_DETECT_CONFIG { + INT maxTimeSlots; + + /* calc transien detection in ]lowerBoundOnsetDetection; + * upperBoundOnsetDetection[ */ + INT lowerBoundOnsetDetection; + INT upperBoundOnsetDetection; + +} ONSET_DETECT_CONFIG; + +typedef struct ONSET_DETECT *HANDLE_ONSET_DETECT; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Open(HANDLE_ONSET_DETECT *phOnset, + const UINT maxTimeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Init( + HANDLE_ONSET_DETECT hOnset, + const ONSET_DETECT_CONFIG *const pOnsetDetectConfig, const UINT initFlags); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Close(HANDLE_ONSET_DETECT *phOnset); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Update(HANDLE_ONSET_DETECT hOnset, + const INT timeSlots); + +FDK_SACENC_ERROR fdk_sacenc_onsetDetect_Apply( + HANDLE_ONSET_DETECT hOnset, const INT nTimeSlots, const INT nHybridBands, + FIXP_DPK *const *const ppHybridData__FDK, const INT hybridDataScale, + const INT prevPos, INT pTransientPos[MAX_NUM_TRANS]); + +#endif /* SACENC_ONSETDETECT_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_paramextract.cpp b/fdk-aac/libSACenc/src/sacenc_paramextract.cpp new file mode 100644 index 0000000..dcbce1e --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_paramextract.cpp @@ -0,0 +1,725 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_paramextract.h" +#include "sacenc_tree.h" +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ +#define LOG10_2_10 (3.01029995664f) /* 10.0f*log10(2.f) */ +#define SCALE_CLDE_SF (7) /* maxVal in Quant tab is +/- 50 */ +#define SCALE_CLDD_SF (8) /* maxVal in Quant tab is +/- 150 */ + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX { + FIXP_DBL pCld__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pIcc__FDK[MAX_NUM_PARAM_BANDS]; + FIXP_DBL pCldQuant__FDK[MAX_NUM_PARAM_BANDS]; + + const FIXP_DBL *pIccQuantTable__FDK; + const FIXP_DBL *pCldQuantTableDec__FDK; + const FIXP_DBL *pCldQuantTableEnc__FDK; + + SCHAR pCldEbQIdx[MAX_NUM_PARAM_BANDS]; + SCHAR pIccDownmixIdx[MAX_NUM_PARAM_BANDS]; + + UCHAR *pParameterBand2HybridBandOffset; + const INT *pSubbandImagSign; + UCHAR nHybridBandsMax; + UCHAR nParameterBands; + UCHAR bFrameKeep; + + UCHAR iccCorrelationCoherenceBorder; + BOX_QUANTMODE boxQuantMode; + + UCHAR nIccQuantSteps; + UCHAR nIccQuantOffset; + + UCHAR nCldQuantSteps; + UCHAR nCldQuantOffset; + + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + +} TTO_BOX; + +struct BOX_SUBBAND_SETUP { + BOX_SUBBAND_CONFIG subbandConfig; + UCHAR nParameterBands; + const UCHAR *pSubband2ParameterIndexLd; + UCHAR iccCorrelationCoherenceBorder; +}; + +/* Constants *****************************************************************/ +static const UCHAR subband2Parameter4_Ld[NUM_QMF_BANDS] = { + 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}; + +static const UCHAR subband2Parameter5_Ld[NUM_QMF_BANDS] = { + 0, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4}; + +static const UCHAR subband2Parameter7_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6}; + +static const UCHAR subband2Parameter9_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8}; + +static const UCHAR subband2Parameter12_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, + 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11}; + +static const UCHAR subband2Parameter15_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 10, 10, 11, 11, + 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14}; + +static const UCHAR subband2Parameter23_Ld[NUM_QMF_BANDS] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 12, 13, 13, + 14, 14, 15, 15, 16, 16, 16, 17, 17, 17, 18, 18, 18, 18, 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, 22, 22, 22, 22, 22, 22}; + +static const INT subbandImagSign_Ld[NUM_QMF_BANDS] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + +#define SCALE_CLDE(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDE_SF))) +static const FIXP_DBL cldQuantTableFineEnc__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-45.0), SCALE_CLDE(-40.0), SCALE_CLDE(-35.0), + SCALE_CLDE(-30.0), SCALE_CLDE(-25.0), SCALE_CLDE(-22.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-16.0), SCALE_CLDE(-13.0), SCALE_CLDE(-10.0), SCALE_CLDE(-8.0), + SCALE_CLDE(-6.0), SCALE_CLDE(-4.0), SCALE_CLDE(-2.0), SCALE_CLDE(0.0), + SCALE_CLDE(2.0), SCALE_CLDE(4.0), SCALE_CLDE(6.0), SCALE_CLDE(8.0), + SCALE_CLDE(10.0), SCALE_CLDE(13.0), SCALE_CLDE(16.0), SCALE_CLDE(19.0), + SCALE_CLDE(22.0), SCALE_CLDE(25.0), SCALE_CLDE(30.0), SCALE_CLDE(35.0), + SCALE_CLDE(40.0), SCALE_CLDE(45.0), SCALE_CLDE(50.0)}; + +static const FIXP_DBL cldQuantTableCoarseEnc__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDE(-50.0), SCALE_CLDE(-35.0), SCALE_CLDE(-25.0), SCALE_CLDE(-19.0), + SCALE_CLDE(-13.0), SCALE_CLDE(-8.0), SCALE_CLDE(-4.0), SCALE_CLDE(0.0), + SCALE_CLDE(4.0), SCALE_CLDE(8.0), SCALE_CLDE(13.0), SCALE_CLDE(19.0), + SCALE_CLDE(25.0), SCALE_CLDE(35.0), SCALE_CLDE(50.0)}; + +#define SCALE_CLDD(a) (FL2FXCONST_DBL(a / (float)(1 << SCALE_CLDD_SF))) +static const FIXP_DBL cldQuantTableFineDec__FDK[MAX_CLD_QUANT_FINE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-45.0), SCALE_CLDD(-40.0), SCALE_CLDD(-35.0), + SCALE_CLDD(-30.0), SCALE_CLDD(-25.0), SCALE_CLDD(-22.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-16.0), SCALE_CLDD(-13.0), SCALE_CLDD(-10.0), SCALE_CLDD(-8.0), + SCALE_CLDD(-6.0), SCALE_CLDD(-4.0), SCALE_CLDD(-2.0), SCALE_CLDD(0.0), + SCALE_CLDD(2.0), SCALE_CLDD(4.0), SCALE_CLDD(6.0), SCALE_CLDD(8.0), + SCALE_CLDD(10.0), SCALE_CLDD(13.0), SCALE_CLDD(16.0), SCALE_CLDD(19.0), + SCALE_CLDD(22.0), SCALE_CLDD(25.0), SCALE_CLDD(30.0), SCALE_CLDD(35.0), + SCALE_CLDD(40.0), SCALE_CLDD(45.0), SCALE_CLDD(150.0)}; + +static const FIXP_DBL cldQuantTableCoarseDec__FDK[MAX_CLD_QUANT_COARSE] = { + SCALE_CLDD(-150.0), SCALE_CLDD(-35.0), SCALE_CLDD(-25.0), SCALE_CLDD(-19.0), + SCALE_CLDD(-13.0), SCALE_CLDD(-8.0), SCALE_CLDD(-4.0), SCALE_CLDD(0.0), + SCALE_CLDD(4.0), SCALE_CLDD(8.0), SCALE_CLDD(13.0), SCALE_CLDD(19.0), + SCALE_CLDD(25.0), SCALE_CLDD(35.0), SCALE_CLDD(150.0)}; + +#define SCALE_ICC(a) (FL2FXCONST_DBL(a)) +static const FIXP_DBL iccQuantTableFine__FDK[MAX_ICC_QUANT_FINE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.937f), SCALE_ICC(0.84118f), + SCALE_ICC(0.60092f), SCALE_ICC(0.36764f), SCALE_ICC(0.0f), + SCALE_ICC(-0.589f), SCALE_ICC(-0.99f)}; + +static const FIXP_DBL iccQuantTableCoarse__FDK[MAX_ICC_QUANT_COARSE] = { + SCALE_ICC(0.99999999953), SCALE_ICC(0.84118f), SCALE_ICC(0.36764f), + SCALE_ICC(-0.5890f)}; + +static const BOX_SUBBAND_SETUP boxSubbandSetup[] = { + {BOX_SUBBANDS_4, 4, subband2Parameter4_Ld, 1}, + {BOX_SUBBANDS_5, 5, subband2Parameter5_Ld, 2}, + {BOX_SUBBANDS_7, 7, subband2Parameter7_Ld, 3}, + {BOX_SUBBANDS_9, 9, subband2Parameter9_Ld, 4}, + {BOX_SUBBANDS_12, 12, subband2Parameter12_Ld, 4}, + {BOX_SUBBANDS_15, 15, subband2Parameter15_Ld, 5}, + {BOX_SUBBANDS_23, 23, subband2Parameter23_Ld, 8}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static const BOX_SUBBAND_SETUP *getBoxSubbandSetup( + const BOX_SUBBAND_CONFIG subbandConfig) { + int i; + const BOX_SUBBAND_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(boxSubbandSetup) / sizeof(BOX_SUBBAND_SETUP)); + i++) { + if (boxSubbandSetup[i].subbandConfig == subbandConfig) { + setup = &boxSubbandSetup[i]; + break; + } + } + return setup; +} + +static inline void ApplyBBCuesFDK(FIXP_DBL *const pData, + const INT nParamBands) { + int i, s; + FIXP_DBL tmp, invParamBands; + + invParamBands = fDivNormHighPrec((FIXP_DBL)1, (FIXP_DBL)nParamBands, &s); + s = -s; + + tmp = fMult(pData[0], invParamBands) >> s; + for (i = 1; i < nParamBands; i++) { + tmp += fMult(pData[i], invParamBands) >> s; + } + + for (i = 0; i < nParamBands; i++) { + pData[i] = tmp; + } +} + +static INT getNumberParameterBands(const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ((setup == NULL) ? 0 : setup->nParameterBands); +} + +static const UCHAR *getSubband2ParameterIndex( + const BOX_SUBBAND_CONFIG subbandConfig) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + + return ((setup == NULL) ? NULL : (setup->pSubband2ParameterIndexLd)); +} + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + const UCHAR *pSubband2ParameterIndex; + + int i, pb; + + pSubband2ParameterIndex = setup->pSubband2ParameterIndexLd; + + for (pb = 0, i = 0; i < nHybridBands - 1; i++) { + if (pSubband2ParameterIndex[i + 1] - pSubband2ParameterIndex[i]) { + pParameterBand2HybridBandOffset[pb++] = (i + 1); + } + } + pParameterBand2HybridBandOffset[pb++] = (i + 1); +} + +const INT *fdk_sacenc_getSubbandImagSign() { + const INT *pImagSign = NULL; + + pImagSign = subbandImagSign_Ld; + + return (pImagSign); +} + +static INT getIccCorrelationCoherenceBorder( + const BOX_SUBBAND_CONFIG subbandConfig, const INT bUseCoherenceOnly) { + const BOX_SUBBAND_SETUP *setup = getBoxSubbandSetup(subbandConfig); + return ( + (setup == NULL) + ? 0 + : ((bUseCoherenceOnly) ? 0 : setup->iccCorrelationCoherenceBorder)); +} + +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hTtoBox) { + error = SACENC_INVALID_HANDLE; + } else { + FDK_ALLOCATE_MEMORY_1D(*hTtoBox, 1, TTO_BOX); + } + return error; + +bail: + fdk_sacenc_destroyTtoBox(hTtoBox); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hTtoBox == NULL) || (ttoBoxConfig == NULL) || + (pParameterBand2HybridBandOffset == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKmemclear(hTtoBox, sizeof(TTO_BOX)); + + hTtoBox->bUseCoarseQuantCld = ttoBoxConfig->bUseCoarseQuantCld; + hTtoBox->bUseCoarseQuantIcc = ttoBoxConfig->bUseCoarseQuantIcc; + hTtoBox->boxQuantMode = ttoBoxConfig->boxQuantMode; + hTtoBox->iccCorrelationCoherenceBorder = getIccCorrelationCoherenceBorder( + ttoBoxConfig->subbandConfig, ttoBoxConfig->bUseCoherenceIccOnly); + hTtoBox->nHybridBandsMax = ttoBoxConfig->nHybridBandsMax; + hTtoBox->nParameterBands = + getNumberParameterBands(ttoBoxConfig->subbandConfig); + hTtoBox->bFrameKeep = ttoBoxConfig->bFrameKeep; + + hTtoBox->nIccQuantSteps = + fdk_sacenc_getNumberIccQuantLevels(hTtoBox->bUseCoarseQuantIcc); + hTtoBox->nIccQuantOffset = + fdk_sacenc_getIccQuantOffset(hTtoBox->bUseCoarseQuantIcc); + + hTtoBox->pIccQuantTable__FDK = hTtoBox->bUseCoarseQuantIcc + ? iccQuantTableCoarse__FDK + : iccQuantTableFine__FDK; + hTtoBox->pCldQuantTableDec__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseDec__FDK + : cldQuantTableFineDec__FDK; + hTtoBox->pCldQuantTableEnc__FDK = hTtoBox->bUseCoarseQuantCld + ? cldQuantTableCoarseEnc__FDK + : cldQuantTableFineEnc__FDK; + + hTtoBox->nCldQuantSteps = + fdk_sacenc_getNumberCldQuantLevels(hTtoBox->bUseCoarseQuantCld); + hTtoBox->nCldQuantOffset = + fdk_sacenc_getCldQuantOffset(hTtoBox->bUseCoarseQuantCld); + + /* sanity */ + if (NULL == (hTtoBox->pParameterBand2HybridBandOffset = + pParameterBand2HybridBandOffset)) { + error = SACENC_INIT_ERROR; + goto bail; + } + + if (NULL == (hTtoBox->pSubbandImagSign = fdk_sacenc_getSubbandImagSign())) { + error = SACENC_INIT_ERROR; + } + + if ((hTtoBox->boxQuantMode != BOX_QUANTMODE_FINE) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ1) && + (hTtoBox->boxQuantMode != BOX_QUANTMODE_EBQ2)) { + error = SACENC_INIT_ERROR; + goto bail; + } + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (*hTtoBox != NULL) { + FDKfree(*hTtoBox); + *hTtoBox = NULL; + } + + return error; +} + +static FDK_SACENC_ERROR calculateIccFDK(const INT nParamBand, + const INT correlationCoherenceBorder, + const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, + const FIXP_DBL *const pProdReal, + FIXP_DBL const *const pProdImag, + FIXP_DBL *const pIcc) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((pPwr1 == NULL) || (pPwr2 == NULL) || (pProdReal == NULL) || + (pProdImag == NULL) || (pIcc == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + /* sanity check border */ + if (correlationCoherenceBorder > nParamBand) { + error = SACENC_INVALID_CONFIG; + } else { + /* correlation */ + FDKcalcCorrelationVec(pIcc, pProdReal, pPwr1, pPwr2, + correlationCoherenceBorder); + + /* coherence */ + calcCoherenceVec(&pIcc[correlationCoherenceBorder], + &pProdReal[correlationCoherenceBorder], + &pProdImag[correlationCoherenceBorder], + &pPwr1[correlationCoherenceBorder], + &pPwr2[correlationCoherenceBorder], 0, 0, + nParamBand - correlationCoherenceBorder); + + } /* valid configuration */ + } /* valid handle */ + + return error; +} + +static void QuantizeCoefFDK(const FIXP_DBL *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, const INT nQuantSteps, + SCHAR *const quantOut) { + int band; + const int reverse = (quantTable[0] > quantTable[1]); + + for (band = 0; band < nBands; band++) { + FIXP_DBL qVal; + FIXP_DBL curVal = input[band]; + + int lower = 0; + int upper = nQuantSteps - 1; + + if (reverse) { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal >= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) >= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* if reverse */ + else { + while (upper - lower > 1) { + int idx = (lower + upper) >> 1; + qVal = quantTable[idx]; + if (curVal <= qVal) { + upper = idx; + } else { + lower = idx; + } + } /* while */ + + if ((curVal - quantTable[lower]) <= (quantTable[upper] - curVal)) { + quantOut[band] = lower - idxOffset; + } else { + quantOut[band] = upper - idxOffset; + } + } /* else reverse */ + } /* for band */ +} + +static void deQuantizeCoefFDK(const SCHAR *const input, const INT nBands, + const FIXP_DBL *const quantTable, + const INT idxOffset, FIXP_DBL *const dequantOut) { + int band; + + for (band = 0; band < nBands; band++) { + dequantOut[band] = quantTable[input[band] + idxOffset]; + } +} + +static void CalculateCldFDK(FIXP_DBL *const pCld, const FIXP_DBL *const pPwr1, + const FIXP_DBL *const pPwr2, const INT scaleCh1, + const INT *const pbScaleCh1, const INT scaleCh2, + const INT *const pbScaleCh2, const int nParamBand) { + INT i; + FIXP_DBL ldPwr1, ldPwr2, cld; + FIXP_DBL maxPwr = FL2FXCONST_DBL( + 30.0f / + (1 << (LD_DATA_SHIFT + + 1))); /* consider SACENC_FLOAT_EPSILON in power calculation */ + + for (i = 0; i < nParamBand; i++) { + ldPwr1 = + (CalcLdData(pPwr1[i]) >> 1) + ((FIXP_DBL)(scaleCh1 + pbScaleCh1[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + ldPwr2 = + (CalcLdData(pPwr2[i]) >> 1) + ((FIXP_DBL)(scaleCh2 + pbScaleCh2[i]) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT)); + + ldPwr1 = fixMax(fixMin(ldPwr1, maxPwr), -maxPwr); + ldPwr2 = fixMax(fixMin(ldPwr2, maxPwr), -maxPwr); + + /* ldPwr1 and ldPwr2 are scaled by LD_DATA_SHIFT and additional 1 bit; 1 bit + * scale by fMultDiv2() */ + cld = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / (1 << SCALE_CLDE_SF)), + ldPwr1 - ldPwr2); + + cld = + fixMin(cld, (FIXP_DBL)(((FIXP_DBL)MAXVAL_DBL) >> (LD_DATA_SHIFT + 2))); + cld = + fixMax(cld, (FIXP_DBL)(((FIXP_DBL)MINVAL_DBL) >> (LD_DATA_SHIFT + 2))); + pCld[i] = cld << (LD_DATA_SHIFT + 2); + } +} + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh1, + INT *scaleCh2) { + FDK_SACENC_ERROR error = SACENC_OK; + + C_ALLOC_SCRATCH_START(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_START(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_START(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + + if ((hTtoBox == NULL) || (pCldIdx == NULL) || (pbCldQuantCoarse == NULL) || + (ppHybridData1__FDK == NULL) || (ppHybridData2__FDK == NULL) || + (pIccIdx == NULL) || (pbIccQuantCoarse == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int j, pb; + const int nParamBands = hTtoBox->nParameterBands; + const int bUseEbQ = (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ1) || + (hTtoBox->boxQuantMode == BOX_QUANTMODE_EBQ2); + + /* sanity check */ + if ((nHybridBands < 0) || (nHybridBands > hTtoBox->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + int outScale; /* scalefactor will not be evaluated */ + int inScale = 5; /* scale factor determined empirically */ + + /* calculate the headroom of the hybrid data for each parameter band */ + FDKcalcPbScaleFactor(ppHybridData1__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh1, + startTimeSlot, nTimeSlots, nParamBands); + FDKcalcPbScaleFactor(ppHybridData2__FDK, + hTtoBox->pParameterBand2HybridBandOffset, pbScaleCh2, + startTimeSlot, nTimeSlots, nParamBands); + + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL data1, data2; + data1 = data2 = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + data1 += sumUpCplxPow2Dim2(ppHybridData1__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh1[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + data2 += sumUpCplxPow2Dim2(ppHybridData2__FDK, SUM_UP_STATIC_SCALE, + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + } /* for j */ + powerHybridData1__FDK[pb] = data1; + powerHybridData2__FDK[pb] = data2; + } /* pb */ + + { + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL dataReal, dataImag; + dataReal = dataImag = (FIXP_DBL)0; + for (; j < hTtoBox->pParameterBand2HybridBandOffset[pb]; j++) { + FIXP_DPK scalarProd; + cplx_cplxScalarProduct(&scalarProd, ppHybridData1__FDK, + ppHybridData2__FDK, inScale + pbScaleCh1[pb], + inScale + pbScaleCh2[pb], &outScale, + startTimeSlot, nTimeSlots, j, j + 1); + dataReal += scalarProd.v.re; + if (hTtoBox->pSubbandImagSign[j] < 0) { + dataImag -= scalarProd.v.im; + } else { + dataImag += scalarProd.v.im; + } + } /* for j */ + prodHybridDataReal__FDK[pb] = dataReal; + prodHybridDataImag__FDK[pb] = dataImag; + } /* pb */ + + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, hTtoBox->iccCorrelationCoherenceBorder, + powerHybridData1__FDK, powerHybridData2__FDK, + prodHybridDataReal__FDK, prodHybridDataImag__FDK, + hTtoBox->pIcc__FDK))) { + goto bail; + } + + /* calculate correlation based Icc for downmix */ + if (SACENC_OK != (error = calculateIccFDK( + nParamBands, nParamBands, powerHybridData1__FDK, + powerHybridData2__FDK, prodHybridDataReal__FDK, + prodHybridDataImag__FDK, IccDownmix__FDK))) { + goto bail; + } + } + + if (!bUseEbQ) { + CalculateCldFDK(hTtoBox->pCld__FDK, powerHybridData1__FDK, + powerHybridData2__FDK, *scaleCh1 + inScale + 1, + pbScaleCh1, *scaleCh2 + inScale + 1, pbScaleCh2, + nParamBands); + } + + if (bUseBBCues) { + ApplyBBCuesFDK(&hTtoBox->pCld__FDK[0], nParamBands); + + { ApplyBBCuesFDK(&hTtoBox->pIcc__FDK[0], nParamBands); } + + } /* bUseBBCues */ + + /* quantize/de-quantize icc */ + { + QuantizeCoefFDK(hTtoBox->pIcc__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, pIccIdx); + QuantizeCoefFDK(IccDownmix__FDK, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + hTtoBox->nIccQuantSteps, hTtoBox->pIccDownmixIdx); + deQuantizeCoefFDK(hTtoBox->pIccDownmixIdx, nParamBands, + hTtoBox->pIccQuantTable__FDK, hTtoBox->nIccQuantOffset, + IccDownmixQuant__FDK); + + *pbIccQuantCoarse = hTtoBox->bUseCoarseQuantIcc; + } + + /* quantize/de-quantize cld */ + if (!bUseEbQ) { + QuantizeCoefFDK(hTtoBox->pCld__FDK, nParamBands, + hTtoBox->pCldQuantTableEnc__FDK, hTtoBox->nCldQuantOffset, + hTtoBox->nCldQuantSteps, pCldIdx); + deQuantizeCoefFDK(pCldIdx, nParamBands, hTtoBox->pCldQuantTableDec__FDK, + hTtoBox->nCldQuantOffset, hTtoBox->pCldQuant__FDK); + } else { + FDKmemcpy(pCldIdx, hTtoBox->pCldEbQIdx, nParamBands * sizeof(SCHAR)); + } + *pbCldQuantCoarse = hTtoBox->bUseCoarseQuantCld; + + } /* valid handle */ + +bail: + C_ALLOC_SCRATCH_END(pbScaleCh2, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(pbScaleCh1, INT, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmixQuant__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(IccDownmix__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + C_ALLOC_SCRATCH_END(prodHybridDataImag__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(prodHybridDataReal__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData2__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + C_ALLOC_SCRATCH_END(powerHybridData1__FDK, FIXP_DBL, MAX_NUM_PARAM_BANDS) + + return error; +} + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband) { + INT nParamBand = -1; + const UCHAR *pSubband2ParameterIndex = + getSubband2ParameterIndex(boxSubbandConfig); + + if (pSubband2ParameterIndex != NULL) { + const int hybrid_resolution = 64; + + if ((nSubband > -1) && (nSubband < hybrid_resolution)) { + nParamBand = pSubband2ParameterIndex[nSubband]; + } + } + + return nParamBand; +} diff --git a/fdk-aac/libSACenc/src/sacenc_paramextract.h b/fdk-aac/libSACenc/src/sacenc_paramextract.h new file mode 100644 index 0000000..9ebb902 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_paramextract.h @@ -0,0 +1,214 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): M. Multrus + + Description: Parameter Extraction + +*******************************************************************************/ + +#ifndef SACENC_PARAMEXTRACT_H +#define SACENC_PARAMEXTRACT_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define MAX_CLD_QUANT_FINE (31) +#define MAX_CLD_QUANT_COARSE (15) +#define OFFSET_CLD_QUANT_COARSE (7) +#define OFFSET_CLD_QUANT_FINE (15) + +#define MAX_ICC_QUANT_COARSE (4) +#define MAX_ICC_QUANT_FINE (8) +#define OFFSET_ICC_QUANT_COARSE (0) +#define OFFSET_ICC_QUANT_FINE (0) + +#define MAX_NUM_PARAM_BANDS (28) + +#define NUM_MAPPED_HYBRID_BANDS (16) + +/* Data Types ****************************************************************/ +typedef struct T_TTO_BOX *HANDLE_TTO_BOX; + +typedef enum { + BOX_SUBBANDS_INVALID = 0, + BOX_SUBBANDS_4 = 4, + BOX_SUBBANDS_5 = 5, + BOX_SUBBANDS_7 = 7, + BOX_SUBBANDS_9 = 9, + BOX_SUBBANDS_12 = 12, + BOX_SUBBANDS_15 = 15, + BOX_SUBBANDS_23 = 23 + +} BOX_SUBBAND_CONFIG; + +typedef enum { + BOX_QUANTMODE_INVALID = -1, + BOX_QUANTMODE_FINE = 0, + BOX_QUANTMODE_EBQ1 = 1, + BOX_QUANTMODE_EBQ2 = 2, + BOX_QUANTMODE_RESERVED3 = 3, + BOX_QUANTMODE_RESERVED4 = 4, + BOX_QUANTMODE_RESERVED5 = 5, + BOX_QUANTMODE_RESERVED6 = 6, + BOX_QUANTMODE_RESERVED7 = 7 + +} BOX_QUANTMODE; + +typedef struct T_TTO_BOX_CONFIG { + UCHAR bUseCoarseQuantCld; + UCHAR bUseCoarseQuantIcc; + UCHAR bUseCoherenceIccOnly; + + BOX_SUBBAND_CONFIG subbandConfig; + BOX_QUANTMODE boxQuantMode; + + UCHAR nHybridBandsMax; + + UCHAR bFrameKeep; + +} TTO_BOX_CONFIG; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_createTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_initTtoBox(HANDLE_TTO_BOX hTtoBox, + const TTO_BOX_CONFIG *const ttoBoxConfig, + UCHAR *pParameterBand2HybridBandOffset); + +FDK_SACENC_ERROR fdk_sacenc_destroyTtoBox(HANDLE_TTO_BOX *hTtoBox); + +FDK_SACENC_ERROR fdk_sacenc_applyTtoBox( + HANDLE_TTO_BOX hTtoBox, const INT nTimeSlots, const INT startTimeSlot, + const INT nHybridBands, const FIXP_DPK *const *const ppHybridData1__FDK, + const FIXP_DPK *const *const ppHybridData2__FDK, SCHAR *const pIccIdx, + UCHAR *const pbIccQuantCoarse, SCHAR *const pCldIdx, + UCHAR *const pbCldQuantCoarse, const INT bUseBBCues, INT *scaleCh0, + INT *scaleCh1); + +INT fdk_sacenc_subband2ParamBand(const BOX_SUBBAND_CONFIG boxSubbandConfig, + const INT nSubband); + +const INT *fdk_sacenc_getSubbandImagSign(); + +void fdk_sacenc_calcParameterBand2HybridBandOffset( + const BOX_SUBBAND_CONFIG subbandConfig, const INT nHybridBands, + UCHAR *pParameterBand2HybridBandOffset); + +/* Function / Class Definition ***********************************************/ +static inline UCHAR fdk_sacenc_getCldQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_CLD_QUANT_COARSE : OFFSET_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getIccQuantOffset(const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? OFFSET_ICC_QUANT_COARSE : OFFSET_ICC_QUANT_FINE); +} + +static inline UCHAR fdk_sacenc_getNumberCldQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_CLD_QUANT_COARSE : MAX_CLD_QUANT_FINE); +} +static inline UCHAR fdk_sacenc_getNumberIccQuantLevels( + const INT bUseCoarseQuant) { + return ((bUseCoarseQuant) ? MAX_ICC_QUANT_COARSE : MAX_ICC_QUANT_FINE); +} + +#endif /* SACENC_PARAMEXTRACT_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_staticgain.cpp b/fdk-aac/libSACenc/src/sacenc_staticgain.cpp new file mode 100644 index 0000000..fef9f8d --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_staticgain.cpp @@ -0,0 +1,446 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interface + gain management of the encoder + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains all static gain infrastructure +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_staticgain.h" + +/* Defines *******************************************************************/ +#define MP4SPACEENC_DMX_GAIN_DEFAULT SACENC_DMXGAIN_3_dB +#define GAINCF_SF (4) +#define GAINCT1(x) FL2FXCONST_DBL(x) +#define GAINCF(x) FL2FXCONST_DBL(x) + +#define GAINCT2(x) FL2FXCONST_DBL(x) +#define FX_DBL2FX_GAIN(x) (x) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN { + /* External Config Values */ + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; + + /* Internal Values */ + FIXP_GAIN PostGain__FDK; + FIXP_GAIN pPreGain__FDK[SACENC_MAX_INPUT_CHANNELS]; +}; + +/* Constants *****************************************************************/ +/* + preGainFactorTable: + + pre calculation: (float)pow(10.f,(((float) x)/20.f))/(float)(1<encMode = SACENC_INVALID_MODE; + + /* Optional Configs Set to Default Values */ + hStaticGainConfig->fixedGainDMX = MP4SPACEENC_DMX_GAIN_DEFAULT; + hStaticGainConfig->preGainFactorDb = 0; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_CloseConfig() +description: destructs Static Gain Config Structure +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGainConfig == NULL) || (*phStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGainConfig); + *phStaticGainConfig = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Open() +description: initializes Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == phStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + /* Allocate Instance */ + FDK_ALLOCATE_MEMORY_1D(*phStaticGain, 1, struct STATIC_GAIN); + } + return error; + +bail: + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hStaticGain == NULL) || (hStaticGainConfig == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGain->encMode = hStaticGainConfig->encMode; + hStaticGain->fixedGainDMX = hStaticGainConfig->fixedGainDMX; + hStaticGain->preGainFactorDb = hStaticGainConfig->preGainFactorDb; + + if ((hStaticGain->preGainFactorDb < -20) || + (hStaticGain->preGainFactorDb > 20)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + FIXP_DBL fPreGainFactor__FDK; + + if (hStaticGain->preGainFactorDb == 0) { + fPreGainFactor__FDK = (FIXP_DBL)MAXVAL_DBL; + *scale = 0; + } else { + int s; + fPreGainFactor__FDK = + preGainFactorTable__FDK[hStaticGain->preGainFactorDb + 20]; + s = fixMax(0, CntLeadingZeros(fPreGainFactor__FDK) - 1); + fPreGainFactor__FDK = fPreGainFactor__FDK << (s); + *scale = GAINCF_SF - s; + } + + if (hStaticGain->fixedGainDMX == 0) + hStaticGain->PostGain__FDK = MAXVAL_GAIN; + else + hStaticGain->PostGain__FDK = + dmxGainTable__FDK[hStaticGain->fixedGainDMX - 1]; + + FDKmemclear( + hStaticGain->pPreGain__FDK, + sizeof(hStaticGain->pPreGain__FDK)); /* zero all input channels */ + + /* Configure PreGain-Vector */ + if (hStaticGain->encMode == SACENC_212) { + hStaticGain->pPreGain__FDK[0] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* L */ + hStaticGain->pPreGain__FDK[1] = + FX_DBL2FX_GAIN(fPreGainFactor__FDK); /* R */ + } else { + error = SACENC_INVALID_CONFIG; + } + + } /* valid handle */ + +bail: + + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticGain_Close() +description: destructs Static Gains +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phStaticGain == NULL) || (*phStaticGain == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + FDKfree(*phStaticGain); + *phStaticGain = NULL; + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_staticPostGain_Apply +description: multiply the Output samples with the PostGain +returns: noError on success, an apropriate error code else +-----------------------------------------------------------------------------*/ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGain) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + FIXP_GAIN postGain = hStaticGain->PostGain__FDK; + + if (scale < 0) { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = pOutputSamples[i] >> (-scale); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])) >> (-scale)); + } + } + } else { + if (postGain == MAXVAL_GAIN) { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + FX_PCM2FX_DBL(pOutputSamples[i]), scale, DFRACT_BITS)); + } + } else { + for (i = 0; i < nOutputSamples; i++) { + pOutputSamples[i] = FX_DBL2FX_PCM(SATURATE_LEFT_SHIFT( + fMult(postGain, FX_PCM2FX_DBL(pOutputSamples[i])), scale, + DFRACT_BITS)); + } + } + } + } + return error; +} + +/*----------------------------------------------------------------------------- +functionname: fdk_sacenc_getPreGainPtr()/ fdk_sacenc_getPostGain() +description: get Gain-Pointers from struct +returns: Pointer to PreGain or postGain +-----------------------------------------------------------------------------*/ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain) { + return ((hStaticGain == NULL) ? NULL : hStaticGain->pPreGain__FDK); +} + +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain) { + return (hStaticGain->PostGain__FDK); +} + +/* get fixed downmix gain and map it to bitstream enum */ +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain) { + FIXEDGAINDMXCONFIG dmxGain = FIXEDGAINDMX_INVALID; + + switch (hStaticGain->fixedGainDMX) { + case 0: + dmxGain = FIXEDGAINDMX_0; + break; + case 1: + dmxGain = FIXEDGAINDMX_1; + break; + case 2: + dmxGain = FIXEDGAINDMX_2; + break; + case 3: + dmxGain = FIXEDGAINDMX_3; + break; + case 4: + dmxGain = FIXEDGAINDMX_4; + break; + case 5: + dmxGain = FIXEDGAINDMX_5; + break; + case 6: + dmxGain = FIXEDGAINDMX_6; + break; + case 7: + dmxGain = FIXEDGAINDMX_7; + break; + default: + dmxGain = FIXEDGAINDMX_INVALID; + } + return dmxGain; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->fixedGainDMX = dmxGain; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode) { + FDK_SACENC_ERROR error = SACENC_OK; + + if (NULL == hStaticGainCfg) { + error = SACENC_INVALID_HANDLE; + } else { + hStaticGainCfg->encMode = encMode; + } + return error; +} diff --git a/fdk-aac/libSACenc/src/sacenc_staticgain.h b/fdk-aac/libSACenc/src/sacenc_staticgain.h new file mode 100644 index 0000000..5db3bec --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_staticgain.h @@ -0,0 +1,177 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Christian Goettlinger + + Description: Encoder Library Interfac + gain management of the encoder + +*******************************************************************************/ + +/**************************************************************************/ /** + \file + ******************************************************************************/ + +#ifndef SACENC_STATICGAIN_H +#define SACENC_STATICGAIN_H + +/* Includes ******************************************************************/ +#include "common_fix.h" +#include "sacenc_lib.h" +#include "sacenc_const.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ +#define FIXP_GAIN FIXP_DBL +#define MAXVAL_GAIN ((FIXP_DBL)MAXVAL_DBL) + +/* Data Types ****************************************************************/ +struct STATIC_GAIN_CONFIG { + MP4SPACEENC_MODE encMode; + MP4SPACEENC_DMX_GAIN fixedGainDMX; + INT preGainFactorDb; +}; + +typedef struct STATIC_GAIN_CONFIG *HANDLE_STATIC_GAIN_CONFIG; +typedef struct STATIC_GAIN *HANDLE_STATIC_GAIN; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Initializes Static Gain Computation Config */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_OpenConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_InitDefaultConfig( + HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig); + +/* Deletes Static Gain Computation Config ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_CloseConfig( + HANDLE_STATIC_GAIN_CONFIG *phStaticGainConfig); + +/* Initializes Static Gain Computation ~Constructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Open(HANDLE_STATIC_GAIN *phStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_Init( + HANDLE_STATIC_GAIN hStaticGain, + const HANDLE_STATIC_GAIN_CONFIG hStaticGainConfig, INT *const scale); + +/* Deletes Static Gain Computation Infrastucture ~Destructor */ +FDK_SACENC_ERROR fdk_sacenc_staticGain_Close(HANDLE_STATIC_GAIN *phStaticGain); + +/* Apply PostGain to the output PCM Downmix-Signal */ +FDK_SACENC_ERROR fdk_sacenc_staticPostGain_ApplyFDK( + const HANDLE_STATIC_GAIN hStaticGain, INT_PCM *const pOutputSamples, + const INT nOutputSamples, const INT scale); + +/* Get Pointer to PreGain-vector */ +FIXP_GAIN *fdk_sacenc_getPreGainPtrFDK(HANDLE_STATIC_GAIN hStaticGain); + +/* Get Pointer to PostGain-coef */ +FIXP_GAIN fdk_sacenc_getPostGainFDK(HANDLE_STATIC_GAIN hStaticGain); + +FIXEDGAINDMXCONFIG fdk_sacenc_staticGain_GetDmxGain( + const HANDLE_STATIC_GAIN hStaticGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetDmxGain( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, + const MP4SPACEENC_DMX_GAIN dmxGain); + +FDK_SACENC_ERROR fdk_sacenc_staticGain_SetEncMode( + HANDLE_STATIC_GAIN_CONFIG hStaticGainCfg, const MP4SPACEENC_MODE encMode); + +#endif /* SACENC_STATICGAIN_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_tree.cpp b/fdk-aac/libSACenc/src/sacenc_tree.cpp new file mode 100644 index 0000000..c7d3128 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_tree.cpp @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_tree.h" +#include "genericStds.h" +#include "sacenc_const.h" +#include "sacenc_paramextract.h" +#include "sacenc_framewindowing.h" +#include "FDK_matrixCalloc.h" + +/* Defines *******************************************************************/ +enum { BOX_0 = 0, BOX_1 = 1 }; + +enum { CH_L = 0, CH_R = 1 }; + +enum { TTO_CH_0 = 0, TTO_CH_1 = 1 }; + +enum { WIN_INACTIV = 0, WIN_ACTIV = 1 }; + +enum { MAX_KEEP_FRAMECOUNT = 100 }; + +/* Data Types ****************************************************************/ +struct SPACE_TREE { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION descr; + HANDLE_TTO_BOX ttoBox[SACENC_MAX_NUM_BOXES]; + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoIcc; + UCHAR bUseCoarseQuantTtoCld; + QUANTMODE quantMode; + INT frameCount; + UCHAR bFrameKeep; + + /* Intermediate buffers */ + UCHAR pCld_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + UCHAR pIcc_prev[SACENC_MAX_NUM_BOXES][MAX_NUM_PARAM_BANDS]; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; +}; + +typedef struct { + UCHAR boxId; + UCHAR inCh1; + UCHAR inCh2; + UCHAR inCh3; + UCHAR inCh4; + UCHAR wCh1; + UCHAR wCh2; + +} TTO_DESCRIPTOR; + +typedef struct { + SPACETREE_MODE mode; + SPACE_TREE_DESCRIPTION treeDescription; + +} TREE_CONFIG; + +typedef struct { + SPACETREE_MODE mode; + UCHAR nChannelsIn; + UCHAR nChannelsOut; + UCHAR nTtoBoxes; + TTO_DESCRIPTOR tto_descriptor[1]; + +} TREE_SETUP; + +/* Constants *****************************************************************/ +static const TREE_CONFIG treeConfigTable[] = { + {SPACETREE_INVALID_MODE, {0, 0, 0}}, {SPACETREE_212, {1, 1, 2}}}; + +static const TREE_SETUP treeSetupTable[] = { + {SPACETREE_INVALID_MODE, 0, 0, 0, {{0, 0, 0, 0, 0, 0, 0}}}, + {SPACETREE_212, + 2, + 1, + 1, + {{BOX_0, CH_L, CH_R, TTO_CH_0, TTO_CH_1, WIN_ACTIV, WIN_ACTIV}}}}; + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ +static FDK_SACENC_ERROR getTreeConfig( + const SPACETREE_MODE mode, SPACE_TREE_DESCRIPTION *pTreeDescription) { + FDK_SACENC_ERROR error = SACENC_INIT_ERROR; + + if (pTreeDescription == NULL) { + error = SACENC_INVALID_HANDLE; + } else { + int i; + for (i = 0; i < (int)(sizeof(treeConfigTable) / sizeof(TREE_CONFIG)); i++) { + if (treeConfigTable[i].mode == mode) { + *pTreeDescription = treeConfigTable[i].treeDescription; + error = SACENC_OK; + break; + } + } + } /* valid handle */ + return error; +} + +static const TREE_SETUP *getTreeSetup(const SPACETREE_MODE mode) { + int i; + const TREE_SETUP *setup = NULL; + + for (i = 0; i < (int)(sizeof(treeSetupTable) / sizeof(TREE_SETUP)); i++) { + if (treeSetupTable[i].mode == mode) { + setup = &treeSetupTable[i]; + break; + } + } + return setup; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + HANDLE_SPACE_TREE hSpaceTree = NULL; + + if (NULL == phSpaceTree) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + + FDK_ALLOCATE_MEMORY_1D(hSpaceTree, 1, struct SPACE_TREE); + + for (box = 0; box < SACENC_MAX_NUM_BOXES; box++) { + HANDLE_TTO_BOX ttoBox = NULL; + if (SACENC_OK != (error = fdk_sacenc_createTtoBox(&ttoBox))) { + goto bail; + } + if (NULL != hSpaceTree) { + hSpaceTree->ttoBox[box] = ttoBox; + } + } + *phSpaceTree = hSpaceTree; + } + return error; + +bail: + fdk_sacenc_spaceTree_Close(&hSpaceTree); + return ((SACENC_OK == error) ? SACENC_MEMORY_ERROR : error); +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hST == NULL) || (hSetup == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int bTtoBoxFrontBackCombin[SACENC_MAX_NUM_BOXES] = {0}; + int box = 0; + + hST->frameCount = 0; + hST->bFrameKeep = bFrameKeep; + + /* Init */ + hST->mode = hSetup->mode; + hST->nParamBands = hSetup->nParamBands; + hST->bUseCoarseQuantTtoIcc = hSetup->bUseCoarseQuantTtoIcc; + hST->bUseCoarseQuantTtoCld = hSetup->bUseCoarseQuantTtoCld; + hST->quantMode = hSetup->quantMode; + hST->nChannelsInMax = hSetup->nChannelsInMax; + hST->nHybridBandsMax = hSetup->nHybridBandsMax; + + if (SACENC_OK != (error = getTreeConfig(hST->mode, &hST->descr))) { + goto bail; + } + + switch (hST->mode) { + case SPACETREE_212: + bTtoBoxFrontBackCombin[BOX_0] = 0; + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INIT_ERROR; + goto bail; + } /* switch (hST->mode) */ + + if (hST->descr.nOttBoxes > SACENC_MAX_NUM_BOXES) { + error = SACENC_INIT_ERROR; + goto bail; + } + + for (box = 0; box < hST->descr.nOttBoxes; box++) { + TTO_BOX_CONFIG boxConfig; + boxConfig.subbandConfig = (BOX_SUBBAND_CONFIG)hST->nParamBands; + boxConfig.bUseCoarseQuantCld = hST->bUseCoarseQuantTtoCld; + boxConfig.bUseCoarseQuantIcc = hST->bUseCoarseQuantTtoIcc; + boxConfig.bUseCoherenceIccOnly = bTtoBoxFrontBackCombin[box]; + boxConfig.boxQuantMode = (BOX_QUANTMODE)hST->quantMode; + boxConfig.nHybridBandsMax = hST->nHybridBandsMax; + boxConfig.bFrameKeep = hST->bFrameKeep; + + if (SACENC_OK != + (error = fdk_sacenc_initTtoBox(hST->ttoBox[box], &boxConfig, + pParameterBand2HybridBandOffset))) { + goto bail; + } + } /* for box */ + + } /* valid handle */ + +bail: + return error; +} + +static void SpaceTree_FrameKeep212(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + int pb; + + if (avoid_keep == 0) { + if (hST->frameCount % 2 == 0) { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hSTOut->ottData.cld[BOX_0][0][pb] = hST->pCld_prev[BOX_0][pb]; + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hSTOut->ottData.icc[BOX_0][0][pb] = hST->pIcc_prev[BOX_0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + } else { + for (pb = 0; pb < hST->nParamBands; pb++) { + hST->pIcc_prev[BOX_0][pb] = hSTOut->ottData.icc[BOX_0][0][pb]; + hST->pCld_prev[BOX_0][pb] = hSTOut->ottData.cld[BOX_0][0][pb]; + } + } + hST->frameCount++; + if (hST->frameCount == MAX_KEEP_FRAMECOUNT) { + hST->frameCount = 0; + } +} + +static FDK_SACENC_ERROR SpaceTree_FrameKeep(const HANDLE_SPACE_TREE hST, + SPATIALFRAME *const hSTOut, + const INT avoid_keep) { + FDK_SACENC_ERROR error = SACENC_OK; + + switch (hST->mode) { + case SPACETREE_212: + SpaceTree_FrameKeep212(hST, hSTOut, avoid_keep); + break; + case SPACETREE_INVALID_MODE: + default: + error = SACENC_INVALID_CONFIG; + break; + } + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale) { + /** \verbatim + ============================================================================================================================= + TREE_212 + ============================================================================================================================= + _______ + L -- TTO_CH_0 --| | + | TTO_0 |-- TTO_CH_0 + R -- TTO_CH_1 --|_______| + + \endverbatim */ + + FDK_SACENC_ERROR error = SACENC_OK; + int k; + const TREE_SETUP *treeSetup = NULL; + + if ((hST == NULL) || (hSTOut == NULL) || (pppHybrid__FDK == NULL) || + (pppHybridIn__FDK == NULL)) { + error = SACENC_INVALID_HANDLE; + goto bail; + } + + if ((treeSetup = getTreeSetup(hST->mode)) == NULL) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Sanity Checks */ + if ((nChannelsIn != treeSetup->nChannelsIn) || + (nChannelsIn > hST->nChannelsInMax) || + (nHybridBands > hST->nHybridBandsMax)) { + error = SACENC_INVALID_CONFIG; + goto bail; + } + + /* Apply all TTO boxes. */ + for (k = 0; k < treeSetup->nTtoBoxes; k++) { + const TTO_DESCRIPTOR *pTTO = &treeSetup->tto_descriptor[k]; + + int i, inCh[2], outCh[2], win[2]; + + inCh[0] = pTTO->inCh1; + outCh[0] = pTTO->inCh3; + win[0] = pTTO->wCh1; + inCh[1] = pTTO->inCh2; + outCh[1] = pTTO->inCh4; + win[1] = pTTO->wCh2; + + for (i = 0; i < 2; i++) { + if (win[i] == WIN_ACTIV) { + fdk_sacenc_analysisWindowing( + nTimeSlots, startTimeSlot, pFrameWindowAna__FDK, + pppHybrid__FDK[inCh[i]], pppHybridIn__FDK[outCh[i]], nHybridBands, + FW_LEAVE_DIM); + } + } + + /* Calculate output downmix within last TTO box, if no TTT box is applied. + */ + if (SACENC_OK != + (error = fdk_sacenc_applyTtoBox( + hST->ttoBox[pTTO->boxId], nTimeSlots, startTimeSlot, nHybridBands, + pppHybridIn__FDK[pTTO->inCh3], pppHybridIn__FDK[pTTO->inCh4], + hSTOut->ottData.icc[pTTO->boxId][paramSet], + &(hSTOut->ICCLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->ottData.cld[pTTO->boxId][paramSet], + &(hSTOut->CLDLosslessData.bsQuantCoarseXXX[pTTO->boxId][paramSet]), + hSTOut->bUseBBCues, &pEncoderInputChScale[inCh[0]], + &pEncoderInputChScale[inCh[1]]))) { + goto bail; + } + } + + if (hST->bFrameKeep == 1) { + if (SACENC_OK != (error = SpaceTree_FrameKeep(hST, hSTOut, avoid_keep))) { + goto bail; + } + } + +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((phSpaceTree == NULL) || (*phSpaceTree == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + int box; + HANDLE_SPACE_TREE const hST = *phSpaceTree; + + /* for (box = 0; box < hST->descr.nOttBoxes; ++box) { */ + for (box = 0; box < SACENC_MAX_NUM_BOXES; ++box) { + if (SACENC_OK != (error = fdk_sacenc_destroyTtoBox(&hST->ttoBox[box]))) { + goto bail; + } + } + + FDKfree(*phSpaceTree); + *phSpaceTree = NULL; + } +bail: + return error; +} + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription) { + FDK_SACENC_ERROR error = SACENC_OK; + + if ((hSpaceTree == NULL) || (pSpaceTreeDescription == NULL)) { + error = SACENC_INVALID_HANDLE; + } else { + *pSpaceTreeDescription = hSpaceTree->descr; + } + return error; +} + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand) { + return fdk_sacenc_subband2ParamBand((BOX_SUBBAND_CONFIG)nParamBands, + nHybridBand); +} + +/***************************************************************************** +******************************************************************************/ diff --git a/fdk-aac/libSACenc/src/sacenc_tree.h b/fdk-aac/libSACenc/src/sacenc_tree.h new file mode 100644 index 0000000..09f5b2b --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_tree.h @@ -0,0 +1,168 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Max Neuendorf + + Description: Encoder Library Interface + Tree Structure for Space Encoder + +*******************************************************************************/ + +#ifndef SACENC_TREE_H +#define SACENC_TREE_H + +/* Includes ******************************************************************/ +#include "sacenc_framewindowing.h" +#include "sacenc_lib.h" +#include "sacenc_bitstream.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ +typedef enum { + SPACETREE_INVALID_MODE = 0, + SPACETREE_212 = 8 + +} SPACETREE_MODE; + +typedef struct SPACE_TREE *HANDLE_SPACE_TREE; + +typedef struct { + UCHAR nParamBands; + UCHAR bUseCoarseQuantTtoCld; + UCHAR bUseCoarseQuantTtoIcc; + QUANTMODE quantMode; + SPACETREE_MODE mode; + + UCHAR nChannelsInMax; + UCHAR nHybridBandsMax; + +} SPACE_TREE_SETUP; + +typedef struct { + UCHAR nOttBoxes; + UCHAR nInChannels; + UCHAR nOutChannels; + +} SPACE_TREE_DESCRIPTION; + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Open(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Init( + HANDLE_SPACE_TREE hST, const SPACE_TREE_SETUP *const hSetup, + UCHAR *pParameterBand2HybridBandOffset, const INT bFrameKeep); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Apply( + HANDLE_SPACE_TREE hST, const INT paramSet, const INT nChannelsIn, + const INT nTimeSlots, const INT startTimeSlot, const INT nHybridBands, + FIXP_WIN *pFrameWindowAna__FDK, + FIXP_DPK *const *const *const pppHybrid__FDK, + FIXP_DPK *const *const *const pppHybridIn__FDK, SPATIALFRAME *const hSTOut, + const INT avoid_keep, INT *pEncoderInputChScale); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_Close(HANDLE_SPACE_TREE *phSpaceTree); + +FDK_SACENC_ERROR fdk_sacenc_spaceTree_GetDescription( + const HANDLE_SPACE_TREE hSpaceTree, + SPACE_TREE_DESCRIPTION *pSpaceTreeDescription); + +INT fdk_sacenc_spaceTree_Hybrid2ParamBand(const INT nParamBands, + const INT nHybridBand); + +#endif /* SACENC_TREE_H */ diff --git a/fdk-aac/libSACenc/src/sacenc_vectorfunctions.cpp b/fdk-aac/libSACenc/src/sacenc_vectorfunctions.cpp new file mode 100644 index 0000000..c1e24b7 --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_vectorfunctions.cpp @@ -0,0 +1,450 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +/* Includes ******************************************************************/ +#include "sacenc_vectorfunctions.h" + +/* Defines *******************************************************************/ + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/* Function / Class Definition ***********************************************/ + +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n) { + int i, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i].v.re); + maxVal |= fAbs(x[i].v.im); + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re << cs); + im += fPow2Div2(x[i].v.im << cs); + } + } else { + cs = 2 * cs; + for (i = 0; i < n; i++) { + re += fPow2Div2(x[i].v.re) >> cs; + im += fPow2Div2(x[i].v.im) >> cs; + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, cs; + + if (scaleMode == SUM_UP_DYNAMIC_SCALE) { + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + cs = inScaleFactor - fixMax(0, CntLeadingZeros(maxVal) - 1); + } else { + cs = inScaleFactor; + } + + /* consider scaling of energy and scaling in fPow2Div2 and addition */ + *outScaleFactor = 2 * cs + 2; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + cs = fixMax(fixMin(cs, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* sum up complex energy samples */ + FIXP_DBL re, im, sum; + + re = im = sum = FL2FXCONST_DBL(0.0); + if (cs < 0) { + cs = -cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re << cs); + im += fPow2Div2(x[i][j].v.im << cs); + } + } + } else { + cs = 2 * cs; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + re += fPow2Div2(x[i][j].v.re) >> cs; + im += fPow2Div2(x[i][j].v.im) >> cs; + } + } + } + + sum = (re >> 1) + (im >> 1); + + return (sum); +} + +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n) { + FDKmemmove(Z, X, sizeof(FIXP_DPK) * n); +} + +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n) { + int i; + + for (i = 0; i < n; i++) { + Z[i].v.re = a; + Z[i].v.im = a; + } +} + +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2) { + int i, j, sx, sy; + FIXP_DBL xre, yre, xim, yim, re, im; + + /* make sure that the scalefactor is in the range of -(DFRACT_BITS-1), ... , + * (DFRACT_BITS-1) */ + sx = fixMax(fixMin(scaleX, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + sy = fixMax(fixMin(scaleY, DFRACT_BITS - 1), -(DFRACT_BITS - 1)); + + /* consider scaling of energy and scaling in fMultDiv2 and shift of result + * values */ + *scaleZ = sx + sy + 2; + + re = (FIXP_DBL)0; + im = (FIXP_DBL)0; + if ((sx < 0) && (sy < 0)) { + sx = -sx; + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += fMultDiv2(xre, yre) + fMultDiv2(xim, yim); + im += fMultDiv2(xim, yre) - fMultDiv2(xre, yim); + } + } + } else if ((sx >= 0) && (sy >= 0)) { + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> (sx + sy); + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> (sx + sy); + } + } + } else if ((sx < 0) && (sy >= 0)) { + sx = -sx; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re << sx; + xim = X[i][j].v.im << sx; + yre = Y[i][j].v.re; + yim = Y[i][j].v.im; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sy; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sy; + } + } + } else { + sy = -sy; + for (i = sDim1; i < nDim1; i++) { + for (j = sDim2; j < nDim2; j++) { + xre = X[i][j].v.re; + xim = X[i][j].v.im; + yre = Y[i][j].v.re << sy; + yim = Y[i][j].v.im << sy; + re += (fMultDiv2(xre, yre) + fMultDiv2(xim, yim)) >> sx; + im += (fMultDiv2(xim, yre) - fMultDiv2(xre, yim)) >> sx; + } + } + } + + Z->v.re = re >> 1; + Z->v.im = im >> 1; +} + +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n) { + int i, s; + FIXP_DBL p12, cor; + + /* correlation */ + for (i = 0; i < n; i++) { + p12 = fMult(p1[i], p2[i]); + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + cor = fMult(pr12[i], p12); + z[i] = SATURATE_LEFT_SHIFT(cor, s, DFRACT_BITS); + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n) { + int i, s, s1, s2; + FIXP_DBL coh, p12, p12ri; + + for (i = 0; i < n; i++) { + s2 = fixMin(fixMax(0, CountLeadingBits(p12r[i]) - 1), + fixMax(0, CountLeadingBits(p12i[i]) - 1)); + p12ri = sqrtFixp(fPow2Div2(p12r[i] << s2) + fPow2Div2(p12i[i] << s2)); + s1 = fixMin(fixMax(0, CountLeadingBits(p1[i]) - 1), + fixMax(0, CountLeadingBits(p2[i]) - 1)); + p12 = fMultDiv2(p1[i] << s1, p2[i] << s1); + + if (p12 > FL2FXCONST_DBL(0.0f)) { + p12 = invSqrtNorm2(p12, &s); + coh = fMult(p12ri, p12); + s = fixMax(fixMin((scaleP12 - scaleP + s + s1 - s2), DFRACT_BITS - 1), + -(DFRACT_BITS - 1)); + if (s < 0) { + z[i] = coh >> (-s); + } else { + z[i] = SATURATE_LEFT_SHIFT(coh, s, DFRACT_BITS); + } + } else { + z[i] = (FIXP_DBL)MAXVAL_DBL; + } + } +} + +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot) { + int pb, j, i; + int cs, s1, s2; + + /* determine maximum scale of both channels */ + cs = fixMax(*scaleCh1, scaleCh2); + s1 = cs - (*scaleCh1); + s2 = cs - scaleCh2; + + /* scalefactor 1 is updated with common scale of channel 1 and channel2 */ + *scaleCh1 = cs; + + /* scale of a and b; additional scale for fMultDiv2() */ + for (j = 0, pb = 0; pb < nParameterBands; pb++) { + FIXP_DBL aPb, bPb; + aPb = a[pb], bPb = b[pb]; + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + Z[j][i].v.re = ((fMultDiv2(aPb, X[j][i].v.re) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.re) >> s2)) + << (scale + 1); + Z[j][i].v.im = ((fMultDiv2(aPb, X[j][i].v.im) >> s1) + + (fMultDiv2(bPb, Y[j][i].v.im) >> s2)) + << (scale + 1); + } + } + } +} + +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands) { + int i, j, pb; + + /* calculate headroom */ + for (j = 0, pb = 0; pb < nParamBands; pb++) { + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + for (; j < pParameterBand2HybridBandOffset[pb]; j++) { + for (i = startTimeSlot; i < nTimeSlots; i++) { + maxVal |= fAbs(x[i][j].v.re); + maxVal |= fAbs(x[i][j].v.im); + } + } + outScaleFactor[pb] = -fixMax(0, CntLeadingZeros(maxVal) - 1); + } +} + +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n) { + int i; + + /* calculate headroom */ + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + if (x != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(x[i]); + } + } + + if (y != NULL) { + for (i = 0; i < n; i++) { + maxVal |= fAbs(y[i]); + } + } + + if (maxVal == (FIXP_DBL)0) + return (-(DFRACT_BITS - 1)); + else + return (-CountLeadingBits(maxVal)); +} + +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands) { + INT qs, clz; + FIXP_DBL maxVal = FL2FXCONST_DBL(0.0f); + + for (qs = startBand; qs < bands; qs++) { + maxVal |= fAbs(x[qs].v.re); + maxVal |= fAbs(x[qs].v.im); + } + + clz = -fixMax(0, CntLeadingZeros(maxVal) - 1); + + return (clz); +} diff --git a/fdk-aac/libSACenc/src/sacenc_vectorfunctions.h b/fdk-aac/libSACenc/src/sacenc_vectorfunctions.h new file mode 100644 index 0000000..e9c4abd --- /dev/null +++ b/fdk-aac/libSACenc/src/sacenc_vectorfunctions.h @@ -0,0 +1,488 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/*********************** MPEG surround encoder library ************************* + + Author(s): Josef Hoepfl + + Description: Encoder Library Interface + vector functions + +*******************************************************************************/ + +/***************************************************************************** +\file +This file contains vector functions +******************************************************************************/ + +#ifndef SACENC_VECTORFUNCTIONS_H +#define SACENC_VECTORFUNCTIONS_H + +/* Includes ******************************************************************/ +#include "common_fix.h" + +/* Defines *******************************************************************/ +#define SUM_UP_STATIC_SCALE 0 +#define SUM_UP_DYNAMIC_SCALE 1 + +/* Data Types ****************************************************************/ + +/* Constants *****************************************************************/ + +/* Function / Class Declarations *********************************************/ + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i]} * re{X[i]} + im{X[i]} * + * im{X[i]} ), i=0,...,n-1 ret is scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2(const FIXP_DPK *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT n); + +/** + * \brief Vector function : Sum up complex power + * + * Description : ret = sum( re{X[i][j]} * re{X[i][]} + + * im{X[i][]} * im{X[i][]} ), i=sDim1,...,nDim1-1 i=sDim2,...,nDim2-1 ret is + * scaled by outScaleFactor + * + * \param const FIXP_DPK x[] + * Input: complex vector of the length n + * + * \param int scaleMode + * Input: choose static or dynamic scaling + * (SUM_UP_DYNAMIC_SCALE/SUM_UP_STATIC_SCALE) + * + * \param int inScaleFactor + * Input: determine headroom bits for the complex input vector + * + * \param int outScaleFactor + * Output: complete scaling in energy calculation + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return FIXP_DBL ret + */ +FIXP_DBL sumUpCplxPow2Dim2(const FIXP_DPK *const *const x, const INT scaleMode, + const INT inScaleFactor, INT *const outScaleFactor, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Z[i] = X[i], i=0,...,n-1 + * + * Description : re{Z[i]} = re{X[i]}, i=0,...,n-1 + * im{Z[i]} = im{X[i]}, i=0,...,n-1 + * + * Copy complex vector X[] to complex vector Z[]. + * It is allowed to overlay X[] with Z[]. + * + * \param FIXP_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DPK X[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector Z[] and X[] + * + * \return void + */ +void copyCplxVec(FIXP_DPK *const Z, const FIXP_DPK *const X, const INT n); + +/** + * \brief Vector function : Z[i] = a, i=0,...,n-1 + * + * Description : re{Z[i]} = a, i=0,...,n-1 + * im{Z[i]} = a, i=0,...,n-1 + * + * Set real and imaginary part of the complex value Z to a. + * + * \param FIPX_DPK Z[] + * Output: vector of the length n + * + * \param const FIXP_DBL a + * Input: constant value + * + * \param int n + * Input: length of vector Z[] + * + * \return void + */ +void setCplxVec(FIXP_DPK *const Z, const FIXP_DBL a, const INT n); + +/** + * \brief Vector function : Calculate complex-valued result of complex + * scalar product + * + * Description : re{Z} = sum( re{X[i]} * re{Y[i]} + im{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) im{Z} = sum( im{X[i]} * re{Y[i]} - re{X[i]} * + * im{Y[i]}, i=0,...,n-1 ) + * + * The function returns the complex-valued result of the complex + * scalar product at the address of Z. The result is scaled by scaleZ. + * + * \param FIXP_DPK *Z + * Output: pointer to Z + * + * \param const FIXP_DPK *const *const X + * Input: vector of the length n + * + * \param const FIXP_DPK *const *const Y + * Input: vector of the length n + * + * \param int scaleX + * Input: scalefactor of vector X[] + * + * \param int scaleY + * Input: scalefactor of vector Y[] + * + * \param int scaleZ + * Output: scalefactor of vector Z[] + * + * \param int sDim1 + * Input: start index for loop counter in dimension 1 + * + * \param int nDim1 + * Input: loop counter in dimension 1 + * + * \param int sDim2 + * Input: start index for loop counter in dimension 2 + * + * \param int nDim2 + * Input: loop counter in dimension 2 + * + * \return void + */ +void cplx_cplxScalarProduct(FIXP_DPK *const Z, const FIXP_DPK *const *const X, + const FIXP_DPK *const *const Y, const INT scaleX, + const INT scaleY, INT *const scaleZ, + const INT sDim1, const INT nDim1, const INT sDim2, + const INT nDim2); + +/** + * \brief Vector function : Calculate correlation + * + * Description : z[i] = pr12[i] / sqrt(p1[i]*p2[i]) , + * i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL pr12[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int n + * Input: length of vector pr12[], p1[] and p2[] + * + * \return void + */ +void FDKcalcCorrelationVec(FIXP_DBL *const z, const FIXP_DBL *const pr12, + const FIXP_DBL *const p1, const FIXP_DBL *const p2, + const INT n); + +/** + * \brief Vector function : Calculate coherence + * + * Description : z[i] = sqrt( (p12r[i]*p12r[i] + + * p12i[i]*p12i[i]) / (p1[i]*p2[i]) ), i=0,...,n-1 + * + * \param FIXP_DBL z[] + * Output: vector of length n + * + * \param const FIXP_DBL p12r[] + * Input: vector of the length n + * + * \param const FIXP_DBL p12i[] + * Input: vector of the length n + * + * \param const FIXP_DBL p1[] + * Input: vector of the length n + * + * \param const FIXP_DBL p2[] + * Input: vector of the length n + * + * \param int scaleP12[] + * Input: scalefactor of p12r and p12i + * + * \param int scaleP + * Input: scalefactor of p1 and p2 + * + * \param int n + * Input: length of vector p12r[], p12i[], p1[] and p2[] + * + * \return void + */ +void calcCoherenceVec(FIXP_DBL *const z, const FIXP_DBL *const p12r, + const FIXP_DBL *const p12i, const FIXP_DBL *const p1, + const FIXP_DBL *const p2, const INT scaleP12, + const INT scaleP, const INT n); + +/** + * \brief Vector function : Z[j][i] = a[pb] * X[j][i] + b[pb] * + * Y[j][i], j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 + * + * Description : re{Z[j][i]} = a[pb] * re{X[j][i]} + b[pb] * + * re{Y[j][i]}, j=0,...,nHybridBands-1; i=startTimeSlot,...,nTimeSlots-1; + * pb=0,...,nParameterBands-1 im{Z[j][i]} = a[pb] * im{X[j][i]} + b[pb] * + * im{Y[j][i]}, j=0,...,nHybridBands-1; + * i=startTimeSlot,...,nTimeSlots-1; pb=0,...,nParameterBands-1 + * + * It is allowed to overlay X[] or Y[] with Z[]. The scalefactor + * of channel 1 is updated with the common scalefactor of channel 1 and + * channel 2. + * + * \param FIXP_DPK **Z + * Output: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *a + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **X + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param const FIXP_DBL *b + * Input: vector of length nParameterBands + * + * \param const FIXP_DPK **Y + * Input: vector of the length nHybridBands*nTimeSlots + * + * \param int scale + * Input: scale of vector a and b + * + * \param int *scaleCh1 + * Input: scale of ch1 + * + * \param int scaleCh2 + * Input: scale of ch2 + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: vector of length nParameterBands + * + * \param int nTimeSlots + * Input: number of time slots + * + * \param int startTimeSlot + * Input: start time slot + * + * \return void + */ +void addWeightedCplxVec(FIXP_DPK *const *const Z, const FIXP_DBL *const a, + const FIXP_DPK *const *const X, const FIXP_DBL *const b, + const FIXP_DPK *const *const Y, const INT scale, + INT *const scaleCh1, const INT scaleCh2, + const UCHAR *const pParameterBand2HybridBandOffset, + const INT nParameterBands, const INT nTimeSlots, + const INT startTimeSlot); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * in a parameter band grid + * + * \param FIXP_DPK **x + * Input: pointer to complex input vector + * + * \param UCHAR *pParameterBand2HybridBandOffset + * Input: pointer to hybrid band offsets + * + * \param int *outScaleFactor + * Input: pointer to ouput scalefactor + * + * \param int startTimeSlot + * Input: start time slot + * + * \param int nTimeSlots + * Input: number of time slot + * + * \param int nParamBands + * Input: number of parameter bands + * + * \return void + */ +void FDKcalcPbScaleFactor(const FIXP_DPK *const *const x, + const UCHAR *const pParameterBand2HybridBandOffset, + INT *const outScaleFactor, const INT startTimeSlot, + const INT nTimeSlots, const INT nParamBands); + +/** + * \brief Vector function : Calculate the common headroom of two + * sparate vectors + * + * \param FIXP_DBL *x + * Input: pointer to first input vector + * + * \param FIXP_DBL *y + * Input: pointer to second input vector + * + * \param int n + * Input: number of samples + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactor(const FIXP_DBL *const x, const FIXP_DBL *const y, + const INT n); + +/** + * \brief Vector function : Calculate the headroom of a complex vector + * + * \param FIXP_DPK *x + * Input: pointer to complex input vector + * + * \param INT startBand + * Input: start band + * + * \param INT bands + * Input: number of bands + * + * \return int headromm in bits + */ +INT FDKcalcScaleFactorDPK(const FIXP_DPK *RESTRICT x, const INT startBand, + const INT bands); + +/* Function / Class Definition ***********************************************/ +template +inline void FDKmemcpy_flex(T *const dst, const INT dstStride, + const T *const src, const INT srcStride, + const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + dst[i * dstStride] = src[i * srcStride]; + } +} + +template +inline void FDKmemset_flex(T *const x, const T c, const INT nSamples) { + int i; + + for (i = 0; i < nSamples; i++) { + x[i] = c; + } +} + +#endif /* SACENC_VECTORFUNCTIONS_H */ diff --git a/fdk-aac/libSBRdec/include/sbrdecoder.h b/fdk-aac/libSBRdec/include/sbrdecoder.h new file mode 100644 index 0000000..cc55572 --- /dev/null +++ b/fdk-aac/libSBRdec/include/sbrdecoder.h @@ -0,0 +1,401 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: SBR decoder front-end prototypes and definitions. + +*******************************************************************************/ + +#ifndef SBRDECODER_H +#define SBRDECODER_H + +#include "common_fix.h" + +#include "FDK_bitstream.h" +#include "FDK_audio.h" + +#include "FDK_qmf_domain.h" + +#define SBR_DEBUG_EXTHLP \ + "\ +--- SBR ---\n\ + 0x00000010 Ancillary data and SBR-Header\n\ + 0x00000020 SBR-Side info\n\ + 0x00000040 Decoded SBR-bitstream data, e.g. envelope data\n\ + 0x00000080 SBR-Bitstream statistics\n\ + 0x00000100 Miscellaneous SBR-messages\n\ + 0x00000200 SBR-Energies and gains in the adjustor\n\ + 0x00000400 Fatal SBR errors\n\ + 0x00000800 Transposer coefficients for inverse filtering\n\ +" + +/* Capability flags */ +#define CAPF_SBR_LP \ + 0x00000001 /*!< Flag indicating library's capability of Low Power mode. */ +#define CAPF_SBR_HQ \ + 0x00000002 /*!< Flag indicating library's capability of High Quality mode. \ + */ +#define CAPF_SBR_DRM_BS \ + 0x00000004 /*!< Flag indicating library's capability to decode DRM SBR data. \ + */ +#define CAPF_SBR_CONCEALMENT \ + 0x00000008 /*!< Flag indicating library's capability to conceal erroneous \ + frames. */ +#define CAPF_SBR_DRC \ + 0x00000010 /*!< Flag indicating library's capability for Dynamic Range \ + Control. */ +#define CAPF_SBR_PS_MPEG \ + 0x00000020 /*!< Flag indicating library's capability to do MPEG Parametric \ + Stereo. */ +#define CAPF_SBR_PS_DRM \ + 0x00000040 /*!< Flag indicating library's capability to do DRM Parametric \ + Stereo. */ +#define CAPF_SBR_ELD_DOWNSCALE \ + 0x00000080 /*!< Flag indicating library's capability to do ELD decoding in \ + downscaled mode */ +#define CAPF_SBR_HBEHQ \ + 0x00000100 /*!< Flag indicating library's capability to do HQ Harmonic \ + transposing */ + +typedef enum { + SBRDEC_OK = 0, /*!< All fine. */ + /* SBRDEC_CONCEAL, */ + /* SBRDEC_NOSYNCH, */ + /* SBRDEC_ILLEGAL_PROGRAM, */ + /* SBRDEC_ILLEGAL_TAG, */ + /* SBRDEC_ILLEGAL_CHN_CONFIG, */ + /* SBRDEC_ILLEGAL_SECTION, */ + /* SBRDEC_ILLEGAL_SCFACTORS, */ + /* SBRDEC_ILLEGAL_PULSE_DATA, */ + /* SBRDEC_MAIN_PROFILE_NOT_IMPLEMENTED, */ + /* SBRDEC_GC_NOT_IMPLEMENTED, */ + /* SBRDEC_ILLEGAL_PLUS_ELE_ID, */ + SBRDEC_INVALID_ARGUMENT, /*!< */ + SBRDEC_CREATE_ERROR, /*!< */ + SBRDEC_NOT_INITIALIZED, /*!< */ + SBRDEC_MEM_ALLOC_FAILED, /*!< Memory allocation failed. Probably not enough + memory available. */ + SBRDEC_PARSE_ERROR, /*!< */ + SBRDEC_UNSUPPORTED_CONFIG, /*!< */ + SBRDEC_SET_PARAM_FAIL, /*!< */ + SBRDEC_OUTPUT_BUFFER_TOO_SMALL /*!< */ +} SBR_ERROR; + +typedef enum { + SBR_SYSTEM_BITSTREAM_DELAY, /*!< System: Switch to enable an additional SBR + bitstream delay of one frame. */ + SBR_QMF_MODE, /*!< Set QMF mode, either complex or low power. */ + SBR_LD_QMF_TIME_ALIGN, /*!< Set QMF type, either LD-MPS or CLDFB. Relevant for + ELD streams only. */ + SBR_FLUSH_DATA, /*!< Set internal state to flush the decoder with the next + process call. */ + SBR_CLEAR_HISTORY, /*!< Clear all internal states (delay lines, QMF states, + ...). */ + SBR_BS_INTERRUPTION /*!< Signal bit stream interruption. Value is ignored. */ + , + SBR_SKIP_QMF /*!< Enable skipping of QMF step: 1 skip analysis, 2 skip + synthesis */ +} SBRDEC_PARAM; + +typedef struct SBR_DECODER_INSTANCE *HANDLE_SBRDECODER; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Allocates and initializes one SBR decoder instance. + * \param pSelf Pointer to where a SBR decoder handle is copied into. + * \param pQmfDomain Pointer to QMF domain data structure. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain); + +/** + * \brief Initialize a SBR decoder runtime instance. Must be called before + * decoding starts. + * + * \param self Handle to a SBR decoder instance. + * \param sampleRateIn Input samplerate of the SBR decoder instance. + * \param sampleRateOut Output samplerate of the SBR decoder instance. + * \param samplesPerFrame Number of samples per frames. + * \param coreCodec Audio Object Type (AOT) of the core codec. + * \param elementID Table with MPEG-4 element Ids in canonical order. + * \param elementIndex SBR element index + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor + * \param configMode Table with MPEG-4 element Ids in canonical order. + * \param configChanged Flag that enforces a complete decoder reset. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_InitElement( + HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut, + const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const int elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor); + +/** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self); + +/** + * \brief pass out of band SBR header to SBR decoder + * + * \param self Handle to a SBR decoder instance. + * \param hBs bit stream handle data source. + * \param sampleRateIn SBR input sampling rate + * \param sampleRateOut SBR output sampling rate + * \param samplesPerFrame frame length + * \param elementID SBR element ID. + * \param elementIndex SBR element index. + * \param harmonicSBR + * \param stereoConfigIndex + * \param downscaleFactor ELD downscale factor + * + * \return Error code. + */ +INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor); + +/** + * \brief Set a parameter of the SBR decoder runtime instance. + * \param self SBR decoder handle. + * \param param Parameter which will be set if successfull. + * \param value New parameter value. + * \return Error code. + */ +SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param, + const INT value); + +/** + * \brief Feed DRC channel data into a SBR decoder runtime instance. + * + * \param self SBR decoder handle. + * \param ch Channel number to which the DRC data is + * associated to. + * \param numBands Number of DRC bands. + * \param pNextFact_mag Pointer to a table with the DRC factor + * magnitudes. + * \param nextFact_exp Exponent for all DRC factors. + * \param drcInterpolationScheme DRC interpolation scheme. + * \param winSequence Window sequence from core coder (eight short + * or one long window). + * \param pBandTop Pointer to a table with the top borders for + * all DRC bands. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch, + UINT numBands, FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, USHORT *pBandTop); + +/** + * \brief Disable SBR DRC for a certain channel. + * + * \param hSbrDecoder SBR decoder handle. + * \param ch Number of the channel that has to be disabled. + * + * \return None. + */ +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch); + +/** + * \brief Parse one SBR element data extension data block. The bit stream + * position will be placed at the end of the SBR payload block. The remaining + * bits will be returned into *count if a payload length is given + * (byPayLen > 0). If no SBR payload length is given (bsPayLen < 0) then + * the bit stream position on return will be random after this function + * call in case of errors, and any further decoding will be completely + * pointless. This function accepts either normal ordered SBR data or reverse + * ordered DRM SBR data. + * + * \param self SBR decoder handle. + * \param hBs Bit stream handle as data source. + * \param count Pointer to an integer where the amount of parsed SBR + * payload bits is stored into. + * \param bsPayLen If > 0 this value is the SBR payload length. If < 0, + * the SBR payload length is unknown. + * \param flags CRC flag (0: EXT_SBR_DATA; 1: EXT_SBR_DATA_CRC) + * \param prev_element Previous MPEG-4 element ID. + * \param element_index Index of the current element. + * \param acFlags Audio codec flags + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prev_element, int element_index, + UINT acFlags, UINT acElFlags[]); + +/** + * \brief This function decodes the given SBR bitstreams and applies SBR to the + * given time data. + * + * SBR-processing works InPlace. I.e. the calling function has to provide + * a time domain buffer timeData which can hold the completely decoded + * result. + * + * Left and right channel are read and stored according to the + * interleaving flag, frame length and number of channels. + * + * \param self Handle of an open SBR decoder instance. + * \param hSbrBs SBR Bitstream handle. + * \param input Pointer to input data. + * \param timeData Pointer to upsampled output data. + * \param timeDataSize Size of timeData. + * \param numChannels Pointer to a buffer holding the number of channels in + * time data buffer. + * \param sampleRate Output samplerate. + * \param channelMapping Channel mapping indices. + * \param coreDecodedOk Flag indicating if the core decoder did not find any + * error (0: core decoder found errors, 1: no errors). + * \param psDecoded Pointer to a buffer holding a flag. Input: PS is + * possible, Output: PS has been rendered. + * + * \return Error code. + */ +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, + INT_PCM *timeData, const int timeDataSize, + int *numChannels, int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded); + +/** + * \brief Close SBR decoder instance and free memory. + * \param self SBR decoder handle. + * \return Error Code. + */ +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *self); + +/** + * \brief Get SBR decoder library information. + * \param info Pointer to a LIB_INFO struct, where library information is + * written to. + * \return 0 on success, -1 if invalid handle or if no free element is + * available to write information to. + */ +INT sbrDecoder_GetLibInfo(LIB_INFO *info); + +/** + * \brief Determine the modules output signal delay in samples. + * \param self SBR decoder handle. + * \return The number of samples signal delay added by the module. + */ +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/fdk-aac/libSBRdec/src/HFgen_preFlat.cpp b/fdk-aac/libSBRdec/src/HFgen_preFlat.cpp new file mode 100644 index 0000000..96adbb9 --- /dev/null +++ b/fdk-aac/libSBRdec/src/HFgen_preFlat.cpp @@ -0,0 +1,993 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Oliver Moser, Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre-whitening for SBR. + In the documentation the terms "scale factor" and "exponent" + mean the same. Variables containing such information have + the suffix "_sf". + +*******************************************************************************/ + +#include "HFgen_preFlat.h" + +#define POLY_ORDER 3 +#define MAXLOWBANDS 32 +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/20 * 2^2 */ + +#define FIXP_CHB FIXP_SGL /* STB sinus Tab used in transformation */ +#define CHC(a) (FX_DBL2FXCONST_SGL(a)) +#define FX_CHB2FX_DBL(a) FX_SGL2FX_DBL(a) + +typedef struct backsubst_data { + FIXP_CHB Lnorm1d[3]; /*!< Normalized L matrix */ + SCHAR Lnorm1d_sf[3]; + FIXP_CHB Lnormii + [3]; /*!< The diagonal data points [i][i] of the normalized L matrix */ + SCHAR Lnormii_sf[3]; + FIXP_CHB Bmul0 + [4]; /*!< To normalize L*x=b, Bmul0 is what we need to multiply b with. */ + SCHAR Bmul0_sf[4]; + FIXP_CHB LnormInv1d[6]; /*!< Normalized inverted L matrix (L') */ + SCHAR LnormInv1d_sf[6]; + FIXP_CHB + Bmul1[4]; /*!< To normalize L'*x=b, Bmul1 is what we need to multiply b + with. */ + SCHAR Bmul1_sf[4]; +} backsubst_data; + +/* for each element n do, f(n) = trunc(log2(n))+1 */ +const UCHAR getLog2[32] = {0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}; + +/** \def BSD_IDX_OFFSET + * + * bsd[] begins at index 0 with data for numBands=5. The correct bsd[] is + * indexed like bsd[numBands-BSD_IDX_OFFSET]. + */ +#define BSD_IDX_OFFSET 5 + +#define N_NUMBANDS \ + MAXLOWBANDS - BSD_IDX_OFFSET + \ + 1 /*!< Number of backsubst_data elements in bsd */ + +const backsubst_data bsd[N_NUMBANDS] = { + { + /* numBands=5 */ + {CHC(0x66c85a52), CHC(0x4278e587), CHC(0x697dcaff)}, + {-1, 0, 0}, + {CHC(0x66a61789), CHC(0x5253b8e3), CHC(0x5addad81)}, + {3, 4, 1}, + {CHC(0x7525ee90), CHC(0x6e2a1210), CHC(0x6523bb40), CHC(0x59822ead)}, + {-6, -4, -2, 0}, + {CHC(0x609e4cad), CHC(0x59c7e312), CHC(0x681eecac), CHC(0x440ea893), + CHC(0x4a214bb3), CHC(0x53c345a1)}, + {1, 0, -1, -1, -3, -5}, + {CHC(0x7525ee90), CHC(0x58587936), CHC(0x410d0b38), CHC(0x7f1519d6)}, + {-6, -1, 2, 0}, + }, + { + /* numBands=6 */ + {CHC(0x68943285), CHC(0x4841d2c3), CHC(0x6a6214c7)}, + {-1, 0, 0}, + {CHC(0x63c5923e), CHC(0x4e906e18), CHC(0x6285af8a)}, + {3, 4, 1}, + {CHC(0x7263940b), CHC(0x424a69a5), CHC(0x4ae8383a), CHC(0x517b7730)}, + {-7, -4, -2, 0}, + {CHC(0x518aee5f), CHC(0x4823a096), CHC(0x43764a39), CHC(0x6e6faf23), + CHC(0x61bba44f), CHC(0x59d8b132)}, + {1, 0, -1, -2, -4, -6}, + {CHC(0x7263940b), CHC(0x6757bff2), CHC(0x5bf40fe0), CHC(0x7d6f4292)}, + {-7, -2, 1, 0}, + }, + { + /* numBands=7 */ + {CHC(0x699b4c3c), CHC(0x4b8b702f), CHC(0x6ae51a4f)}, + {-1, 0, 0}, + {CHC(0x623a7f49), CHC(0x4ccc91fc), CHC(0x68f048dd)}, + {3, 4, 1}, + {CHC(0x7e6ebe18), CHC(0x5701daf2), CHC(0x74a8198b), CHC(0x4b399aa1)}, + {-8, -5, -3, 0}, + {CHC(0x464a64a6), CHC(0x78e42633), CHC(0x5ee174ba), CHC(0x5d0008c8), + CHC(0x455cff0f), CHC(0x6b9100e7)}, + {1, -1, -2, -2, -4, -7}, + {CHC(0x7e6ebe18), CHC(0x42c52efe), CHC(0x45fe401f), CHC(0x7b5808ef)}, + {-8, -2, 1, 0}, + }, + { + /* numBands=8 */ + {CHC(0x6a3fd9b4), CHC(0x4d99823f), CHC(0x6b372a94)}, + {-1, 0, 0}, + {CHC(0x614c6ef7), CHC(0x4bd06699), CHC(0x6e59cfca)}, + {3, 4, 1}, + {CHC(0x4c389cc5), CHC(0x79686681), CHC(0x5e2544c2), CHC(0x46305b43)}, + {-8, -6, -3, 0}, + {CHC(0x7b4ca7c6), CHC(0x68270ac5), CHC(0x467c644c), CHC(0x505c1b0f), + CHC(0x67a14778), CHC(0x45801767)}, + {0, -1, -2, -2, -5, -7}, + {CHC(0x4c389cc5), CHC(0x5c499ceb), CHC(0x6f863c9f), CHC(0x79059bfc)}, + {-8, -3, 0, 0}, + }, + { + /* numBands=9 */ + {CHC(0x6aad9988), CHC(0x4ef8ac18), CHC(0x6b6df116)}, + {-1, 0, 0}, + {CHC(0x60b159b0), CHC(0x4b33f772), CHC(0x72f5573d)}, + {3, 4, 1}, + {CHC(0x6206cb18), CHC(0x58a7d8dc), CHC(0x4e0b2d0b), CHC(0x4207ad84)}, + {-9, -6, -3, 0}, + {CHC(0x6dadadae), CHC(0x5b8b2cfc), CHC(0x6cf61db2), CHC(0x46c3c90b), + CHC(0x506314ea), CHC(0x5f034acd)}, + {0, -1, -3, -2, -5, -8}, + {CHC(0x6206cb18), CHC(0x42f8b8de), CHC(0x5bb4776f), CHC(0x769acc79)}, + {-9, -3, 0, 0}, + }, + { + /* numBands=10 */ + {CHC(0x6afa7252), CHC(0x4feed3ed), CHC(0x6b94504d)}, + {-1, 0, 0}, + {CHC(0x60467899), CHC(0x4acbafba), CHC(0x76eb327f)}, + {3, 4, 1}, + {CHC(0x42415b15), CHC(0x431080da), CHC(0x420f1c32), CHC(0x7d0c1aeb)}, + {-9, -6, -3, -1}, + {CHC(0x62b2c7a4), CHC(0x51b040a6), CHC(0x56caddb4), CHC(0x7e74a2c8), + CHC(0x4030adf5), CHC(0x43d1dc4f)}, + {0, -1, -3, -3, -5, -8}, + {CHC(0x42415b15), CHC(0x64e299b3), CHC(0x4d33b5e8), CHC(0x742cee5f)}, + {-9, -4, 0, 0}, + }, + { + /* numBands=11 */ + {CHC(0x6b3258bb), CHC(0x50a21233), CHC(0x6bb03c19)}, + {-1, 0, 0}, + {CHC(0x5ff997c6), CHC(0x4a82706e), CHC(0x7a5aae36)}, + {3, 4, 1}, + {CHC(0x5d2fb4fb), CHC(0x685bddd8), CHC(0x71b5e983), CHC(0x7708c90b)}, + {-10, -7, -4, -1}, + {CHC(0x59aceea2), CHC(0x49c428a0), CHC(0x46ca5527), CHC(0x724be884), + CHC(0x68e586da), CHC(0x643485b6)}, + {0, -1, -3, -3, -6, -9}, + {CHC(0x5d2fb4fb), CHC(0x4e3fad1a), CHC(0x42310ba2), CHC(0x71c8b3ce)}, + {-10, -4, 0, 0}, + }, + { + /* numBands=12 */ + {CHC(0x6b5c4726), CHC(0x5128a4a8), CHC(0x6bc52ee1)}, + {-1, 0, 0}, + {CHC(0x5fc06618), CHC(0x4a4ce559), CHC(0x7d5c16e9)}, + {3, 4, 1}, + {CHC(0x43af8342), CHC(0x531533d3), CHC(0x633660a6), CHC(0x71ce6052)}, + {-10, -7, -4, -1}, + {CHC(0x522373d7), CHC(0x434150cb), CHC(0x75b58afc), CHC(0x68474f2d), + CHC(0x575348a5), CHC(0x4c20973f)}, + {0, -1, -4, -3, -6, -9}, + {CHC(0x43af8342), CHC(0x7c4d3d11), CHC(0x732e13db), CHC(0x6f756ac4)}, + {-10, -5, -1, 0}, + }, + { + /* numBands=13 */ + {CHC(0x6b7c8953), CHC(0x51903fcd), CHC(0x6bd54d2e)}, + {-1, 0, 0}, + {CHC(0x5f94abf0), CHC(0x4a2480fa), CHC(0x40013553)}, + {3, 4, 2}, + {CHC(0x6501236e), CHC(0x436b9c4e), CHC(0x578d7881), CHC(0x6d34f92e)}, + {-11, -7, -4, -1}, + {CHC(0x4bc0e2b2), CHC(0x7b9d12ac), CHC(0x636c1c1b), CHC(0x5fe15c2b), + CHC(0x49d54879), CHC(0x7662cfa5)}, + {0, -2, -4, -3, -6, -10}, + {CHC(0x6501236e), CHC(0x64b059fe), CHC(0x656d8359), CHC(0x6d370900)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=14 */ + {CHC(0x6b95e276), CHC(0x51e1b637), CHC(0x6be1f7ed)}, + {-1, 0, 0}, + {CHC(0x5f727a1c), CHC(0x4a053e9c), CHC(0x412e528c)}, + {3, 4, 2}, + {CHC(0x4d178bd4), CHC(0x6f33b4e8), CHC(0x4e028f7f), CHC(0x691ee104)}, + {-11, -8, -4, -1}, + {CHC(0x46473d3f), CHC(0x725bd0a6), CHC(0x55199885), CHC(0x58bcc56b), + CHC(0x7e7e6288), CHC(0x5ddef6eb)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x4d178bd4), CHC(0x52ebd467), CHC(0x5a395a6e), CHC(0x6b0f724f)}, + {-11, -5, -1, 0}, + }, + { + /* numBands=15 */ + {CHC(0x6baa2a22), CHC(0x5222eb91), CHC(0x6bec1a86)}, + {-1, 0, 0}, + {CHC(0x5f57393b), CHC(0x49ec8934), CHC(0x423b5b58)}, + {3, 4, 2}, + {CHC(0x77fd2486), CHC(0x5cfbdf2c), CHC(0x46153bd1), CHC(0x65757ed9)}, + {-12, -8, -4, -1}, + {CHC(0x41888ee6), CHC(0x6a661db3), CHC(0x49abc8c8), CHC(0x52965848), + CHC(0x6d9301b7), CHC(0x4bb04721)}, + {0, -2, -4, -3, -7, -10}, + {CHC(0x77fd2486), CHC(0x45424c68), CHC(0x50f33cc6), CHC(0x68ff43f0)}, + {-12, -5, -1, 0}, + }, + { + /* numBands=16 */ + {CHC(0x6bbaa499), CHC(0x5257ed94), CHC(0x6bf456e4)}, + {-1, 0, 0}, + {CHC(0x5f412594), CHC(0x49d8a766), CHC(0x432d1dbd)}, + {3, 4, 2}, + {CHC(0x5ef5cfde), CHC(0x4eafcd2d), CHC(0x7ed36893), CHC(0x62274b45)}, + {-12, -8, -5, -1}, + {CHC(0x7ac438f5), CHC(0x637aab21), CHC(0x4067617a), CHC(0x4d3c6ec7), + CHC(0x5fd6e0dd), CHC(0x7bd5f024)}, + {-1, -2, -4, -3, -7, -11}, + {CHC(0x5ef5cfde), CHC(0x751d0d4f), CHC(0x492b3c41), CHC(0x67065409)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=17 */ + {CHC(0x6bc836c9), CHC(0x5283997e), CHC(0x6bfb1f5e)}, + {-1, 0, 0}, + {CHC(0x5f2f02b6), CHC(0x49c868e9), CHC(0x44078151)}, + {3, 4, 2}, + {CHC(0x4c43b65a), CHC(0x4349dcf6), CHC(0x73799e2d), CHC(0x5f267274)}, + {-12, -8, -5, -1}, + {CHC(0x73726394), CHC(0x5d68511a), CHC(0x7191bbcc), CHC(0x48898c70), + CHC(0x548956e1), CHC(0x66981ce8)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x4c43b65a), CHC(0x64131116), CHC(0x429028e2), CHC(0x65240211)}, + {-12, -6, -1, 0}, + }, + { + /* numBands=18 */ + {CHC(0x6bd3860d), CHC(0x52a80156), CHC(0x6c00c68d)}, + {-1, 0, 0}, + {CHC(0x5f1fed86), CHC(0x49baf636), CHC(0x44cdb9dc)}, + {3, 4, 2}, + {CHC(0x7c189389), CHC(0x742666d8), CHC(0x69b8c776), CHC(0x5c67e27d)}, + {-13, -9, -5, -1}, + {CHC(0x6cf1ea76), CHC(0x58095703), CHC(0x64e351a9), CHC(0x4460da90), + CHC(0x4b1f8083), CHC(0x55f2d3e1)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x7c189389), CHC(0x5651792a), CHC(0x79cb9b3d), CHC(0x635769c0)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=19 */ + {CHC(0x6bdd0c40), CHC(0x52c6abf6), CHC(0x6c058950)}, + {-1, 0, 0}, + {CHC(0x5f133f88), CHC(0x49afb305), CHC(0x45826d73)}, + {3, 4, 2}, + {CHC(0x6621a164), CHC(0x6512528e), CHC(0x61449fc8), CHC(0x59e2a0c0)}, + {-13, -9, -5, -1}, + {CHC(0x6721cadb), CHC(0x53404cd4), CHC(0x5a389e91), CHC(0x40abcbd2), + CHC(0x43332f01), CHC(0x48b82e46)}, + {-1, -2, -5, -3, -7, -11}, + {CHC(0x6621a164), CHC(0x4b12cc28), CHC(0x6ffd4df8), CHC(0x619f835e)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=20 */ + {CHC(0x6be524c5), CHC(0x52e0beb3), CHC(0x6c099552)}, + {-1, 0, 0}, + {CHC(0x5f087c68), CHC(0x49a62bb5), CHC(0x4627d175)}, + {3, 4, 2}, + {CHC(0x54ec6afe), CHC(0x58991a42), CHC(0x59e23e8c), CHC(0x578f4ef4)}, + {-13, -9, -5, -1}, + {CHC(0x61e78f6f), CHC(0x4ef5e1e9), CHC(0x5129c3b8), CHC(0x7ab0f7b2), + CHC(0x78efb076), CHC(0x7c2567ea)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x54ec6afe), CHC(0x41c7812c), CHC(0x676f6f8d), CHC(0x5ffb383f)}, + {-13, -6, -2, 0}, + }, + { + /* numBands=21 */ + {CHC(0x6bec1542), CHC(0x52f71929), CHC(0x6c0d0d5e)}, + {-1, 0, 0}, + {CHC(0x5eff45c5), CHC(0x499e092d), CHC(0x46bfc0c9)}, + {3, 4, 2}, + {CHC(0x47457a78), CHC(0x4e2d99b3), CHC(0x53637ea5), CHC(0x5567d0e9)}, + {-13, -9, -5, -1}, + {CHC(0x5d2dc61b), CHC(0x4b1760c8), CHC(0x4967cf39), CHC(0x74b113d8), + CHC(0x6d6676b6), CHC(0x6ad114e9)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x47457a78), CHC(0x740accaa), CHC(0x5feb6609), CHC(0x5e696f95)}, + {-13, -7, -2, 0}, + }, + { + /* numBands=22 */ + {CHC(0x6bf21387), CHC(0x530a683c), CHC(0x6c100c59)}, + {-1, 0, 0}, + {CHC(0x5ef752ea), CHC(0x499708c6), CHC(0x474bcd1b)}, + {3, 4, 2}, + {CHC(0x78a21ab7), CHC(0x45658aec), CHC(0x4da3c4fe), CHC(0x5367094b)}, + {-14, -9, -5, -1}, + {CHC(0x58e2df6a), CHC(0x4795990e), CHC(0x42b5e0f7), CHC(0x6f408c64), + CHC(0x6370bebf), CHC(0x5c91ca85)}, + {-1, -2, -5, -4, -8, -12}, + {CHC(0x78a21ab7), CHC(0x66f951d6), CHC(0x594605bb), CHC(0x5ce91657)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=23 */ + {CHC(0x6bf749b2), CHC(0x531b3348), CHC(0x6c12a750)}, + {-1, 0, 0}, + {CHC(0x5ef06b17), CHC(0x4990f6c9), CHC(0x47cd4c5b)}, + {3, 4, 2}, + {CHC(0x66dede36), CHC(0x7bdf90a9), CHC(0x4885b2b9), CHC(0x5188a6b7)}, + {-14, -10, -5, -1}, + {CHC(0x54f85812), CHC(0x446414ae), CHC(0x79c8d519), CHC(0x6a4c2f31), + CHC(0x5ac8325f), CHC(0x50bf9200)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x66dede36), CHC(0x5be0d90e), CHC(0x535cc453), CHC(0x5b7923f0)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=24 */ + {CHC(0x6bfbd91d), CHC(0x5329e580), CHC(0x6c14eeed)}, + {-1, 0, 0}, + {CHC(0x5eea6179), CHC(0x498baa90), CHC(0x4845635d)}, + {3, 4, 2}, + {CHC(0x58559b7e), CHC(0x6f1b231f), CHC(0x43f1789b), CHC(0x4fc8fcb8)}, + {-14, -10, -5, -1}, + {CHC(0x51621775), CHC(0x417881a3), CHC(0x6f9ba9b6), CHC(0x65c412b2), + CHC(0x53352c61), CHC(0x46db9caf)}, + {-1, -2, -6, -4, -8, -12}, + {CHC(0x58559b7e), CHC(0x52636003), CHC(0x4e13b316), CHC(0x5a189cdf)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=25 */ + {CHC(0x6bffdc73), CHC(0x5336d4af), CHC(0x6c16f084)}, + {-1, 0, 0}, + {CHC(0x5ee51249), CHC(0x498703cc), CHC(0x48b50e4f)}, + {3, 4, 2}, + {CHC(0x4c5616cf), CHC(0x641b9fad), CHC(0x7fa735e0), CHC(0x4e24e57a)}, + {-14, -10, -6, -1}, + {CHC(0x4e15f47a), CHC(0x7d9481d6), CHC(0x66a82f8a), CHC(0x619ae971), + CHC(0x4c8b2f5f), CHC(0x7d09ec11)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x4c5616cf), CHC(0x4a3770fb), CHC(0x495402de), CHC(0x58c693fa)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=26 */ + {CHC(0x6c036943), CHC(0x53424625), CHC(0x6c18b6dc)}, + {-1, 0, 0}, + {CHC(0x5ee060aa), CHC(0x4982e88a), CHC(0x491d277f)}, + {3, 4, 2}, + {CHC(0x425ada5b), CHC(0x5a9368ac), CHC(0x78380a42), CHC(0x4c99aa05)}, + {-14, -10, -6, -1}, + {CHC(0x4b0b569c), CHC(0x78a420da), CHC(0x5ebdf203), CHC(0x5dc57e63), + CHC(0x46a650ff), CHC(0x6ee13fb8)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x425ada5b), CHC(0x4323073c), CHC(0x450ae92b), CHC(0x57822ad5)}, + {-14, -7, -2, 0}, + }, + { + /* numBands=27 */ + {CHC(0x6c06911a), CHC(0x534c7261), CHC(0x6c1a4aba)}, + {-1, 0, 0}, + {CHC(0x5edc3524), CHC(0x497f43c0), CHC(0x497e6cd8)}, + {3, 4, 2}, + {CHC(0x73fb550e), CHC(0x5244894f), CHC(0x717aad78), CHC(0x4b24ef6c)}, + {-15, -10, -6, -1}, + {CHC(0x483aebe4), CHC(0x74139116), CHC(0x57b58037), CHC(0x5a3a4f3c), + CHC(0x416950fe), CHC(0x62c7f4f2)}, + {-1, -3, -6, -4, -8, -13}, + {CHC(0x73fb550e), CHC(0x79efb994), CHC(0x4128cab7), CHC(0x564a919a)}, + {-15, -8, -2, 0}, + }, + { + /* numBands=28 */ + {CHC(0x6c096264), CHC(0x535587cd), CHC(0x6c1bb355)}, + {-1, 0, 0}, + {CHC(0x5ed87c76), CHC(0x497c0439), CHC(0x49d98452)}, + {3, 4, 2}, + {CHC(0x65dec5bf), CHC(0x4afd1ba3), CHC(0x6b58b4b3), CHC(0x49c4a7b0)}, + {-15, -10, -6, -1}, + {CHC(0x459e6eb1), CHC(0x6fd850b7), CHC(0x516e7be9), CHC(0x56f13d05), + CHC(0x79785594), CHC(0x58617de7)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x65dec5bf), CHC(0x6f2168aa), CHC(0x7b41310f), CHC(0x551f0692)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=29 */ + {CHC(0x6c0be913), CHC(0x535dacd5), CHC(0x6c1cf6a3)}, + {-1, 0, 0}, + {CHC(0x5ed526b4), CHC(0x49791bc5), CHC(0x4a2eff99)}, + {3, 4, 2}, + {CHC(0x59e44afe), CHC(0x44949ada), CHC(0x65bf36f5), CHC(0x487705a0)}, + {-15, -10, -6, -1}, + {CHC(0x43307779), CHC(0x6be959c4), CHC(0x4bce2122), CHC(0x53e34d89), + CHC(0x7115ff82), CHC(0x4f6421a1)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x59e44afe), CHC(0x659eab7d), CHC(0x74cea459), CHC(0x53fed574)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=30 */ + {CHC(0x6c0e2f17), CHC(0x53650181), CHC(0x6c1e199d)}, + {-1, 0, 0}, + {CHC(0x5ed2269f), CHC(0x49767e9e), CHC(0x4a7f5f0b)}, + {3, 4, 2}, + {CHC(0x4faa4ae6), CHC(0x7dd3bf11), CHC(0x609e2732), CHC(0x473a72e9)}, + {-15, -11, -6, -1}, + {CHC(0x40ec57c6), CHC(0x683ee147), CHC(0x46be261d), CHC(0x510a7983), + CHC(0x698a84cb), CHC(0x4794a927)}, + {-1, -3, -6, -4, -9, -13}, + {CHC(0x4faa4ae6), CHC(0x5d3615ad), CHC(0x6ee74773), CHC(0x52e956a1)}, + {-15, -8, -3, 0}, + }, + { + /* numBands=31 */ + {CHC(0x6c103cc9), CHC(0x536ba0ac), CHC(0x6c1f2070)}, + {-1, 0, 0}, + {CHC(0x5ecf711e), CHC(0x497422ea), CHC(0x4acb1438)}, + {3, 4, 2}, + {CHC(0x46e322ad), CHC(0x73c32f3c), CHC(0x5be7d172), CHC(0x460d8800)}, + {-15, -11, -6, -1}, + {CHC(0x7d9bf8ad), CHC(0x64d22351), CHC(0x422bdc81), CHC(0x4e6184aa), + CHC(0x62ba2375), CHC(0x40c325de)}, + {-2, -3, -6, -4, -9, -13}, + {CHC(0x46e322ad), CHC(0x55bef2a3), CHC(0x697b3135), CHC(0x51ddee4d)}, + {-15, -8, -3, 0}, + }, + { + // numBands=32 + {CHC(0x6c121933), CHC(0x5371a104), CHC(0x6c200ea0)}, + {-1, 0, 0}, + {CHC(0x5eccfcd3), CHC(0x49720060), CHC(0x4b1283f0)}, + {3, 4, 2}, + {CHC(0x7ea12a52), CHC(0x6aca3303), CHC(0x579072bf), CHC(0x44ef056e)}, + {-16, -11, -6, -1}, + {CHC(0x79a3a9ab), CHC(0x619d38fc), CHC(0x7c0f0734), CHC(0x4be3dd5d), + CHC(0x5c8d7163), CHC(0x7591065f)}, + {-2, -3, -7, -4, -9, -14}, + {CHC(0x7ea12a52), CHC(0x4f1782a6), CHC(0x647cbcb2), CHC(0x50dc0bb1)}, + {-16, -8, -3, 0}, + }, +}; + +/** \def SUM_SAFETY + * + * SUM_SAFTEY defines the bits needed to right-shift every summand in + * order to be overflow-safe. In the two backsubst functions we sum up 4 + * values. Since one of which is definitely not MAXVAL_DBL (the L[x][y]), + * we spare just 2 safety bits instead of 3. + */ +#define SUM_SAFETY 2 + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[0] = b[0]; + * x[1] = (b[1] - x[0]) / L[1][1]; + * x[2] = (b[2] - x[1]*L[2][1] - x[0]) / L[2][2]; + * x[3] = (b[3] - x[2]*L[3][2] - x[1]*L[3][1] - x[0]) / L[3][3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x output polynomial coefficients (mantissa) + * \param[out] x_sf exponents of x[] + */ +static void backsubst_fw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through Lnorm1d[] */ + + const FIXP_CHB *RESTRICT pLnorm1d = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d; + const SCHAR *RESTRICT pLnorm1d_sf = bsd[numBands - BSD_IDX_OFFSET].Lnorm1d_sf; + const FIXP_CHB *RESTRICT pLnormii = bsd[numBands - BSD_IDX_OFFSET].Lnormii; + const SCHAR *RESTRICT pLnormii_sf = bsd[numBands - BSD_IDX_OFFSET].Lnormii_sf; + + x[0] = b[0]; + + for (i = 1, m = 0; i <= POLY_ORDER; ++i) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; + for (k = i - 1; k > 0; --k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnorm1d[m]), x[k], &e); + int mult_sf = pLnorm1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than the sum currently + * has */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + sum -= (mult >> SUM_SAFETY); + } + + /* - x[0] */ + if (x_sf[0] > sum_sf) { + sum >>= (x_sf[0] - sum_sf); + sum_sf = x_sf[0]; + } + sum -= (x[0] >> (sum_sf - x_sf[0] + SUM_SAFETY)); + + /* instead of the division /L[i][i], we multiply by the inverse */ + int e; + x[i] = fMultNorm(sum, FX_CHB2FX_DBL(pLnormii[i - 1]), &e); + x_sf[i] = sum_sf + pLnormii_sf[i - 1] + e + SUM_SAFETY; + } +} + +/** + * \brief Solves L*x=b via backsubstitution according to the following + * structure: + * + * x[3] = b[3]; + * x[2] = b[2] - L[2][3]*x[3]; + * x[1] = b[1] - L[1][2]*x[2] - L[1][3]*x[3]; + * x[0] = b[0] - L[0][1]*x[1] - L[0][2]*x[2] - L[0][3]*x[3]; + * + * \param[in] numBands SBR crossover band index + * \param[in] b the b in L*x=b (one-dimensional) + * \param[out] x solution vector + * \param[out] x_sf exponents of x[] + */ +static void backsubst_bw(const int numBands, const FIXP_DBL *const b, + FIXP_DBL *RESTRICT x, int *RESTRICT x_sf) { + int i, k; + int m; /* the trip counter that indexes incrementally through LnormInv1d[] */ + + const FIXP_CHB *RESTRICT pLnormInv1d = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d; + const SCHAR *RESTRICT pLnormInv1d_sf = + bsd[numBands - BSD_IDX_OFFSET].LnormInv1d_sf; + + x[POLY_ORDER] = b[POLY_ORDER]; + + for (i = POLY_ORDER - 1, m = 0; i >= 0; i--) { + FIXP_DBL sum = b[i] >> SUM_SAFETY; + int sum_sf = x_sf[i]; /* sum's sf but disregarding SUM_SAFETY (added at the + iteration's end) */ + + for (k = i + 1; k <= POLY_ORDER; ++k, ++m) { + int e; + FIXP_DBL mult = fMultNorm(FX_CHB2FX_DBL(pLnormInv1d[m]), x[k], &e); + int mult_sf = pLnormInv1d_sf[m] + x_sf[k] + e; + + /* check if the new summand mult has a different sf than sum currently has + */ + int diff = mult_sf - sum_sf; + + if (diff > 0) { + /* yes, and it requires the sum v to be adjusted (scaled down) */ + sum >>= diff; + sum_sf = mult_sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. */ + /* scale mult down additionally so that building the sum is overflow-safe. + */ + sum -= (mult >> SUM_SAFETY); + } + + x_sf[i] = sum_sf + SUM_SAFETY; + x[i] = sum; + } +} + +/** + * \brief Solves a system of linear equations (L*x=b) with the Cholesky + * algorithm. + * + * \param[in] numBands SBR crossover band index + * \param[in,out] b input: vector b, output: solution vector p. + * \param[in,out] b_sf input: exponent of b; output: exponent of solution + * p. + */ +static void choleskySolve(const int numBands, FIXP_DBL *RESTRICT b, + int *RESTRICT b_sf) { + int i, e; + + const FIXP_CHB *RESTRICT pBmul0 = bsd[numBands - BSD_IDX_OFFSET].Bmul0; + const SCHAR *RESTRICT pBmul0_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul0_sf; + const FIXP_CHB *RESTRICT pBmul1 = bsd[numBands - BSD_IDX_OFFSET].Bmul1; + const SCHAR *RESTRICT pBmul1_sf = bsd[numBands - BSD_IDX_OFFSET].Bmul1_sf; + + /* normalize b */ + FIXP_DBL bnormed[POLY_ORDER + 1]; + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul0[i]), &e); + b_sf[i] += pBmul0_sf[i] + e; + } + + backsubst_fw(numBands, bnormed, b, b_sf); + + /* normalize b again */ + for (i = 0; i <= POLY_ORDER; ++i) { + bnormed[i] = fMultNorm(b[i], FX_CHB2FX_DBL(pBmul1[i]), &e); + b_sf[i] += pBmul1_sf[i] + e; + } + + backsubst_bw(numBands, bnormed, b, b_sf); +} + +/** + * \brief Find polynomial approximation of vector y with implicit abscisas + * x=0,1,2,3..n-1 + * + * The problem (V^T * V * p = V^T * y) is solved with Cholesky. + * V is the Vandermode Matrix constructed with x = 0...n-1; + * A = V^T * V; b = V^T * y; + * + * \param[in] numBands SBR crossover band index (BSD_IDX_OFFSET <= numBands <= + * MAXLOWBANDS) + * \param[in] y input vector (mantissa) + * \param[in] y_sf exponents of y[] + * \param[out] p output polynomial coefficients (mantissa) + * \param[out] p_sf exponents of p[] + */ +static void polyfit(const int numBands, const FIXP_DBL *const y, const int y_sf, + FIXP_DBL *RESTRICT p, int *RESTRICT p_sf) { + int i, k; + LONG v[POLY_ORDER + 1]; + int sum_saftey = getLog2[numBands - 1]; + + FDK_ASSERT((numBands >= BSD_IDX_OFFSET) && (numBands <= MAXLOWBANDS)); + + /* construct vector b[] temporarily stored in array p[] */ + FDKmemclear(p, (POLY_ORDER + 1) * sizeof(FIXP_DBL)); + + /* p[] are the sums over n values and each p[i] has its own sf */ + for (i = 0; i <= POLY_ORDER; ++i) p_sf[i] = 1 - DFRACT_BITS; + + for (k = 0; k < numBands; k++) { + v[0] = (LONG)1; + for (i = 1; i <= POLY_ORDER; i++) { + v[i] = k * v[i - 1]; + } + + for (i = 0; i <= POLY_ORDER; i++) { + if (v[POLY_ORDER - i] != 0 && y[k] != FIXP_DBL(0)) { + int e; + FIXP_DBL mult = fMultNorm((FIXP_DBL)v[POLY_ORDER - i], y[k], &e); + int sf = DFRACT_BITS - 1 + y_sf + e; + + /* check if the new summand has a different sf than the sum p[i] + * currently has */ + int diff = sf - p_sf[i]; + + if (diff > 0) { + /* yes, and it requires the sum p[i] to be adjusted (scaled down) */ + p[i] >>= fMin(DFRACT_BITS - 1, diff); + p_sf[i] = sf; + } else if (diff < 0) { + /* yes, but here mult needs to be scaled down */ + mult >>= -diff; + } + + /* mult has now the same sf than what it is about to be added to. + scale mult down additionally so that building the sum is + overflow-safe. */ + p[i] += mult >> sum_saftey; + } + } + } + + p_sf[0] += sum_saftey; + p_sf[1] += sum_saftey; + p_sf[2] += sum_saftey; + p_sf[3] += sum_saftey; + + choleskySolve(numBands, p, p_sf); +} + +/** + * \brief Calculates the output of a POLY_ORDER-degree polynomial function + * with Horner scheme: + * + * y(x) = p3 + p2*x + p1*x^2 + p0*x^3 + * = p3 + x*(p2 + x*(p1 + x*p0)) + * + * The for loop iterates through the mult/add parts in y(x) as above, + * during which regular upscaling ensures a stable exponent of the + * result. + * + * \param[in] p coefficients as in y(x) + * \param[in] p_sf exponents of p[] + * \param[in] x_int non-fractional integer representation of x as in y(x) + * \param[out] out_sf exponent of return value + * + * \return result y(x) + */ +static FIXP_DBL polyval(const FIXP_DBL *const p, const int *const p_sf, + const int x_int, int *out_sf) { + FDK_ASSERT(x_int <= 31); /* otherwise getLog2[] needs more elements */ + + int k, x_sf; + int result_sf; /* working space to compute return value *out_sf */ + FIXP_DBL x; /* fractional value of x_int */ + FIXP_DBL result; /* return value */ + + /* if x == 0, then y(x) is just p3 */ + if (x_int != 0) { + x_sf = getLog2[x_int]; + x = (FIXP_DBL)x_int << (DFRACT_BITS - 1 - x_sf); + } else { + *out_sf = p_sf[3]; + return p[3]; + } + + result = p[0]; + result_sf = p_sf[0]; + + for (k = 1; k <= POLY_ORDER; ++k) { + FIXP_DBL mult = fMult(x, result); + int mult_sf = x_sf + result_sf; + + int room = CountLeadingBits(mult); + mult <<= room; + mult_sf -= room; + + FIXP_DBL pp = p[k]; + int pp_sf = p_sf[k]; + + /* equalize the shift factors of pp and mult so that we can sum them up */ + int diff = pp_sf - mult_sf; + + if (diff > 0) { + diff = fMin(diff, DFRACT_BITS - 1); + mult >>= diff; + } else if (diff < 0) { + diff = fMax(diff, 1 - DFRACT_BITS); + pp >>= -diff; + } + + /* downshift by 1 to ensure safe summation */ + mult >>= 1; + mult_sf++; + pp >>= 1; + pp_sf++; + + result_sf = fMax(pp_sf, mult_sf); + + result = mult + pp; + /* rarely, mult and pp happen to be almost equal except their sign, + and then upon summation, result becomes so small, that it is within + the inaccuracy range of a few bits, and then the relative error + produced by this function may become HUGE */ + } + + *out_sf = result_sf; + return result; +} + +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuf_e_overlap, + int sourceBuf_e_current, int overlap, + FIXP_DBL *RESTRICT GainVec, int *GainVec_exp, + int numBands, const int startSample, + const int stopSample) { + FIXP_DBL p[POLY_ORDER + 1]; + FIXP_DBL meanNrg; + FIXP_DBL LowEnv[MAXLOWBANDS]; + FIXP_DBL invNumBands = GetInvInt(numBands); + FIXP_DBL invNumSlots = GetInvInt(stopSample - startSample); + int i, loBand, exp, scale_nrg, scale_nrg_ov; + int sum_scale = 5, sum_scale_ov = 3; + + if (overlap > 8) { + FDK_ASSERT(overlap <= 16); + sum_scale_ov += 1; + sum_scale += 1; + } + + /* exponents of energy values */ + sourceBuf_e_overlap = sourceBuf_e_overlap * 2 + sum_scale_ov; + sourceBuf_e_current = sourceBuf_e_current * 2 + sum_scale; + exp = fMax(sourceBuf_e_overlap, sourceBuf_e_current); + scale_nrg = sourceBuf_e_current - exp; + scale_nrg_ov = sourceBuf_e_overlap - exp; + + meanNrg = (FIXP_DBL)0; + /* Calculate the spectral envelope in dB over the current copy-up frame. */ + for (loBand = 0; loBand < numBands; loBand++) { + FIXP_DBL nrg_ov, nrg; + INT reserve = 0, exp_new; + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + + for (i = startSample; i < stopSample; i++) { + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferReal[i][loBand]) ^ + ((LONG)sourceBufferReal[i][loBand] >> (SAMPLE_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(sourceBufferImag[i][loBand]) ^ + ((LONG)sourceBufferImag[i][loBand] >> (SAMPLE_BITS - 1))); + } + + if (maxVal != FL2FX_DBL(0.0f)) { + reserve = fixMax(0, CntLeadingZeros(maxVal) - 2); + } + + nrg_ov = nrg = (FIXP_DBL)0; + if (scale_nrg_ov > -31) { + for (i = startSample; i < overlap; i++) { + nrg_ov += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) + + fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >> + sum_scale_ov; + } + } else { + scale_nrg_ov = 0; + } + if (scale_nrg > -31) { + for (i = overlap; i < stopSample; i++) { + nrg += (fPow2Div2(sourceBufferReal[i][loBand] << reserve) + + fPow2Div2(sourceBufferImag[i][loBand] << reserve)) >> + sum_scale; + } + } else { + scale_nrg = 0; + } + + nrg = (scaleValue(nrg_ov, scale_nrg_ov) >> 1) + + (scaleValue(nrg, scale_nrg) >> 1); + nrg = fMult(nrg, invNumSlots); + + exp_new = + exp - (2 * reserve) + + 2; /* +1 for addition directly above, +1 for fPow2Div2 in loops above */ + + /* LowEnv = 10*log10(nrg) = log2(nrg) * 10/log2(10) */ + /* exponent of logarithmic energy is 8 */ + if (nrg > (FIXP_DBL)0) { + int exp_log2; + nrg = CalcLog2(nrg, exp_new, &exp_log2); + nrg = scaleValue(nrg, exp_log2 - 6); + nrg = fMult(FL2FXCONST_SGL(LOG10FAC), nrg); + } else { + nrg = (FIXP_DBL)0; + } + LowEnv[loBand] = nrg; + meanNrg += fMult(nrg, invNumBands); + } + exp = 6 + 2; /* exponent of LowEnv: +2 is exponent of LOG10FAC */ + + /* subtract mean before polynomial approximation to reduce dynamic of p[] */ + for (loBand = 0; loBand < numBands; loBand++) { + LowEnv[loBand] = meanNrg - LowEnv[loBand]; + } + + /* For numBands < BSD_IDX_OFFSET (== POLY_ORDER+2) we dont get an + overdetermined equation system. The calculated polynomial will exactly fit + the input data and evaluating the polynomial will lead to the same vector + than the original input vector: lowEnvSlope[] == lowEnv[] + */ + if (numBands > POLY_ORDER + 1) { + /* Find polynomial approximation of LowEnv */ + int p_sf[POLY_ORDER + 1]; + + polyfit(numBands, LowEnv, exp, p, p_sf); + + for (i = 0; i < numBands; i++) { + int sf; + + /* lowBandEnvSlope[i] = tmp; */ + FIXP_DBL tmp = polyval(p, p_sf, i, &sf); + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } else { /* numBands <= POLY_ORDER+1 */ + for (i = 0; i < numBands; i++) { + int sf = exp; /* exponent of LowEnv[] */ + + /* lowBandEnvSlope[i] = LowEnv[i]; */ + FIXP_DBL tmp = LowEnv[i]; + + /* GainVec = 10^((mean(y)-y)/20) = 2^( (mean(y)-y) * log2(10)/20 ) */ + tmp = fMult(tmp, FL2FXCONST_SGL(LOG10FAC_INV)); + GainVec[i] = f2Pow(tmp, sf - 2, + &GainVec_exp[i]); /* -2 is exponent of LOG10FAC_INV */ + } + } +} diff --git a/fdk-aac/libSBRdec/src/HFgen_preFlat.h b/fdk-aac/libSBRdec/src/HFgen_preFlat.h new file mode 100644 index 0000000..c1fc49d --- /dev/null +++ b/fdk-aac/libSBRdec/src/HFgen_preFlat.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Manuel Jander, Matthias Hildenbrand + + Description: QMF frequency pre whitening for SBR + +*******************************************************************************/ + +#include "common_fix.h" + +#ifndef HFGEN_PREFLAT_H +#define HFGEN_PREFLAT_H + +#define GAIN_VEC_EXP 6 /* exponent of GainVec[] */ + +/** + * \brief Find gain vector to flatten the QMF frequency bands whithout loosing + * the fine structure. + * \param[in] sourceBufferReal real part of QMF domain data. + * \param[in] sourceBufferImag imaginary part of QMF domain data. + * \param[in] sourceBuffer_e_overlap exponent of sourceBufferReal. + * \param[in] sourceBuffer_e_current exponent of sourceBufferImag. + * \param[in] overlap number of overlap samples. + * \param[out] GainVec array of gain values (one for each QMF band). + * \param[out] GainVec_exp exponents of GainVec (one for each QMF band). + * \param[in] numBands number of low bands (k_0). + * \param[in] startSample time slot start. + * \param[in] stopSample time slot stop. + */ +void sbrDecoder_calculateGainVec(FIXP_DBL **sourceBufferReal, + FIXP_DBL **sourceBufferImag, + int sourceBuffer_e_overlap, + int sourceBuffer_e_current, int overlap, + FIXP_DBL GainVec[], int GainVec_exp[], + const int numBands, const int startSample, + const int stopSample); + +#endif /* __HFGEN_PREFLAT_H */ diff --git a/fdk-aac/libSBRdec/src/arm/lpp_tran_arm.cpp b/fdk-aac/libSBRdec/src/arm/lpp_tran_arm.cpp new file mode 100644 index 0000000..db1948f --- /dev/null +++ b/fdk-aac/libSBRdec/src/arm/lpp_tran_arm.cpp @@ -0,0 +1,159 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Arthur Tritthart + + Description: (ARM optimised) LPP transposer subroutines + +*******************************************************************************/ + +#if defined(__arm__) + +#define FUNCTION_LPPTRANSPOSER_func1 + +#ifdef FUNCTION_LPPTRANSPOSER_func1 + +/* Note: This code requires only 43 cycles per iteration instead of 61 on + * ARM926EJ-S */ +static void lppTransposer_func1(FIXP_DBL *lowBandReal, FIXP_DBL *lowBandImag, + FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, int loops, int hiBand, + int dynamicScale, int descale, FIXP_SGL a0r, + FIXP_SGL a0i, FIXP_SGL a1r, FIXP_SGL a1i, + const int fPreWhitening, + FIXP_DBL preWhiteningGain, + int preWhiteningGains_sf) { + FIXP_DBL real1, real2, imag1, imag2, accu1, accu2; + + real2 = lowBandReal[-2]; + real1 = lowBandReal[-1]; + imag2 = lowBandImag[-2]; + imag1 = lowBandImag[-1]; + for (int i = 0; i < loops; i++) { + accu1 = fMultDiv2(a0r, real1); + accu2 = fMultDiv2(a0i, imag1); + accu1 = fMultAddDiv2(accu1, a1r, real2); + accu2 = fMultAddDiv2(accu2, a1i, imag2); + real2 = fMultDiv2(a1i, real2); + accu1 = accu1 - accu2; + accu1 = accu1 >> dynamicScale; + + accu2 = fMultAddDiv2(real2, a1r, imag2); + real2 = real1; + imag2 = imag1; + accu2 = fMultAddDiv2(accu2, a0i, real1); + real1 = lowBandReal[i]; + accu2 = fMultAddDiv2(accu2, a0r, imag1); + imag1 = lowBandImag[i]; + accu2 = accu2 >> dynamicScale; + + accu1 <<= 1; + accu2 <<= 1; + accu1 += (real1 >> descale); + accu2 += (imag1 >> descale); + if (fPreWhitening) { + accu1 = scaleValueSaturate(fMultDiv2(accu1, preWhiteningGain), + preWhiteningGains_sf); + accu2 = scaleValueSaturate(fMultDiv2(accu2, preWhiteningGain), + preWhiteningGains_sf); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; + } +} +#endif /* #ifdef FUNCTION_LPPTRANSPOSER_func1 */ + +#endif /* __arm__ */ diff --git a/fdk-aac/libSBRdec/src/env_calc.cpp b/fdk-aac/libSBRdec/src/env_calc.cpp new file mode 100644 index 0000000..cb1474f --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_calc.cpp @@ -0,0 +1,3158 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope calculation + + The envelope adjustor compares the energies present in the transposed + highband to the reference energies conveyed with the bitstream. + The highband is amplified (sometimes) or attenuated (mostly) to the + desired level. + + The spectral shape of the reference energies can be changed several times per + frame if necessary. Each set of energy values corresponding to a certain range + in time will be called an envelope here. + The bitstream supports several frequency scales and two resolutions. Normally, + one or more QMF-subbands are grouped to one SBR-band. An envelope contains + reference energies for each SBR-band. + In addition to the energy envelopes, noise envelopes are transmitted that + define the ratio of energy which is generated by adding noise instead of + transposing the lowband. The noise envelopes are given in a coarser time + and frequency resolution. + If a signal contains strong tonal components, synthetic sines can be + generated in individual SBR bands. + + An overlap buffer of 6 QMF-timeslots is used to allow a more + flexible alignment of the envelopes in time that is not restricted to the + core codec's frame borders. + Therefore the envelope adjustor has access to the spectral data of the + current frame as well as the last 6 QMF-timeslots of the previous frame. + However, in average only the data of 1 frame is being processed as + the adjustor is called once per frame. + + Depending on the frequency range set in the bitstream, only QMF-subbands + between lowSubband and highSubband are adjusted. + + Scaling of spectral data to maximize SNR (see #QMF_SCALE_FACTOR) as well as a + special Mantissa-Exponent format ( see calculateSbrEnvelope() ) are being + used. The main entry point for this modules is calculateSbrEnvelope(). + + \sa sbr_scale.h, #QMF_SCALE_FACTOR, calculateSbrEnvelope(), \ref + documentationOverview +*/ + +#include "env_calc.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "transcendent.h" +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" /* need FDKpow() for debug outputs */ + +typedef struct { + FIXP_DBL nrgRef[MAX_FREQ_COEFFS]; + FIXP_DBL nrgEst[MAX_FREQ_COEFFS]; + FIXP_DBL nrgGain[MAX_FREQ_COEFFS]; + FIXP_DBL noiseLevel[MAX_FREQ_COEFFS]; + FIXP_DBL nrgSine[MAX_FREQ_COEFFS]; + + SCHAR nrgRef_e[MAX_FREQ_COEFFS]; + SCHAR nrgEst_e[MAX_FREQ_COEFFS]; + SCHAR nrgGain_e[MAX_FREQ_COEFFS]; + SCHAR noiseLevel_e[MAX_FREQ_COEFFS]; + SCHAR nrgSine_e[MAX_FREQ_COEFFS]; + /* yet another exponent [0]: for ts < no_cols; [1]: for ts >= no_cols */ + SCHAR exponent[2]; +} ENV_CALC_NRGS; + +static void equalizeFiltBufferExp(FIXP_DBL *filtBuffer, SCHAR *filtBuffer_e, + FIXP_DBL *NrgGain, SCHAR *NrgGain_e, + int subbands); + +static void calcNrgPerSubband(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int lowSubband, + int highSubband, int start_pos, int next_pos, + SCHAR frameExp, FIXP_DBL *nrgEst, + SCHAR *nrgEst_e); + +static void calcNrgPerSfb(FIXP_DBL **analysBufferReal, + FIXP_DBL **analysBufferImag, int nSfb, + UCHAR *freqBandTable, int start_pos, int next_pos, + SCHAR input_e, FIXP_DBL *nrg_est, SCHAR *nrg_est_e); + +static void calcSubbandGain(FIXP_DBL nrgRef, SCHAR nrgRef_e, + ENV_CALC_NRGS *nrgs, int c, FIXP_DBL tmpNoise, + SCHAR tmpNoise_e, UCHAR sinePresentFlag, + UCHAR sineMapped, int noNoiseFlag); + +static void calcAvgGain(ENV_CALC_NRGS *nrgs, int lowSubband, int highSubband, + FIXP_DBL *sumRef_m, SCHAR *sumRef_e, + FIXP_DBL *ptrAvgGain_m, SCHAR *ptrAvgGain_e); + +static void adjustTimeSlot_EldGrid(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, + int noNoiseFlag, int *ptrPhaseIndex, + int scale_diff_low); + +static void adjustTimeSlotLC(FIXP_DBL *ptrReal, ENV_CALC_NRGS *nrgs, + UCHAR *ptrHarmIndex, int lowSubbands, + int noSubbands, int scale_change, int noNoiseFlag, + int *ptrPhaseIndex); + +/** + * \brief Variant of adjustTimeSlotHQ() which only regards gain and noise but no + * additional harmonics + */ +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change, FIXP_SGL smooth_ratio, + int noNoiseFlag, int filtBufferNoiseShift); +/** + * \brief Variant of adjustTimeSlotHQ() which only adds the additional harmonics + */ +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubbands, int noSubbands, int scale_change); + +static void adjustTimeSlotHQ(FIXP_DBL *ptrReal, FIXP_DBL *ptrImag, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + ENV_CALC_NRGS *nrgs, int lowSubbands, + int noSubbands, int scale_change, + FIXP_SGL smooth_ratio, int noNoiseFlag, + int filtBufferNoiseShift); + +/*! + \brief Map sine flags from bitstream to QMF bands + + The bitstream carries only 1 sine flag per band (Sfb) and frame. + This function maps every sine flag from the bitstream to a specific QMF + subband and to a specific envelope where the sine shall start. The result is + stored in the vector sineMapped which contains one entry per QMF subband. The + value of an entry specifies the envelope where a sine shall start. A value of + 32 indicates that no sine is present in the subband. The missing harmonics + flags from the previous frame (harmFlagsPrev) determine if a sine starts at + the beginning of the frame or at the transient position. Additionally, the + flags in harmFlagsPrev are being updated by this function for the next frame. +*/ +static void mapSineFlags( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *addHarmonics, /*!< Packed addHarmonics of current frame (aligned to + the MSB) */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame (aligned to + the LSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous frame + (aligned to the LSB) */ + int tranEnv, /*!< Transient position */ + SCHAR *sineMapped) /*!< Resulting vector of sine start positions for each + QMF band */ + +{ + int i; + int bitcount = 31; + ULONG harmFlagsQmfBands[ADD_HARMONICS_FLAGS_SIZE] = {0}; + ULONG *curFlags = addHarmonics; + + /* + Format of addHarmonics (aligned to MSB): + + Up to MAX_FREQ_COEFFS sfb bands can be flagged for a sign. + first word = flags for lowest 32 sfb bands in use + second word = flags for higest 32 sfb bands (if present) + + Format of harmFlagsPrev (aligned to LSB): + + Index is absolute (not relative to lsb) so it is correct even if lsb + changes first word = flags for lowest 32 qmf bands (0...31) second word = + flags for next higher 32 qmf bands (32...63) + + */ + + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, + MAX_FREQ_COEFFS * sizeof(SCHAR)); /* 32 means 'no sine' */ + FDKmemclear(harmFlagsPrevActive, ADD_HARMONICS_FLAGS_SIZE * sizeof(ULONG)); + for (i = 0; i < nSfb; i++) { + ULONG maskSfb = + 1 << bitcount; /* mask to extract addHarmonics flag of current Sfb */ + + if (*curFlags & maskSfb) { /* There is a sine in this band */ + const int lsb = freqBandTable[0]; /* start of sbr range */ + /* qmf band to which sine should be added */ + const int qmfBand = (freqBandTable[i] + freqBandTable[i + 1]) >> 1; + const int qmfBandDiv32 = qmfBand >> 5; + const int maskQmfBand = + 1 << (qmfBand & + 31); /* mask to extract harmonic flag from prevFlags */ + + /* mapping of sfb with sine to a certain qmf band -> for harmFlagsPrev */ + harmFlagsQmfBands[qmfBandDiv32] |= maskQmfBand; + + /* + If there was a sine in the last frame, let it continue from the first + envelope on else start at the transient position. Indexing of sineMapped + starts relative to lsb. + */ + sineMapped[qmfBand - lsb] = + (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) ? 0 : tranEnv; + if (sineMapped[qmfBand - lsb] < PVC_NTIMESLOT) { + harmFlagsPrevActive[qmfBandDiv32] |= maskQmfBand; + } + } + + if (bitcount-- == 0) { + bitcount = 31; + curFlags++; + } + } + FDKmemcpy(harmFlagsPrev, harmFlagsQmfBands, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); +} + +/*! + \brief Restore sineMapped of previous frame + + For PVC it might happen that the PVC framing (always 0) is out of sync with + the SBR framing. The adding of additional harmonics is done based on the SBR + framing. If the SBR framing is trailing the PVC framing the sine mapping of + the previous SBR frame needs to be used for the overlapping time slots. +*/ +/*static*/ void mapSineFlagsPvc( + UCHAR *freqBandTable, /*!< Band borders (there's only 1 flag per + band) */ + int nSfb, /*!< Number of bands in the table */ + ULONG *harmFlagsPrev, /*!< Packed addHarmonics of previous frame + (aligned to the MSB) */ + ULONG *harmFlagsPrevActive, /*!< Packed sineMapped of previous + frame (aligned to the LSB) */ + SCHAR *sineMapped, /*!< Resulting vector of sine start positions + for each QMF band */ + int sinusoidalPos, /*!< sinusoidal position */ + SCHAR *sinusoidalPosPrev, /*!< sinusoidal position of previous + frame */ + int trailingSbrFrame) /*!< indication if the SBR framing is + trailing the PVC framing */ +{ + /* Reset the output vector first */ + FDKmemset(sineMapped, 32, MAX_FREQ_COEFFS); /* 32 means 'no sine' */ + + if (trailingSbrFrame) { + /* restore sineMapped[] of previous frame */ + int i; + const int lsb = freqBandTable[0]; + const int usb = freqBandTable[nSfb]; + for (i = lsb; i < usb; i++) { + const int qmfBandDiv32 = i >> 5; + const int maskQmfBand = + 1 << (i & 31); /* mask to extract harmonic flag from prevFlags */ + + /* Two cases need to be distinguished ... */ + if (harmFlagsPrevActive[qmfBandDiv32] & maskQmfBand) { + /* the sine mapping already started last PVC frame -> seamlessly + * continue */ + sineMapped[i - lsb] = 0; + } else if (harmFlagsPrev[qmfBandDiv32] & maskQmfBand) { + /* sinusoidalPos of prev PVC frame was >= PVC_NTIMESLOT -> sine starts + * in this frame */ + sineMapped[i - lsb] = + *sinusoidalPosPrev - PVC_NTIMESLOT; /* we are 16 sbr time slots + ahead of last frame now */ + } + } + } + *sinusoidalPosPrev = sinusoidalPos; +} + +/*! + \brief Reduce gain-adjustment induced aliasing for real valued filterbank. +*/ +/*static*/ void aliasingReduction( + FIXP_DBL *degreeAlias, /*!< estimated aliasing for each QMF + channel */ + ENV_CALC_NRGS *nrgs, + UCHAR *useAliasReduction, /*!< synthetic sine energy for each + subband, used as flag */ + int noSubbands) /*!< number of QMF channels to process */ +{ + FIXP_DBL *nrgGain = nrgs->nrgGain; /*!< subband gains to be modified */ + SCHAR *nrgGain_e = + nrgs->nrgGain_e; /*!< subband gains to be modified (exponents) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< subband energy before amplification */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< subband energy before amplification (exponents) */ + int grouping = 0, index = 0, noGroups, k; + int groupVector[MAX_FREQ_COEFFS]; + + /* Calculate grouping*/ + for (k = 0; k < noSubbands - 1; k++) { + if ((degreeAlias[k + 1] != FL2FXCONST_DBL(0.0f)) && useAliasReduction[k]) { + if (grouping == 0) { + groupVector[index++] = k; + grouping = 1; + } else { + if (groupVector[index - 1] + 3 == k) { + groupVector[index++] = k + 1; + grouping = 0; + } + } + } else { + if (grouping) { + if (useAliasReduction[k]) + groupVector[index++] = k + 1; + else + groupVector[index++] = k; + grouping = 0; + } + } + } + + if (grouping) { + groupVector[index++] = noSubbands; + } + noGroups = index >> 1; + + /*Calculate new gain*/ + for (int group = 0; group < noGroups; group++) { + FIXP_DBL nrgOrig = FL2FXCONST_DBL( + 0.0f); /* Original signal energy in current group of bands */ + SCHAR nrgOrig_e = 0; + FIXP_DBL nrgAmp = FL2FXCONST_DBL( + 0.0f); /* Amplified signal energy in group (using current gains) */ + SCHAR nrgAmp_e = 0; + FIXP_DBL nrgMod = FL2FXCONST_DBL( + 0.0f); /* Signal energy in group when applying modified gains */ + SCHAR nrgMod_e = 0; + FIXP_DBL groupGain; /* Total energy gain in group */ + SCHAR groupGain_e; + FIXP_DBL compensation; /* Compensation factor for the energy change when + applying modified gains */ + SCHAR compensation_e; + + int startGroup = groupVector[2 * group]; + int stopGroup = groupVector[2 * group + 1]; + + /* Calculate total energy in group before and after amplification with + * current gains: */ + for (k = startGroup; k < stopGroup; k++) { + /* Get original band energy */ + FIXP_DBL tmp = nrgEst[k]; + SCHAR tmp_e = nrgEst_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgOrig, nrgOrig_e, &nrgOrig, &nrgOrig_e); + + /* Multiply band energy with current gain */ + tmp = fMult(tmp, nrgGain[k]); + tmp_e = tmp_e + nrgGain_e[k]; + + FDK_add_MantExp(tmp, tmp_e, nrgAmp, nrgAmp_e, &nrgAmp, &nrgAmp_e); + } + + /* Calculate total energy gain in group */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgOrig, nrgOrig_e, &groupGain, + &groupGain_e); + + for (k = startGroup; k < stopGroup; k++) { + FIXP_DBL tmp; + SCHAR tmp_e; + + FIXP_DBL alpha = degreeAlias[k]; + if (k < noSubbands - 1) { + if (degreeAlias[k + 1] > alpha) alpha = degreeAlias[k + 1]; + } + + /* Modify gain depending on the degree of aliasing */ + FDK_add_MantExp( + fMult(alpha, groupGain), groupGain_e, + fMult(/*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - alpha, + nrgGain[k]), + nrgGain_e[k], &nrgGain[k], &nrgGain_e[k]); + + /* Apply modified gain to original energy */ + tmp = fMult(nrgGain[k], nrgEst[k]); + tmp_e = nrgGain_e[k] + nrgEst_e[k]; + + /* Accumulate energy with modified gains applied */ + FDK_add_MantExp(tmp, tmp_e, nrgMod, nrgMod_e, &nrgMod, &nrgMod_e); + } + + /* Calculate compensation factor to retain the energy of the amplified + * signal */ + FDK_divide_MantExp(nrgAmp, nrgAmp_e, nrgMod, nrgMod_e, &compensation, + &compensation_e); + + /* Apply compensation factor to all gains of the group */ + for (k = startGroup; k < stopGroup; k++) { + nrgGain[k] = fMult(nrgGain[k], compensation); + nrgGain_e[k] = nrgGain_e[k] + compensation_e; + } + } +} + +#define INTER_TES_SF_CHANGE 3 + +typedef struct { + FIXP_DBL subsample_power_low[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL subsample_power_high[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL gain[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_low_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + SCHAR subsample_power_high_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; +} ITES_TEMP; + +static void apply_inter_tes(FIXP_DBL **qmfReal, FIXP_DBL **qmfImag, + const QMF_SCALE_FACTOR *sbrScaleFactor, + const SCHAR exp[2], const int RATE, + const int startPos, const int stopPos, + const int lowSubband, const int nbSubband, + const UCHAR gamma_idx) { + int highSubband = lowSubband + nbSubband; + FIXP_DBL *subsample_power_high, *subsample_power_low; + SCHAR *subsample_power_high_sf, *subsample_power_low_sf; + FIXP_DBL total_power_high = (FIXP_DBL)0; + FIXP_DBL total_power_low = (FIXP_DBL)0; + FIXP_DBL *gain; + int gain_sf[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + + /* gamma[gamma_idx] = {0.0f, 1.0f, 2.0f, 4.0f} */ + int gamma_sf = + (int)gamma_idx - 1; /* perhaps +1 to save one bit? (0.99999f vs 1.f) */ + + int nbSubsample = stopPos - startPos; + int i, j; + + C_ALLOC_SCRATCH_START(pTmp, ITES_TEMP, 1); + subsample_power_high = pTmp->subsample_power_high; + subsample_power_low = pTmp->subsample_power_low; + subsample_power_high_sf = pTmp->subsample_power_high_sf; + subsample_power_low_sf = pTmp->subsample_power_low_sf; + gain = pTmp->gain; + + if (gamma_idx > 0) { + int preShift2 = 32 - fNormz((FIXP_DBL)nbSubsample); + int total_power_low_sf = 1 - DFRACT_BITS; + int total_power_high_sf = 1 - DFRACT_BITS; + + for (i = 0; i < nbSubsample; ++i) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal = (FIXP_DBL)0; + + int ts = startPos + i; + + int low_sf = (ts < 3 * RATE) ? sbrScaleFactor->ov_lb_scale + : sbrScaleFactor->lb_scale; + low_sf = 15 - low_sf; + + for (j = 0; j < lowSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_low[i] = (FIXP_DBL)0; + subsample_power_low_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + /* multiply first, then shift for safe summation */ + int preShift = 1 - CntLeadingZeros(maxVal); + int postShift = 32 - fNormz((FIXP_DBL)lowSubband); + + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + subsample_power_low_sf[i] += (low_sf + preShift) * 2 + postShift + 1; + + scaleValues(bufferReal, lowSubband, -preShift); + scaleValues(bufferImag, lowSubband, -preShift); + for (j = 0; j < lowSubband; ++j) { + FIXP_DBL addme; + addme = fPow2Div2(bufferReal[j]); + subsample_power_low[i] += addme >> postShift; + addme = fPow2Div2(bufferImag[j]); + subsample_power_low[i] += addme >> postShift; + } + } + + /* now get high */ + + maxVal = (FIXP_DBL)0; + + int high_sf = exp[(ts < 16 * RATE) ? 0 : 1]; + + for (j = lowSubband; j < highSubband; ++j) { + bufferImag[j] = qmfImag[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[j]) ^ + ((LONG)bufferImag[j] >> (DFRACT_BITS - 1))); + bufferReal[j] = qmfReal[startPos + i][j]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[j]) ^ + ((LONG)bufferReal[j] >> (DFRACT_BITS - 1))); + } + + subsample_power_high[i] = (FIXP_DBL)0; + subsample_power_high_sf[i] = 0; + + if (maxVal != FL2FXCONST_DBL(0.f)) { + int preShift = 1 - CntLeadingZeros(maxVal); + /* reduce preShift because otherwise we risk to square -1.f */ + if (preShift != 0) preShift++; + + int postShift = 32 - fNormz((FIXP_DBL)(highSubband - lowSubband)); + subsample_power_high_sf[i] += (high_sf + preShift) * 2 + postShift + 1; + + scaleValues(&bufferReal[lowSubband], highSubband - lowSubband, + -preShift); + scaleValues(&bufferImag[lowSubband], highSubband - lowSubband, + -preShift); + for (j = lowSubband; j < highSubband; j++) { + subsample_power_high[i] += fPow2Div2(bufferReal[j]) >> postShift; + subsample_power_high[i] += fPow2Div2(bufferImag[j]) >> postShift; + } + } + + /* sum all together */ + FIXP_DBL new_summand = subsample_power_low[i]; + int new_summand_sf = subsample_power_low_sf[i]; + + /* make sure the current sum, and the new summand have the same SF */ + if (new_summand_sf > total_power_low_sf) { + int diff = fMin(DFRACT_BITS - 1, new_summand_sf - total_power_low_sf); + total_power_low >>= diff; + total_power_low_sf = new_summand_sf; + } else if (new_summand_sf < total_power_low_sf) { + new_summand >>= + fMin(DFRACT_BITS - 1, total_power_low_sf - new_summand_sf); + } + + total_power_low += (new_summand >> preShift2); + + new_summand = subsample_power_high[i]; + new_summand_sf = subsample_power_high_sf[i]; + if (new_summand_sf > total_power_high_sf) { + total_power_high >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_sf); + total_power_high_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_sf) { + new_summand >>= + fMin(DFRACT_BITS - 1, total_power_high_sf - new_summand_sf); + } + + total_power_high += (new_summand >> preShift2); + } + + total_power_low_sf += preShift2; + total_power_high_sf += preShift2; + + /* gain[i] = e_LOW[i] */ + for (i = 0; i < nbSubsample; ++i) { + int sf2; + FIXP_DBL mult = + fMultNorm(subsample_power_low[i], (FIXP_DBL)nbSubsample, &sf2); + int mult_sf = subsample_power_low_sf[i] + DFRACT_BITS - 1 + sf2; + + if (total_power_low != FIXP_DBL(0)) { + gain[i] = fDivNorm(mult, total_power_low, &sf2); + gain_sf[i] = mult_sf - total_power_low_sf + sf2; + gain[i] = sqrtFixp_lookup(gain[i], &gain_sf[i]); + if (gain_sf[i] < 0) { + gain[i] >>= -gain_sf[i]; + gain_sf[i] = 0; + } + } else { + if (mult == FIXP_DBL(0)) { + gain[i] = FIXP_DBL(0); + gain_sf[i] = 0; + } else { + gain[i] = (FIXP_DBL)MAXVAL_DBL; + gain_sf[i] = 0; + } + } + } + + FIXP_DBL total_power_high_after = (FIXP_DBL)0; + int total_power_high_after_sf = 1 - DFRACT_BITS; + + /* gain[i] = g_inter[i] */ + for (i = 0; i < nbSubsample; ++i) { + if (gain_sf[i] < 0) { + gain[i] >>= -gain_sf[i]; + gain_sf[i] = 0; + } + + /* calculate: gain[i] = 1.0f + gamma * (gain[i] - 1.0f); */ + FIXP_DBL one = (FIXP_DBL)MAXVAL_DBL >> + gain_sf[i]; /* to substract this from gain[i] */ + + /* gamma is actually always 1 according to the table, so skip the + * fMultDiv2 */ + FIXP_DBL mult = (gain[i] - one) >> 1; + int mult_sf = gain_sf[i] + gamma_sf; + + one = FL2FXCONST_DBL(0.5f) >> mult_sf; + gain[i] = one + mult; + gain_sf[i] += gamma_sf + 1; /* +1 because of fMultDiv2() */ + + /* set gain to at least 0.2f */ + FIXP_DBL point_two = FL2FXCONST_DBL(0.8f); /* scaled up by 2 */ + int point_two_sf = -2; + + FIXP_DBL tmp = gain[i]; + if (point_two_sf < gain_sf[i]) { + point_two >>= gain_sf[i] - point_two_sf; + } else { + tmp >>= point_two_sf - gain_sf[i]; + } + + /* limit and calculate gain[i]^2 too */ + FIXP_DBL gain_pow2; + int gain_pow2_sf; + if (tmp < point_two) { + gain[i] = FL2FXCONST_DBL(0.8f); + gain_sf[i] = -2; + gain_pow2 = FL2FXCONST_DBL(0.64f); + gain_pow2_sf = -4; + } else { + /* this upscaling seems quite important */ + int r = CountLeadingBits(gain[i]); + gain[i] <<= r; + gain_sf[i] -= r; + + gain_pow2 = fPow2(gain[i]); + gain_pow2_sf = gain_sf[i] << 1; + } + + int room; + subsample_power_high[i] = + fMultNorm(subsample_power_high[i], gain_pow2, &room); + subsample_power_high_sf[i] = + subsample_power_high_sf[i] + gain_pow2_sf + room; + + int new_summand_sf = subsample_power_high_sf[i]; /* + gain_pow2_sf; */ + if (new_summand_sf > total_power_high_after_sf) { + total_power_high_after >>= + fMin(DFRACT_BITS - 1, new_summand_sf - total_power_high_after_sf); + total_power_high_after_sf = new_summand_sf; + } else if (new_summand_sf < total_power_high_after_sf) { + subsample_power_high[i] >>= total_power_high_after_sf - new_summand_sf; + } + total_power_high_after += subsample_power_high[i] >> preShift2; + } + + total_power_high_after_sf += preShift2; + + int sf2 = 0; + FIXP_DBL gain_adj_2 = FL2FX_DBL(0.5f); + int gain_adj_2_sf = 1; + + if ((total_power_high != (FIXP_DBL)0) && + (total_power_high_after != (FIXP_DBL)0)) { + gain_adj_2 = fDivNorm(total_power_high, total_power_high_after, &sf2); + gain_adj_2_sf = total_power_high_sf - total_power_high_after_sf + sf2; + } + + FIXP_DBL gain_adj = sqrtFixp_lookup(gain_adj_2, &gain_adj_2_sf); + int gain_adj_sf = gain_adj_2_sf; + + for (i = 0; i < nbSubsample; ++i) { + gain[i] = fMult(gain[i], gain_adj); + gain_sf[i] += gain_adj_sf; + + /* limit gain */ + if (gain_sf[i] > INTER_TES_SF_CHANGE) { + gain[i] = (FIXP_DBL)MAXVAL_DBL; + gain_sf[i] = INTER_TES_SF_CHANGE; + } + } + + for (i = 0; i < nbSubsample; ++i) { + /* equalize gain[]'s scale factors */ + gain[i] >>= INTER_TES_SF_CHANGE - gain_sf[i]; + + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] = fMult(qmfReal[startPos + i][j], gain[i]); + qmfImag[startPos + i][j] = fMult(qmfImag[startPos + i][j], gain[i]); + } + } + } else { /* gamma_idx == 0 */ + /* Inter-TES is not active. Still perform the scale change to have a + * consistent scaling for all envelopes of this frame. */ + for (i = 0; i < nbSubsample; ++i) { + for (j = lowSubband; j < highSubband; j++) { + qmfReal[startPos + i][j] >>= INTER_TES_SF_CHANGE; + qmfImag[startPos + i][j] >>= INTER_TES_SF_CHANGE; + } + } + } + C_ALLOC_SCRATCH_END(pTmp, ITES_TEMP, 1); +} + +/*! + \brief Apply spectral envelope to subband samples + + This function is called from sbr_dec.cpp in each frame. + + To enhance accuracy and due to the usage of tables for squareroots and + inverse, some calculations are performed with the operands being split + into mantissa and exponent. The variable names in the source code carry + the suffixes _m and _e respectively. The control data + in #hFrameData containts envelope data which is represented by this format but + stored in single words. (See requantizeEnvelopeData() for details). This data + is unpacked within calculateSbrEnvelope() to follow the described suffix + convention. + + The actual value (comparable to the corresponding float-variable in the + research-implementation) of a mantissa/exponent-pair can be calculated as + + \f$ value = value\_m * 2^{value\_e} \f$ + + All energies and noise levels decoded from the bitstream suit for an + original signal magnitude of \f$\pm 32768 \f$ rather than \f$ \pm 1\f$. + Therefore, the scale factor hb_scale passed into this function will + be converted to an 'input exponent' (#input_e), which fits the internal + representation. + + Before the actual processing, an exponent #adj_e for resulting adjusted + samples is derived from the maximum reference energy. + + Then, for each envelope, the following steps are performed: + + \li Calculate energy in the signal to be adjusted. Depending on the the value + of #interpolFreq (interpolation mode), this is either done seperately for each + QMF-subband or for each SBR-band. The resulting energies are stored in + #nrgEst_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgEst_e[#MAX_FREQ_COEFFS] + (exponents). \li Calculate gain and noise level for each subband:
\f$ gain + = \sqrt{ \frac{nrgRef}{nrgEst} \cdot (1 - noiseRatio) } \hspace{2cm} noise = + \sqrt{ nrgRef \cdot noiseRatio } \f$
where noiseRatio and + nrgRef are extracted from the bitstream and nrgEst is the + subband energy before adjustment. The resulting gains are stored in + #nrgGain_m[#MAX_FREQ_COEFFS] (mantissas) and #nrgGain_e[#MAX_FREQ_COEFFS] + (exponents), the noise levels are stored in #noiseLevel_m[#MAX_FREQ_COEFFS] + and #noiseLevel_e[#MAX_FREQ_COEFFS] (exponents). The sine levels are stored in + #nrgSine_m[#MAX_FREQ_COEFFS] and #nrgSine_e[#MAX_FREQ_COEFFS]. \li Noise + limiting: The gain for each subband is limited both absolutely and relatively + compared to the total gain over all subbands. \li Boost gain: Calculate and + apply boost factor for each limiter band in order to compensate for the energy + loss imposed by the limiting. \li Apply gains and add noise: The gains and + noise levels are applied to all timeslots of the current envelope. A short + FIR-filter (length 4 QMF-timeslots) can be used to smooth the sudden change at + the envelope borders. Each complex subband sample of the current timeslot is + multiplied by the smoothed gain, then random noise with the calculated level + is added. + + \note + To reduce the stack size, some of the local arrays could be located within + the time output buffer. Of the 512 samples temporarily available there, + about half the size is already used by #SBR_FRAME_DATA. A pointer to the + remaining free memory could be supplied by an additional argument to + calculateSbrEnvelope() in sbr_dec: + + \par + \code + calculateSbrEnvelope (&hSbrDec->sbrScaleFactor, + &hSbrDec->SbrCalculateEnvelope, + hHeaderData, + hFrameData, + QmfBufferReal, + QmfBufferImag, + timeOutPtr + sizeof(SBR_FRAME_DATA)/sizeof(Float) + + 1); \endcode + + \par + Within calculateSbrEnvelope(), some pointers could be defined instead of the + arrays #nrgRef_m, #nrgRef_e, #nrgEst_m, #nrgEst_e, #noiseLevel_m: + + \par + \code + fract* nrgRef_m = timeOutPtr; + SCHAR* nrgRef_e = nrgRef_m + MAX_FREQ_COEFFS; + fract* nrgEst_m = nrgRef_e + MAX_FREQ_COEFFS; + SCHAR* nrgEst_e = nrgEst_m + MAX_FREQ_COEFFS; + fract* noiseLevel_m = nrgEst_e + MAX_FREQ_COEFFS; + \endcode + +
+*/ +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + HANDLE_SBR_CALCULATE_ENVELOPE + h_sbr_cal_env, /*!< Handle to struct filled by the create-function */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL * + *analysBufferReal, /*!< Real part of subband samples to be processed */ + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag) { + int c, i, i_stop, j, envNoise = 0; + UCHAR *borders = hFrameData->frameInfo.borders; + UCHAR *bordersPvc = hFrameData->frameInfo.pvcBorders; + int pvc_mode = pPvcDynamicData->pvc_mode; + int first_start = + ((pvc_mode > 0) ? bordersPvc[0] : borders[0]) * hHeaderData->timeStep; + FIXP_SGL *noiseLevels = hFrameData->sbrNoiseFloorLevel; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + UCHAR **pFreqBandTable = hFreq->freqBandTable; + UCHAR *pFreqBandTableNoise = hFreq->freqBandTableNoise; + + int lowSubband = hFreq->lowSubband; + int highSubband = hFreq->highSubband; + int noSubbands = highSubband - lowSubband; + + /* old high subband before headerchange + we asume no headerchange here */ + int ov_highSubband = hFreq->highSubband; + + int noNoiseBands = hFreq->nNfb; + UCHAR *noSubFrameBands = hFreq->nSfb; + int no_cols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + SCHAR sineMapped[MAX_FREQ_COEFFS]; + SCHAR ov_adj_e = SCALE2EXP(sbrScaleFactor->ov_hb_scale); + SCHAR adj_e = 0; + SCHAR output_e; + SCHAR final_e = 0; + /* inter-TES is active in one or more envelopes of the current SBR frame */ + const int iTES_enable = hFrameData->iTESactive; + const int iTES_scale_change = (iTES_enable) ? INTER_TES_SF_CHANGE : 0; + SCHAR maxGainLimit_e = (frameErrorFlag) ? MAX_GAIN_CONCEAL_EXP : MAX_GAIN_EXP; + + UCHAR smooth_length = 0; + + FIXP_SGL *pIenv = hFrameData->iEnvelope; + + C_ALLOC_SCRATCH_START(useAliasReduction, UCHAR, 64) + + /* if values differ we had a headerchange; if old highband is bigger then new + one we need to patch overlap-highband-scaling for this frame (see use of + ov_highSubband) as overlap contains higher frequency components which would + get lost */ + if (hFreq->highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } + + if (pvc_mode > 0) { + if (hFrameData->frameInfo.bordersNoise[0] > bordersPvc[0]) { + /* noise envelope of previous frame is trailing into current PVC frame */ + envNoise = -1; + noiseLevels = h_sbr_cal_env->prevSbrNoiseFloorLevel; + noNoiseBands = h_sbr_cal_env->prevNNfb; + noSubFrameBands = h_sbr_cal_env->prevNSfb; + lowSubband = h_sbr_cal_env->prevLoSubband; + highSubband = h_sbr_cal_env->prevHiSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < h_sbr_cal_env->prev_ov_highSubband) { + ov_highSubband = h_sbr_cal_env->prev_ov_highSubband; + } + + pFreqBandTable[0] = h_sbr_cal_env->prevFreqBandTableLo; + pFreqBandTable[1] = h_sbr_cal_env->prevFreqBandTableHi; + pFreqBandTableNoise = h_sbr_cal_env->prevFreqBandTableNoise; + } + + mapSineFlagsPvc(pFreqBandTable[1], noSubFrameBands[1], + h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, sineMapped, + hFrameData->sinusoidal_position, + &h_sbr_cal_env->sinusoidal_positionPrev, + (borders[0] > bordersPvc[0]) ? 1 : 0); + } else { + /* + Extract sine flags for all QMF bands + */ + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->frameInfo.tranEnv, sineMapped); + } + + /* + Scan for maximum in bufferd noise levels. + This is needed in case that we had strong noise in the previous frame + which is smoothed into the current frame. + The resulting exponent is used as start value for the maximum search + in reference energies + */ + if (!useLP) + adj_e = h_sbr_cal_env->filtBufferNoise_e - + getScalefactor(h_sbr_cal_env->filtBufferNoise, noSubbands); + + /* + Scan for maximum reference energy to be able + to select appropriate values for adj_e and final_e. + */ + if (pvc_mode > 0) { + INT maxSfbNrg_e = pPvcDynamicData->predEsg_expMax; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the + current + */ + maxSfbNrg_e += 6; + + adj_e = maxSfbNrg_e; + // final_e should not exist for PVC fixfix framing + } else { + for (i = 0; i < hFrameData->frameInfo.nEnvelopes; i++) { + INT maxSfbNrg_e = + -FRACT_BITS + NRG_EXP_OFFSET; /* start value for maximum search */ + + /* Fetch frequency resolution for current envelope: */ + for (j = noSubFrameBands[hFrameData->frameInfo.freqRes[i]]; j != 0; j--) { + maxSfbNrg_e = fixMax(maxSfbNrg_e, (INT)((LONG)(*pIenv++) & MASK_E)); + } + maxSfbNrg_e -= NRG_EXP_OFFSET; + + /* Energy -> magnitude (sqrt halfens exponent) */ + maxSfbNrg_e = + (maxSfbNrg_e + 1) >> 1; /* +1 to go safe (round to next higher int) */ + + /* Some safety margin is needed for 2 reasons: + - The signal energy is not equally spread over all subband samples in + a specific sfb of an envelope (Nrg could be too high by a factor of + envWidth * sfbWidth) + - Smoothing can smear high gains of the previous envelope into the + current + */ + maxSfbNrg_e += 6; + + if (borders[i] < hHeaderData->numberTimeSlots) + /* This envelope affects timeslots that belong to the output frame */ + adj_e = fMax(maxSfbNrg_e, adj_e); + + if (borders[i + 1] > hHeaderData->numberTimeSlots) + /* This envelope affects timeslots after the output frame */ + final_e = fMax(maxSfbNrg_e, final_e); + } + } + /* + Calculate adjustment factors and apply them for every envelope. + */ + pIenv = hFrameData->iEnvelope; + + if (pvc_mode > 0) { + /* iterate over SBR time slots starting with bordersPvc[i] */ + i = bordersPvc[0]; /* usually 0; can be >0 if switching from legacy SBR to + PVC */ + i_stop = PVC_NTIMESLOT; + FDK_ASSERT(bordersPvc[hFrameData->frameInfo.nEnvelopes] == PVC_NTIMESLOT); + } else { + /* iterate over SBR envelopes starting with 0 */ + i = 0; + i_stop = hFrameData->frameInfo.nEnvelopes; + } + for (; i < i_stop; i++) { + int k, noNoiseFlag; + SCHAR noise_e, input_e = SCALE2EXP(sbrScaleFactor->hb_scale); + C_ALLOC_SCRATCH_START(pNrgs, ENV_CALC_NRGS, 1); + + /* + Helper variables. + */ + int start_pos, stop_pos, freq_res; + if (pvc_mode > 0) { + start_pos = + hHeaderData->timeStep * + i; /* Start-position in time (subband sample) for current envelope. */ + stop_pos = hHeaderData->timeStep * (i + 1); /* Stop-position in time + (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[0]; /* Frequency resolution for current envelope. */ + FDK_ASSERT( + freq_res == + hFrameData->frameInfo.freqRes[hFrameData->frameInfo.nEnvelopes - 1]); + } else { + start_pos = hHeaderData->timeStep * + borders[i]; /* Start-position in time (subband sample) for + current envelope. */ + stop_pos = hHeaderData->timeStep * + borders[i + 1]; /* Stop-position in time (subband sample) for + current envelope. */ + freq_res = + hFrameData->frameInfo + .freqRes[i]; /* Frequency resolution for current envelope. */ + } + + /* Always fully initialize the temporary energy table. This prevents + negative energies and extreme gain factors in cases where the number of + limiter bands exceeds the number of subbands. The latter can be caused by + undetected bit errors and is tested by some streams from the + certification set. */ + FDKmemclear(pNrgs, sizeof(ENV_CALC_NRGS)); + + if (pvc_mode > 0) { + /* get predicted energy values from PVC module */ + expandPredEsg(pPvcDynamicData, i, (int)MAX_FREQ_COEFFS, pNrgs->nrgRef, + pNrgs->nrgRef_e); + + if (i == borders[0]) { + mapSineFlags(pFreqBandTable[1], noSubFrameBands[1], + hFrameData->addHarmonics, h_sbr_cal_env->harmFlagsPrev, + h_sbr_cal_env->harmFlagsPrevActive, + hFrameData->sinusoidal_position, sineMapped); + } + + if (i >= hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + if (envNoise >= 0) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a + row [noiseFloor1 noiseFloor2...].*/ + } else { + /* leave trailing noise envelope of past frame */ + noNoiseBands = hFreq->nNfb; + noSubFrameBands = hFreq->nSfb; + noiseLevels = hFrameData->sbrNoiseFloorLevel; + + lowSubband = hFreq->lowSubband; + highSubband = hFreq->highSubband; + + noSubbands = highSubband - lowSubband; + ov_highSubband = highSubband; + if (highSubband < hFreq->ov_highSubband) { + ov_highSubband = hFreq->ov_highSubband; + } + + pFreqBandTable[0] = hFreq->freqBandTableLo; + pFreqBandTable[1] = hFreq->freqBandTableHi; + pFreqBandTableNoise = hFreq->freqBandTableNoise; + } + envNoise++; + } + } else { + /* If the start-pos of the current envelope equals the stop pos of the + current noise envelope, increase the pointer (i.e. choose the next + noise-floor).*/ + if (borders[i] == hFrameData->frameInfo.bordersNoise[envNoise + 1]) { + noiseLevels += noNoiseBands; /* The noise floor data is stored in a row + [noiseFloor1 noiseFloor2...].*/ + envNoise++; + } + } + if (i == hFrameData->frameInfo.tranEnv || + i == h_sbr_cal_env->prevTranEnv) /* attack */ + { + noNoiseFlag = 1; + if (!useLP) smooth_length = 0; /* No smoothing on attacks! */ + } else { + noNoiseFlag = 0; + if (!useLP) + smooth_length = (1 - hHeaderData->bs_data.smoothingLength) + << 2; /* can become either 0 or 4 */ + } + + /* + Energy estimation in transposed highband. + */ + if (hHeaderData->bs_data.interpolFreq) + calcNrgPerSubband(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, start_pos, stop_pos, input_e, + pNrgs->nrgEst, pNrgs->nrgEst_e); + else + calcNrgPerSfb(analysBufferReal, (useLP) ? NULL : analysBufferImag, + noSubFrameBands[freq_res], pFreqBandTable[freq_res], + start_pos, stop_pos, input_e, pNrgs->nrgEst, + pNrgs->nrgEst_e); + + /* + Calculate subband gains + */ + { + UCHAR *table = pFreqBandTable[freq_res]; + UCHAR *pUiNoise = + &pFreqBandTableNoise[1]; /*! Upper limit of the current noise floor + band. */ + + FIXP_SGL *pNoiseLevels = noiseLevels; + + FIXP_DBL tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + SCHAR tmpNoise_e = + (UCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + int cc = 0; + c = 0; + if (pvc_mode > 0) { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; + + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; + } + + for (k = li; k < ui; k++) { + FIXP_DBL refNrg = pNrgs->nrgRef[k - lowSubband]; + SCHAR refNrg_e = pNrgs->nrgRef_e[k - lowSubband]; + + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); + + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); + + c++; + } + } + } else { + for (j = 0; j < noSubFrameBands[freq_res]; j++) { + FIXP_DBL refNrg = FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pIenv) & MASK_M)); + SCHAR refNrg_e = (SCHAR)((LONG)(*pIenv) & MASK_E) - NRG_EXP_OFFSET; + + UCHAR sinePresentFlag = 0; + int li = table[j]; + int ui = table[j + 1]; + + for (k = li; k < ui; k++) { + sinePresentFlag |= (i >= sineMapped[cc]); + cc++; + } + + for (k = li; k < ui; k++) { + if (k >= *pUiNoise) { + tmpNoise = + FX_SGL2FX_DBL((FIXP_SGL)((LONG)(*pNoiseLevels) & MASK_M)); + tmpNoise_e = + (SCHAR)((LONG)(*pNoiseLevels++) & MASK_E) - NOISE_EXP_OFFSET; + + pUiNoise++; + } + + FDK_ASSERT(k >= lowSubband); + + if (useLP) useAliasReduction[k - lowSubband] = !sinePresentFlag; + + pNrgs->nrgSine[c] = FL2FXCONST_DBL(0.0f); + pNrgs->nrgSine_e[c] = 0; + + calcSubbandGain(refNrg, refNrg_e, pNrgs, c, tmpNoise, tmpNoise_e, + sinePresentFlag, i >= sineMapped[c], noNoiseFlag); + + pNrgs->nrgRef[c] = refNrg; + pNrgs->nrgRef_e[c] = refNrg_e; + + c++; + } + pIenv++; + } + } + } + + /* + Noise limiting + */ + + for (c = 0; c < hFreq->noLimiterBands; c++) { + FIXP_DBL sumRef, boostGain, maxGain; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + SCHAR sumRef_e, boostGain_e, maxGain_e, accu_e = 0; + int maxGainLimGainSum_e = 0; + + calcAvgGain(pNrgs, hFreq->limiterBandTable[c], + hFreq->limiterBandTable[c + 1], &sumRef, &sumRef_e, &maxGain, + &maxGain_e); + + /* Multiply maxGain with limiterGain: */ + maxGain = fMult( + maxGain, + FDK_sbrDecoder_sbr_limGains_m[hHeaderData->bs_data.limiterGains]); + /* maxGain_e += + * FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; */ + /* The addition of maxGain_e and FDK_sbrDecoder_sbr_limGains_e[3] might + yield values greater than 127 which doesn't fit into an SCHAR! In these + rare situations limit maxGain_e to 127. + */ + maxGainLimGainSum_e = + maxGain_e + + FDK_sbrDecoder_sbr_limGains_e[hHeaderData->bs_data.limiterGains]; + maxGain_e = + (maxGainLimGainSum_e > 127) ? (SCHAR)127 : (SCHAR)maxGainLimGainSum_e; + + /* Scale mantissa of MaxGain into range between 0.5 and 1: */ + if (maxGain == FL2FXCONST_DBL(0.0f)) + maxGain_e = -FRACT_BITS; + else { + SCHAR charTemp = CountLeadingBits(maxGain); + maxGain_e -= charTemp; + maxGain <<= (int)charTemp; + } + + if (maxGain_e >= maxGainLimit_e) { /* upper limit (e.g. 96 dB) */ + maxGain = FL2FXCONST_DBL(0.5f); + maxGain_e = maxGainLimit_e; + } + + /* Every subband gain is compared to the scaled "average gain" + and limited if necessary: */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + if ((pNrgs->nrgGain_e[k] > maxGain_e) || + (pNrgs->nrgGain_e[k] == maxGain_e && pNrgs->nrgGain[k] > maxGain)) { + FIXP_DBL noiseAmp; + SCHAR noiseAmp_e; + + FDK_divide_MantExp(maxGain, maxGain_e, pNrgs->nrgGain[k], + pNrgs->nrgGain_e[k], &noiseAmp, &noiseAmp_e); + pNrgs->noiseLevel[k] = fMult(pNrgs->noiseLevel[k], noiseAmp); + pNrgs->noiseLevel_e[k] += noiseAmp_e; + pNrgs->nrgGain[k] = maxGain; + pNrgs->nrgGain_e[k] = maxGain_e; + } + } + + /* -- Boost gain + Calculate and apply boost factor for each limiter band: + 1. Check how much energy would be present when using the limited gain + 2. Calculate boost factor by comparison with reference energy + 3. Apply boost factor to compensate for the energy loss due to limiting + */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + /* 1.a Add energy of adjusted signal (using preliminary gain) */ + FIXP_DBL tmp = fMult(pNrgs->nrgGain[k], pNrgs->nrgEst[k]); + SCHAR tmp_e = pNrgs->nrgGain_e[k] + pNrgs->nrgEst_e[k]; + FDK_add_MantExp(tmp, tmp_e, accu, accu_e, &accu, &accu_e); + + /* 1.b Add sine energy (if present) */ + if (pNrgs->nrgSine[k] != FL2FXCONST_DBL(0.0f)) { + FDK_add_MantExp(pNrgs->nrgSine[k], pNrgs->nrgSine_e[k], accu, accu_e, + &accu, &accu_e); + } else { + /* 1.c Add noise energy (if present) */ + if (noNoiseFlag == 0) { + FDK_add_MantExp(pNrgs->noiseLevel[k], pNrgs->noiseLevel_e[k], accu, + accu_e, &accu, &accu_e); + } + } + } + + /* 2.a Calculate ratio of wanted energy and accumulated energy */ + if (accu == (FIXP_DBL)0) { /* If divisor is 0, limit quotient to +4 dB */ + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } else { + INT div_e; + boostGain = fDivNorm(sumRef, accu, &div_e); + boostGain_e = sumRef_e - accu_e + div_e; + } + + /* 2.b Result too high? --> Limit the boost factor to +4 dB */ + if ((boostGain_e > 3) || + (boostGain_e == 2 && boostGain > FL2FXCONST_DBL(0.6279716f)) || + (boostGain_e == 3 && boostGain > FL2FXCONST_DBL(0.3139858f))) { + boostGain = FL2FXCONST_DBL(0.6279716f); + boostGain_e = 2; + } + /* 3. Multiply all signal components with the boost factor */ + for (k = hFreq->limiterBandTable[c]; k < hFreq->limiterBandTable[c + 1]; + k++) { + pNrgs->nrgGain[k] = fMultDiv2(pNrgs->nrgGain[k], boostGain); + pNrgs->nrgGain_e[k] = pNrgs->nrgGain_e[k] + boostGain_e + 1; + + pNrgs->nrgSine[k] = fMultDiv2(pNrgs->nrgSine[k], boostGain); + pNrgs->nrgSine_e[k] = pNrgs->nrgSine_e[k] + boostGain_e + 1; + + pNrgs->noiseLevel[k] = fMultDiv2(pNrgs->noiseLevel[k], boostGain); + pNrgs->noiseLevel_e[k] = pNrgs->noiseLevel_e[k] + boostGain_e + 1; + } + } + /* End of noise limiting */ + + if (useLP) + aliasingReduction(degreeAlias + lowSubband, pNrgs, useAliasReduction, + noSubbands); + + /* For the timeslots within the range for the output frame, + use the same scale for the noise levels. + Drawback: If the envelope exceeds the frame border, the noise levels + will have to be rescaled later to fit final_e of + the gain-values. + */ + noise_e = (start_pos < no_cols) ? adj_e : final_e; + + /* + Convert energies to amplitude levels + */ + for (k = 0; k < noSubbands; k++) { + FDK_sqrt_MantExp(&pNrgs->nrgSine[k], &pNrgs->nrgSine_e[k], &noise_e); + FDK_sqrt_MantExp(&pNrgs->nrgGain[k], &pNrgs->nrgGain_e[k], + &pNrgs->nrgGain_e[k]); + FDK_sqrt_MantExp(&pNrgs->noiseLevel[k], &pNrgs->noiseLevel_e[k], + &noise_e); + } + + /* + Apply calculated gains and adaptive noise + */ + + /* assembleHfSignals() */ + { + int scale_change, sc_change; + FIXP_SGL smooth_ratio; + int filtBufferNoiseShift = 0; + + /* Initialize smoothing buffers with the first valid values */ + if (h_sbr_cal_env->startUp) { + if (!useLP) { + h_sbr_cal_env->filtBufferNoise_e = noise_e; + + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); + } + h_sbr_cal_env->startUp = 0; + } + + if (!useLP) { + equalizeFiltBufferExp(h_sbr_cal_env->filtBuffer, /* buffered */ + h_sbr_cal_env->filtBuffer_e, /* buffered */ + pNrgs->nrgGain, /* current */ + pNrgs->nrgGain_e, /* current */ + noSubbands); + + /* Adapt exponent of buffered noise levels to the current exponent + so they can easily be smoothed */ + if ((h_sbr_cal_env->filtBufferNoise_e - noise_e) >= 0) { + int shift = fixMin(DFRACT_BITS - 1, + (int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) + h_sbr_cal_env->filtBufferNoise[k] <<= shift; + } else { + int shift = + fixMin(DFRACT_BITS - 1, + -(int)(h_sbr_cal_env->filtBufferNoise_e - noise_e)); + for (k = 0; k < noSubbands; k++) + h_sbr_cal_env->filtBufferNoise[k] >>= shift; + } + + h_sbr_cal_env->filtBufferNoise_e = noise_e; + } + + /* find best scaling! */ + scale_change = -(DFRACT_BITS - 1); + for (k = 0; k < noSubbands; k++) { + scale_change = fixMax(scale_change, (int)pNrgs->nrgGain_e[k]); + } + sc_change = (start_pos < no_cols) ? adj_e - input_e : final_e - input_e; + + if ((scale_change - sc_change + 1) < 0) + scale_change -= (scale_change - sc_change + 1); + + scale_change = (scale_change - sc_change) + 1; + + for (k = 0; k < noSubbands; k++) { + int sc = scale_change - pNrgs->nrgGain_e[k] + (sc_change - 1); + pNrgs->nrgGain[k] >>= sc; + pNrgs->nrgGain_e[k] += sc; + } + + if (!useLP) { + for (k = 0; k < noSubbands; k++) { + int sc = + scale_change - h_sbr_cal_env->filtBuffer_e[k] + (sc_change - 1); + h_sbr_cal_env->filtBuffer[k] >>= sc; + } + } + + for (j = start_pos; j < stop_pos; j++) { + /* This timeslot is located within the first part of the processing + buffer and will be fed into the QMF-synthesis for the current frame. + adj_e - input_e + This timeslot will not yet be fed into the QMF so we do not care + about the adj_e. + sc_change = final_e - input_e + */ + if ((j == no_cols) && (start_pos < no_cols)) { + int shift = (int)(noise_e - final_e); + if (!useLP) + filtBufferNoiseShift = shift; /* shifting of + h_sbr_cal_env->filtBufferNoise[k] + will be applied in function + adjustTimeSlotHQ() */ + if (shift >= 0) { + shift = fixMin(DFRACT_BITS - 1, shift); + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgSine[k] <<= shift; + pNrgs->noiseLevel[k] <<= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] <<= shift; + */ + } + } else { + shift = fixMin(DFRACT_BITS - 1, -shift); + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgSine[k] >>= shift; + pNrgs->noiseLevel[k] >>= shift; + /* + if (!useLP) + h_sbr_cal_env->filtBufferNoise[k] >>= shift; + */ + } + } + + /* update noise scaling */ + noise_e = final_e; + if (!useLP) + h_sbr_cal_env->filtBufferNoise_e = + noise_e; /* scaling value unused! */ + + /* update gain buffer*/ + sc_change -= (final_e - input_e); + + if (sc_change < 0) { + for (k = 0; k < noSubbands; k++) { + pNrgs->nrgGain[k] >>= -sc_change; + pNrgs->nrgGain_e[k] += -sc_change; + } + if (!useLP) { + for (k = 0; k < noSubbands; k++) { + h_sbr_cal_env->filtBuffer[k] >>= -sc_change; + } + } + } else { + scale_change += sc_change; + } + + } /* if */ + + if (!useLP) { + /* Prevent the smoothing filter from running on constant levels */ + if (j - start_pos < smooth_length) + smooth_ratio = FDK_sbrDecoder_sbr_smoothFilter[j - start_pos]; + else + smooth_ratio = FL2FXCONST_SGL(0.0f); + + if (iTES_enable) { + /* adjustTimeSlotHQ() without adding of additional harmonics */ + adjustTimeSlotHQ_GainAndNoise( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, fMin(scale_change, DFRACT_BITS - 1), + smooth_ratio, noNoiseFlag, filtBufferNoiseShift); + } else { + adjustTimeSlotHQ(&analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, + pNrgs, lowSubband, noSubbands, + fMin(scale_change, DFRACT_BITS - 1), smooth_ratio, + noNoiseFlag, filtBufferNoiseShift); + } + } else { + FDK_ASSERT(!iTES_enable); /* not supported */ + if (flags & SBRDEC_ELD_GRID) { + /* FDKmemset(analysBufferReal[j], 0, 64 * sizeof(FIXP_DBL)); */ + adjustTimeSlot_EldGrid(&analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, + noSubbands, + fMin(scale_change, DFRACT_BITS - 1), + noNoiseFlag, &h_sbr_cal_env->phaseIndex, + EXP2SCALE(adj_e) - sbrScaleFactor->lb_scale); + } else { + adjustTimeSlotLC(&analysBufferReal[j][lowSubband], pNrgs, + &h_sbr_cal_env->harmIndex, lowSubband, noSubbands, + fMin(scale_change, DFRACT_BITS - 1), noNoiseFlag, + &h_sbr_cal_env->phaseIndex); + } + } + /* In case the envelope spans accross the no_cols border both exponents + * are needed. */ + /* nrgGain_e[0...(noSubbands-1)] are equalized by + * equalizeFiltBufferExp() */ + pNrgs->exponent[(j < no_cols) ? 0 : 1] = + (SCHAR)((15 - sbrScaleFactor->hb_scale) + pNrgs->nrgGain_e[0] + 1 - + scale_change); + } /* for */ + + if (iTES_enable) { + apply_inter_tes( + analysBufferReal, /* pABufR, */ + analysBufferImag, /* pABufI, */ + sbrScaleFactor, pNrgs->exponent, hHeaderData->timeStep, start_pos, + stop_pos, lowSubband, noSubbands, + hFrameData + ->interTempShapeMode[i] /* frameData->interTempShapeMode[env] */ + ); + + /* add additional harmonics */ + for (j = start_pos; j < stop_pos; j++) { + /* match exponent of additional harmonics to scale change of QMF data + * caused by apply_inter_tes() */ + scale_change = 0; + + if ((start_pos <= no_cols) && (stop_pos > no_cols)) { + /* Scaling of analysBuffers was potentially changed within this + envelope. The pNrgs->nrgSine_e match the second part of the + envelope. For (j<=no_cols) the exponent of the sine energies has + to be adapted. */ + scale_change = pNrgs->exponent[1] - pNrgs->exponent[0]; + } + + adjustTimeSlotHQ_AddHarmonics( + &analysBufferReal[j][lowSubband], + &analysBufferImag[j][lowSubband], h_sbr_cal_env, pNrgs, + lowSubband, noSubbands, + -iTES_scale_change + ((j < no_cols) ? scale_change : 0)); + } + } + + if (!useLP) { + /* Update time-smoothing-buffers for gains and noise levels + The gains and the noise values of the current envelope are copied + into the buffer. This has to be done at the end of each envelope as + the values are required for a smooth transition to the next envelope. + */ + FDKmemcpy(h_sbr_cal_env->filtBuffer, pNrgs->nrgGain, + noSubbands * sizeof(FIXP_DBL)); + FDKmemcpy(h_sbr_cal_env->filtBuffer_e, pNrgs->nrgGain_e, + noSubbands * sizeof(SCHAR)); + FDKmemcpy(h_sbr_cal_env->filtBufferNoise, pNrgs->noiseLevel, + noSubbands * sizeof(FIXP_DBL)); + } + } + C_ALLOC_SCRATCH_END(pNrgs, ENV_CALC_NRGS, 1); + } + + /* adapt adj_e to the scale change caused by apply_inter_tes() */ + adj_e += iTES_scale_change; + + /* Rescale output samples */ + { + FIXP_DBL maxVal; + int ov_reserve, reserve; + + /* Determine headroom in old adjusted samples */ + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start); + + ov_reserve = fNorm(maxVal); + + /* Determine headroom in new adjusted samples */ + maxVal = + maxSubbandSample(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols); + + reserve = fNorm(maxVal); + + /* Determine common output exponent */ + output_e = fMax(ov_adj_e - ov_reserve, adj_e - reserve); + + /* Rescale old samples */ + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, ov_highSubband, 0, first_start, + ov_adj_e - output_e); + + /* Rescale new samples */ + rescaleSubbandSamples(analysBufferReal, (useLP) ? NULL : analysBufferImag, + lowSubband, highSubband, first_start, no_cols, + adj_e - output_e); + } + + /* Update hb_scale */ + sbrScaleFactor->hb_scale = EXP2SCALE(output_e); + + /* Save the current final exponent for the next frame: */ + /* adapt final_e to the scale change caused by apply_inter_tes() */ + sbrScaleFactor->ov_hb_scale = EXP2SCALE(final_e + iTES_scale_change); + + /* We need to remember to the next frame that the transient + will occur in the first envelope (if tranEnv == nEnvelopes). */ + if (hFrameData->frameInfo.tranEnv == hFrameData->frameInfo.nEnvelopes) + h_sbr_cal_env->prevTranEnv = 0; + else + h_sbr_cal_env->prevTranEnv = -1; + + if (pvc_mode > 0) { + /* Not more than just the last noise envelope reaches into the next PVC + frame! This should be true because bs_noise_position is <= 15 */ + FDK_ASSERT(hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes - 1] < + PVC_NTIMESLOT); + if (hFrameData->frameInfo + .bordersNoise[hFrameData->frameInfo.nNoiseEnvelopes] > + PVC_NTIMESLOT) { + FDK_ASSERT(noiseLevels == + (hFrameData->sbrNoiseFloorLevel + + (hFrameData->frameInfo.nNoiseEnvelopes - 1) * noNoiseBands)); + h_sbr_cal_env->prevNNfb = noNoiseBands; + + h_sbr_cal_env->prevNSfb[0] = noSubFrameBands[0]; + h_sbr_cal_env->prevNSfb[1] = noSubFrameBands[1]; + + h_sbr_cal_env->prevLoSubband = lowSubband; + h_sbr_cal_env->prevHiSubband = highSubband; + h_sbr_cal_env->prev_ov_highSubband = ov_highSubband; + + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableLo, pFreqBandTable[0], + noSubFrameBands[0] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableHi, pFreqBandTable[1], + noSubFrameBands[1] + 1); + FDKmemcpy(h_sbr_cal_env->prevFreqBandTableNoise, + hFreq->freqBandTableNoise, sizeof(hFreq->freqBandTableNoise)); + + FDKmemcpy(h_sbr_cal_env->prevSbrNoiseFloorLevel, noiseLevels, + MAX_NOISE_COEFFS * sizeof(FIXP_SGL)); + } + } + + C_ALLOC_SCRATCH_END(useAliasReduction, UCHAR, 64) +} + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be + used. + + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hs, /*!< pointer to envelope instance */ + HANDLE_SBR_HEADER_DATA + hHeaderData, /*!< static SBR control data, initialized with defaults */ + const int chan, /*!< Channel for which to assign buffers */ + const UINT flags) { + SBR_ERROR err = SBRDEC_OK; + int i; + + /* Clear previous missing harmonics flags */ + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) { + hs->harmFlagsPrev[i] = 0; + hs->harmFlagsPrevActive[i] = 0; + } + hs->harmIndex = 0; + + FDKmemclear(hs->prevSbrNoiseFloorLevel, sizeof(hs->prevSbrNoiseFloorLevel)); + hs->prevNNfb = 0; + FDKmemclear(hs->prevFreqBandTableNoise, sizeof(hs->prevFreqBandTableNoise)); + hs->sinusoidal_positionPrev = 0; + + /* + Setup pointers for time smoothing. + The buffer itself will be initialized later triggered by the startUp-flag. + */ + hs->prevTranEnv = -1; + + /* initialization */ + resetSbrEnvelopeCalc(hs); + + if (chan == 0) { /* do this only once */ + err = resetFreqBandTables(hHeaderData, flags); + } + + return err; +} + +/*! + \brief Create envelope instance + + Must be called once for each channel before calculateSbrEnvelope() can be + used. + + \return errorCode, 0 if successful +*/ +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hs) { return 0; } + +/*! + \brief Reset envelope instance + + This function must be called for each channel on a change of configuration. + Note that resetFreqBandTables should also be called in this case. + + \return errorCode, 0 if successful +*/ +void resetSbrEnvelopeCalc( + HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv) /*!< pointer to envelope instance */ +{ + hCalEnv->phaseIndex = 0; + + /* Noise exponent needs to be reset because the output exponent for the next + * frame depends on it */ + hCalEnv->filtBufferNoise_e = 0; + + hCalEnv->startUp = 1; +} + +/*! + \brief Equalize exponents of the buffered gain values and the new ones + + After equalization of exponents, the FIR-filter addition for smoothing + can be performed. + This function is called once for each envelope before adjusting. +*/ +static void equalizeFiltBufferExp( + FIXP_DBL *filtBuffer, /*!< bufferd gains */ + SCHAR *filtBuffer_e, /*!< exponents of bufferd gains */ + FIXP_DBL *nrgGain, /*!< gains for current envelope */ + SCHAR *nrgGain_e, /*!< exponents of gains for current envelope */ + int subbands) /*!< Number of QMF subbands */ +{ + int band; + int diff; + + for (band = 0; band < subbands; band++) { + diff = (int)(nrgGain_e[band] - filtBuffer_e[band]); + if (diff > 0) { + filtBuffer[band] >>= + diff; /* Compensate for the scale change by shifting the mantissa. */ + filtBuffer_e[band] += diff; /* New gain is bigger, use its exponent */ + } else if (diff < 0) { + /* The buffered gains seem to be larger, but maybe there + are some unused bits left in the mantissa */ + + int reserve = CntLeadingZeros(fixp_abs(filtBuffer[band])) - 1; + + if ((-diff) <= reserve) { + /* There is enough space in the buffered mantissa so + that we can take the new exponent as common. + */ + filtBuffer[band] <<= (-diff); + filtBuffer_e[band] += diff; /* becomes equal to *ptrNewExp */ + } else { + filtBuffer[band] <<= + reserve; /* Shift the mantissa as far as possible: */ + filtBuffer_e[band] -= reserve; /* Compensate in the exponent: */ + + /* For the remaining difference, change the new gain value */ + diff = fixMin(-(reserve + diff), DFRACT_BITS - 1); + nrgGain[band] >>= diff; + nrgGain_e[band] += diff; + } + } + } +} + +/*! + \brief Shift left the mantissas of all subband samples + in the giventime and frequency range by the specified number of bits. + + This function is used to rescale the audio data in the overlap buffer + which has already been envelope adjusted with the last frame. +*/ +void rescaleSubbandSamples( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Imaginary part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< End of frequency range to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos, /*!< End of time rage (QMF-timeslot) */ + int shift) /*!< number of bits to shift */ +{ + int width = highSubband - lowSubband; + + if ((width > 0) && (shift != 0)) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); + scaleValues(&im[l][lowSubband], width, shift); + } + } else { + for (int l = start_pos; l < next_pos; l++) { + scaleValues(&re[l][lowSubband], width, shift); + } + } + } +} + +static inline FIXP_DBL FDK_get_maxval_real(FIXP_DBL maxVal, FIXP_DBL *reTmp, + INT width) { + maxVal = (FIXP_DBL)0; + while (width-- != 0) { + FIXP_DBL tmp = *(reTmp++); + maxVal |= (FIXP_DBL)((LONG)(tmp) ^ ((LONG)tmp >> (DFRACT_BITS - 1))); + } + + return maxVal; +} + +/*! + \brief Determine headroom for shifting + + Determine by how much the spectrum can be shifted left + for better accuracy in later processing. + + \return Number of free bits in the biggest spectral value +*/ + +FIXP_DBL maxSubbandSample( + FIXP_DBL **re, /*!< Real part of input and output subband samples */ + FIXP_DBL **im, /*!< Real part of input and output subband samples */ + int lowSubband, /*!< Begin of frequency range to process */ + int highSubband, /*!< Number of QMF bands to process */ + int start_pos, /*!< Begin of time rage (QMF-timeslot) */ + int next_pos /*!< End of time rage (QMF-timeslot) */ +) { + FIXP_DBL maxVal = FL2FX_DBL(0.0f); + unsigned int width = highSubband - lowSubband; + + FDK_ASSERT(width <= (64)); + + if (width > 0) { + if (im != NULL) { + for (int l = start_pos; l < next_pos; l++) { + int k = width; + FIXP_DBL *reTmp = &re[l][lowSubband]; + FIXP_DBL *imTmp = &im[l][lowSubband]; + do { + FIXP_DBL tmp1 = *(reTmp++); + FIXP_DBL tmp2 = *(imTmp++); + maxVal |= + (FIXP_DBL)((LONG)(tmp1) ^ ((LONG)tmp1 >> (DFRACT_BITS - 1))); + maxVal |= + (FIXP_DBL)((LONG)(tmp2) ^ ((LONG)tmp2 >> (DFRACT_BITS - 1))); + } while (--k != 0); + } + } else { + for (int l = start_pos; l < next_pos; l++) { + maxVal |= FDK_get_maxval_real(maxVal, &re[l][lowSubband], width); + } + } + } + + if (maxVal > (FIXP_DBL)0) { + /* For negative input values, maxVal is too small by 1. Add 1 only when + * necessary: if maxVal is a power of 2 */ + FIXP_DBL lowerPow2 = + (FIXP_DBL)(1 << (DFRACT_BITS - 1 - CntLeadingZeros(maxVal))); + if (maxVal == lowerPow2) maxVal += (FIXP_DBL)1; + } + + return (maxVal); +} + +/* #define SHIFT_BEFORE_SQUARE (3) */ /* (7/2) */ +/* Avoid assertion failures triggerd by overflows which occured in robustness + tests. Setting the SHIFT_BEFORE_SQUARE to 4 has negligible effect on (USAC) + conformance results. */ +#define SHIFT_BEFORE_SQUARE (4) /* ((8 - 0) / 2) */ + +/*!< + If the accumulator does not provide enough overflow bits or + does not provide a high dynamic range, the below energy calculation + requires an additional shift operation for each sample. + On the other hand, doing the shift allows using a single-precision + multiplication for the square (at least 16bit x 16bit). + For even values of OVRFLW_BITS (0, 2, 4, 6), saturated arithmetic + is required for the energy accumulation. + Theoretically, the sample-squares can sum up to a value of 76, + requiring 7 overflow bits. However since such situations are *very* + rare, accu can be limited to 64. + In case native saturated arithmetic is not available, overflows + can be prevented by replacing the above #define by + #define SHIFT_BEFORE_SQUARE ((8 - OVRFLW_BITS) / 2) + which will result in slightly reduced accuracy. +*/ + +/*! + \brief Estimates the mean energy of each filter-bank channel for the + duration of the current envelope + + This function is used when interpolFreq is true. +*/ +static void calcNrgPerSubband( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int lowSubband, /*!< Begin of the SBR frequency range */ + int highSubband, /*!< High end of the SBR frequency range */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR frameExp, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + SCHAR preShift; + SCHAR shift; + FIXP_DBL sum; + int k; + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: + */ + frameExp = frameExp << 1; + + for (k = lowSubband; k < highSubband; k++) { + FIXP_DBL bufferReal[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL bufferImag[(((1024) / (32) * (4) / 2) + (3 * (4)))]; + FIXP_DBL maxVal; + + if (analysBufferImag != NULL) { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { + bufferImag[l] = analysBufferImag[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferImag[l]) ^ + ((LONG)bufferImag[l] >> (DFRACT_BITS - 1))); + bufferReal[l] = analysBufferReal[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); + } + } else { + int l; + maxVal = FL2FX_DBL(0.0f); + for (l = start_pos; l < next_pos; l++) { + bufferReal[l] = analysBufferReal[l][k]; + maxVal |= (FIXP_DBL)((LONG)(bufferReal[l]) ^ + ((LONG)bufferReal[l] >> (DFRACT_BITS - 1))); + } + } + + if (maxVal != FL2FXCONST_DBL(0.f)) { + /* If the accu does not provide enough overflow bits, we cannot + shift the samples up to the limit. + Instead, keep up to 3 free bits in each sample, i.e. up to + 6 bits after calculation of square. + Please note the comment on saturated arithmetic above! + */ + FIXP_DBL accu; + preShift = CntLeadingZeros(maxVal) - 1; + preShift -= SHIFT_BEFORE_SQUARE; + + /* Limit preShift to a maximum value to prevent accumulator overflow in + exceptional situations where the signal in the analysis-buffer is very + small (small maxVal). + */ + preShift = fMin(preShift, (SCHAR)25); + + accu = FL2FXCONST_DBL(0.0f); + if (preShift >= 0) { + int l; + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp1 = bufferReal[l] << (int)preShift; + FIXP_DBL temp2 = bufferImag[l] << (int)preShift; + accu = fPow2AddDiv2(accu, temp1); + accu = fPow2AddDiv2(accu, temp2); + } + } else { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp = bufferReal[l] << (int)preShift; + accu = fPow2AddDiv2(accu, temp); + } + } + } else { /* if negative shift value */ + int l; + int negpreShift = -preShift; + if (analysBufferImag != NULL) { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp1 = bufferReal[l] >> (int)negpreShift; + FIXP_DBL temp2 = bufferImag[l] >> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp1); + accu = fPow2AddDiv2(accu, temp2); + } + } else { + for (l = start_pos; l < next_pos; l++) { + FIXP_DBL temp = bufferReal[l] >> (int)negpreShift; + accu = fPow2AddDiv2(accu, temp); + } + } + } + accu <<= 1; + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(accu); + sum = accu << (int)shift; + + /* Divide by width of envelope and apply frame scale: */ + *nrgEst++ = fMult(sum, invWidth); + shift += 2 * preShift; + if (analysBufferImag != NULL) + *nrgEst_e++ = frameExp - shift; + else + *nrgEst_e++ = frameExp - shift + 1; /* +1 due to missing imag. part */ + } /* maxVal!=0 */ + else { + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + *nrgEst++ = FL2FXCONST_DBL(0.0f); + *nrgEst_e++ = 0; + } + } +} + +/*! + \brief Estimates the mean energy of each Scale factor band for the + duration of the current envelope. + + This function is used when interpolFreq is false. +*/ +static void calcNrgPerSfb( + FIXP_DBL **analysBufferReal, /*!< Real part of subband samples */ + FIXP_DBL **analysBufferImag, /*!< Imaginary part of subband samples */ + int nSfb, /*!< Number of scale factor bands */ + UCHAR *freqBandTable, /*!< First Subband for each Sfb */ + int start_pos, /*!< First QMF-slot of current envelope */ + int next_pos, /*!< Last QMF-slot of current envelope + 1 */ + SCHAR input_e, /*!< Common exponent for all input samples */ + FIXP_DBL *nrgEst, /*!< resulting Energy (0..1) */ + SCHAR *nrgEst_e) /*!< Exponent of resulting Energy */ +{ + FIXP_SGL invWidth; + FIXP_DBL temp; + SCHAR preShift; + SCHAR shift, sum_e; + FIXP_DBL sum; + + int j, k, l, li, ui; + FIXP_DBL sumAll, sumLine; /* Single precision would be sufficient, + but overflow bits are required for accumulation */ + + /* Divide by width of envelope later: */ + invWidth = FX_DBL2FX_SGL(GetInvInt(next_pos - start_pos)); + /* The common exponent needs to be doubled because all mantissas are squared: + */ + input_e = input_e << 1; + + for (j = 0; j < nSfb; j++) { + li = freqBandTable[j]; + ui = freqBandTable[j + 1]; + + FIXP_DBL maxVal = maxSubbandSample(analysBufferReal, analysBufferImag, li, + ui, start_pos, next_pos); + + if (maxVal != FL2FXCONST_DBL(0.f)) { + preShift = CntLeadingZeros(maxVal) - 1; + + /* If the accu does not provide enough overflow bits, we cannot + shift the samples up to the limit. + Instead, keep up to 3 free bits in each sample, i.e. up to + 6 bits after calculation of square. + Please note the comment on saturated arithmetic above! + */ + preShift -= SHIFT_BEFORE_SQUARE; + + sumAll = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + sumLine = FL2FXCONST_DBL(0.0f); + + if (analysBufferImag != NULL) { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + temp = analysBufferImag[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + } + } else { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + temp = analysBufferImag[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } else { + if (preShift >= 0) { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] << (int)preShift; + sumLine += fPow2Div2(temp); + } + } else { + for (l = start_pos; l < next_pos; l++) { + temp = analysBufferReal[l][k] >> -(int)preShift; + sumLine += fPow2Div2(temp); + } + } + } + + /* The number of QMF-channels per SBR bands may be up to 15. + Shift right to avoid overflows in sum over all channels. */ + sumLine = sumLine >> (4 - 1); + sumAll += sumLine; + } + + /* Convert double precision to Mantissa/Exponent: */ + shift = fNorm(sumAll); + sum = sumAll << (int)shift; + + /* Divide by width of envelope: */ + sum = fMult(sum, invWidth); + + /* Divide by width of Sfb: */ + sum = fMult(sum, FX_DBL2FX_SGL(GetInvInt(ui - li))); + + /* Set all Subband energies in the Sfb to the average energy: */ + if (analysBufferImag != NULL) + sum_e = input_e + 4 - shift; /* -4 to compensate right-shift */ + else + sum_e = input_e + 4 + 1 - + shift; /* -4 to compensate right-shift; +1 due to missing + imag. part */ + + sum_e -= 2 * preShift; + } /* maxVal!=0 */ + else { + /* Prevent a zero-mantissa-number from being misinterpreted + due to its exponent. */ + sum = FL2FXCONST_DBL(0.0f); + sum_e = 0; + } + + for (k = li; k < ui; k++) { + *nrgEst++ = sum; + *nrgEst_e++ = sum_e; + } + } +} + +/*! + \brief Calculate gain, noise, and additional sine level for one subband. + + The resulting energy gain is given by mantissa and exponent. +*/ +static void calcSubbandGain( + FIXP_DBL nrgRef, /*!< Reference Energy according to envelope data */ + SCHAR + nrgRef_e, /*!< Reference Energy according to envelope data (exponent) */ + ENV_CALC_NRGS *nrgs, int i, FIXP_DBL tmpNoise, /*!< Relative noise level */ + SCHAR tmpNoise_e, /*!< Relative noise level (exponent) */ + UCHAR sinePresentFlag, /*!< Indicates if sine is present on band */ + UCHAR sineMapped, /*!< Indicates if sine must be added */ + int noNoiseFlag) /*!< Flag to suppress noise addition */ +{ + FIXP_DBL nrgEst = nrgs->nrgEst[i]; /*!< Energy in transposed signal */ + SCHAR nrgEst_e = + nrgs->nrgEst_e[i]; /*!< Energy in transposed signal (exponent) */ + FIXP_DBL *ptrNrgGain = &nrgs->nrgGain[i]; /*!< Resulting energy gain */ + SCHAR *ptrNrgGain_e = + &nrgs->nrgGain_e[i]; /*!< Resulting energy gain (exponent) */ + FIXP_DBL *ptrNoiseLevel = + &nrgs->noiseLevel[i]; /*!< Resulting absolute noise energy */ + SCHAR *ptrNoiseLevel_e = + &nrgs->noiseLevel_e[i]; /*!< Resulting absolute noise energy (exponent) */ + FIXP_DBL *ptrNrgSine = &nrgs->nrgSine[i]; /*!< Additional sine energy */ + SCHAR *ptrNrgSine_e = + &nrgs->nrgSine_e[i]; /*!< Additional sine energy (exponent) */ + + FIXP_DBL a, b, c; + SCHAR a_e, b_e, c_e; + + /* + This addition of 1 prevents divisions by zero in the reference code. + For very small energies in nrgEst, it prevents the gains from becoming + very high which could cause some trouble due to the smoothing. + */ + b_e = (int)(nrgEst_e - 1); + if (b_e >= 0) { + nrgEst = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (nrgEst >> 1); + nrgEst_e += 1; /* shift by 1 bit to avoid overflow */ + + } else { + nrgEst = (nrgEst >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + nrgEst_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* A = NrgRef * TmpNoise */ + a = fMult(nrgRef, tmpNoise); + a_e = nrgRef_e + tmpNoise_e; + + /* B = 1 + TmpNoise */ + b_e = (int)(tmpNoise_e - 1); + if (b_e >= 0) { + b = (FL2FXCONST_DBL(0.5f) >> (INT)fixMin(b_e + 1, DFRACT_BITS - 1)) + + (tmpNoise >> 1); + b_e = tmpNoise_e + 1; /* shift by 1 bit to avoid overflow */ + } else { + b = (tmpNoise >> (INT)(fixMin(-b_e + 1, DFRACT_BITS - 1))) + + (FL2FXCONST_DBL(0.5f) >> 1); + b_e = 2; /* shift by 1 bit to avoid overflow */ + } + + /* noiseLevel = A / B = (NrgRef * TmpNoise) / (1 + TmpNoise) */ + FDK_divide_MantExp(a, a_e, b, b_e, ptrNoiseLevel, ptrNoiseLevel_e); + + if (sinePresentFlag) { + /* C = (1 + TmpNoise) * NrgEst */ + c = fMult(b, nrgEst); + c_e = b_e + nrgEst_e; + + /* gain = A / C = (NrgRef * TmpNoise) / (1 + TmpNoise) * NrgEst */ + FDK_divide_MantExp(a, a_e, c, c_e, ptrNrgGain, ptrNrgGain_e); + + if (sineMapped) { + /* sineLevel = nrgRef/ (1 + TmpNoise) */ + FDK_divide_MantExp(nrgRef, nrgRef_e, b, b_e, ptrNrgSine, ptrNrgSine_e); + } + } else { + if (noNoiseFlag) { + /* B = NrgEst */ + b = nrgEst; + b_e = nrgEst_e; + } else { + /* B = NrgEst * (1 + TmpNoise) */ + b = fMult(b, nrgEst); + b_e = b_e + nrgEst_e; + } + + /* gain = nrgRef / B */ + FDK_divide_MantExp(nrgRef, nrgRef_e, b, b_e, ptrNrgGain, ptrNrgGain_e); + } +} + +/*! + \brief Calculate "average gain" for the specified subband range. + + This is rather a gain of the average magnitude than the average + of gains! + The result is used as a relative limit for all gains within the + current "limiter band" (a certain frequency range). +*/ +static void calcAvgGain( + ENV_CALC_NRGS *nrgs, int lowSubband, /*!< Begin of the limiter band */ + int highSubband, /*!< High end of the limiter band */ + FIXP_DBL *ptrSumRef, SCHAR *ptrSumRef_e, + FIXP_DBL *ptrAvgGain, /*!< Resulting overall gain (mantissa) */ + SCHAR *ptrAvgGain_e) /*!< Resulting overall gain (exponent) */ +{ + FIXP_DBL *nrgRef = + nrgs->nrgRef; /*!< Reference Energy according to envelope data */ + SCHAR *nrgRef_e = + nrgs->nrgRef_e; /*!< Reference Energy according to envelope data + (exponent) */ + FIXP_DBL *nrgEst = nrgs->nrgEst; /*!< Energy in transposed signal */ + SCHAR *nrgEst_e = + nrgs->nrgEst_e; /*!< Energy in transposed signal (exponent) */ + + FIXP_DBL sumRef = 1; + FIXP_DBL sumEst = 1; + SCHAR sumRef_e = -FRACT_BITS; + SCHAR sumEst_e = -FRACT_BITS; + int k; + + for (k = lowSubband; k < highSubband; k++) { + /* Add nrgRef[k] to sumRef: */ + FDK_add_MantExp(sumRef, sumRef_e, nrgRef[k], nrgRef_e[k], &sumRef, + &sumRef_e); + + /* Add nrgEst[k] to sumEst: */ + FDK_add_MantExp(sumEst, sumEst_e, nrgEst[k], nrgEst_e[k], &sumEst, + &sumEst_e); + } + + FDK_divide_MantExp(sumRef, sumRef_e, sumEst, sumEst_e, ptrAvgGain, + ptrAvgGain_e); + + *ptrSumRef = sumRef; + *ptrSumRef_e = sumRef_e; +} + +static void adjustTimeSlot_EldGrid( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex, /*!< Start index to random number array */ + int scale_diff_low) /*!< */ + +{ + int k; + FIXP_DBL signalReal, sbNoise; + int tone_count = 0; + + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int phaseIndex = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + + static const INT harmonicPhase[4][2] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}}; + + static const FIXP_DBL harmonicPhaseX[4][2] = { + {FL2FXCONST_DBL(2.0 * 1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * 1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * -1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * 1.123767859325028e-001)}, + {FL2FXCONST_DBL(2.0 * -1.245183154539139e-001), + FL2FXCONST_DBL(2.0 * -1.245183154539139e-001)}, + {FL2FXCONST_DBL(2.0 * 1.123767859325028e-001), + FL2FXCONST_DBL(2.0 * -1.123767859325028e-001)}}; + + const FIXP_DBL *p_harmonicPhaseX = &harmonicPhaseX[harmIndex][0]; + const INT *p_harmonicPhase = &harmonicPhase[harmIndex][0]; + + *(ptrReal - 1) = fAddSaturate( + *(ptrReal - 1), + SATURATE_SHIFT(fMultDiv2(p_harmonicPhaseX[lowSubband & 1], pSineLevel[0]), + scale_diff_low, DFRACT_BITS)); + FIXP_DBL pSineLevel_prev = (FIXP_DBL)0; + + int idx_k = lowSubband & 1; + + for (k = 0; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise) + << 4); + } + signalReal += sineLevel_curr * p_harmonicPhase[0]; + signalReal = + fMultAddDiv2(signalReal, pSineLevel_prev, p_harmonicPhaseX[idx_k]); + pSineLevel_prev = sineLevel_curr; + idx_k = !idx_k; + if (k < noSubbands - 1) { + signalReal = + fMultAddDiv2(signalReal, pSineLevel[0], p_harmonicPhaseX[idx_k]); + } else /* (k == noSubbands - 1) */ + { + if (k + lowSubband + 1 < 63) { + *(ptrReal + 1) += fMultDiv2(pSineLevel_prev, p_harmonicPhaseX[idx_k]); + } + } + *ptrReal++ = signalReal; + + if (pSineLevel_prev != FL2FXCONST_DBL(0.0f)) { + if (++tone_count == 16) { + k++; + break; + } + } + } + /* Run again, if previous loop got breaked with tone_count = 16 */ + for (; k < noSubbands; k++) { + FIXP_DBL sineLevel_curr = *pSineLevel++; + phaseIndex = (phaseIndex + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sbNoise = *pNoiseLevel++; + if (((INT)sineLevel_curr | noNoiseFlag) == 0) { + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[phaseIndex][0], sbNoise) + << 4); + } + signalReal += sineLevel_curr * p_harmonicPhase[0]; + *ptrReal++ = signalReal; + } + + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = phaseIndex & (SBR_NF_NO_RANDOM_VAL - 1); +} + +/*! + \brief Amplify one timeslot of the signal with the calculated gains + and add the noisefloor. +*/ + +static void adjustTimeSlotLC( + FIXP_DBL *ptrReal, /*!< Subband samples to be adjusted, real part */ + ENV_CALC_NRGS *nrgs, UCHAR *ptrHarmIndex, /*!< Harmonic index */ + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + int noNoiseFlag, /*!< Flag to suppress noise addition */ + int *ptrPhaseIndex) /*!< Start index to random number array */ +{ + FIXP_DBL *pGain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *pNoiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + int k; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + UCHAR freqInvFlag = (lowSubband & 1); + FIXP_DBL signalReal, sineLevel, sineLevelNext, sineLevelPrev; + int tone_count = 0; + int sineSign = 1; + +#define C1 ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.00815f)) +#define C1_CLDFB ((FIXP_SGL)FL2FXCONST_SGL(2.f * 0.16773f)) + + /* + First pass for k=0 pulled out of the loop: + */ + + index = (index + 1) & (SBR_NF_NO_RANDOM_VAL - 1); + + /* + The next multiplication constitutes the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #FRACT_BITS valid bits). + */ + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + sineLevel = *pSineLevel++; + sineLevelNext = (noSubbands > 1) ? pSineLevel[0] : FL2FXCONST_DBL(0.0f); + + if (sineLevel != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) + /* Add noisefloor to the amplified signal */ + signalReal += + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]) + << 4); + + { + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + signalReal += (harmIndex & 0x2) ? -sineLevel : sineLevel; + *ptrReal++ = signalReal; + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + int shift = (int)(scale_change + 1); + shift = (shift >= 0) ? fixMin(DFRACT_BITS - 1, shift) + : fixMax(-(DFRACT_BITS - 1), shift); + + FIXP_DBL tmp1 = (shift >= 0) ? (fMultDiv2(C1, sineLevel) >> shift) + : (fMultDiv2(C1, sineLevel) << (-shift)); + FIXP_DBL tmp2 = fMultDiv2(C1, sineLevelNext); + + /* save switch and compare operations and reduce to XOR statement */ + if (((harmIndex >> 1) & 0x1) ^ freqInvFlag) { + *(ptrReal - 1) += tmp1; + signalReal -= tmp2; + } else { + *(ptrReal - 1) -= tmp1; + signalReal += tmp2; + } + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } + } + + pNoiseLevel++; + + if (noSubbands > 2) { + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + if (!harmIndex) { + sineSign = 0; + } + + for (k = noSubbands - 2; k != 0; k--) { + FIXP_DBL sinelevel = *pSineLevel++; + index++; + if (((signalReal = (sineSign ? -sinelevel : sinelevel)) == + FL2FXCONST_DBL(0.0f)) && + !noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + pNoiseLevel[0]) + << 4); + } + + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal += fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + + pNoiseLevel++; + *ptrReal++ = signalReal; + } /* for ... */ + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if (harmIndex == 1) freqInvFlag = !freqInvFlag; + + for (k = noSubbands - 2; k != 0; k--) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of + * the signal. */ + signalReal = fMultDiv2(*ptrReal, *pGain++) << ((int)scale_change); + + if (*pSineLevel++ != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal += (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + pNoiseLevel[0]) + << 4); + } + + pNoiseLevel++; + + if (tone_count <= 16) { + FIXP_DBL addSine = fMultDiv2((pSineLevel[-2] - pSineLevel[0]), C1); + signalReal += (freqInvFlag) ? (-addSine) : (addSine); + } + + *ptrReal++ = signalReal; + freqInvFlag = !freqInvFlag; + } /* for ... */ + } + } + + if (noSubbands > -1) { + index++; + /* The next multiplication constitutes the actual envelope adjustment of the + * signal. */ + signalReal = fMultDiv2(*ptrReal, *pGain) << ((int)scale_change); + sineLevelPrev = fMultDiv2(pSineLevel[-1], FL2FX_SGL(0.0163f)); + sineLevel = pSineLevel[0]; + + if (pSineLevel[0] != FL2FXCONST_DBL(0.0f)) + tone_count++; + else if (!noNoiseFlag) { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + signalReal = + signalReal + + (fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], pNoiseLevel[0]) + << 4); + } + + if (!(harmIndex & 0x1)) { + /* harmIndex 0,2 */ + *ptrReal = signalReal + ((sineSign) ? -sineLevel : sineLevel); + } else { + /* harmIndex 1,3 in combination with freqInvFlag */ + if (tone_count <= 16) { + if (freqInvFlag) { + *ptrReal++ = signalReal - sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal + fMultDiv2(C1, sineLevel); + } else { + *ptrReal++ = signalReal + sineLevelPrev; + if (noSubbands + lowSubband < 63) + *ptrReal = *ptrReal - fMultDiv2(C1, sineLevel); + } + } else + *ptrReal = signalReal; + } + } + *ptrHarmIndex = (harmIndex + 1) & 3; + *ptrPhaseIndex = index & (SBR_NF_NO_RANDOM_VAL - 1); +} + +static void adjustTimeSlotHQ_GainAndNoise( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + int shift; + + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) { + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); + } else { + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); + } + + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + for (k = 0; k < noSubbands; k++) { + /* + Smoothing: The old envelope has been bufferd and a certain ratio + of the old gains and noise levels is used. + */ + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); + + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) + + fMult(direct_ratio, noiseLevel[k]); + } + + /* + The next 2 multiplications constitute the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #DFRACT_BITS valid bits). + */ + signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change); + signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change); + + index++; + + if ((pSineLevel[k] != FL2FXCONST_DBL(0.0f)) || noNoiseFlag) { + /* Just the amplified signal is saved */ + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } else { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise) + << 4; + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise) + << 4; + *ptrReal++ = (signalReal + noiseReal); + *ptrImag++ = (signalImag + noiseImag); + } + } + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; + signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change; + signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change; + + index++; + + if ((pSineLevel[k] == FL2FXCONST_DBL(0.0f)) && (noNoiseFlag == 0)) { + /* Add noisefloor to the amplified signal */ + smoothedNoise = noiseLevel[k]; + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise); + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise); + + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + signalReal += noiseReal << 4; + signalImag += noiseImag << 4; + } + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + } + } +} + +static void adjustTimeSlotHQ_AddHarmonics( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change /*!< Scale mismatch between QMF input and sineLevel + exponent. */ +) { + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + + int k; + FIXP_DBL signalReal, signalImag; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + + *ptrHarmIndex = (harmIndex + 1) & 3; + + for (k = 0; k < noSubbands; k++) { + sineLevel = pSineLevel[k]; + freqInvFlag ^= 1; + if (sineLevel != FL2FXCONST_DBL(0.f)) { + signalReal = ptrReal[k]; + signalImag = ptrImag[k]; + sineLevel = scaleValue(sineLevel, scale_change); + if (harmIndex & 2) { + /* case 2,3 */ + sineLevel = -sineLevel; + } + if (!(harmIndex & 1)) { + /* case 0,2: */ + ptrReal[k] = signalReal + sineLevel; + } else { + /* case 1,3 */ + if (!freqInvFlag) sineLevel = -sineLevel; + ptrImag[k] = signalImag + sineLevel; + } + } + } +} + +static void adjustTimeSlotHQ( + FIXP_DBL *RESTRICT + ptrReal, /*!< Subband samples to be adjusted, real part */ + FIXP_DBL *RESTRICT + ptrImag, /*!< Subband samples to be adjusted, imag part */ + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, ENV_CALC_NRGS *nrgs, + int lowSubband, /*!< Lowest QMF-channel in the currently used SBR range. */ + int noSubbands, /*!< Number of QMF subbands */ + int scale_change, /*!< Number of bits to shift adjusted samples */ + FIXP_SGL smooth_ratio, /*!< Impact of last envelope */ + int noNoiseFlag, /*!< Start index to random number array */ + int filtBufferNoiseShift) /*!< Shift factor of filtBufferNoise */ +{ + FIXP_DBL *RESTRICT gain = nrgs->nrgGain; /*!< Gains of current envelope */ + FIXP_DBL *RESTRICT noiseLevel = + nrgs->noiseLevel; /*!< Noise levels of current envelope */ + FIXP_DBL *RESTRICT pSineLevel = nrgs->nrgSine; /*!< Sine levels */ + + FIXP_DBL *RESTRICT filtBuffer = + h_sbr_cal_env->filtBuffer; /*!< Gains of last envelope */ + FIXP_DBL *RESTRICT filtBufferNoise = + h_sbr_cal_env->filtBufferNoise; /*!< Noise levels of last envelope */ + UCHAR *RESTRICT ptrHarmIndex = + &h_sbr_cal_env->harmIndex; /*!< Harmonic index */ + int *RESTRICT ptrPhaseIndex = + &h_sbr_cal_env->phaseIndex; /*!< Start index to random number array */ + + int k; + FIXP_DBL signalReal, signalImag; + FIXP_DBL noiseReal, noiseImag; + FIXP_DBL smoothedGain, smoothedNoise; + FIXP_SGL direct_ratio = + /*FL2FXCONST_SGL(1.0f) */ (FIXP_SGL)MAXVAL_SGL - smooth_ratio; + int index = *ptrPhaseIndex; + UCHAR harmIndex = *ptrHarmIndex; + int freqInvFlag = (lowSubband & 1); + FIXP_DBL sineLevel; + int shift; + + *ptrPhaseIndex = (index + noSubbands) & (SBR_NF_NO_RANDOM_VAL - 1); + *ptrHarmIndex = (harmIndex + 1) & 3; + + /* + Possible optimization: + smooth_ratio and harmIndex stay constant during the loop. + It might be faster to include a separate loop in each path. + + the check for smooth_ratio is now outside the loop and the workload + of the whole function decreased by about 20 % + */ + + filtBufferNoiseShift += + 1; /* due to later use of fMultDiv2 instead of fMult */ + if (filtBufferNoiseShift < 0) + shift = fixMin(DFRACT_BITS - 1, -filtBufferNoiseShift); + else + shift = fixMin(DFRACT_BITS - 1, filtBufferNoiseShift); + + if (smooth_ratio > FL2FXCONST_SGL(0.0f)) { + for (k = 0; k < noSubbands; k++) { + /* + Smoothing: The old envelope has been bufferd and a certain ratio + of the old gains and noise levels is used. + */ + + smoothedGain = + fMult(smooth_ratio, filtBuffer[k]) + fMult(direct_ratio, gain[k]); + + if (filtBufferNoiseShift < 0) { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) >> shift) + + fMult(direct_ratio, noiseLevel[k]); + } else { + smoothedNoise = (fMultDiv2(smooth_ratio, filtBufferNoise[k]) << shift) + + fMult(direct_ratio, noiseLevel[k]); + } + + /* + The next 2 multiplications constitute the actual envelope adjustment + of the signal and should be carried out with full accuracy + (supplying #DFRACT_BITS valid bits). + */ + signalReal = fMultDiv2(*ptrReal, smoothedGain) << ((int)scale_change); + signalImag = fMultDiv2(*ptrImag, smoothedGain) << ((int)scale_change); + + index++; + + if (pSineLevel[k] != FL2FXCONST_DBL(0.0f)) { + sineLevel = pSineLevel[k]; + + switch (harmIndex) { + case 0: + *ptrReal++ = (signalReal + sineLevel); + *ptrImag++ = (signalImag); + break; + case 2: + *ptrReal++ = (signalReal - sineLevel); + *ptrImag++ = (signalImag); + break; + case 1: + *ptrReal++ = (signalReal); + if (freqInvFlag) + *ptrImag++ = (signalImag - sineLevel); + else + *ptrImag++ = (signalImag + sineLevel); + break; + case 3: + *ptrReal++ = signalReal; + if (freqInvFlag) + *ptrImag++ = (signalImag + sineLevel); + else + *ptrImag++ = (signalImag - sineLevel); + break; + } + } else { + if (noNoiseFlag) { + /* Just the amplified signal is saved */ + *ptrReal++ = (signalReal); + *ptrImag++ = (signalImag); + } else { + /* Add noisefloor to the amplified signal */ + index &= (SBR_NF_NO_RANDOM_VAL - 1); + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + noiseReal = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], smoothedNoise) + << 4; + noiseImag = + fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], smoothedNoise) + << 4; + *ptrReal++ = (signalReal + noiseReal); + *ptrImag++ = (signalImag + noiseImag); + } + } + freqInvFlag ^= 1; + } + + } else { + for (k = 0; k < noSubbands; k++) { + smoothedGain = gain[k]; + signalReal = fMultDiv2(*ptrReal, smoothedGain) << scale_change; + signalImag = fMultDiv2(*ptrImag, smoothedGain) << scale_change; + + index++; + + if ((sineLevel = pSineLevel[k]) != FL2FXCONST_DBL(0.0f)) { + switch (harmIndex) { + case 0: + signalReal += sineLevel; + break; + case 1: + if (freqInvFlag) + signalImag -= sineLevel; + else + signalImag += sineLevel; + break; + case 2: + signalReal -= sineLevel; + break; + case 3: + if (freqInvFlag) + signalImag += sineLevel; + else + signalImag -= sineLevel; + break; + } + } else { + if (noNoiseFlag == 0) { + /* Add noisefloor to the amplified signal */ + smoothedNoise = noiseLevel[k]; + index &= (SBR_NF_NO_RANDOM_VAL - 1); + noiseReal = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][0], + smoothedNoise); + noiseImag = fMultDiv2(FDK_sbrDecoder_sbr_randomPhase[index][1], + smoothedNoise); + + /* FDK_sbrDecoder_sbr_randomPhase is downscaled by 2^3 */ + signalReal += noiseReal << 4; + signalImag += noiseImag << 4; + } + } + *ptrReal++ = signalReal; + *ptrImag++ = signalImag; + + freqInvFlag ^= 1; + } + } +} + +/*! + \brief Reset limiter bands. + + Build frequency band table for the gain limiter dependent on + the previously generated transposer patch areas. + + \return SBRDEC_OK if ok, SBRDEC_UNSUPPORTED_CONFIG on error +*/ +SBR_ERROR +ResetLimiterBands( + UCHAR *limiterBandTable, /*!< Resulting band borders in QMF channels */ + UCHAR *noLimiterBands, /*!< Resulting number of limiter band */ + UCHAR *freqBandTable, /*!< Table with possible band borders */ + int noFreqBands, /*!< Number of bands in freqBandTable */ + const PATCH_PARAM *patchParam, /*!< Transposer patch parameters */ + int noPatches, /*!< Number of transposer patches */ + int limiterBands, /*!< Selected 'band density' from bitstream */ + UCHAR sbrPatchingMode, int xOverQmf[MAX_NUM_PATCHES], int b41Sbr) { + int i, k, isPatchBorder[2], loLimIndex, hiLimIndex, tempNoLim, nBands; + UCHAR workLimiterBandTable[MAX_FREQ_COEFFS / 2 + MAX_NUM_PATCHES + 1]; + int patchBorders[MAX_NUM_PATCHES + 1]; + int kx, k2; + + int lowSubband = freqBandTable[0]; + int highSubband = freqBandTable[noFreqBands]; + + /* 1 limiter band. */ + if (limiterBands == 0) { + limiterBandTable[0] = 0; + limiterBandTable[1] = highSubband - lowSubband; + nBands = 1; + } else { + if (!sbrPatchingMode && xOverQmf != NULL) { + noPatches = 0; + + if (b41Sbr == 1) { + for (i = 1; i < MAX_NUM_PATCHES_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } else { + for (i = 1; i < MAX_STRETCH_HBE; i++) + if (xOverQmf[i] != 0) noPatches++; + } + for (i = 0; i < noPatches; i++) { + patchBorders[i] = xOverQmf[i] - lowSubband; + } + } else { + for (i = 0; i < noPatches; i++) { + patchBorders[i] = patchParam[i].guardStartBand - lowSubband; + } + } + patchBorders[i] = highSubband - lowSubband; + + /* 1.2, 2, or 3 limiter bands/octave plus bandborders at patchborders. */ + for (k = 0; k <= noFreqBands; k++) { + workLimiterBandTable[k] = freqBandTable[k] - lowSubband; + } + for (k = 1; k < noPatches; k++) { + workLimiterBandTable[noFreqBands + k] = patchBorders[k]; + } + + tempNoLim = nBands = noFreqBands + noPatches - 1; + shellsort(workLimiterBandTable, tempNoLim + 1); + + loLimIndex = 0; + hiLimIndex = 1; + + while (hiLimIndex <= tempNoLim) { + FIXP_DBL div_m, oct_m, temp; + INT div_e = 0, oct_e = 0, temp_e = 0; + + k2 = workLimiterBandTable[hiLimIndex] + lowSubband; + kx = workLimiterBandTable[loLimIndex] + lowSubband; + + div_m = fDivNorm(k2, kx, &div_e); + + /* calculate number of octaves */ + oct_m = fLog2(div_m, div_e, &oct_e); + + /* multiply with limiterbands per octave */ + /* values 1, 1.2, 2, 3 -> scale factor of 2 */ + temp = fMultNorm( + oct_m, FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[limiterBands], + &temp_e); + + /* overall scale factor of temp ist addition of scalefactors from log2 + calculation, limiter bands scalefactor (2) and limiter bands + multiplication */ + temp_e += oct_e + 2; + + /* div can be a maximum of 64 (k2 = 64 and kx = 1) + -> oct can be a maximum of 6 + -> temp can be a maximum of 18 (as limiterBandsPerOctoave is a maximum + factor of 3) + -> we need a scale factor of 5 for comparisson + */ + if (temp >> (5 - temp_e) < FL2FXCONST_DBL(0.49f) >> 5) { + if (workLimiterBandTable[hiLimIndex] == + workLimiterBandTable[loLimIndex]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + isPatchBorder[0] = isPatchBorder[1] = 0; + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[hiLimIndex] == patchBorders[k]) { + isPatchBorder[1] = 1; + break; + } + } + if (!isPatchBorder[1]) { + workLimiterBandTable[hiLimIndex] = highSubband; + nBands--; + hiLimIndex++; + continue; + } + for (k = 0; k <= noPatches; k++) { + if (workLimiterBandTable[loLimIndex] == patchBorders[k]) { + isPatchBorder[0] = 1; + break; + } + } + if (!isPatchBorder[0]) { + workLimiterBandTable[loLimIndex] = highSubband; + nBands--; + } + } + loLimIndex = hiLimIndex; + hiLimIndex++; + } + shellsort(workLimiterBandTable, tempNoLim + 1); + + /* Test if algorithm exceeded maximum allowed limiterbands */ + if (nBands > MAX_NUM_LIMITERS || nBands <= 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Copy limiterbands from working buffer into final destination */ + for (k = 0; k <= nBands; k++) { + limiterBandTable[k] = workLimiterBandTable[k]; + } + } + *noLimiterBands = nBands; + + return SBRDEC_OK; +} diff --git a/fdk-aac/libSBRdec/src/env_calc.h b/fdk-aac/libSBRdec/src/env_calc.h new file mode 100644 index 0000000..cff365d --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_calc.h @@ -0,0 +1,182 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope calculation prototypes +*/ +#ifndef ENV_CALC_H +#define ENV_CALC_H + +#include "sbrdecoder.h" +#include "env_extr.h" /* for HANDLE_SBR_HEADER_DATA */ + +typedef struct { + FIXP_DBL filtBuffer[MAX_FREQ_COEFFS]; /*!< previous gains (required for + smoothing) */ + FIXP_DBL filtBufferNoise[MAX_FREQ_COEFFS]; /*!< previous noise levels + (required for smoothing) */ + SCHAR filtBuffer_e[MAX_FREQ_COEFFS]; /*!< Exponents of previous gains */ + SCHAR filtBufferNoise_e; /*!< Common exponent of previous noise levels */ + + int startUp; /*!< flag to signal initial conditions in buffers */ + int phaseIndex; /*!< Index for randomPase array */ + int prevTranEnv; /*!< The transient envelope of the previous frame. */ + + ULONG harmFlagsPrev[ADD_HARMONICS_FLAGS_SIZE]; + /*!< Words with 16 flags each indicating where a sine was added in the + * previous frame.*/ + UCHAR harmIndex; /*!< Current phase of synthetic sine */ + int sbrPatchingMode; /*!< Current patching mode */ + + FIXP_SGL prevSbrNoiseFloorLevel[MAX_NOISE_COEFFS]; + UCHAR prevNNfb; + UCHAR prevNSfb[2]; + UCHAR prevLoSubband; + UCHAR prevHiSubband; + UCHAR prev_ov_highSubband; + UCHAR *prevFreqBandTable[2]; + UCHAR prevFreqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + UCHAR prevFreqBandTableHi[MAX_FREQ_COEFFS + 1]; + UCHAR prevFreqBandTableNoise[MAX_NOISE_COEFFS + 1]; + SCHAR sinusoidal_positionPrev; + ULONG harmFlagsPrevActive[ADD_HARMONICS_FLAGS_SIZE]; +} SBR_CALCULATE_ENVELOPE; + +typedef SBR_CALCULATE_ENVELOPE *HANDLE_SBR_CALCULATE_ENVELOPE; + +void calculateSbrEnvelope( + QMF_SCALE_FACTOR *sbrScaleFactor, + HANDLE_SBR_CALCULATE_ENVELOPE h_sbr_cal_env, + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA hFrameData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **analysBufferReal, + FIXP_DBL * + *analysBufferImag, /*!< Imag part of subband samples to be processed */ + const int useLP, + FIXP_DBL *degreeAlias, /*!< Estimated aliasing for each QMF channel */ + const UINT flags, const int frameErrorFlag); + +SBR_ERROR +createSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope, + HANDLE_SBR_HEADER_DATA hHeaderData, const int chan, + const UINT flags); + +int deleteSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hSbrCalculateEnvelope); + +void resetSbrEnvelopeCalc(HANDLE_SBR_CALCULATE_ENVELOPE hCalEnv); + +SBR_ERROR +ResetLimiterBands(UCHAR *limiterBandTable, UCHAR *noLimiterBands, + UCHAR *freqBandTable, int noFreqBands, + const PATCH_PARAM *patchParam, int noPatches, + int limiterBands, UCHAR sbrPatchingMode, + int xOverQmf[MAX_NUM_PATCHES], int sbrRatio); + +void rescaleSubbandSamples(FIXP_DBL **re, FIXP_DBL **im, int lowSubband, + int noSubbands, int start_pos, int next_pos, + int shift); + +FIXP_DBL maxSubbandSample(FIXP_DBL **analysBufferReal_m, + FIXP_DBL **analysBufferImag_m, int lowSubband, + int highSubband, int start_pos, int stop_pos); + +#endif // ENV_CALC_H diff --git a/fdk-aac/libSBRdec/src/env_dec.cpp b/fdk-aac/libSBRdec/src/env_dec.cpp new file mode 100644 index 0000000..95807c9 --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_dec.cpp @@ -0,0 +1,873 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief envelope decoding + This module provides envelope decoding and error concealment algorithms. The + main entry point is decodeSbrData(). + + \sa decodeSbrData(),\ref documentationOverview +*/ + +#include "env_dec.h" + +#include "env_extr.h" +#include "transcendent.h" + +#include "genericStds.h" + +static void decodeEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_otherChannel); +static void sbr_envelope_unmapping(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_FRAME_DATA h_data_right); +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution); +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void decodeNoiseFloorlevels(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static void timeCompensateFirstEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); +static int checkEnvelopeData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_sbr_data, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data); + +#define SBR_ENERGY_PAN_OFFSET (12 << ENV_EXP_FRACT) +#define SBR_MAX_ENERGY (35 << ENV_EXP_FRACT) + +#define DECAY (1 << ENV_EXP_FRACT) + +#if ENV_EXP_FRACT +#define DECAY_COUPLING \ + (1 << (ENV_EXP_FRACT - 1)) /*!< corresponds to a value of 0.5 */ +#else +#define DECAY_COUPLING \ + 1 /*!< If the energy data is not shifted, use 1 instead of 0.5 */ +#endif + +/*! + \brief Convert table index +*/ +static int indexLow2High(int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequency resolution */ +{ + if (res == 0) { + if (offset >= 0) { + if (index < offset) + return (index); + else + return (2 * index - offset); + } else { + offset = -offset; + if (index < offset) + return (2 * index + index); + else + return (2 * index + offset); + } + } else + return (index); +} + +/*! + \brief Update previous envelope value for delta-coding + + The current envelope values needs to be stored for delta-coding + in the next frame. The stored envelope is always represented with + the high frequency resolution. If the current envelope uses the + low frequency resolution, the energy value will be mapped to the + corresponding high-res bands. +*/ +static void mapLowResEnergyVal( + FIXP_SGL currVal, /*!< current energy value */ + FIXP_SGL *prevData, /*!< pointer to previous data vector */ + int offset, /*!< mapping factor */ + int index, /*!< index to scalefactor band */ + int res) /*!< frequeny resolution */ +{ + if (res == 0) { + if (offset >= 0) { + if (index < offset) + prevData[index] = currVal; + else { + prevData[2 * index - offset] = currVal; + prevData[2 * index + 1 - offset] = currVal; + } + } else { + offset = -offset; + if (index < offset) { + prevData[3 * index] = currVal; + prevData[3 * index + 1] = currVal; + prevData[3 * index + 2] = currVal; + } else { + prevData[2 * index + offset] = currVal; + prevData[2 * index + 1 + offset] = currVal; + } + } + } else + prevData[index] = currVal; +} + +/*! + \brief Convert raw envelope and noisefloor data to energy levels + + This function is being called by sbrDecoder_ParseElement() and provides two + important algorithms: + + First the function decodes envelopes and noise floor levels as described in + requantizeEnvelopeData() and sbr_envelope_unmapping(). The function also + implements concealment algorithms in case there are errors within the sbr + data. For both operations fractional arithmetic is used. Therefore you might + encounter different output values on your target system compared to the + reference implementation. +*/ +void decodeSbrData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA + h_data_left, /*!< pointer to left channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_left, /*!< pointer to left channel previous frame data */ + HANDLE_SBR_FRAME_DATA + h_data_right, /*!< pointer to right channel frame data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data_right) /*!< pointer to right channel previous frame data */ +{ + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + int errLeft; + + /* Save previous energy values to be able to reuse them later for concealment. + */ + FDKmemcpy(tempSfbNrgPrev, h_prev_data_left->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + + if (hHeaderData->frameErrorFlag || hHeaderData->bs_info.pvc_mode == 0) { + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); + } else { + FDK_ASSERT(h_data_right == NULL); + } + decodeNoiseFloorlevels(hHeaderData, h_data_left, h_prev_data_left); + + if (h_data_right != NULL) { + errLeft = hHeaderData->frameErrorFlag; + decodeEnvelope(hHeaderData, h_data_right, h_prev_data_right, + h_prev_data_left); + decodeNoiseFloorlevels(hHeaderData, h_data_right, h_prev_data_right); + + if (!errLeft && hHeaderData->frameErrorFlag) { + /* If an error occurs in the right channel where the left channel seemed + ok, we apply concealment also on the left channel. This ensures that + the coupling modes of both channels match and that we have the same + number of envelopes in coupling mode. However, as the left channel has + already been processed before, the resulting energy levels are not the + same as if the left channel had been concealed during the first call of + decodeEnvelope(). + */ + /* Restore previous energy values for concealment, because the values have + been overwritten by the first call of decodeEnvelope(). */ + FDKmemcpy(h_prev_data_left->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + /* Do concealment */ + decodeEnvelope(hHeaderData, h_data_left, h_prev_data_left, + h_prev_data_right); + } + + if (h_data_left->coupling) { + sbr_envelope_unmapping(hHeaderData, h_data_left, h_data_right); + } + } + + /* Display the data for debugging: */ +} + +/*! + \brief Convert from coupled channels to independent L/R data +*/ +static void sbr_envelope_unmapping( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_data_left, /*!< pointer to left channel */ + HANDLE_SBR_FRAME_DATA h_data_right) /*!< pointer to right channel */ +{ + int i; + FIXP_SGL tempL_m, tempR_m, tempRplus1_m, newL_m, newR_m; + SCHAR tempL_e, tempR_e, tempRplus1_e, newL_e, newR_e; + + /* 1. Unmap (already dequantized) coupled envelope energies */ + + for (i = 0; i < h_data_left->nScaleFactors; i++) { + tempR_m = (FIXP_SGL)((LONG)h_data_right->iEnvelope[i] & MASK_M); + tempR_e = (SCHAR)((LONG)h_data_right->iEnvelope[i] & MASK_E); + + tempR_e -= (18 + NRG_EXP_OFFSET); /* -18 = ld(UNMAPPING_SCALE / + h_data_right->nChannels) */ + tempL_m = (FIXP_SGL)((LONG)h_data_left->iEnvelope[i] & MASK_M); + tempL_e = (SCHAR)((LONG)h_data_left->iEnvelope[i] & MASK_E); + + tempL_e -= NRG_EXP_OFFSET; + + /* Calculate tempRight+1 */ + FDK_add_MantExp(tempR_m, tempR_e, FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + FDK_divide_MantExp(tempL_m, tempL_e + 1, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); + + if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } + + newL_m = FX_DBL2FX_SGL(fMult(tempR_m, newR_m)); + newL_e = tempR_e + newR_e; + + h_data_right->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NRG_EXP_OFFSET) & MASK_E); + h_data_left->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NRG_EXP_OFFSET) & MASK_E); + } + + /* 2. Dequantize and unmap coupled noise floor levels */ + + for (i = 0; i < hHeaderData->freqBandData.nNfb * + h_data_left->frameInfo.nNoiseEnvelopes; + i++) { + tempL_e = (SCHAR)(6 - (LONG)h_data_left->sbrNoiseFloorLevel[i]); + tempR_e = (SCHAR)((LONG)h_data_right->sbrNoiseFloorLevel[i] - + 12) /*SBR_ENERGY_PAN_OFFSET*/; + + /* Calculate tempR+1 */ + FDK_add_MantExp(FL2FXCONST_SGL(0.5f), 1 + tempR_e, /* tempR */ + FL2FXCONST_SGL(0.5f), 1, /* 1.0 */ + &tempRplus1_m, &tempRplus1_e); + + /* Calculate 2*tempLeft/(tempR+1) */ + FDK_divide_MantExp(FL2FXCONST_SGL(0.5f), tempL_e + 2, /* 2 * tempLeft */ + tempRplus1_m, tempRplus1_e, &newR_m, &newR_e); + + /* if (newR_m >= ((FIXP_SGL)MAXVAL_SGL - ROUNDING)) { + newR_m >>= 1; + newR_e += 1; + } */ + + /* L = tempR * R */ + newL_m = newR_m; + newL_e = newR_e + tempR_e; + h_data_right->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newR_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newR_e + NOISE_EXP_OFFSET) & MASK_E); + h_data_left->sbrNoiseFloorLevel[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)(newL_m + ROUNDING) & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)(newL_e + NOISE_EXP_OFFSET) & MASK_E); + } +} + +/*! + \brief Simple alternative to the real SBR concealment + + If the real frameInfo is not available due to a frame loss, a replacement will + be constructed with 1 envelope spanning the whole frame (FIX-FIX). + The delta-coded energies are set to negative values, resulting in a fade-down. + In case of coupling, the balance-channel will move towards the center. +*/ +static void leanSbrConcealment( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { + FIXP_SGL target; /* targeted level for sfb_nrg_prev during fade-down */ + FIXP_SGL step; /* speed of fade */ + int i; + + int currentStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int currentStopPos = hHeaderData->numberTimeSlots; + + /* Use some settings of the previous frame */ + h_sbr_data->ampResolutionCurrentFrame = h_prev_data->ampRes; + h_sbr_data->coupling = h_prev_data->coupling; + for (i = 0; i < MAX_INVF_BANDS; i++) + h_sbr_data->sbr_invf_mode[i] = h_prev_data->sbr_invf_mode[i]; + + /* Generate concealing control data */ + + h_sbr_data->frameInfo.nEnvelopes = 1; + h_sbr_data->frameInfo.borders[0] = currentStartPos; + h_sbr_data->frameInfo.borders[1] = currentStopPos; + h_sbr_data->frameInfo.freqRes[0] = 1; + h_sbr_data->frameInfo.tranEnv = -1; /* no transient */ + h_sbr_data->frameInfo.nNoiseEnvelopes = 1; + h_sbr_data->frameInfo.bordersNoise[0] = currentStartPos; + h_sbr_data->frameInfo.bordersNoise[1] = currentStopPos; + + h_sbr_data->nScaleFactors = hHeaderData->freqBandData.nSfb[1]; + + /* Generate fake envelope data */ + + h_sbr_data->domain_vec[0] = 1; + + if (h_sbr_data->coupling == COUPLING_BAL) { + target = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + step = (FIXP_SGL)DECAY_COUPLING; + } else { + target = FL2FXCONST_SGL(0.0f); + step = (FIXP_SGL)DECAY; + } + if (hHeaderData->bs_info.ampResolution == 0) { + target <<= 1; + step <<= 1; + } + + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + if (h_prev_data->sfb_nrg_prev[i] > target) + h_sbr_data->iEnvelope[i] = -step; + else + h_sbr_data->iEnvelope[i] = step; + } + + /* Noisefloor levels are always cleared ... */ + + h_sbr_data->domain_vec_noise[0] = 1; + FDKmemclear(h_sbr_data->sbrNoiseFloorLevel, + sizeof(h_sbr_data->sbrNoiseFloorLevel)); + + /* ... and so are the sines */ + FDKmemclear(h_sbr_data->addHarmonics, + sizeof(ULONG) * ADD_HARMONICS_FLAGS_SIZE); +} + +/*! + \brief Build reference energies and noise levels from bitstream elements +*/ +static void decodeEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data, /*!< pointer to data of last frame */ + HANDLE_SBR_PREV_FRAME_DATA + otherChannel /*!< other channel's last frame data */ +) { + int i; + int fFrameError = hHeaderData->frameErrorFlag; + FIXP_SGL tempSfbNrgPrev[MAX_FREQ_COEFFS]; + + if (!fFrameError) { + /* + To avoid distortions after bad frames, set the error flag if delta coding + in time occurs. However, SBR can take a little longer to come up again. + */ + if (h_prev_data->frameErrorFlag) { + if (h_sbr_data->domain_vec[0] != 0) { + fFrameError = 1; + } + } else { + /* Check that the previous stop position and the current start position + match. (Could be done in checkFrameInfo(), but the previous frame data + is not available there) */ + if (h_sbr_data->frameInfo.borders[0] != + h_prev_data->stopPos - hHeaderData->numberTimeSlots) { + /* Both the previous as well as the current frame are flagged to be ok, + * but they do not match! */ + if (h_sbr_data->domain_vec[0] == 1) { + /* Prefer concealment over delta-time coding between the mismatching + * frames */ + fFrameError = 1; + } else { + /* Close the gap in time by triggering timeCompensateFirstEnvelope() + */ + fFrameError = 1; + } + } + } + } + + if (fFrameError) /* Error is detected */ + { + leanSbrConcealment(hHeaderData, h_sbr_data, h_prev_data); + + /* decode the envelope data to linear PCM */ + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); + } else /*Do a temporary dummy decoding and check that the envelope values are + within limits */ + { + if (h_prev_data->frameErrorFlag) { + timeCompensateFirstEnvelope(hHeaderData, h_sbr_data, h_prev_data); + if (h_sbr_data->coupling != h_prev_data->coupling) { + /* + Coupling mode has changed during concealment. + The stored energy levels need to be converted. + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + /* Former Level-Channel will be used for both channels */ + if (h_prev_data->coupling == COUPLING_BAL) { + h_prev_data->sfb_nrg_prev[i] = + (otherChannel != NULL) ? otherChannel->sfb_nrg_prev[i] + : (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + } + /* Former L/R will be combined as the new Level-Channel */ + else if (h_sbr_data->coupling == COUPLING_LEVEL && + otherChannel != NULL) { + h_prev_data->sfb_nrg_prev[i] = (h_prev_data->sfb_nrg_prev[i] + + otherChannel->sfb_nrg_prev[i]) >> + 1; + } else if (h_sbr_data->coupling == COUPLING_BAL) { + h_prev_data->sfb_nrg_prev[i] = (FIXP_SGL)SBR_ENERGY_PAN_OFFSET; + } + } + } + } + FDKmemcpy(tempSfbNrgPrev, h_prev_data->sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + + deltaToLinearPcmEnvelopeDecoding(hHeaderData, h_sbr_data, h_prev_data); + + fFrameError = checkEnvelopeData(hHeaderData, h_sbr_data, h_prev_data); + + if (fFrameError) { + hHeaderData->frameErrorFlag = 1; + FDKmemcpy(h_prev_data->sfb_nrg_prev, tempSfbNrgPrev, + MAX_FREQ_COEFFS * sizeof(FIXP_SGL)); + decodeEnvelope(hHeaderData, h_sbr_data, h_prev_data, otherChannel); + return; + } + } + + requantizeEnvelopeData(h_sbr_data, h_sbr_data->ampResolutionCurrentFrame); + + hHeaderData->frameErrorFlag = fFrameError; +} + +/*! + \brief Verify that envelope energies are within the allowed range + \return 0 if all is fine, 1 if an envelope value was too high +*/ +static int checkEnvelopeData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data /*!< pointer to data of last frame */ +) { + FIXP_SGL *iEnvelope = h_sbr_data->iEnvelope; + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + int i = 0, errorFlag = 0; + FIXP_SGL sbr_max_energy = (h_sbr_data->ampResolutionCurrentFrame == 1) + ? SBR_MAX_ENERGY + : (SBR_MAX_ENERGY << 1); + + /* + Range check for current energies + */ + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + if (iEnvelope[i] > sbr_max_energy) { + errorFlag = 1; + } + if (iEnvelope[i] < FL2FXCONST_SGL(0.0f)) { + errorFlag = 1; + /* iEnvelope[i] = FL2FXCONST_SGL(0.0f); */ + } + } + + /* + Range check for previous energies + */ + for (i = 0; i < hHeaderData->freqBandData.nSfb[1]; i++) { + sfb_nrg_prev[i] = fixMax(sfb_nrg_prev[i], FL2FXCONST_SGL(0.0f)); + sfb_nrg_prev[i] = fixMin(sfb_nrg_prev[i], sbr_max_energy); + } + + return (errorFlag); +} + +/*! + \brief Verify that the noise levels are within the allowed range + + The function is equivalent to checkEnvelopeData(). + When the noise-levels are being decoded, it is already too late for + concealment. Therefore the noise levels are simply limited here. +*/ +static void limitNoiseLevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data) /*!< pointer to current data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + +/* + Set range limits. The exact values depend on the coupling mode. + However this limitation is primarily intended to avoid unlimited + accumulation of the delta-coded noise levels. +*/ +#define lowerLimit \ + ((FIXP_SGL)0) /* lowerLimit actually refers to the _highest_ noise energy */ +#define upperLimit \ + ((FIXP_SGL)35) /* upperLimit actually refers to the _lowest_ noise energy */ + + /* + Range check for current noise levels + */ + for (i = 0; i < h_sbr_data->frameInfo.nNoiseEnvelopes * nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMin(h_sbr_data->sbrNoiseFloorLevel[i], upperLimit); + h_sbr_data->sbrNoiseFloorLevel[i] = + fixMax(h_sbr_data->sbrNoiseFloorLevel[i], lowerLimit); + } +} + +/*! + \brief Compensate for the wrong timing that might occur after a frame error. +*/ +static void timeCompensateFirstEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to actual data */ + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data) /*!< pointer to data of last frame */ +{ + int i, nScalefactors; + FRAME_INFO *pFrameInfo = &h_sbr_data->frameInfo; + UCHAR *nSfb = hHeaderData->freqBandData.nSfb; + int estimatedStartPos = + fMax(0, h_prev_data->stopPos - hHeaderData->numberTimeSlots); + int refLen, newLen, shift; + FIXP_SGL deltaExp; + + /* Original length of first envelope according to bitstream */ + refLen = pFrameInfo->borders[1] - pFrameInfo->borders[0]; + /* Corrected length of first envelope (concealing can make the first envelope + * longer) */ + newLen = pFrameInfo->borders[1] - estimatedStartPos; + + if (newLen <= 0) { + /* An envelope length of <= 0 would not work, so we don't use it. + May occur if the previous frame was flagged bad due to a mismatch + of the old and new frame infos. */ + newLen = refLen; + estimatedStartPos = pFrameInfo->borders[0]; + } + + deltaExp = FDK_getNumOctavesDiv8(newLen, refLen); + + /* Shift by -3 to rescale ld-table, ampRes-1 to enable coarser steps */ + shift = (FRACT_BITS - 1 - ENV_EXP_FRACT - 1 + + h_sbr_data->ampResolutionCurrentFrame - 3); + deltaExp = deltaExp >> shift; + pFrameInfo->borders[0] = estimatedStartPos; + pFrameInfo->bordersNoise[0] = estimatedStartPos; + + if (h_sbr_data->coupling != COUPLING_BAL) { + nScalefactors = (pFrameInfo->freqRes[0]) ? nSfb[1] : nSfb[0]; + + for (i = 0; i < nScalefactors; i++) + h_sbr_data->iEnvelope[i] = h_sbr_data->iEnvelope[i] + deltaExp; + } +} + +/*! + \brief Convert each envelope value from logarithmic to linear domain + + Energy levels are transmitted in powers of 2, i.e. only the exponent + is extracted from the bitstream. + Therefore, normally only integer exponents can occur. However during + fading (in case of a corrupt bitstream), a fractional part can also + occur. The data in the array iEnvelope is shifted left by ENV_EXP_FRACT + compared to an integer representation so that numbers smaller than 1 + can be represented. + + This function calculates a mantissa corresponding to the fractional + part of the exponent for each reference energy. The array iEnvelope + is converted in place to save memory. Input and output data must + be interpreted differently, as shown in the below figure: + + \image html EnvelopeData.png + + The data is then used in calculateSbrEnvelope(). +*/ +static void requantizeEnvelopeData(HANDLE_SBR_FRAME_DATA h_sbr_data, + int ampResolution) { + int i; + FIXP_SGL mantissa; + int ampShift = 1 - ampResolution; + int exponent; + + /* In case that ENV_EXP_FRACT is changed to something else but 0 or 8, + the initialization of this array has to be adapted! + */ +#if ENV_EXP_FRACT + static const FIXP_SGL pow2[ENV_EXP_FRACT] = { + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 1))), /* 0.7071 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 2))), /* 0.5946 */ + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 3))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 4))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 5))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 6))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 7))), + FL2FXCONST_SGL(0.5f * pow(2.0f, pow(0.5f, 8))) /* 0.5013 */ + }; + + int bit, mask; +#endif + + for (i = 0; i < h_sbr_data->nScaleFactors; i++) { + exponent = (LONG)h_sbr_data->iEnvelope[i]; + +#if ENV_EXP_FRACT + + exponent = exponent >> ampShift; + mantissa = 0.5f; + + /* Amplify mantissa according to the fractional part of the + exponent (result will be between 0.500000 and 0.999999) + */ + mask = 1; /* begin with lowest bit of exponent */ + + for (bit = ENV_EXP_FRACT - 1; bit >= 0; bit--) { + if (exponent & mask) { + /* The current bit of the exponent is set, + multiply mantissa with the corresponding factor: */ + mantissa = (FIXP_SGL)((mantissa * pow2[bit]) << 1); + } + /* Advance to next bit */ + mask = mask << 1; + } + + /* Make integer part of exponent right aligned */ + exponent = exponent >> ENV_EXP_FRACT; + +#else + /* In case of the high amplitude resolution, 1 bit of the exponent gets lost + by the shift. This will be compensated by a mantissa of 0.5*sqrt(2) + instead of 0.5 if that bit is 1. */ + mantissa = (exponent & ampShift) ? FL2FXCONST_SGL(0.707106781186548f) + : FL2FXCONST_SGL(0.5f); + exponent = exponent >> ampShift; +#endif + + /* + Mantissa was set to 0.5 (instead of 1.0, therefore increase exponent by + 1). Multiply by L=nChannels=64 by increasing exponent by another 6. + => Increase exponent by 7 + */ + exponent += 7 + NRG_EXP_OFFSET; + + /* Combine mantissa and exponent and write back the result */ + h_sbr_data->iEnvelope[i] = + ((FIXP_SGL)((SHORT)(FIXP_SGL)mantissa & MASK_M)) + + (FIXP_SGL)((SHORT)(FIXP_SGL)exponent & MASK_E); + } +} + +/*! + \brief Build new reference energies from old ones and delta coded data +*/ +static void deltaToLinearPcmEnvelopeDecoding( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i, domain, no_of_bands, band, freqRes; + + FIXP_SGL *sfb_nrg_prev = h_prev_data->sfb_nrg_prev; + FIXP_SGL *ptr_nrg = h_sbr_data->iEnvelope; + + int offset = + 2 * hHeaderData->freqBandData.nSfb[0] - hHeaderData->freqBandData.nSfb[1]; + + for (i = 0; i < h_sbr_data->frameInfo.nEnvelopes; i++) { + domain = h_sbr_data->domain_vec[i]; + freqRes = h_sbr_data->frameInfo.freqRes[i]; + + FDK_ASSERT(freqRes >= 0 && freqRes <= 1); + + no_of_bands = hHeaderData->freqBandData.nSfb[freqRes]; + + FDK_ASSERT(no_of_bands < (64)); + + if (domain == 0) { + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, 0, freqRes); + ptr_nrg++; + for (band = 1; band < no_of_bands; band++) { + *ptr_nrg = *ptr_nrg + *(ptr_nrg - 1); + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } else { + for (band = 0; band < no_of_bands; band++) { + *ptr_nrg = + *ptr_nrg + sfb_nrg_prev[indexLow2High(offset, band, freqRes)]; + mapLowResEnergyVal(*ptr_nrg, sfb_nrg_prev, offset, band, freqRes); + ptr_nrg++; + } + } + } +} + +/*! + \brief Build new noise levels from old ones and delta coded data +*/ +static void decodeNoiseFloorlevels( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_sbr_data, /*!< pointer to current data */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_data) /*!< pointer to previous data */ +{ + int i; + int nNfb = hHeaderData->freqBandData.nNfb; + int nNoiseFloorEnvelopes = h_sbr_data->frameInfo.nNoiseEnvelopes; + + /* Decode first noise envelope */ + + if (h_sbr_data->domain_vec_noise[0] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[0]; + for (i = 1; i < nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i] += h_prev_data->prevNoiseLevel[i]; + } + } + + /* If present, decode the second noise envelope + Note: nNoiseFloorEnvelopes can only be 1 or 2 */ + + if (nNoiseFloorEnvelopes > 1) { + if (h_sbr_data->domain_vec_noise[1] == 0) { + FIXP_SGL noiseLevel = h_sbr_data->sbrNoiseFloorLevel[nNfb]; + for (i = nNfb + 1; i < 2 * nNfb; i++) { + noiseLevel += h_sbr_data->sbrNoiseFloorLevel[i]; + h_sbr_data->sbrNoiseFloorLevel[i] = noiseLevel; + } + } else { + for (i = 0; i < nNfb; i++) { + h_sbr_data->sbrNoiseFloorLevel[i + nNfb] += + h_sbr_data->sbrNoiseFloorLevel[i]; + } + } + } + + limitNoiseLevels(hHeaderData, h_sbr_data); + + /* Update prevNoiseLevel with the last noise envelope */ + for (i = 0; i < nNfb; i++) + h_prev_data->prevNoiseLevel[i] = + h_sbr_data->sbrNoiseFloorLevel[i + nNfb * (nNoiseFloorEnvelopes - 1)]; + + /* Requantize the noise floor levels in COUPLING_OFF-mode */ + if (!h_sbr_data->coupling) { + int nf_e; + + for (i = 0; i < nNoiseFloorEnvelopes * nNfb; i++) { + nf_e = 6 - (LONG)h_sbr_data->sbrNoiseFloorLevel[i] + 1 + NOISE_EXP_OFFSET; + /* +1 to compensate for a mantissa of 0.5 instead of 1.0 */ + + h_sbr_data->sbrNoiseFloorLevel[i] = + (FIXP_SGL)(((LONG)FL2FXCONST_SGL(0.5f)) + /* mantissa */ + (nf_e & MASK_E)); /* exponent */ + } + } +} diff --git a/fdk-aac/libSBRdec/src/env_dec.h b/fdk-aac/libSBRdec/src/env_dec.h new file mode 100644 index 0000000..0b11ce1 --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_dec.h @@ -0,0 +1,119 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope decoding +*/ +#ifndef ENV_DEC_H +#define ENV_DEC_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +void decodeSbrData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_data_left, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_left, + HANDLE_SBR_FRAME_DATA h_data_right, + HANDLE_SBR_PREV_FRAME_DATA h_prev_data_right); + +#endif diff --git a/fdk-aac/libSBRdec/src/env_extr.cpp b/fdk-aac/libSBRdec/src/env_extr.cpp new file mode 100644 index 0000000..c72a7b6 --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_extr.cpp @@ -0,0 +1,1728 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope extraction + The functions provided by this module are mostly called by applySBR(). After + it is determined that there is valid SBR data, sbrGetHeaderData() might be + called if the current SBR data contains an \ref SBR_HEADER_ELEMENT as opposed + to a \ref SBR_STANDARD_ELEMENT. This function may return various error codes + as defined in #SBR_HEADER_STATUS . Most importantly it returns HEADER_RESET + when decoder settings need to be recalculated according to the SBR + specifications. In that case applySBR() will initiatite the required + re-configuration. + + The header data is stored in a #SBR_HEADER_DATA structure. + + The actual SBR data for the current frame is decoded into SBR_FRAME_DATA + stuctures by sbrGetChannelPairElement() [for stereo streams] and + sbrGetSingleChannelElement() [for mono streams]. There is no fractional + arithmetic involved. + + Once the information is extracted, the data needs to be further prepared + before the actual decoding process. This is done in decodeSbrData(). + + \sa Description of buffer management in applySBR(). \ref documentationOverview + +

About the SBR data format:

+ + Each frame includes SBR data (side chain information), and can be either the + \ref SBR_HEADER_ELEMENT or the \ref SBR_STANDARD_ELEMENT. Parts of the data + can be protected by a CRC checksum. + + \anchor SBR_HEADER_ELEMENT

The SBR_HEADER_ELEMENT

+ + The SBR_HEADER_ELEMENT can be transmitted with every frame, however, it + typically is send every second or so. It contains fundamental information such + as SBR sampling frequency and frequency range as well as control signals that + do not require frequent changes. It also includes the \ref + SBR_STANDARD_ELEMENT. + + Depending on the changes between the information in a current + SBR_HEADER_ELEMENT and the previous SBR_HEADER_ELEMENT, the SBR decoder might + need to be reset and reconfigured (e.g. new tables need to be calculated). + + \anchor SBR_STANDARD_ELEMENT

The SBR_STANDARD_ELEMENT

+ + This data can be subdivided into "side info" and "raw data", where side info + is defined as signals needed to decode the raw data and some decoder tuning + signals. Raw data is referred to as PCM and Huffman coded envelope and noise + floor estimates. The side info also includes information about the + time-frequency grid for the current frame. + + \sa \ref documentationOverview +*/ + +#include "env_extr.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "huff_dec.h" + +#include "psbitdec.h" + +#define DRM_PARAMETRIC_STEREO 0 +#define EXTENSION_ID_PS_CODING 2 + +static int extractPvcFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where + the previous frame-info + will be stored */ + UCHAR pvc_mode_last, /**< PVC mode of last frame */ + const UINT flags); +static int extractFrameInfo(HANDLE_FDK_BITSTREAM hBs, + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + const UINT nrOfChannels, const UINT flags); + +static int sbrGetPvcEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs, const UINT flags, + const UINT pvcMode); +static int sbrGetEnvelope(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs, const UINT flags); + +static void sbrGetDirectionControlData(HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs, + const UINT flags, const int bs_pvc_mode); + +static void sbrGetNoiseFloorData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA h_frame_data, + HANDLE_FDK_BITSTREAM hBs); + +static int checkFrameInfo(FRAME_INFO *pFrameInfo, int numberOfTimeSlots, + int overlap, int timeStep); + +/* Mapping to std samplerate table according to 14496-3 (4.6.18.2.6) */ +typedef struct SR_MAPPING { + UINT fsRangeLo; /* If fsRangeLo(n+1)>fs>=fsRangeLo(n), it will be mapped to... + */ + UINT fsMapped; /* fsMapped. */ +} SR_MAPPING; + +static const SR_MAPPING stdSampleRatesMapping[] = { + {0, 8000}, {9391, 11025}, {11502, 12000}, {13856, 16000}, + {18783, 22050}, {23004, 24000}, {27713, 32000}, {37566, 44100}, + {46009, 48000}, {55426, 64000}, {75132, 88200}, {92017, 96000}}; +static const SR_MAPPING stdSampleRatesMappingUsac[] = { + {0, 16000}, {18783, 22050}, {23004, 24000}, {27713, 32000}, + {35777, 40000}, {42000, 44100}, {46009, 48000}, {55426, 64000}, + {75132, 88200}, {92017, 96000}}; + +UINT sbrdec_mapToStdSampleRate(UINT fs, + UINT isUsac) /*!< Output sampling frequency */ +{ + UINT fsMapped = fs, tableSize = 0; + const SR_MAPPING *mappingTable; + int i; + + if (!isUsac) { + mappingTable = stdSampleRatesMapping; + tableSize = sizeof(stdSampleRatesMapping) / sizeof(SR_MAPPING); + } else { + mappingTable = stdSampleRatesMappingUsac; + tableSize = sizeof(stdSampleRatesMappingUsac) / sizeof(SR_MAPPING); + } + + for (i = tableSize - 1; i >= 0; i--) { + if (fs >= mappingTable[i].fsRangeLo) { + fsMapped = mappingTable[i].fsMapped; + break; + } + } + + return (fsMapped); +} + +SBR_ERROR +initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn, + const int sampleRateOut, const INT downscaleFactor, + const int samplesPerFrame, const UINT flags, + const int setDefaultHdr) { + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + SBR_ERROR sbrError = SBRDEC_OK; + int numAnalysisBands; + int sampleRateProc; + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + sampleRateProc = + sbrdec_mapToStdSampleRate(sampleRateOut * downscaleFactor, 0); + } else { + sampleRateProc = sampleRateOut * downscaleFactor; + } + + if (sampleRateIn == sampleRateOut) { + hHeaderData->sbrProcSmplRate = sampleRateProc << 1; + numAnalysisBands = 32; + } else { + hHeaderData->sbrProcSmplRate = sampleRateProc; + if ((sampleRateOut >> 1) == sampleRateIn) { + /* 1:2 */ + numAnalysisBands = 32; + } else if ((sampleRateOut >> 2) == sampleRateIn) { + /* 1:4 */ + numAnalysisBands = 16; + } else if ((sampleRateOut * 3) >> 3 == (sampleRateIn * 8) >> 3) { + /* 3:8, 3/4 core frame length */ + numAnalysisBands = 24; + } else { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + } + numAnalysisBands /= downscaleFactor; + + if (setDefaultHdr) { + /* Fill in default values first */ + hHeaderData->syncState = SBR_NOT_INITIALIZED; + hHeaderData->status = 0; + hHeaderData->frameErrorFlag = 0; + + hHeaderData->bs_info.ampResolution = 1; + hHeaderData->bs_info.xover_band = 0; + hHeaderData->bs_info.sbr_preprocessing = 0; + hHeaderData->bs_info.pvc_mode = 0; + + hHeaderData->bs_data.startFreq = 5; + hHeaderData->bs_data.stopFreq = 0; + hHeaderData->bs_data.freqScale = + 0; /* previously 2; for ELD reduced delay bitstreams + /samplerates initializing of the sbr decoder instance fails if + freqScale is set to 2 because no master table can be generated; in + ELD reduced delay bitstreams this value is always 0; gets overwritten + when header is read */ + hHeaderData->bs_data.alterScale = 1; + hHeaderData->bs_data.noise_bands = 2; + hHeaderData->bs_data.limiterBands = 2; + hHeaderData->bs_data.limiterGains = 2; + hHeaderData->bs_data.interpolFreq = 1; + hHeaderData->bs_data.smoothingLength = 1; + + /* Patch some entries */ + if (sampleRateOut * downscaleFactor >= 96000) { + hHeaderData->bs_data.startFreq = + 4; /* having read these frequency values from bit stream before. */ + hHeaderData->bs_data.stopFreq = 3; + } else if (sampleRateOut * downscaleFactor > + 24000) { /* Trigger an error if SBR is going to be processed + without */ + hHeaderData->bs_data.startFreq = + 7; /* having read these frequency values from bit stream before. */ + hHeaderData->bs_data.stopFreq = 3; + } + } + + if ((sampleRateOut >> 2) == sampleRateIn) { + hHeaderData->timeStep = 4; + } else { + hHeaderData->timeStep = (flags & SBRDEC_ELD_GRID) ? 1 : 2; + } + + /* Setup pointers to frequency band tables */ + hFreq->freqBandTable[0] = hFreq->freqBandTableLo; + hFreq->freqBandTable[1] = hFreq->freqBandTableHi; + + /* One SBR timeslot corresponds to the amount of samples equal to the amount + * of analysis bands, divided by the timestep. */ + hHeaderData->numberTimeSlots = + (samplesPerFrame / numAnalysisBands) >> (hHeaderData->timeStep - 1); + if (hHeaderData->numberTimeSlots > (16)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + } + + hHeaderData->numberOfAnalysisBands = numAnalysisBands; + if ((sampleRateOut >> 2) == sampleRateIn) { + hHeaderData->numberTimeSlots <<= 1; + } + +bail: + return sbrError; +} + +/*! + \brief Initialize the SBR_PREV_FRAME_DATA struct +*/ +void initSbrPrevFrameData( + HANDLE_SBR_PREV_FRAME_DATA + h_prev_data, /*!< handle to struct SBR_PREV_FRAME_DATA */ + int timeSlots) /*!< Framelength in SBR-timeslots */ +{ + int i; + + /* Set previous energy and noise levels to 0 for the case + that decoding starts in the middle of a bitstream */ + for (i = 0; i < MAX_FREQ_COEFFS; i++) + h_prev_data->sfb_nrg_prev[i] = (FIXP_DBL)0; + for (i = 0; i < MAX_NOISE_COEFFS; i++) + h_prev_data->prevNoiseLevel[i] = (FIXP_DBL)0; + for (i = 0; i < MAX_INVF_BANDS; i++) h_prev_data->sbr_invf_mode[i] = INVF_OFF; + + h_prev_data->stopPos = timeSlots; + h_prev_data->coupling = COUPLING_OFF; + h_prev_data->ampRes = 0; + + FDKmemclear(&h_prev_data->prevFrameInfo, sizeof(h_prev_data->prevFrameInfo)); +} + +/*! + \brief Read header data from bitstream + + \return error status - 0 if ok +*/ +SBR_HEADER_STATUS +sbrGetHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, HANDLE_FDK_BITSTREAM hBs, + const UINT flags, const int fIsSbrData, + const UCHAR configMode) { + SBR_HEADER_DATA_BS *pBsData; + SBR_HEADER_DATA_BS lastHeader; + SBR_HEADER_DATA_BS_INFO lastInfo; + int headerExtra1 = 0, headerExtra2 = 0; + + /* Read and discard new header in config change detection mode */ + if (configMode & AC_CM_DET_CFG_CHANGE) { + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + /* ampResolution */ + FDKreadBits(hBs, 1); + } + /* startFreq, stopFreq */ + FDKpushFor(hBs, 8); + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + /* xover_band */ + FDKreadBits(hBs, 3); + /* reserved bits */ + FDKreadBits(hBs, 2); + } + headerExtra1 = FDKreadBit(hBs); + headerExtra2 = FDKreadBit(hBs); + FDKpushFor(hBs, 5 * headerExtra1 + 6 * headerExtra2); + + return HEADER_OK; + } + + /* Copy SBR bit stream header to temporary header */ + lastHeader = hHeaderData->bs_data; + lastInfo = hHeaderData->bs_info; + + /* Read new header from bitstream */ + if ((flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) && !fIsSbrData) { + pBsData = &hHeaderData->bs_dflt; + } else { + pBsData = &hHeaderData->bs_data; + } + + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + hHeaderData->bs_info.ampResolution = FDKreadBits(hBs, 1); + } + + pBsData->startFreq = FDKreadBits(hBs, 4); + pBsData->stopFreq = FDKreadBits(hBs, 4); + + if (!(flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC))) { + hHeaderData->bs_info.xover_band = FDKreadBits(hBs, 3); + FDKreadBits(hBs, 2); + } + + headerExtra1 = FDKreadBits(hBs, 1); + headerExtra2 = FDKreadBits(hBs, 1); + + /* Handle extra header information */ + if (headerExtra1) { + pBsData->freqScale = FDKreadBits(hBs, 2); + pBsData->alterScale = FDKreadBits(hBs, 1); + pBsData->noise_bands = FDKreadBits(hBs, 2); + } else { + pBsData->freqScale = 2; + pBsData->alterScale = 1; + pBsData->noise_bands = 2; + } + + if (headerExtra2) { + pBsData->limiterBands = FDKreadBits(hBs, 2); + pBsData->limiterGains = FDKreadBits(hBs, 2); + pBsData->interpolFreq = FDKreadBits(hBs, 1); + pBsData->smoothingLength = FDKreadBits(hBs, 1); + } else { + pBsData->limiterBands = 2; + pBsData->limiterGains = 2; + pBsData->interpolFreq = 1; + pBsData->smoothingLength = 1; + } + + /* Look for new settings. IEC 14496-3, 4.6.18.3.1 */ + if (hHeaderData->syncState < SBR_HEADER || + lastHeader.startFreq != pBsData->startFreq || + lastHeader.stopFreq != pBsData->stopFreq || + lastHeader.freqScale != pBsData->freqScale || + lastHeader.alterScale != pBsData->alterScale || + lastHeader.noise_bands != pBsData->noise_bands || + lastInfo.xover_band != hHeaderData->bs_info.xover_band) { + return HEADER_RESET; /* New settings */ + } + + return HEADER_OK; +} + +/*! + \brief Get missing harmonics parameters (only used for AAC+SBR) + + \return error status - 0 if ok +*/ +int sbrGetSyntheticCodedData(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameData, + HANDLE_FDK_BITSTREAM hBs, const UINT flags) { + int i, bitsRead = 0; + + int add_harmonic_flag = FDKreadBits(hBs, 1); + bitsRead++; + + if (add_harmonic_flag) { + int nSfb = hHeaderData->freqBandData.nSfb[1]; + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) { + /* read maximum 32 bits and align them to the MSB */ + int readBits = fMin(32, nSfb); + nSfb -= readBits; + if (readBits > 0) { + hFrameData->addHarmonics[i] = FDKreadBits(hBs, readBits) + << (32 - readBits); + } else { + hFrameData->addHarmonics[i] = 0; + } + + bitsRead += readBits; + } + /* bs_pvc_mode = 0 for Rsvd50 */ + if (flags & SBRDEC_SYNTAX_USAC) { + if (hHeaderData->bs_info.pvc_mode) { + int bs_sinusoidal_position = 31; + if (FDKreadBit(hBs) /* bs_sinusoidal_position_flag */) { + bs_sinusoidal_position = FDKreadBits(hBs, 5); + } + hFrameData->sinusoidal_position = bs_sinusoidal_position; + } + } + } else { + for (i = 0; i < ADD_HARMONICS_FLAGS_SIZE; i++) + hFrameData->addHarmonics[i] = 0; + } + + return (bitsRead); +} + +/*! + \brief Reads extension data from the bitstream + + The bitstream format allows up to 4 kinds of extended data element. + Extended data may contain several elements, each identified by a 2-bit-ID. + So far, no extended data elements are defined hence the first 2 parameters + are unused. The data should be skipped in order to update the number + of read bits for the consistency check in applySBR(). +*/ +static int extractExtendedData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< handle to SBR header */ + HANDLE_FDK_BITSTREAM hBs /*!< Handle to the bit buffer */ + , + HANDLE_PS_DEC hParametricStereoDec /*!< Parametric Stereo Decoder */ +) { + INT nBitsLeft; + int extended_data; + int i, frameOk = 1; + + extended_data = FDKreadBits(hBs, 1); + + if (extended_data) { + int cnt; + int bPsRead = 0; + + cnt = FDKreadBits(hBs, 4); + if (cnt == (1 << 4) - 1) cnt += FDKreadBits(hBs, 8); + + nBitsLeft = 8 * cnt; + + /* sanity check for cnt */ + if (nBitsLeft > (INT)FDKgetValidBits(hBs)) { + /* limit nBitsLeft */ + nBitsLeft = (INT)FDKgetValidBits(hBs); + /* set frame error */ + frameOk = 0; + } + + while (nBitsLeft > 7) { + int extension_id = FDKreadBits(hBs, 2); + nBitsLeft -= 2; + + switch (extension_id) { + case EXTENSION_ID_PS_CODING: + + /* Read PS data from bitstream */ + + if (hParametricStereoDec != NULL) { + if (bPsRead && + !hParametricStereoDec->bsData[hParametricStereoDec->bsReadSlot] + .mpeg.bPsHeaderValid) { + cnt = nBitsLeft >> 3; /* number of remaining bytes */ + for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8); + nBitsLeft -= cnt * 8; + } else { + nBitsLeft -= + (INT)ReadPsData(hParametricStereoDec, hBs, nBitsLeft); + bPsRead = 1; + } + } + + /* parametric stereo detected, could set channelMode accordingly here + */ + /* */ + /* "The usage of this parametric stereo extension to HE-AAC is */ + /* signalled implicitly in the bitstream. Hence, if an sbr_extension() + */ + /* with bs_extension_id==EXTENSION_ID_PS is found in the SBR part of + */ + /* the bitstream, a decoder supporting the combination of SBR and PS + */ + /* shall operate the PS tool to generate a stereo output signal." */ + /* source: ISO/IEC 14496-3:2001/FDAM 2:2004(E) */ + + break; + + default: + cnt = nBitsLeft >> 3; /* number of remaining bytes */ + for (i = 0; i < cnt; i++) FDKreadBits(hBs, 8); + nBitsLeft -= cnt * 8; + break; + } + } + + if (nBitsLeft < 0) { + frameOk = 0; + goto bail; + } else { + /* Read fill bits for byte alignment */ + FDKreadBits(hBs, nBitsLeft); + } + } + +bail: + return (frameOk); +} + +/*! + \brief Read bitstream elements of a SBR channel element + \return SbrFrameOK +*/ +int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameDataLeft, + HANDLE_SBR_FRAME_DATA hFrameDataRight, + HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev, + UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBs, + HANDLE_PS_DEC hParametricStereoDec, const UINT flags, + const int overlap) { + int i, bs_coupling = COUPLING_OFF; + const int nCh = (hFrameDataRight == NULL) ? 1 : 2; + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + /* Reserved bits */ + if (FDKreadBits(hBs, 1)) { /* bs_data_extra */ + FDKreadBits(hBs, 4); + if ((flags & SBRDEC_SYNTAX_SCAL) || (nCh == 2)) { + FDKreadBits(hBs, 4); + } + } + } + + if (nCh == 2) { + /* Read coupling flag */ + bs_coupling = FDKreadBits(hBs, 1); + if (bs_coupling) { + hFrameDataLeft->coupling = COUPLING_LEVEL; + hFrameDataRight->coupling = COUPLING_BAL; + } else { + hFrameDataLeft->coupling = COUPLING_OFF; + hFrameDataRight->coupling = COUPLING_OFF; + } + } else { + if (flags & SBRDEC_SYNTAX_SCAL) { + FDKreadBits(hBs, 1); /* bs_coupling */ + } + hFrameDataLeft->coupling = COUPLING_OFF; + } + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (flags & SBRDEC_USAC_HARMONICSBR) { + hFrameDataLeft->sbrPatchingMode = FDKreadBit(hBs); + if (hFrameDataLeft->sbrPatchingMode == 0) { + hFrameDataLeft->sbrOversamplingFlag = FDKreadBit(hBs); + if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */ + hFrameDataLeft->sbrPitchInBins = FDKreadBits(hBs, 7); + } else { + hFrameDataLeft->sbrPitchInBins = 0; + } + } else { + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + + if (nCh == 2) { + if (bs_coupling) { + hFrameDataRight->sbrPatchingMode = hFrameDataLeft->sbrPatchingMode; + hFrameDataRight->sbrOversamplingFlag = + hFrameDataLeft->sbrOversamplingFlag; + hFrameDataRight->sbrPitchInBins = hFrameDataLeft->sbrPitchInBins; + } else { + hFrameDataRight->sbrPatchingMode = FDKreadBit(hBs); + if (hFrameDataRight->sbrPatchingMode == 0) { + hFrameDataRight->sbrOversamplingFlag = FDKreadBit(hBs); + if (FDKreadBit(hBs)) { /* sbrPitchInBinsFlag */ + hFrameDataRight->sbrPitchInBins = FDKreadBits(hBs, 7); + } else { + hFrameDataRight->sbrPitchInBins = 0; + } + } else { + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + } + } + } else { + if (nCh == 2) { + hFrameDataRight->sbrPatchingMode = 1; + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + } else { + if (nCh == 2) { + hFrameDataRight->sbrPatchingMode = 1; + hFrameDataRight->sbrOversamplingFlag = 0; + hFrameDataRight->sbrPitchInBins = 0; + } + + hFrameDataLeft->sbrPatchingMode = 1; + hFrameDataLeft->sbrOversamplingFlag = 0; + hFrameDataLeft->sbrPitchInBins = 0; + } + + /* + sbr_grid(): Grid control + */ + if (hHeaderData->bs_info.pvc_mode) { + FDK_ASSERT(nCh == 1); /* PVC not possible for CPE */ + if (!extractPvcFrameInfo(hBs, hHeaderData, hFrameDataLeft, + hFrameDataLeftPrev, pvc_mode_last, flags)) + return 0; + + if (!checkFrameInfo(&hFrameDataLeft->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } else { + if (!extractFrameInfo(hBs, hHeaderData, hFrameDataLeft, 1, flags)) return 0; + + if (!checkFrameInfo(&hFrameDataLeft->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } + if (nCh == 2) { + if (hFrameDataLeft->coupling) { + FDKmemcpy(&hFrameDataRight->frameInfo, &hFrameDataLeft->frameInfo, + sizeof(FRAME_INFO)); + hFrameDataRight->ampResolutionCurrentFrame = + hFrameDataLeft->ampResolutionCurrentFrame; + } else { + if (!extractFrameInfo(hBs, hHeaderData, hFrameDataRight, 2, flags)) + return 0; + + if (!checkFrameInfo(&hFrameDataRight->frameInfo, + hHeaderData->numberTimeSlots, overlap, + hHeaderData->timeStep)) + return 0; + } + } + + /* + sbr_dtdf(): Fetch domain vectors (time or frequency direction for + delta-coding) + */ + sbrGetDirectionControlData(hFrameDataLeft, hBs, flags, + hHeaderData->bs_info.pvc_mode); + if (nCh == 2) { + sbrGetDirectionControlData(hFrameDataRight, hBs, flags, 0); + } + + /* sbr_invf() */ + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataLeft->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2); + } + if (nCh == 2) { + if (hFrameDataLeft->coupling) { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = hFrameDataLeft->sbr_invf_mode[i]; + } + } else { + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hFrameDataRight->sbr_invf_mode[i] = (INVF_MODE)FDKreadBits(hBs, 2); + } + } + } + + if (nCh == 1) { + if (hHeaderData->bs_info.pvc_mode) { + if (!sbrGetPvcEnvelope(hHeaderData, hFrameDataLeft, hBs, flags, + hHeaderData->bs_info.pvc_mode)) + return 0; + } else if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) + return 0; + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + } else if (hFrameDataLeft->coupling) { + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) { + return 0; + } + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) { + return 0; + } + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); + } else { /* nCh == 2 && no coupling */ + + if (!sbrGetEnvelope(hHeaderData, hFrameDataLeft, hBs, flags)) return 0; + + if (!sbrGetEnvelope(hHeaderData, hFrameDataRight, hBs, flags)) return 0; + + sbrGetNoiseFloorData(hHeaderData, hFrameDataLeft, hBs); + + sbrGetNoiseFloorData(hHeaderData, hFrameDataRight, hBs); + } + + sbrGetSyntheticCodedData(hHeaderData, hFrameDataLeft, hBs, flags); + if (nCh == 2) { + sbrGetSyntheticCodedData(hHeaderData, hFrameDataRight, hBs, flags); + } + + if (!(flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50))) { + if (!extractExtendedData(hHeaderData, hBs, hParametricStereoDec)) { + return 0; + } + } + + return 1; +} + +/*! + \brief Read direction control data from bitstream +*/ +void sbrGetDirectionControlData( + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, const int bs_pvc_mode) + +{ + int i; + int indepFlag = 0; + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + indepFlag = flags & SBRDEC_USAC_INDEP; + } + + if (bs_pvc_mode == 0) { + i = 0; + if (indepFlag) { + h_frame_data->domain_vec[i++] = 0; + } + for (; i < h_frame_data->frameInfo.nEnvelopes; i++) { + h_frame_data->domain_vec[i] = FDKreadBits(hBs, 1); + } + } + + i = 0; + if (indepFlag) { + h_frame_data->domain_vec_noise[i++] = 0; + } + for (; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { + h_frame_data->domain_vec_noise[i] = FDKreadBits(hBs, 1); + } +} + +/*! + \brief Read noise-floor-level data from bitstream +*/ +void sbrGetNoiseFloorData( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs) /*!< handle to struct BIT_BUF */ +{ + int i, j; + int delta; + COUPLING_MODE coupling; + int noNoiseBands = hHeaderData->freqBandData.nNfb; + + Huffman hcb_noiseF; + Huffman hcb_noise; + int envDataTableCompFactor; + + coupling = h_frame_data->coupling; + + /* + Select huffman codebook depending on coupling mode + */ + if (coupling == COUPLING_BAL) { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T; + hcb_noiseF = + (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; /* "sbr_huffBook_NoiseBalance11F" + */ + envDataTableCompFactor = 1; + } else { + hcb_noise = (Huffman)&FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T; + hcb_noiseF = + (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; /* "sbr_huffBook_NoiseLevel11F" + */ + envDataTableCompFactor = 0; + } + + /* + Read raw noise-envelope data + */ + for (i = 0; i < h_frame_data->frameInfo.nNoiseEnvelopes; i++) { + if (h_frame_data->domain_vec_noise[i] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] = + (FIXP_SGL)(((int)FDKreadBits(hBs, 5)) << envDataTableCompFactor); + } else { + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands] = + (FIXP_SGL)(int)FDKreadBits(hBs, 5); + } + + for (j = 1; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noiseF, hBs); + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + } else { + for (j = 0; j < noNoiseBands; j++) { + delta = DecodeHuffmanCW(hcb_noise, hBs); + h_frame_data->sbrNoiseFloorLevel[i * noNoiseBands + j] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + } + } +} + +/* ns = mapNsMode2ns[pvcMode-1][nsMode] */ +static const UCHAR mapNsMode2ns[2][2] = { + {16, 4}, /* pvcMode = 1 */ + {12, 3} /* pvcMode = 2 */ +}; + +static int sbrGetPvcEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags, const UINT pvcMode) { + int divMode, nsMode; + int indepFlag = flags & SBRDEC_USAC_INDEP; + UCHAR *pvcID = h_frame_data->pvcID; + + divMode = FDKreadBits(hBs, PVC_DIVMODE_BITS); + nsMode = FDKreadBit(hBs); + FDK_ASSERT((pvcMode == 1) || (pvcMode == 2)); + h_frame_data->ns = mapNsMode2ns[pvcMode - 1][nsMode]; + + if (divMode <= 3) { + int i, k = 1, sum_length = 0, reuse_pcvID; + + /* special treatment for first time slot k=0 */ + indepFlag ? (reuse_pcvID = 0) : (reuse_pcvID = FDKreadBit(hBs)); + if (reuse_pcvID) { + pvcID[0] = hHeaderData->pvcIDprev; + } else { + pvcID[0] = FDKreadBits(hBs, PVC_PVCID_BITS); + } + + /* other time slots k>0 */ + for (i = 0; i < divMode; i++) { + int length, numBits = 4; + + if (sum_length >= 13) { + numBits = 1; + } else if (sum_length >= 11) { + numBits = 2; + } else if (sum_length >= 7) { + numBits = 3; + } + + length = FDKreadBits(hBs, numBits); + sum_length += length + 1; + if (sum_length >= PVC_NTIMESLOT) { + return 0; /* parse error */ + } + for (; length--; k++) { + pvcID[k] = pvcID[k - 1]; + } + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + } + for (; k < 16; k++) { + pvcID[k] = pvcID[k - 1]; + } + } else { /* divMode >= 4 */ + int num_grid_info, fixed_length, grid_info, j, k = 0; + + divMode -= 4; + num_grid_info = 2 << divMode; + fixed_length = 8 >> divMode; + FDK_ASSERT(num_grid_info * fixed_length == PVC_NTIMESLOT); + + /* special treatment for first time slot k=0 */ + indepFlag ? (grid_info = 1) : (grid_info = FDKreadBit(hBs)); + if (grid_info) { + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + } else { + pvcID[k++] = hHeaderData->pvcIDprev; + } + j = fixed_length - 1; + for (; j--; k++) { + pvcID[k] = pvcID[k - 1]; + } + num_grid_info--; + + /* other time slots k>0 */ + for (; num_grid_info--;) { + j = fixed_length; + grid_info = FDKreadBit(hBs); + if (grid_info) { + pvcID[k++] = FDKreadBits(hBs, PVC_PVCID_BITS); + j--; + } + for (; j--; k++) { + pvcID[k] = pvcID[k - 1]; + } + } + } + + hHeaderData->pvcIDprev = pvcID[PVC_NTIMESLOT - 1]; + + /* usage of PVC excludes inter-TES tool */ + h_frame_data->iTESactive = (UCHAR)0; + + return 1; +} +/*! + \brief Read envelope data from bitstream +*/ +static int sbrGetEnvelope( + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< handle to struct SBR_FRAME_DATA */ + HANDLE_FDK_BITSTREAM hBs, /*!< handle to struct BIT_BUF */ + const UINT flags) { + int i, j; + UCHAR no_band[MAX_ENVELOPES]; + int delta = 0; + int offset = 0; + COUPLING_MODE coupling = h_frame_data->coupling; + int ampRes = hHeaderData->bs_info.ampResolution; + int nEnvelopes = h_frame_data->frameInfo.nEnvelopes; + int envDataTableCompFactor; + int start_bits, start_bits_balance; + Huffman hcb_t, hcb_f; + + h_frame_data->nScaleFactors = 0; + + if ((h_frame_data->frameInfo.frameClass == 0) && (nEnvelopes == 1)) { + if (flags & SBRDEC_ELD_GRID) + ampRes = h_frame_data->ampResolutionCurrentFrame; + else + ampRes = 0; + } + h_frame_data->ampResolutionCurrentFrame = ampRes; + + /* + Set number of bits for first value depending on amplitude resolution + */ + if (ampRes == 1) { + start_bits = 6; + start_bits_balance = 5; + } else { + start_bits = 7; + start_bits_balance = 6; + } + + /* + Calculate number of values for each envelope and alltogether + */ + for (i = 0; i < nEnvelopes; i++) { + no_band[i] = + hHeaderData->freqBandData.nSfb[h_frame_data->frameInfo.freqRes[i]]; + h_frame_data->nScaleFactors += no_band[i]; + } + if (h_frame_data->nScaleFactors > MAX_NUM_ENVELOPE_VALUES) return 0; + + /* + Select Huffman codebook depending on coupling mode and amplitude resolution + */ + if (coupling == COUPLING_BAL) { + envDataTableCompFactor = 1; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance10F; + } else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvBalance11F; + } + } else { + envDataTableCompFactor = 0; + if (ampRes == 0) { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel10F; + } else { + hcb_t = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11T; + hcb_f = (Huffman)&FDK_sbrDecoder_sbr_huffBook_EnvLevel11F; + } + } + + h_frame_data->iTESactive = (UCHAR)0; /* disable inter-TES by default */ + /* + Now read raw envelope data + */ + for (j = 0, offset = 0; j < nEnvelopes; j++) { + if (h_frame_data->domain_vec[j] == 0) { + if (coupling == COUPLING_BAL) { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL)(((int)FDKreadBits(hBs, start_bits_balance)) + << envDataTableCompFactor); + } else { + h_frame_data->iEnvelope[offset] = + (FIXP_SGL)(int)FDKreadBits(hBs, start_bits); + } + } + + for (i = (1 - h_frame_data->domain_vec[j]); i < no_band[j]; i++) { + if (h_frame_data->domain_vec[j] == 0) { + delta = DecodeHuffmanCW(hcb_f, hBs); + } else { + delta = DecodeHuffmanCW(hcb_t, hBs); + } + + h_frame_data->iEnvelope[offset + i] = + (FIXP_SGL)(delta << envDataTableCompFactor); + } + if ((flags & SBRDEC_SYNTAX_USAC) && (flags & SBRDEC_USAC_ITES)) { + int bs_temp_shape = FDKreadBit(hBs); + FDK_ASSERT(j < 8); + h_frame_data->iTESactive |= (UCHAR)(bs_temp_shape << j); + if (bs_temp_shape) { + h_frame_data->interTempShapeMode[j] = + FDKread2Bits(hBs); /* bs_inter_temp_shape_mode */ + } else { + h_frame_data->interTempShapeMode[j] = 0; + } + } + offset += no_band[j]; + } + +#if ENV_EXP_FRACT + /* Convert from int to scaled fract (ENV_EXP_FRACT bits for the fractional + * part) */ + for (i = 0; i < h_frame_data->nScaleFactors; i++) { + h_frame_data->iEnvelope[i] <<= ENV_EXP_FRACT; + } +#endif + + return 1; +} + +/***************************************************************************/ +/*! + \brief Generates frame info for FIXFIXonly frame class used for low delay + version + + \return zero for error, one for correct. + ****************************************************************************/ +static int generateFixFixOnly(FRAME_INFO *hSbrFrameInfo, int tranPosInternal, + int numberTimeSlots, const UINT flags) { + int nEnv, i, tranIdx; + const int *pTable; + + switch (numberTimeSlots) { + case 8: + pTable = FDK_sbrDecoder_envelopeTable_8[tranPosInternal]; + break; + case 15: + pTable = FDK_sbrDecoder_envelopeTable_15[tranPosInternal]; + break; + case 16: + pTable = FDK_sbrDecoder_envelopeTable_16[tranPosInternal]; + break; + default: + return 0; + } + + /* look number of envelopes in table */ + nEnv = pTable[0]; + /* look up envelope distribution in table */ + for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2]; + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + hSbrFrameInfo->nEnvelopes = nEnv; + + /* transient idx */ + tranIdx = hSbrFrameInfo->tranEnv = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[tranIdx ? tranIdx : 1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + /* nEnv is always > 1, so nNoiseEnvelopes is always 2 (IEC 14496-3 4.6.19.3.2) + */ + hSbrFrameInfo->nNoiseEnvelopes = 2; + + return 1; +} + +/*! + \brief Extracts LowDelaySBR control data from the bitstream. + + \return zero for bitstream error, one for correct. +*/ +static int extractLowDelayGrid( + HANDLE_FDK_BITSTREAM hBitBuf, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA + h_frame_data, /*!< contains the FRAME_INFO struct to be filled */ + int timeSlots, const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + INT numberTimeSlots = hHeaderData->numberTimeSlots; + INT temp = 0, k; + + /* FIXFIXonly framing case */ + h_frame_data->frameInfo.frameClass = 0; + + /* get the transient position from the bitstream */ + switch (timeSlots) { + case 8: + /* 3bit transient position (temp={0;..;7}) */ + temp = FDKreadBits(hBitBuf, 3); + break; + + case 16: + case 15: + /* 4bit transient position (temp={0;..;15}) */ + temp = FDKreadBits(hBitBuf, 4); + break; + + default: + return 0; + } + + /* For "case 15" only*/ + if (temp >= timeSlots) { + return 0; + } + + /* calculate borders according to the transient position */ + if (!generateFixFixOnly(pFrameInfo, temp, numberTimeSlots, flags)) { + return 0; + } + + /* decode freq res: */ + for (k = 0; k < pFrameInfo->nEnvelopes; k++) { + pFrameInfo->freqRes[k] = + (UCHAR)FDKreadBits(hBitBuf, 1); /* f = F [1 bits] */ + } + + return 1; +} + +/*! + \brief Extract the PVC frame information (structure FRAME_INFO) from the + bitstream \return Zero for bitstream error, one for correct. +*/ +int extractPvcFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + HANDLE_SBR_PREV_FRAME_DATA h_prev_frame_data, /*!< pointer to memory where + the previous frame-info + will be stored */ + UCHAR pvc_mode_last, /**< PVC mode of last frame */ + const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + FRAME_INFO *pPrevFrameInfo = &h_prev_frame_data->prevFrameInfo; + int bs_var_len_hf, bs_noise_position; + bs_noise_position = FDKreadBits(hBs, 4); /* SBR_PVC_NOISEPOSITION_BITS 4 */ + bs_var_len_hf = FDKreadBit(hBs); + pFrameInfo->noisePosition = bs_noise_position; + pFrameInfo->tranEnv = -1; + + /* Init for bs_noise_position == 0 in case a parse error is found below. */ + pFrameInfo->nEnvelopes = 1; + pFrameInfo->nNoiseEnvelopes = 1; + pFrameInfo->freqRes[0] = 0; + + if (bs_var_len_hf) { /* 1 or 3 Bits */ + pFrameInfo->varLength = FDKreadBits(hBs, 2) + 1; + if (pFrameInfo->varLength > 3) { + pFrameInfo->varLength = + 0; /* assume bs_var_len_hf == 0 in case of error */ + return 0; /* reserved value -> parse error */ + } + } else { + pFrameInfo->varLength = 0; + } + + if (bs_noise_position) { + pFrameInfo->nEnvelopes = 2; + pFrameInfo->nNoiseEnvelopes = 2; + FDKmemclear(pFrameInfo->freqRes, sizeof(pFrameInfo->freqRes)); + } + + /* frame border calculation */ + if (hHeaderData->bs_info.pvc_mode > 0) { + /* See "7.5.1.4 HF adjustment of SBR envelope scalefactors" for reference. + */ + + FDK_ASSERT((pFrameInfo->nEnvelopes == 1) || (pFrameInfo->nEnvelopes == 2)); + + /* left timeborder-offset: use the timeborder of prev SBR frame */ + if (pPrevFrameInfo->nEnvelopes > 0) { + pFrameInfo->borders[0] = + pPrevFrameInfo->borders[pPrevFrameInfo->nEnvelopes] - PVC_NTIMESLOT; + FDK_ASSERT(pFrameInfo->borders[0] <= 3); + } else { + pFrameInfo->borders[0] = 0; + } + + /* right timeborder-offset: */ + pFrameInfo->borders[pFrameInfo->nEnvelopes] = 16 + pFrameInfo->varLength; + + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->borders[1] = pFrameInfo->noisePosition; + } + + /* Calculation of PVC time borders t_EPVC */ + if (pvc_mode_last == 0) { + /* there was a legacy SBR frame before this frame => use bs_var_len' for + * first PVC timeslot */ + pFrameInfo->pvcBorders[0] = pFrameInfo->borders[0]; + } else { + pFrameInfo->pvcBorders[0] = 0; + } + if (pFrameInfo->nEnvelopes == 2) { + pFrameInfo->pvcBorders[1] = pFrameInfo->borders[1]; + } + pFrameInfo->pvcBorders[pFrameInfo->nEnvelopes] = 16; + + /* calculation of SBR noise-floor time-border vector: */ + for (INT i = 0; i <= pFrameInfo->nNoiseEnvelopes; i++) { + pFrameInfo->bordersNoise[i] = pFrameInfo->borders[i]; + } + + pFrameInfo->tranEnv = -1; /* tranEnv not used */ + } + return 1; +} + +/*! + \brief Extract the frame information (structure FRAME_INFO) from the + bitstream \return Zero for bitstream error, one for correct. +*/ +int extractFrameInfo( + HANDLE_FDK_BITSTREAM hBs, /*!< bitbuffer handle */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA h_frame_data, /*!< pointer to memory where the + frame-info will be stored */ + const UINT nrOfChannels, const UINT flags) { + FRAME_INFO *pFrameInfo = &h_frame_data->frameInfo; + int numberTimeSlots = hHeaderData->numberTimeSlots; + int pointer_bits = 0, nEnv = 0, b = 0, border, i, n = 0, k, p, aL, aR, nL, nR, + temp = 0, staticFreqRes; + UCHAR frameClass; + + if (flags & SBRDEC_ELD_GRID) { + /* CODEC_AACLD (LD+SBR) only uses the normal 0 Grid for non-transient Frames + * and the LowDelayGrid for transient Frames */ + frameClass = FDKreadBits(hBs, 1); /* frameClass = [1 bit] */ + if (frameClass == 1) { + /* if frameClass == 1, extract LowDelaySbrGrid, otherwise extract normal + * SBR-Grid for FIXIFX */ + /* extract the AACLD-Sbr-Grid */ + pFrameInfo->frameClass = frameClass; + int err = 1; + err = extractLowDelayGrid(hBs, hHeaderData, h_frame_data, numberTimeSlots, + flags); + return err; + } + } else { + frameClass = FDKreadBits(hBs, 2); /* frameClass = C [2 bits] */ + } + + switch (frameClass) { + case 0: + temp = FDKreadBits(hBs, 2); /* E [2 bits ] */ + nEnv = (int)(1 << temp); /* E -> e */ + + if ((flags & SBRDEC_ELD_GRID) && (nEnv == 1)) + h_frame_data->ampResolutionCurrentFrame = + FDKreadBits(hBs, 1); /* new ELD Syntax 07-11-09 */ + + staticFreqRes = FDKreadBits(hBs, 1); + + if (flags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (nEnv > MAX_ENVELOPES_USAC) return 0; + } else + + b = nEnv + 1; + switch (nEnv) { + case 1: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info1_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info2_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info4_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 8: +#if (MAX_ENVELOPES >= 8) + switch (numberTimeSlots) { + case 15: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_15, + sizeof(FRAME_INFO)); + break; + case 16: + FDKmemcpy(pFrameInfo, &FDK_sbrDecoder_sbr_frame_info8_16, + sizeof(FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; +#else + return 0; +#endif + } + /* Apply correct freqRes (High is default) */ + if (!staticFreqRes) { + for (i = 0; i < nEnv; i++) pFrameInfo->freqRes[i] = 0; + } + + break; + case 1: + case 2: + temp = FDKreadBits(hBs, 2); /* A [2 bits] */ + + n = FDKreadBits(hBs, 2); /* n = N [2 bits] */ + + nEnv = n + 1; /* # envelopes */ + b = nEnv + 1; /* # borders */ + + break; + } + + switch (frameClass) { + case 1: + /* Decode borders: */ + pFrameInfo->borders[0] = 0; /* first border */ + border = temp + numberTimeSlots; /* A -> aR */ + i = b - 1; /* frame info index for last border */ + pFrameInfo->borders[i] = border; /* last border */ + + for (k = 0; k < n; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > n + 1) return 0; + + pFrameInfo->tranEnv = p ? n + 2 - p : -1; + + /* Decode freq res: */ + for (k = n; k >= 0; k--) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /* Calculate noise floor middle border: */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + else + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[pFrameInfo->tranEnv]; + + break; + + case 2: + /* Decode borders: */ + border = temp; /* A -> aL */ + pFrameInfo->borders[0] = border; /* first border */ + + for (k = 1; k <= n; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + pFrameInfo->borders[k] = numberTimeSlots; /* last border */ + + /* Decode pointer: */ + pointer_bits = DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(n + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + if (p > n + 1) return 0; + + if (p == 0 || p == 1) + pFrameInfo->tranEnv = -1; + else + pFrameInfo->tranEnv = p - 1; + + /* Decode freq res: */ + for (k = 0; k <= n; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /* Calculate noise floor middle border: */ + switch (p) { + case 0: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[1]; + break; + case 1: + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[n]; + break; + default: + pFrameInfo->bordersNoise[1] = + pFrameInfo->borders[pFrameInfo->tranEnv]; + break; + } + + break; + + case 3: + /* v_ctrlSignal = [frameClass,aL,aR,nL,nR,v_rL,v_rR,p,v_fLR]; */ + + aL = FDKreadBits(hBs, 2); /* AL [2 bits], AL -> aL */ + + aR = FDKreadBits(hBs, 2) + numberTimeSlots; /* AR [2 bits], AR -> aR */ + + nL = FDKreadBits(hBs, 2); /* nL = NL [2 bits] */ + + nR = FDKreadBits(hBs, 2); /* nR = NR [2 bits] */ + + /*------------------------------------------------------------------------- + Calculate help variables + --------------------------------------------------------------------------*/ + + /* general: */ + nEnv = nL + nR + 1; /* # envelopes */ + if (nEnv > MAX_ENVELOPES) return 0; + b = nEnv + 1; /* # borders */ + + /*------------------------------------------------------------------------- + Decode envelopes + --------------------------------------------------------------------------*/ + + /* L-borders: */ + border = aL; /* first border */ + pFrameInfo->borders[0] = border; + + for (k = 1; k <= nL; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border += (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[k] = border; + } + + /* R-borders: */ + border = aR; /* last border */ + i = nEnv; + + pFrameInfo->borders[i] = border; + + for (k = 0; k < nR; k++) { + temp = FDKreadBits(hBs, 2); /* R [2 bits] */ + border -= (2 * temp + 2); /* R -> r */ + pFrameInfo->borders[--i] = border; + } + + /* decode pointer: */ + pointer_bits = + DFRACT_BITS - 1 - CountLeadingBits((FIXP_DBL)(nL + nR + 1)); + p = FDKreadBits(hBs, pointer_bits); /* p = P [pointer_bits bits] */ + + if (p > nL + nR + 1) return 0; + + pFrameInfo->tranEnv = p ? b - p : -1; + + /* decode freq res: */ + for (k = 0; k < nEnv; k++) { + pFrameInfo->freqRes[k] = FDKreadBits(hBs, 1); /* f = F [1 bits] */ + } + + /*------------------------------------------------------------------------- + Decode noise floors + --------------------------------------------------------------------------*/ + pFrameInfo->bordersNoise[0] = aL; + + if (nEnv == 1) { + /* 1 noise floor envelope: */ + pFrameInfo->bordersNoise[1] = aR; + } else { + /* 2 noise floor envelopes */ + if (p == 0 || p == 1) + pFrameInfo->bordersNoise[1] = pFrameInfo->borders[nEnv - 1]; + else + pFrameInfo->bordersNoise[1] = + pFrameInfo->borders[pFrameInfo->tranEnv]; + pFrameInfo->bordersNoise[2] = aR; + } + break; + } + + /* + Store number of envelopes, noise floor envelopes and frame class + */ + pFrameInfo->nEnvelopes = nEnv; + + if (nEnv == 1) + pFrameInfo->nNoiseEnvelopes = 1; + else + pFrameInfo->nNoiseEnvelopes = 2; + + pFrameInfo->frameClass = frameClass; + + if (pFrameInfo->frameClass == 2 || pFrameInfo->frameClass == 1) { + /* calculate noise floor first and last borders: */ + pFrameInfo->bordersNoise[0] = pFrameInfo->borders[0]; + pFrameInfo->bordersNoise[pFrameInfo->nNoiseEnvelopes] = + pFrameInfo->borders[nEnv]; + } + + return 1; +} + +/*! + \brief Check if the frameInfo vector has reasonable values. + \return Zero for error, one for correct +*/ +static int checkFrameInfo( + FRAME_INFO *pFrameInfo, /*!< pointer to frameInfo */ + int numberOfTimeSlots, /*!< QMF time slots per frame */ + int overlap, /*!< Amount of overlap QMF time slots */ + int timeStep) /*!< QMF slots to SBR slots step factor */ +{ + int maxPos, i, j; + int startPos; + int stopPos; + int tranEnv; + int startPosNoise; + int stopPosNoise; + int nEnvelopes = pFrameInfo->nEnvelopes; + int nNoiseEnvelopes = pFrameInfo->nNoiseEnvelopes; + + if (nEnvelopes < 1 || nEnvelopes > MAX_ENVELOPES) return 0; + + if (nNoiseEnvelopes > MAX_NOISE_ENVELOPES) return 0; + + startPos = pFrameInfo->borders[0]; + stopPos = pFrameInfo->borders[nEnvelopes]; + tranEnv = pFrameInfo->tranEnv; + startPosNoise = pFrameInfo->bordersNoise[0]; + stopPosNoise = pFrameInfo->bordersNoise[nNoiseEnvelopes]; + + if (overlap < 0 || overlap > (3 * (4))) { + return 0; + } + if (timeStep < 1 || timeStep > (4)) { + return 0; + } + maxPos = numberOfTimeSlots + (overlap / timeStep); + + /* Check that the start and stop positions of the frame are reasonable values. + */ + if ((startPos < 0) || (startPos >= stopPos)) return 0; + if (startPos > maxPos - numberOfTimeSlots) /* First env. must start in or + directly after the overlap + buffer */ + return 0; + if (stopPos < numberOfTimeSlots) /* One complete frame must be ready for + output after processing */ + return 0; + if (stopPos > maxPos) return 0; + + /* Check that the start border for every envelope is strictly later in time + */ + for (i = 0; i < nEnvelopes; i++) { + if (pFrameInfo->borders[i] >= pFrameInfo->borders[i + 1]) return 0; + } + + /* Check that the envelope to be shortened is actually among the envelopes */ + if (tranEnv > nEnvelopes) return 0; + + /* Check the noise borders */ + if (nEnvelopes == 1 && nNoiseEnvelopes > 1) return 0; + + if (startPos != startPosNoise || stopPos != stopPosNoise) return 0; + + /* Check that the start border for every noise-envelope is strictly later in + * time*/ + for (i = 0; i < nNoiseEnvelopes; i++) { + if (pFrameInfo->bordersNoise[i] >= pFrameInfo->bordersNoise[i + 1]) + return 0; + } + + /* Check that every noise border is the same as an envelope border*/ + for (i = 0; i < nNoiseEnvelopes; i++) { + startPosNoise = pFrameInfo->bordersNoise[i]; + + for (j = 0; j < nEnvelopes; j++) { + if (pFrameInfo->borders[j] == startPosNoise) break; + } + if (j == nEnvelopes) return 0; + } + + return 1; +} diff --git a/fdk-aac/libSBRdec/src/env_extr.h b/fdk-aac/libSBRdec/src/env_extr.h new file mode 100644 index 0000000..38c04a3 --- /dev/null +++ b/fdk-aac/libSBRdec/src/env_extr.h @@ -0,0 +1,415 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope extraction prototypes +*/ + +#ifndef ENV_EXTR_H +#define ENV_EXTR_H + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" +#include "lpp_tran.h" + +#include "psdec.h" +#include "pvc_dec.h" + +#define ENV_EXP_FRACT 0 +/*!< Shift raw envelope data to support fractional numbers. + Can be set to 8 instead of 0 to enhance accuracy during concealment. + This is not required for conformance and #requantizeEnvelopeData() will + become more expensive. +*/ + +#define EXP_BITS 6 +/*!< Size of exponent-part of a pseudo float envelope value (should be at least + 6). The remaining bits in each word are used for the mantissa (should be at + least 10). This format is used in the arrays iEnvelope[] and + sbrNoiseFloorLevel[] in the FRAME_DATA struct which must fit in a certain part + of the output buffer (See buffer management in sbr_dec.cpp). Exponents and + mantissas could also be stored in separate arrays. Accessing the exponent or + the mantissa would be simplified and the masks #MASK_E resp. #MASK_M would + no longer be required. +*/ + +#define MASK_M \ + (((1 << (FRACT_BITS - EXP_BITS)) - 1) \ + << EXP_BITS) /*!< Mask for extracting the mantissa of a pseudo float \ + envelope value */ +#define MASK_E \ + ((1 << EXP_BITS) - 1) /*!< Mask for extracting the exponent of a pseudo \ + float envelope value */ + +#define SIGN_EXT \ + (((SCHAR)-1) ^ \ + MASK_E) /*!< a CHAR-constant with all bits above our sign-bit set */ +#define ROUNDING \ + ((FIXP_SGL)( \ + 1 << (EXP_BITS - 1))) /*!< 0.5-offset for rounding the mantissa of a \ + pseudo-float envelope value */ +#define NRG_EXP_OFFSET \ + 16 /*!< Will be added to the reference energy's exponent to prevent negative \ + numbers */ +#define NOISE_EXP_OFFSET \ + 38 /*!< Will be added to the noise level exponent to prevent negative \ + numbers */ + +#define ADD_HARMONICS_FLAGS_SIZE 2 /* ceil(MAX_FREQ_COEFFS/32) */ + +typedef enum { + HEADER_NOT_PRESENT, + HEADER_ERROR, + HEADER_OK, + HEADER_RESET +} SBR_HEADER_STATUS; + +typedef enum { + SBR_NOT_INITIALIZED = 0, + UPSAMPLING = 1, + SBR_HEADER = 2, + SBR_ACTIVE = 3 +} SBR_SYNC_STATE; + +typedef enum { COUPLING_OFF = 0, COUPLING_LEVEL, COUPLING_BAL } COUPLING_MODE; + +typedef struct { + UCHAR nSfb[2]; /*!< Number of SBR-bands for low and high freq-resolution */ + UCHAR nNfb; /*!< Actual number of noise bands to read from the bitstream*/ + UCHAR numMaster; /*!< Number of SBR-bands in v_k_master */ + UCHAR lowSubband; /*!< QMF-band where SBR frequency range starts */ + UCHAR highSubband; /*!< QMF-band where SBR frequency range ends */ + UCHAR ov_highSubband; /*!< if headerchange applies this value holds the old + highband value -> highband value of overlap area; + required for overlap in usac when headerchange + occurs between XVAR and VARX frame */ + UCHAR limiterBandTable[MAX_NUM_LIMITERS + 1]; /*!< Limiter band table. */ + UCHAR noLimiterBands; /*!< Number of limiter bands. */ + UCHAR nInvfBands; /*!< Number of bands for inverse filtering */ + UCHAR + *freqBandTable[2]; /*!< Pointers to freqBandTableLo and freqBandTableHi */ + UCHAR freqBandTableLo[MAX_FREQ_COEFFS / 2 + 1]; + /*!< Mapping of SBR bands to QMF bands for low frequency resolution */ + UCHAR freqBandTableHi[MAX_FREQ_COEFFS + 1]; + /*!< Mapping of SBR bands to QMF bands for high frequency resolution */ + UCHAR freqBandTableNoise[MAX_NOISE_COEFFS + 1]; + /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR v_k_master[MAX_FREQ_COEFFS + 1]; + /*!< Master BandTable which freqBandTable is derived from */ +} FREQ_BAND_DATA; + +typedef FREQ_BAND_DATA *HANDLE_FREQ_BAND_DATA; + +#define SBRDEC_ELD_GRID 1 +#define SBRDEC_SYNTAX_SCAL 2 +#define SBRDEC_SYNTAX_USAC 4 +#define SBRDEC_SYNTAX_RSVD50 8 +#define SBRDEC_USAC_INDEP \ + 16 /* Flag indicating that USAC global independency flag is active. */ +#define SBRDEC_LOW_POWER \ + 32 /* Flag indicating that Low Power QMF mode shall be used. */ +#define SBRDEC_PS_DECODED \ + 64 /* Flag indicating that PS was decoded and rendered. */ +#define SBRDEC_QUAD_RATE \ + 128 /* Flag indicating that USAC SBR 4:1 is active. \ + */ +#define SBRDEC_USAC_HARMONICSBR \ + 256 /* Flag indicating that USAC HBE tool is active. */ +#define SBRDEC_LD_MPS_QMF \ + 512 /* Flag indicating that the LD-MPS QMF shall be used. */ +#define SBRDEC_USAC_ITES \ + 1024 /* Flag indicating that USAC inter TES tool is active. */ +#define SBRDEC_SYNTAX_DRM \ + 2048 /* Flag indicating that DRM30/DRM+ reverse syntax is being used. */ +#define SBRDEC_ELD_DOWNSCALE \ + 4096 /* Flag indicating that ELD downscaled mode decoding is used */ +#define SBRDEC_DOWNSAMPLE \ + 8192 /* Flag indicating that the downsampling mode is used. */ +#define SBRDEC_FLUSH 16384 /* Flag is used to flush all elements in use. */ +#define SBRDEC_FORCE_RESET \ + 32768 /* Flag is used to force a reset of all elements in use. */ +#define SBRDEC_SKIP_QMF_ANA \ + (1 << 21) /* Flag indicating that the input data is provided in the QMF \ + domain. */ +#define SBRDEC_SKIP_QMF_SYN \ + (1 << 22) /* Flag indicating that the output data is exported in the QMF \ + domain. */ + +#define SBRDEC_HDR_STAT_RESET 1 +#define SBRDEC_HDR_STAT_UPDATE 2 + +typedef struct { + UCHAR ampResolution; /*!< Amplitude resolution of envelope values (0: 1.5dB, + 1: 3dB) */ + UCHAR + xover_band; /*!< Start index in #v_k_master[] used for dynamic crossover + frequency */ + UCHAR sbr_preprocessing; /*!< SBR prewhitening flag. */ + UCHAR pvc_mode; /*!< Predictive vector coding mode */ +} SBR_HEADER_DATA_BS_INFO; + +typedef struct { + /* Changes in these variables causes a reset of the decoder */ + UCHAR startFreq; /*!< Index for SBR start frequency */ + UCHAR stopFreq; /*!< Index for SBR highest frequency */ + UCHAR freqScale; /*!< 0: linear scale, 1-3 logarithmic scales */ + UCHAR alterScale; /*!< Flag for coarser frequency resolution */ + UCHAR noise_bands; /*!< Noise bands per octave, read from bitstream*/ + + /* don't require reset */ + UCHAR limiterBands; /*!< Index for number of limiter bands per octave */ + UCHAR limiterGains; /*!< Index to select gain limit */ + UCHAR interpolFreq; /*!< Select gain calculation method (1: per QMF channel, + 0: per SBR band) */ + UCHAR smoothingLength; /*!< Smoothing of gains over time (0: on 1: off) */ + +} SBR_HEADER_DATA_BS; + +typedef struct { + SBR_SYNC_STATE + syncState; /*!< The current initialization status of the header */ + + UCHAR status; /*!< Flags field used for signaling a reset right before the + processing starts and an update from config (e.g. ASC). */ + UCHAR + frameErrorFlag; /*!< Frame data valid flag. CAUTION: This variable will be + overwritten by the flag stored in the element + structure. This is necessary because of the frame + delay. There it might happen that different slots use + the same header. */ + UCHAR numberTimeSlots; /*!< AAC: 16,15 */ + UCHAR numberOfAnalysisBands; /*!< Number of QMF analysis bands */ + UCHAR timeStep; /*!< Time resolution of SBR in QMF-slots */ + UINT + sbrProcSmplRate; /*!< SBR processing sampling frequency (!= + OutputSamplingRate) (always: CoreSamplingRate * + UpSamplingFactor; even in single rate mode) */ + + SBR_HEADER_DATA_BS bs_data; /*!< current SBR header. */ + SBR_HEADER_DATA_BS bs_dflt; /*!< Default sbr header. */ + SBR_HEADER_DATA_BS_INFO bs_info; /*!< SBR info. */ + + FREQ_BAND_DATA freqBandData; /*!< Pointer to struct #FREQ_BAND_DATA */ + UCHAR pvcIDprev; +} SBR_HEADER_DATA; + +typedef SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + +typedef struct { + UCHAR frameClass; /*!< Select grid type */ + UCHAR nEnvelopes; /*!< Number of envelopes */ + UCHAR borders[MAX_ENVELOPES + 1]; /*!< Envelope borders (in SBR-timeslots, + e.g. mp3PRO: 0..11) */ + UCHAR freqRes[MAX_ENVELOPES]; /*!< Frequency resolution for each envelope + (0=low, 1=high) */ + SCHAR tranEnv; /*!< Transient envelope, -1 if none */ + UCHAR nNoiseEnvelopes; /*!< Number of noise envelopes */ + UCHAR + bordersNoise[MAX_NOISE_ENVELOPES + 1]; /*!< borders of noise envelopes */ + UCHAR pvcBorders[MAX_PVC_ENVELOPES + 1]; + UCHAR noisePosition; + UCHAR varLength; +} FRAME_INFO; + +typedef struct { + FIXP_SGL sfb_nrg_prev[MAX_FREQ_COEFFS]; /*!< Previous envelope (required for + differential-coded values) */ + FIXP_SGL + prevNoiseLevel[MAX_NOISE_COEFFS]; /*!< Previous noise envelope (required + for differential-coded values) */ + COUPLING_MODE coupling; /*!< Stereo-mode of previous frame */ + INVF_MODE sbr_invf_mode[MAX_INVF_BANDS]; /*!< Previous strength of filtering + in transposer */ + UCHAR ampRes; /*!< Previous amplitude resolution (0: 1.5dB, 1: 3dB) */ + UCHAR stopPos; /*!< Position in time where last envelope ended */ + UCHAR frameErrorFlag; /*!< Previous frame status */ + UCHAR prevSbrPitchInBins; /*!< Previous frame pitchInBins */ + FRAME_INFO prevFrameInfo; +} SBR_PREV_FRAME_DATA; + +typedef SBR_PREV_FRAME_DATA *HANDLE_SBR_PREV_FRAME_DATA; + +typedef struct { + int nScaleFactors; /*!< total number of scalefactors in frame */ + + FRAME_INFO frameInfo; /*!< time grid for current frame */ + UCHAR domain_vec[MAX_ENVELOPES]; /*!< Bitfield containing direction of + delta-coding for each envelope + (0:frequency, 1:time) */ + UCHAR domain_vec_noise + [MAX_NOISE_ENVELOPES]; /*!< Same as above, but for noise envelopes */ + + INVF_MODE + sbr_invf_mode[MAX_INVF_BANDS]; /*!< Strength of filtering in transposer */ + COUPLING_MODE coupling; /*!< Stereo-mode */ + int ampResolutionCurrentFrame; /*!< Amplitude resolution of envelope values + (0: 1.5dB, 1: 3dB) */ + + ULONG addHarmonics[ADD_HARMONICS_FLAGS_SIZE]; /*!< Flags for synthetic sine + addition (aligned to MSB) */ + + FIXP_SGL iEnvelope[MAX_NUM_ENVELOPE_VALUES]; /*!< Envelope data */ + FIXP_SGL sbrNoiseFloorLevel[MAX_NUM_NOISE_VALUES]; /*!< Noise envelope data */ + UCHAR iTESactive; /*!< One flag for each envelope to enable USAC inter-TES */ + UCHAR + interTempShapeMode[MAX_ENVELOPES]; /*!< USAC inter-TES: + bs_inter_temp_shape_mode[ch][env] + value */ + UCHAR pvcID[PVC_NTIMESLOT]; /*!< One PVC ID value for each time slot */ + UCHAR ns; + UCHAR sinusoidal_position; + + UCHAR sbrPatchingMode; + UCHAR sbrOversamplingFlag; + UCHAR sbrPitchInBins; +} SBR_FRAME_DATA; + +typedef SBR_FRAME_DATA *HANDLE_SBR_FRAME_DATA; + +/*! +\brief Maps sampling frequencies to frequencies for which setup tables are +available + +Maps arbitary sampling frequency to nearest neighbors for which setup tables +are available (e.g. 25600 -> 24000). +Used for startFreq calculation. +The mapping is defined in 14496-3 (4.6.18.2.6), fs(SBR), and table 4.82 + +\return mapped sampling frequency +*/ +UINT sbrdec_mapToStdSampleRate(UINT fs, + UINT isUsac); /*!< Output sampling frequency */ + +void initSbrPrevFrameData(HANDLE_SBR_PREV_FRAME_DATA h_prev_data, + int timeSlots); + +int sbrGetChannelElement(HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_FRAME_DATA hFrameDataLeft, + HANDLE_SBR_FRAME_DATA hFrameDataRight, + HANDLE_SBR_PREV_FRAME_DATA hFrameDataLeftPrev, + UCHAR pvc_mode_last, HANDLE_FDK_BITSTREAM hBitBuf, + HANDLE_PS_DEC hParametricStereoDec, const UINT flags, + const int overlap); + +SBR_HEADER_STATUS +sbrGetHeaderData(HANDLE_SBR_HEADER_DATA headerData, + HANDLE_FDK_BITSTREAM hBitBuf, const UINT flags, + const int fIsSbrData, const UCHAR configMode); + +/*! + \brief Initialize SBR header data + + Copy default values to the header data struct and patch some entries + depending on the core codec. +*/ +SBR_ERROR +initHeaderData(HANDLE_SBR_HEADER_DATA hHeaderData, const int sampleRateIn, + const int sampleRateOut, const INT downscaleFactor, + const int samplesPerFrame, const UINT flags, + const int setDefaultHdr); +#endif + +/* Convert headroom bits to exponent */ +#define SCALE2EXP(s) (15 - (s)) +#define EXP2SCALE(e) (15 - (e)) diff --git a/fdk-aac/libSBRdec/src/hbe.cpp b/fdk-aac/libSBRdec/src/hbe.cpp new file mode 100644 index 0000000..3310dcd --- /dev/null +++ b/fdk-aac/libSBRdec/src/hbe.cpp @@ -0,0 +1,2202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Fast FFT routines prototypes + \author Fabian Haussel +*/ + +#include "hbe.h" +#include "qmf.h" +#include "env_extr.h" + +#define HBE_MAX_QMF_BANDS (40) + +#define HBE_MAX_OUT_SLOTS (11) + +#define QMF_WIN_LEN \ + (12 + 6 - 4 - 1) /* 6 subband slots extra delay to align with HQ - 4 slots \ + to compensate for critical sampling delay - 1 slot to \ + align critical sampling exactly (w additional time \ + domain delay)*/ + +#ifndef PI +#define PI 3.14159265358979323846 +#endif + +static const int xProducts[MAX_STRETCH_HBE - 1] = { + 1, 1, 1}; /* Cross products on(1)/off(0) for T=2,3,4. */ +static const int startSubband2kL[33] = { + 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, + 6, 8, 8, 8, 8, 8, 10, 10, 10, 12, 12, 12, 12, 12, 12, 12}; + +static const int pmin = 12; + +static const FIXP_DBL hintReal_F[4][3] = { + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(0.39840335f)}, + {FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f), + FL2FXCONST_DBL(0.39840335f)}}; + +static const FIXP_DBL factors[4] = { + FL2FXCONST_DBL(0.39840335f), FL2FXCONST_DBL(-0.39840335f), + FL2FXCONST_DBL(-0.39840335f), FL2FXCONST_DBL(0.39840335f)}; + +#define PSCALE 32 + +static const FIXP_DBL p_F[128] = {FL2FXCONST_DBL(0.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(1.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(2.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(3.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(4.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(5.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(6.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(7.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(8.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(9.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(10.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(11.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(12.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(13.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(14.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(15.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(16.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(17.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(18.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(19.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(20.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(21.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(22.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(23.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(24.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(25.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(26.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(27.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(28.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(29.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(30.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(31.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(32.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(33.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(34.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(35.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(36.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(37.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(38.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(39.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(40.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(41.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(42.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(43.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(44.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(45.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(46.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(47.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(48.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(49.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(50.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(51.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(52.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(53.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(54.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(55.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(56.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(57.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(58.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(59.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(60.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(61.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(62.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(63.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(64.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(65.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(66.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(67.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(68.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(69.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(70.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(71.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(72.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(73.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(74.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(75.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(76.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(77.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(78.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(79.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(80.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(81.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(82.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(83.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(84.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(85.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(86.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(87.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(88.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(89.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(90.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(91.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(92.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(93.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(94.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(95.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(96.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(97.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(98.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(99.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(100.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(101.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(102.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(103.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(104.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(105.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(106.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(107.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(108.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(109.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(110.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(111.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(112.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(113.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(114.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(115.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(116.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(117.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(118.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(119.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(120.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(121.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(122.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(123.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(124.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(125.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(126.f / (PSCALE * 12.f)), + FL2FXCONST_DBL(127.f / (PSCALE * 12.f))}; + +static const FIXP_DBL band_F[64] = { + FL2FXCONST_DBL((0.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((1.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((2.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((3.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((4.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((5.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((6.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((7.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((8.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((9.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((10.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((11.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((12.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((13.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((14.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((15.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((16.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((17.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((18.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((19.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((20.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((21.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((22.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((23.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((24.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((25.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((26.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((27.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((28.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((29.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((30.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((31.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((32.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((33.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((34.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((35.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((36.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((37.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((38.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((39.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((40.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((41.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((42.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((43.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((44.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((45.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((46.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((47.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((48.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((49.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((50.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((51.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((52.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((53.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((54.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((55.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((56.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((57.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((58.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((59.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((60.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((61.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((62.f * 2.f + 1) / (PSCALE << 2)), + FL2FXCONST_DBL((63.f * 2.f + 1) / (PSCALE << 2))}; + +static const FIXP_DBL tr_str[3] = {FL2FXCONST_DBL(1.f / 4.f), + FL2FXCONST_DBL(2.f / 4.f), + FL2FXCONST_DBL(3.f / 4.f)}; + +static const FIXP_DBL stretchfac[3] = {FL2FXCONST_DBL(1.f / 2.f), + FL2FXCONST_DBL(1.f / 3.f), + FL2FXCONST_DBL(1.f / 4.f)}; + +static const FIXP_DBL cos_F[64] = { + 26353028, -79043208, 131685776, -184244944, 236697216, -289006912, + 341142496, -393072608, 444773984, -496191392, 547325824, -598114752, + 648559104, -698597248, 748230016, -797411904, 846083200, -894275136, + 941928192, -989013760, 1035474624, -1081340672, 1126555136, -1171063296, + 1214893696, -1257992192, 1300332544, -1341889408, 1382612736, -1422503808, + 1461586944, -1499741440, 1537039104, -1573364864, 1608743808, -1643196672, + 1676617344, -1709028992, 1740450560, -1770784896, 1800089472, -1828273536, + 1855357440, -1881356288, 1906190080, -1929876608, 1952428928, -1973777664, + 1993962880, -2012922240, 2030670208, -2047216000, 2062508288, -2076559488, + 2089376128, -2100932224, 2111196800, -2120214784, 2127953792, -2134394368, + 2139565056, -2143444864, 2146026624, -2147321856}; + +static const FIXP_DBL twiddle[121] = {1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0, + -70226075, + -140151432, + -209476638, + -277904834, + -345142998, + -410903207, + -474903865, + -536870912, + -596538995, + -653652607, + -707967178, + -759250125, + -807281846, + -851856663, + -892783698, + -929887697, + -963009773, + -992008094, + -1016758484, + -1037154959, + -1053110176, + -1064555814, + -1071442860, + -1073741824, + -1071442860, + -1064555814, + -1053110176, + -1037154959, + -1016758484, + -992008094, + -963009773, + -929887697, + -892783698, + -851856663, + -807281846, + -759250125, + -707967178, + -653652607, + -596538995, + -536870912, + -474903865, + -410903207, + -345142998, + -277904834, + -209476638, + -140151432, + -70226075, + 0, + 70226075, + 140151432, + 209476638, + 277904834, + 345142998, + 410903207, + 474903865, + 536870912, + 596538995, + 653652607, + 707967178, + 759250125, + 807281846, + 851856663, + 892783698, + 929887697, + 963009773, + 992008094, + 1016758484, + 1037154959, + 1053110176, + 1064555814, + 1071442860, + 1073741824, + 1071442860, + 1064555814, + 1053110176, + 1037154959, + 1016758484, + 992008094, + 963009773, + 929887697, + 892783698, + 851856663, + 807281846, + 759250125, + 707967178, + 653652607, + 596538995, + 536870912, + 474903865, + 410903207, + 345142998, + 277904834, + 209476638, + 140151432, + 70226075, + 0}; + +#if FIXP_QTW == FIXP_SGL +#define HTW(x) (x) +#else +#define HTW(x) FX_DBL2FX_QTW(FX_SGL2FX_DBL((const FIXP_SGL)x)) +#endif + +static const FIXP_QTW post_twiddle_cos_8[8] = { + HTW(-1606), HTW(4756), HTW(-7723), HTW(10394), + HTW(-12665), HTW(14449), HTW(-15679), HTW(16305)}; + +static const FIXP_QTW post_twiddle_cos_16[16] = { + HTW(-804), HTW(2404), HTW(-3981), HTW(5520), HTW(-7005), HTW(8423), + HTW(-9760), HTW(11003), HTW(-12140), HTW(13160), HTW(-14053), HTW(14811), + HTW(-15426), HTW(15893), HTW(-16207), HTW(16364)}; + +static const FIXP_QTW post_twiddle_cos_24[24] = { + HTW(-536), HTW(1606), HTW(-2669), HTW(3720), HTW(-4756), HTW(5771), + HTW(-6762), HTW(7723), HTW(-8652), HTW(9543), HTW(-10394), HTW(11200), + HTW(-11958), HTW(12665), HTW(-13318), HTW(13913), HTW(-14449), HTW(14924), + HTW(-15334), HTW(15679), HTW(-15956), HTW(16165), HTW(-16305), HTW(16375)}; + +static const FIXP_QTW post_twiddle_cos_32[32] = { + HTW(-402), HTW(1205), HTW(-2006), HTW(2801), HTW(-3590), HTW(4370), + HTW(-5139), HTW(5897), HTW(-6639), HTW(7366), HTW(-8076), HTW(8765), + HTW(-9434), HTW(10080), HTW(-10702), HTW(11297), HTW(-11866), HTW(12406), + HTW(-12916), HTW(13395), HTW(-13842), HTW(14256), HTW(-14635), HTW(14978), + HTW(-15286), HTW(15557), HTW(-15791), HTW(15986), HTW(-16143), HTW(16261), + HTW(-16340), HTW(16379)}; + +static const FIXP_QTW post_twiddle_cos_40[40] = { + HTW(-322), HTW(965), HTW(-1606), HTW(2245), HTW(-2880), HTW(3511), + HTW(-4137), HTW(4756), HTW(-5368), HTW(5971), HTW(-6566), HTW(7150), + HTW(-7723), HTW(8285), HTW(-8833), HTW(9368), HTW(-9889), HTW(10394), + HTW(-10883), HTW(11356), HTW(-11810), HTW(12247), HTW(-12665), HTW(13063), + HTW(-13441), HTW(13799), HTW(-14135), HTW(14449), HTW(-14741), HTW(15011), + HTW(-15257), HTW(15480), HTW(-15679), HTW(15853), HTW(-16003), HTW(16129), + HTW(-16229), HTW(16305), HTW(-16356), HTW(16381)}; + +static const FIXP_QTW post_twiddle_sin_8[8] = { + HTW(16305), HTW(-15679), HTW(14449), HTW(-12665), + HTW(10394), HTW(-7723), HTW(4756), HTW(-1606)}; + +static const FIXP_QTW post_twiddle_sin_16[16] = { + HTW(16364), HTW(-16207), HTW(15893), HTW(-15426), HTW(14811), HTW(-14053), + HTW(13160), HTW(-12140), HTW(11003), HTW(-9760), HTW(8423), HTW(-7005), + HTW(5520), HTW(-3981), HTW(2404), HTW(-804)}; + +static const FIXP_QTW post_twiddle_sin_24[24] = { + HTW(16375), HTW(-16305), HTW(16165), HTW(-15956), HTW(15679), HTW(-15334), + HTW(14924), HTW(-14449), HTW(13913), HTW(-13318), HTW(12665), HTW(-11958), + HTW(11200), HTW(-10394), HTW(9543), HTW(-8652), HTW(7723), HTW(-6762), + HTW(5771), HTW(-4756), HTW(3720), HTW(-2669), HTW(1606), HTW(-536)}; + +static const FIXP_QTW post_twiddle_sin_32[32] = { + HTW(16379), HTW(-16340), HTW(16261), HTW(-16143), HTW(15986), HTW(-15791), + HTW(15557), HTW(-15286), HTW(14978), HTW(-14635), HTW(14256), HTW(-13842), + HTW(13395), HTW(-12916), HTW(12406), HTW(-11866), HTW(11297), HTW(-10702), + HTW(10080), HTW(-9434), HTW(8765), HTW(-8076), HTW(7366), HTW(-6639), + HTW(5897), HTW(-5139), HTW(4370), HTW(-3590), HTW(2801), HTW(-2006), + HTW(1205), HTW(-402)}; + +static const FIXP_QTW post_twiddle_sin_40[40] = { + HTW(16381), HTW(-16356), HTW(16305), HTW(-16229), HTW(16129), HTW(-16003), + HTW(15853), HTW(-15679), HTW(15480), HTW(-15257), HTW(15011), HTW(-14741), + HTW(14449), HTW(-14135), HTW(13799), HTW(-13441), HTW(13063), HTW(-12665), + HTW(12247), HTW(-11810), HTW(11356), HTW(-10883), HTW(10394), HTW(-9889), + HTW(9368), HTW(-8833), HTW(8285), HTW(-7723), HTW(7150), HTW(-6566), + HTW(5971), HTW(-5368), HTW(4756), HTW(-4137), HTW(3511), HTW(-2880), + HTW(2245), HTW(-1606), HTW(965), HTW(-322)}; + +static const FIXP_DBL preModCos[32] = { + -749875776, 786681536, 711263552, -821592064, -670937792, 854523392, + 628995648, -885396032, -585538240, 914135680, 540670208, -940673088, + -494499680, 964944384, 447137824, -986891008, -398698816, 1006460096, + 349299264, -1023604544, -299058240, 1038283072, 248096752, -1050460288, + -196537584, 1060106816, 144504928, -1067199488, -92124160, 1071721152, + 39521456, -1073660992}; + +static const FIXP_DBL preModSin[32] = { + 768510144, 730789760, -804379072, -691308864, 838310208, 650162560, + -870221760, -607449920, 900036928, 563273856, -927683776, -517740896, + 953095808, 470960608, -976211712, -423045728, 996975808, 374111712, + -1015338112, -324276416, 1031254400, 273659904, -1044686336, -222384144, + 1055601472, 170572640, -1063973632, -118350192, 1069782528, 65842640, + -1073014208, -13176464}; + +/* The cube root function */ +/***************************************************************************** + + functionname: invCubeRootNorm2 + description: delivers 1/cuberoot(op) in Q1.31 format and modified exponent + +*****************************************************************************/ +#define CUBE_ROOT_BITS 7 +#define CUBE_ROOT_VALUES (128 + 2) +#define CUBE_ROOT_BITS_MASK 0x7f +#define CUBE_ROOT_FRACT_BITS_MASK 0x007FFFFF +/* Inverse cube root table for operands running from 0.5 to 1.0 */ +/* (INT) (1.0/cuberoot((op))); */ +/* Implicit exponent is 1. */ + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invCubeRootTab[CUBE_ROOT_VALUES] = { + (0x50a28be6), (0x506d1172), (0x503823c4), (0x5003c05a), (0x4fcfe4c0), + (0x4f9c8e92), (0x4f69bb7d), (0x4f37693b), (0x4f059594), (0x4ed43e5f), + (0x4ea36181), (0x4e72fcea), (0x4e430e98), (0x4e139495), (0x4de48cf5), + (0x4db5f5db), (0x4d87cd73), (0x4d5a11f2), (0x4d2cc19c), (0x4cffdabb), + (0x4cd35ba4), (0x4ca742b7), (0x4c7b8e5c), (0x4c503d05), (0x4c254d2a), + (0x4bfabd50), (0x4bd08c00), (0x4ba6b7cd), (0x4b7d3f53), (0x4b542134), + (0x4b2b5c18), (0x4b02eeb1), (0x4adad7b8), (0x4ab315ea), (0x4a8ba80d), + (0x4a648cec), (0x4a3dc35b), (0x4a174a30), (0x49f1204a), (0x49cb448d), + (0x49a5b5e2), (0x49807339), (0x495b7b86), (0x4936cdc2), (0x491268ec), + (0x48ee4c08), (0x48ca761f), (0x48a6e63e), (0x48839b76), (0x486094de), + (0x483dd190), (0x481b50ad), (0x47f91156), (0x47d712b3), (0x47b553f0), + (0x4793d43c), (0x477292c9), (0x47518ece), (0x4730c785), (0x47103c2d), + (0x46efec06), (0x46cfd655), (0x46affa61), (0x46905777), (0x4670ece4), + (0x4651b9f9), (0x4632be0b), (0x4613f871), (0x45f56885), (0x45d70da5), + (0x45b8e72f), (0x459af487), (0x457d3511), (0x455fa835), (0x45424d5d), + (0x452523f6), (0x45082b6e), (0x44eb6337), (0x44cecac5), (0x44b2618d), + (0x44962708), (0x447a1ab1), (0x445e3c02), (0x44428a7c), (0x4427059e), + (0x440bacec), (0x43f07fe9), (0x43d57e1c), (0x43baa70e), (0x439ffa48), + (0x43857757), (0x436b1dc8), (0x4350ed2b), (0x4336e511), (0x431d050c), + (0x43034cb2), (0x42e9bb98), (0x42d05156), (0x42b70d85), (0x429defc0), + (0x4284f7a2), (0x426c24cb), (0x425376d8), (0x423aed6a), (0x42228823), + (0x420a46a6), (0x41f22898), (0x41da2d9f), (0x41c25561), (0x41aa9f86), + (0x41930bba), (0x417b99a5), (0x416448f5), (0x414d1956), (0x41360a76), + (0x411f1c06), (0x41084db5), (0x40f19f35), (0x40db1039), (0x40c4a074), + (0x40ae4f9b), (0x40981d64), (0x40820985), (0x406c13b6), (0x40563bb1), + (0x4040812e), (0x402ae3e7), (0x40156399), (0x40000000), (0x3FEAB8D9)}; +/* n.a. */ +static const FIXP_DBL invCubeRootCorrection[3] = {0x40000000, 0x50A28BE6, + 0x6597FA95}; + +/***************************************************************************** + * \brief calculate 1.0/cube_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invCubeRootNorm2 By + * means of activating the macro INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invCubeRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FIXP_DBL(0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (CUBE_ROOT_BITS + 1))) & + CUBE_ROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & CUBE_ROOT_FRACT_BITS_MASK) + << (CUBE_ROOT_BITS + 1)); + FIXP_DBL diff = invCubeRootTab[index + 1] - invCubeRootTab[index]; + op_m = fMultAddDiv2(invCubeRootTab[index], diff << 1, fract); +#if defined(INVCUBEROOTNORM2_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 != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invCubeRootTab[index + 2] - invCubeRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVCUBEROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + /* calculate the output exponent = input * exp/3 = cubicroot(m)*2^(exp/3) + * where 2^(exp/3) = 2^k'*2 or 2^k'*2^(1/3) or 2^k'*2^(2/3) */ + exponent = exponent - *op_e + 3; + INT shift_tmp = + ((INT)fMultDiv2((FIXP_SGL)fAbs(exponent), (FIXP_SGL)0x5556)) >> 16; + if (exponent < 0) { + shift_tmp = -shift_tmp; + } + INT rem = exponent - 3 * shift_tmp; + if (rem < 0) { + rem += 3; + shift_tmp--; + } + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invCubeRootCorrection[rem]) << 2; + + return (op_m); +} + + /***************************************************************************** + + functionname: invFourthRootNorm2 + description: delivers 1/FourthRoot(op) in Q1.31 format and modified + exponent + + *****************************************************************************/ + +#define FOURTHROOT_BITS 7 +#define FOURTHROOT_VALUES (128 + 2) +#define FOURTHROOT_BITS_MASK 0x7f +#define FOURTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL invFourthRootTab[FOURTHROOT_VALUES] = { + (0x4c1bf829), (0x4bf61977), (0x4bd09843), (0x4bab72ef), (0x4b86a7eb), + (0x4b6235ac), (0x4b3e1ab6), (0x4b1a5592), (0x4af6e4d4), (0x4ad3c718), + (0x4ab0fb03), (0x4a8e7f42), (0x4a6c5288), (0x4a4a7393), (0x4a28e126), + (0x4a079a0c), (0x49e69d16), (0x49c5e91f), (0x49a57d04), (0x498557ac), + (0x49657802), (0x4945dcf9), (0x49268588), (0x490770ac), (0x48e89d6a), + (0x48ca0ac9), (0x48abb7d6), (0x488da3a6), (0x486fcd4f), (0x485233ed), + (0x4834d6a3), (0x4817b496), (0x47faccf0), (0x47de1ee0), (0x47c1a999), + (0x47a56c51), (0x47896643), (0x476d96af), (0x4751fcd6), (0x473697ff), + (0x471b6773), (0x47006a81), (0x46e5a079), (0x46cb08ae), (0x46b0a279), + (0x46966d34), (0x467c683d), (0x466292f4), (0x4648ecbc), (0x462f74fe), + (0x46162b20), (0x45fd0e91), (0x45e41ebe), (0x45cb5b19), (0x45b2c315), + (0x459a562a), (0x458213cf), (0x4569fb81), (0x45520cbc), (0x453a4701), + (0x4522a9d1), (0x450b34b0), (0x44f3e726), (0x44dcc0ba), (0x44c5c0f7), + (0x44aee768), (0x4498339e), (0x4481a527), (0x446b3b96), (0x4454f67e), + (0x443ed576), (0x4428d815), (0x4412fdf3), (0x43fd46ad), (0x43e7b1de), + (0x43d23f23), (0x43bcee1e), (0x43a7be6f), (0x4392afb8), (0x437dc19d), + (0x4368f3c5), (0x435445d6), (0x433fb779), (0x432b4856), (0x4316f81a), + (0x4302c66f), (0x42eeb305), (0x42dabd8a), (0x42c6e5ad), (0x42b32b21), + (0x429f8d96), (0x428c0cc2), (0x4278a859), (0x42656010), (0x4252339e), + (0x423f22bc), (0x422c2d23), (0x4219528b), (0x420692b2), (0x41f3ed51), + (0x41e16228), (0x41cef0f2), (0x41bc9971), (0x41aa5b62), (0x41983687), + (0x41862aa2), (0x41743775), (0x41625cc3), (0x41509a50), (0x413eefe2), + (0x412d5d3e), (0x411be22b), (0x410a7e70), (0x40f931d5), (0x40e7fc23), + (0x40d6dd24), (0x40c5d4a2), (0x40b4e268), (0x40a40642), (0x40933ffc), + (0x40828f64), (0x4071f447), (0x40616e73), (0x4050fdb9), (0x4040a1e6), + (0x40305acc), (0x4020283c), (0x40100a08), (0x40000000), (0x3ff009f9), +}; + +static const FIXP_DBL invFourthRootCorrection[4] = {0x40000000, 0x4C1BF829, + 0x5A82799A, 0x6BA27E65}; + +/* The fourth root function */ +/***************************************************************************** + * \brief calculate 1.0/fourth_root(op), op contains mantissa and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_invFourthRootNorm2 By + * means of activating the macro INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + invFourthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift value */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (FOURTHROOT_BITS + 1))) & + FOURTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & FOURTHROOT_FRACT_BITS_MASK) + << (FOURTHROOT_BITS + 1)); + FIXP_DBL diff = invFourthRootTab[index + 1] - invFourthRootTab[index]; + op_m = invFourthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVFOURTHROOTNORM2_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 != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (invFourthRootTab[index + 2] - invFourthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVFOURTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 4; + INT rem = exponent & 0x00000003; + INT shift_tmp = (exponent >> 2); + + *op_e = shift_tmp; + op_m = fMultDiv2(op_m, invFourthRootCorrection[rem]) << 2; + + return (op_m); +} + +/***************************************************************************** + + functionname: inv3EigthRootNorm2 + description: delivers 1/cubert(op) normalized to .5...1 and the shift value +of the OUTPUT + +*****************************************************************************/ +#define THREEIGTHROOT_BITS 7 +#define THREEIGTHROOT_VALUES (128 + 2) +#define THREEIGTHROOT_BITS_MASK 0x7f +#define THREEIGTHROOT_FRACT_BITS_MASK 0x007FFFFF + +LNK_SECTION_CONSTDATA +static const FIXP_DBL inv3EigthRootTab[THREEIGTHROOT_VALUES] = { + (0x45cae0f2), (0x45b981bf), (0x45a8492a), (0x45973691), (0x45864959), + (0x457580e6), (0x4564dca4), (0x45545c00), (0x4543fe6b), (0x4533c35a), + (0x4523aa44), (0x4513b2a4), (0x4503dbf7), (0x44f425be), (0x44e48f7b), + (0x44d518b6), (0x44c5c0f7), (0x44b687c8), (0x44a76cb8), (0x44986f58), + (0x44898f38), (0x447acbef), (0x446c2514), (0x445d9a3f), (0x444f2b0d), + (0x4440d71a), (0x44329e07), (0x44247f73), (0x44167b04), (0x4408905e), + (0x43fabf28), (0x43ed070b), (0x43df67b0), (0x43d1e0c5), (0x43c471f7), + (0x43b71af6), (0x43a9db71), (0x439cb31c), (0x438fa1ab), (0x4382a6d2), + (0x4375c248), (0x4368f3c5), (0x435c3b03), (0x434f97bc), (0x434309ac), + (0x43369091), (0x432a2c28), (0x431ddc30), (0x4311a06c), (0x4305789c), + (0x42f96483), (0x42ed63e5), (0x42e17688), (0x42d59c30), (0x42c9d4a6), + (0x42be1fb1), (0x42b27d1a), (0x42a6ecac), (0x429b6e2f), (0x42900172), + (0x4284a63f), (0x42795c64), (0x426e23b0), (0x4262fbf2), (0x4257e4f9), + (0x424cde96), (0x4241e89a), (0x423702d8), (0x422c2d23), (0x4221674d), + (0x4216b12c), (0x420c0a94), (0x4201735b), (0x41f6eb57), (0x41ec725f), + (0x41e2084b), (0x41d7acf3), (0x41cd6030), (0x41c321db), (0x41b8f1ce), + (0x41aecfe5), (0x41a4bbf8), (0x419ab5e6), (0x4190bd89), (0x4186d2bf), + (0x417cf565), (0x41732558), (0x41696277), (0x415faca1), (0x415603b4), + (0x414c6792), (0x4142d818), (0x4139552a), (0x412fdea6), (0x41267470), + (0x411d1668), (0x4113c472), (0x410a7e70), (0x41014445), (0x40f815d4), + (0x40eef302), (0x40e5dbb4), (0x40dccfcd), (0x40d3cf33), (0x40cad9cb), + (0x40c1ef7b), (0x40b9102a), (0x40b03bbd), (0x40a7721c), (0x409eb32e), + (0x4095feda), (0x408d5508), (0x4084b5a0), (0x407c208b), (0x407395b2), + (0x406b14fd), (0x40629e56), (0x405a31a6), (0x4051ced8), (0x404975d5), + (0x40412689), (0x4038e0dd), (0x4030a4bd), (0x40287215), (0x402048cf), + (0x401828d7), (0x4010121a), (0x40080483), (0x40000000), (0x3ff8047d), +}; + +/* The last value is rounded in order to avoid any overflow due to the values + * range of the root table */ +static const FIXP_DBL inv3EigthRootCorrection[8] = { + 0x40000000, 0x45CAE0F2, 0x4C1BF829, 0x52FF6B55, + 0x5A82799A, 0x62B39509, 0x6BA27E65, 0x75606373}; + +/* The 3/8 root function */ +/***************************************************************************** + * \brief calculate 1.0/3Eigth_root(op) = 1.0/(x)^(3/8), op contains mantissa + * and exponent + * \param op_m: (i) mantissa of operand, must not be zero (0x0000.0000) or + * negative + * \param op_e: (i) pointer to the exponent of the operand (must be initialized) + * and .. (o) pointer to the exponent of the result + * \return: (o) mantissa of the result + * \description: + * This routine calculates the cube root of the input operand, that is + * given with its mantissa in Q31 format (FIXP_DBL) and its exponent (INT). + * The resulting mantissa is returned in format Q31. The exponent (*op_e) + * is modified accordingly. It is not assured, that the result is fully + * left-aligned but assumed to have not more than 2 bits headroom. There is one + * macro to activate the use of this algorithm: FUNCTION_inv3EigthRootNorm2 By + * means of activating the macro INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ, a + * slightly higher precision is reachable (by default, not active). For DEBUG + * purpose only: a FDK_ASSERT macro validates, if the input mantissa is greater + * zero. + * + */ + +/* #define INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + +static +#ifdef __arm__ + FIXP_DBL FDK_FORCEINLINE + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#else + FIXP_DBL + inv3EigthRootNorm2(FIXP_DBL op_m, INT* op_e) +#endif +{ + FDK_ASSERT(op_m > FL2FXCONST_DBL(0.0)); + + /* normalize input, calculate shift op_mue */ + INT exponent = (INT)fNormz(op_m) - 1; + op_m <<= exponent; + + INT index = (INT)(op_m >> (DFRACT_BITS - 1 - (THREEIGTHROOT_BITS + 1))) & + THREEIGTHROOT_BITS_MASK; + FIXP_DBL fract = (FIXP_DBL)(((INT)op_m & THREEIGTHROOT_FRACT_BITS_MASK) + << (THREEIGTHROOT_BITS + 1)); + FIXP_DBL diff = inv3EigthRootTab[index + 1] - inv3EigthRootTab[index]; + op_m = inv3EigthRootTab[index] + (fMultDiv2(diff, fract) << 1); + +#if defined(INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ) + /* op_m = t[i] + (t[i+1]-t[i])*fract ... already computed ... + + * (1-fract)fract*(t[i+2]-t[i+1])/2 */ + if (fract != (FIXP_DBL)0) { + /* fract = fract * (1 - fract) */ + fract = fMultDiv2(fract, (FIXP_DBL)((LONG)0x80000000 - (LONG)fract)) << 1; + diff = diff - (inv3EigthRootTab[index + 2] - inv3EigthRootTab[index + 1]); + op_m = fMultAddDiv2(op_m, fract, diff); + } +#endif /* INVTHREEIGTHROOTNORM2_LINEAR_INTERPOLATE_HQ */ + + exponent = exponent - *op_e + 8; + INT rem = exponent & 0x00000007; + INT shift_tmp = (exponent >> 3); + + *op_e = shift_tmp * 3; + op_m = fMultDiv2(op_m, inv3EigthRootCorrection[rem]) << 2; + + return (fMult(op_m, fMult(op_m, op_m))); +} + +SBR_ERROR +QmfTransposerCreate(HANDLE_HBE_TRANSPOSER* hQmfTransposer, const int frameSize, + int bDisableCrossProducts, int bSbr41) { + HANDLE_HBE_TRANSPOSER hQmfTran = NULL; + + int i; + + if (hQmfTransposer != NULL) { + /* Memory allocation */ + /*--------------------------------------------------------------------------------------------*/ + hQmfTran = + (HANDLE_HBE_TRANSPOSER)FDKcalloc(1, sizeof(struct hbeTransposer)); + if (hQmfTran == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < MAX_STRETCH_HBE - 1; i++) { + hQmfTran->bXProducts[i] = (bDisableCrossProducts ? 0 : xProducts[i]); + } + + hQmfTran->timeDomainWinLen = frameSize; + if (frameSize == 768) { + hQmfTran->noCols = + (8 * frameSize / 3) / QMF_SYNTH_CHANNELS; /* 32 for 24:64 */ + } else { + hQmfTran->noCols = + (bSbr41 + 1) * 2 * frameSize / + QMF_SYNTH_CHANNELS; /* 32 for 32:64 and 64 for 16:64 -> identical to + sbrdec->no_cols */ + } + + hQmfTran->noChannels = frameSize / hQmfTran->noCols; + + hQmfTran->qmfInBufSize = QMF_WIN_LEN; + hQmfTran->qmfOutBufSize = 2 * (hQmfTran->noCols / 2 + QMF_WIN_LEN - 1); + + hQmfTran->inBuf_F = + (INT_PCM*)FDKcalloc(QMF_SYNTH_CHANNELS + 20 + 1, sizeof(INT_PCM)); + /* buffered time signal needs to be delayed by synthesis_size; max + * synthesis_size = 20; */ + if (hQmfTran->inBuf_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->qmfInBufReal_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + hQmfTran->qmfInBufImag_F = + (FIXP_DBL**)FDKcalloc(hQmfTran->qmfInBufSize, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfInBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < hQmfTran->qmfInBufSize; i++) { + hQmfTran->qmfInBufReal_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + hQmfTran->qmfInBufImag_F[i] = (FIXP_DBL*)FDKaalloc( + QMF_SYNTH_CHANNELS * sizeof(FIXP_DBL), ALIGNMENT_DEFAULT); + if (hQmfTran->qmfInBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfInBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfHBEBufReal_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + hQmfTran->qmfHBEBufImag_F = + (FIXP_DBL**)FDKcalloc(HBE_MAX_OUT_SLOTS, sizeof(FIXP_DBL*)); + + if (hQmfTran->qmfHBEBufReal_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + hQmfTran->qmfHBEBufReal_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + hQmfTran->qmfHBEBufImag_F[i] = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS, sizeof(FIXP_DBL)); + if (hQmfTran->qmfHBEBufReal_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + if (hQmfTran->qmfHBEBufImag_F[i] == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + } + + hQmfTran->qmfBufferCodecTempSlot_F = + (FIXP_DBL*)FDKcalloc(QMF_SYNTH_CHANNELS / 2, sizeof(FIXP_DBL)); + if (hQmfTran->qmfBufferCodecTempSlot_F == NULL) { + QmfTransposerClose(hQmfTran); + return SBRDEC_MEM_ALLOC_FAILED; + } + + hQmfTran->bSbr41 = bSbr41; + + hQmfTran->highband_exp[0] = 0; + hQmfTran->highband_exp[1] = 0; + hQmfTran->target_exp[0] = 0; + hQmfTran->target_exp[1] = 0; + + *hQmfTransposer = hQmfTran; + } + + return SBRDEC_OK; +} + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR* FreqBandTable[2], UCHAR NSfb[2]) +/* removed bSbr41 from parameterlist: + don't know where to get this value from + at call-side */ +{ + int L, sfb, patch, stopPatch, qmfErr; + + if (hQmfTransposer != NULL) { + const FIXP_QTW* tmp_t_cos; + const FIXP_QTW* tmp_t_sin; + + hQmfTransposer->startBand = FreqBandTable[0][0]; + FDK_ASSERT((!hQmfTransposer->bSbr41 && hQmfTransposer->startBand <= 32) || + (hQmfTransposer->bSbr41 && + hQmfTransposer->startBand <= + 16)); /* is checked by resetFreqBandTables() */ + hQmfTransposer->stopBand = FreqBandTable[0][NSfb[0]]; + + hQmfTransposer->synthSize = + 4 * ((hQmfTransposer->startBand + 4) / 8 + 1); /* 8, 12, 16, 20 */ + hQmfTransposer->kstart = startSubband2kL[hQmfTransposer->startBand]; + + /* don't know where to take this information from */ + /* hQmfTransposer->bSbr41 = bSbr41; */ + + if (hQmfTransposer->bSbr41) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 16) + hQmfTransposer->kstart = 16 - hQmfTransposer->synthSize; + } else if (hQmfTransposer->timeDomainWinLen == 768) { + if (hQmfTransposer->kstart + hQmfTransposer->synthSize > 24) + hQmfTransposer->kstart = 24 - hQmfTransposer->synthSize; + } + + hQmfTransposer->synthesisQmfPreModCos_F = + &preModCos[hQmfTransposer->kstart]; + hQmfTransposer->synthesisQmfPreModSin_F = + &preModSin[hQmfTransposer->kstart]; + + L = 2 * hQmfTransposer->synthSize; /* 8, 16, 24, 32, 40 */ + /* Change analysis post twiddles */ + + switch (L) { + case 8: + tmp_t_cos = post_twiddle_cos_8; + tmp_t_sin = post_twiddle_sin_8; + break; + case 16: + tmp_t_cos = post_twiddle_cos_16; + tmp_t_sin = post_twiddle_sin_16; + break; + case 24: + tmp_t_cos = post_twiddle_cos_24; + tmp_t_sin = post_twiddle_sin_24; + break; + case 32: + tmp_t_cos = post_twiddle_cos_32; + tmp_t_sin = post_twiddle_sin_32; + break; + case 40: + tmp_t_cos = post_twiddle_cos_40; + tmp_t_sin = post_twiddle_sin_40; + break; + default: + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitSynthesisFilterBank( + &hQmfTransposer->HBESynthesisQMF, hQmfTransposer->synQmfStates, + hQmfTransposer->noCols, 0, hQmfTransposer->synthSize, + hQmfTransposer->synthSize, 1); + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + qmfErr = qmfInitAnalysisFilterBank( + &hQmfTransposer->HBEAnalysiscQMF, hQmfTransposer->anaQmfStates, + hQmfTransposer->noCols / 2, 0, 2 * hQmfTransposer->synthSize, + 2 * hQmfTransposer->synthSize, 0); + + if (qmfErr != 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + hQmfTransposer->HBEAnalysiscQMF.t_cos = tmp_t_cos; + hQmfTransposer->HBEAnalysiscQMF.t_sin = tmp_t_sin; + + FDKmemset(hQmfTransposer->xOverQmf, 0, + MAX_NUM_PATCHES * sizeof(int)); /* global */ + sfb = 0; + if (hQmfTransposer->bSbr41) { + stopPatch = MAX_NUM_PATCHES; + hQmfTransposer->maxStretch = MAX_STRETCH_HBE; + } else { + stopPatch = MAX_STRETCH_HBE; + } + + for (patch = 1; patch <= stopPatch; patch++) { + while (sfb <= NSfb[0] && + FreqBandTable[0][sfb] <= patch * hQmfTransposer->startBand) + sfb++; + if (sfb <= NSfb[0]) { + /* If the distance is larger than three QMF bands - try aligning to high + * resolution frequency bands instead. */ + if ((patch * hQmfTransposer->startBand - FreqBandTable[0][sfb - 1]) <= + 3) { + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[0][sfb - 1]; + } else { + int sfb_tmp = 0; + while (sfb_tmp <= NSfb[1] && + FreqBandTable[1][sfb_tmp] <= patch * hQmfTransposer->startBand) + sfb_tmp++; + hQmfTransposer->xOverQmf[patch - 1] = FreqBandTable[1][sfb_tmp - 1]; + } + } else { + hQmfTransposer->xOverQmf[patch - 1] = hQmfTransposer->stopBand; + hQmfTransposer->maxStretch = fMin(patch, MAX_STRETCH_HBE); + break; + } + } + + hQmfTransposer->highband_exp[0] = 0; + hQmfTransposer->highband_exp[1] = 0; + hQmfTransposer->target_exp[0] = 0; + hQmfTransposer->target_exp[1] = 0; + } + + return SBRDEC_OK; +} + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + int i; + + if (hQmfTransposer != NULL) { + if (hQmfTransposer->inBuf_F) FDKfree(hQmfTransposer->inBuf_F); + + if (hQmfTransposer->qmfInBufReal_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufReal_F); + } + + if (hQmfTransposer->qmfInBufImag_F) { + for (i = 0; i < hQmfTransposer->qmfInBufSize; i++) { + FDKafree(hQmfTransposer->qmfInBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfInBufImag_F); + } + + if (hQmfTransposer->qmfHBEBufReal_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufReal_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufReal_F); + } + + if (hQmfTransposer->qmfHBEBufImag_F) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + FDKfree(hQmfTransposer->qmfHBEBufImag_F[i]); + } + FDKfree(hQmfTransposer->qmfHBEBufImag_F); + } + + FDKfree(hQmfTransposer->qmfBufferCodecTempSlot_F); + + FDKfree(hQmfTransposer); + } +} + +inline void scaleUp(FIXP_DBL* real_m, FIXP_DBL* imag_m, INT* _e) { + INT reserve; + /* shift gc_r and gc_i up if possible */ + reserve = CntLeadingZeros((INT(*real_m) ^ INT((*real_m >> 31))) | + (INT(*imag_m) ^ INT((*imag_m >> 31)))) - + 1; + reserve = fMax(reserve - 1, + 0); /* Leave one bit headroom such that (real_m^2 + imag_m^2) + does not overflow later if both are 0x80000000. */ + reserve = fMin(reserve, *_e); + FDK_ASSERT(reserve >= 0); + *real_m <<= reserve; + *imag_m <<= reserve; + *_e -= reserve; +} + +static void calculateCenterFIXP(FIXP_DBL gammaVecReal, FIXP_DBL gammaVecImag, + FIXP_DBL* centerReal, FIXP_DBL* centerImag, + INT* exponent, int stretch, int mult) { + scaleUp(&gammaVecReal, &gammaVecImag, exponent); + FIXP_DBL energy = fPow2Div2(gammaVecReal) + fPow2Div2(gammaVecImag); + + if (energy != FL2FXCONST_DBL(0.f)) { + FIXP_DBL gc_r_m, gc_i_m, factor_m = (FIXP_DBL)0; + INT factor_e, gc_e; + factor_e = 2 * (*exponent) + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + gc_r_m = fMultDiv2(gammaVecReal, + factor_m); /* exponent = HBE_SCALE + factor_e + 1 */ + gc_i_m = fMultDiv2(gammaVecImag, + factor_m); /* exponent = HBE_SCALE + factor_e + 1*/ + gc_e = *exponent + factor_e + 1; + + scaleUp(&gc_r_m, &gc_i_m, &gc_e); + + switch (mult) { + case 0: + *centerReal = gc_r_m; + *centerImag = gc_i_m; + break; + case 1: + *centerReal = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + *centerImag = fMult(gc_r_m, gc_i_m); + gc_e = 2 * gc_e + 1; + break; + case 2: + FIXP_DBL tmp_r = gc_r_m; + FIXP_DBL tmp_i = gc_i_m; + gc_r_m = fPow2Div2(gc_r_m) - fPow2Div2(gc_i_m); + gc_i_m = fMult(tmp_r, gc_i_m); + gc_e = 3 * gc_e + 1 + 1; + cplxMultDiv2(¢erReal[0], ¢erImag[0], gc_r_m, gc_i_m, tmp_r, + tmp_i); + break; + } + + scaleUp(centerReal, centerImag, &gc_e); + + FDK_ASSERT(gc_e >= 0); + *exponent = gc_e; + } else { + *centerReal = energy; /* energy = 0 */ + *centerImag = energy; /* energy = 0 */ + *exponent = (INT)energy; + } +} + +static int getHBEScaleFactorFrame(const int bSbr41, const int maxStretch, + const int pitchInBins) { + if (pitchInBins >= pmin * (1 + bSbr41)) { + /* crossproducts enabled */ + return 26; + } else { + return (maxStretch == 2) ? 24 : 25; + } +} + +static void addHighBandPart(FIXP_DBL g_r_m, FIXP_DBL g_i_m, INT g_e, + FIXP_DBL mult, FIXP_DBL gammaCenterReal_m, + FIXP_DBL gammaCenterImag_m, INT gammaCenter_e, + INT stretch, INT scale_factor_hbe, + FIXP_DBL* qmfHBEBufReal_F, + FIXP_DBL* qmfHBEBufImag_F) { + if ((g_r_m | g_i_m) != FL2FXCONST_DBL(0.f)) { + FIXP_DBL factor_m = (FIXP_DBL)0; + INT factor_e; + INT add = (stretch == 4) ? 1 : 0; + INT shift = (stretch == 4) ? 1 : 2; + + scaleUp(&g_r_m, &g_i_m, &g_e); + FIXP_DBL energy = fPow2AddDiv2(fPow2Div2(g_r_m), g_i_m); + factor_e = 2 * g_e + 1; + + switch (stretch) { + case 2: + factor_m = invFourthRootNorm2(energy, &factor_e); + break; + case 3: + factor_m = invCubeRootNorm2(energy, &factor_e); + break; + case 4: + factor_m = inv3EigthRootNorm2(energy, &factor_e); + break; + } + + factor_m = fMult(factor_m, mult); + + FIXP_DBL tmp_r, tmp_i; + cplxMultDiv2(&tmp_r, &tmp_i, g_r_m, g_i_m, gammaCenterReal_m, + gammaCenterImag_m); + + g_r_m = fMultDiv2(tmp_r, factor_m) << shift; + g_i_m = fMultDiv2(tmp_i, factor_m) << shift; + g_e = scale_factor_hbe - (g_e + factor_e + gammaCenter_e + add); + fMax((INT)0, g_e); + *qmfHBEBufReal_F += g_r_m >> g_e; + *qmfHBEBufImag_F += g_i_m >> g_e; + } +} + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL** qmfBufferCodecReal, + FIXP_DBL** qmfBufferCodecImag, int nColsIn, + FIXP_DBL** ppQmfBufferOutReal_F, + FIXP_DBL** ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int* scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode) { + int i, j, stretch, band, sourceband, r, s; + int qmfVocoderColsIn = hQmfTransposer->noCols / 2; + int bSbr41 = hQmfTransposer->bSbr41; + + const int winLength[3] = {10, 8, 6}; + const int slotOffset = 6; /* hQmfTransposer->winLen-6; */ + + int qmfOffset = 2 * hQmfTransposer->kstart; + int scale_border = (nColsIn == 64) ? 32 : nColsIn; + + INT slot_stretch4[9] = {0, 0, 0, 0, 2, 4, 6, 8, 10}; + INT slot_stretch2[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + INT slot_stretch3[10] = {0, 0, 0, 1, 3, 4, 6, 7, 9, 10}; + INT filt_stretch3[10] = {0, 0, 0, 1, 0, 1, 0, 1, 0, 1}; + INT filt_dummy[11] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + INT* pSlotStretch; + INT* pFilt; + + int offset = 0; /* where to take QmfTransposer data */ + + int signPreMod = + (hQmfTransposer->synthesisQmfPreModCos_F[0] < FL2FXCONST_DBL(0.f)) ? 1 + : -1; + + int scale_factor_hbe = + getHBEScaleFactorFrame(bSbr41, hQmfTransposer->maxStretch, pitchInBins); + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_OFF) { + offset = hQmfTransposer->noCols - ov_len - LPC_ORDER; + } + + hQmfTransposer->highband_exp[0] = hQmfTransposer->highband_exp[1]; + hQmfTransposer->target_exp[0] = hQmfTransposer->target_exp[1]; + + hQmfTransposer->highband_exp[1] = scale_factor_hbe; + hQmfTransposer->target_exp[1] = + fixMax(hQmfTransposer->highband_exp[1], hQmfTransposer->highband_exp[0]); + + scale_factor_hbe = hQmfTransposer->target_exp[1]; + + int shift_ov = hQmfTransposer->target_exp[0] - hQmfTransposer->target_exp[1]; + + if (shift_ov != 0) { + for (i = 0; i < HBE_MAX_OUT_SLOTS; i++) { + for (band = 0; band < QMF_SYNTH_CHANNELS; band++) { + if (shift_ov >= 0) { + hQmfTransposer->qmfHBEBufReal_F[i][band] <<= shift_ov; + hQmfTransposer->qmfHBEBufImag_F[i][band] <<= shift_ov; + } else { + hQmfTransposer->qmfHBEBufReal_F[i][band] >>= (-shift_ov); + hQmfTransposer->qmfHBEBufImag_F[i][band] >>= (-shift_ov); + } + } + } + } + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_OFF) && shift_ov != 0) { + for (i = timeStep * firstSlotOffsset; i < ov_len; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + if (shift_ov >= 0) { + ppQmfBufferOutReal_F[i][band] <<= shift_ov; + ppQmfBufferOutImag_F[i][band] <<= shift_ov; + } else { + ppQmfBufferOutReal_F[i][band] >>= (-shift_ov); + ppQmfBufferOutImag_F[i][band] >>= (-shift_ov); + } + } + } + + /* shift lpc filterstates */ + for (i = 0; i < timeStep * firstSlotOffsset + LPC_ORDER; i++) { + for (band = 0; band < (64); band++) { + if (shift_ov >= 0) { + lpcFilterStatesReal[i][band] <<= shift_ov; + lpcFilterStatesImag[i][band] <<= shift_ov; + } else { + lpcFilterStatesReal[i][band] >>= (-shift_ov); + lpcFilterStatesImag[i][band] >>= (-shift_ov); + } + } + } + } + + FIXP_DBL twid_m_new[3][2]; /* [stretch][cos/sin] */ + INT stepsize = 1 + !bSbr41, sine_offset = 24, mod = 96; + INT mult[3] = {1, 2, 3}; + + for (s = 0; s <= MAX_STRETCH_HBE - 2; s++) { + twid_m_new[s][0] = twiddle[(mult[s] * (stepsize * pitchInBins)) % mod]; + twid_m_new[s][1] = + twiddle[((mult[s] * (stepsize * pitchInBins)) + sine_offset) % mod]; + } + + /* Time-stretch */ + for (j = 0; j < qmfVocoderColsIn; j++) { + int sign = -1, k, z, addrshift, codecTemp_e; + /* update inbuf */ + for (i = 0; i < hQmfTransposer->synthSize; i++) { + hQmfTransposer->inBuf_F[i] = + hQmfTransposer->inBuf_F[i + 2 * hQmfTransposer->synthSize]; + } + + /* run synthesis for two sbr slots as transposer uses + half slots double bands representation */ + for (z = 0; z < 2; z++) { + int scale_factor = ((nColsIn == 64) && ((2 * j + z) < scale_border)) + ? scale_lb + : scale_hbe; + codecTemp_e = scale_factor - 1; /* -2 for Div2 and cos/sin scale of 1 */ + + for (k = 0; k < hQmfTransposer->synthSize; k++) { + int ki = hQmfTransposer->kstart + k; + hQmfTransposer->qmfBufferCodecTempSlot_F[k] = + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModCos_F[k], + qmfBufferCodecReal[2 * j + z][ki]); + hQmfTransposer->qmfBufferCodecTempSlot_F[k] += + fMultDiv2(signPreMod * hQmfTransposer->synthesisQmfPreModSin_F[k], + qmfBufferCodecImag[2 * j + z][ki]); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfSynthesisFilteringSlot( + &hQmfTransposer->HBESynthesisQMF, + hQmfTransposer->qmfBufferCodecTempSlot_F, NULL, 0, + -7 - hQmfTransposer->HBESynthesisQMF.filterScale - codecTemp_e + 1, + hQmfTransposer->inBuf_F + hQmfTransposer->synthSize * (z + 1), 1, + pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + } + + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + qmfAnalysisFilteringSlot(&hQmfTransposer->HBEAnalysiscQMF, + hQmfTransposer->qmfInBufReal_F[QMF_WIN_LEN - 1], + hQmfTransposer->qmfInBufImag_F[QMF_WIN_LEN - 1], + hQmfTransposer->inBuf_F + 1, 1, pWorkBuffer); + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, (HBE_MAX_QMF_BANDS << 1)); + + if ((keepStatesSyncedMode == KEEP_STATES_SYNCED_NORMAL) && + j <= qmfVocoderColsIn - ((LPC_ORDER + ov_len + QMF_WIN_LEN - 1) >> 1)) { + /* update in buffer */ + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy( + hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy( + hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + continue; + } + + for (stretch = 2; stretch <= hQmfTransposer->maxStretch; stretch++) { + int start = slotOffset - winLength[stretch - 2] / 2; + int stop = slotOffset + winLength[stretch - 2] / 2; + + FIXP_DBL factor = FL2FXCONST_DBL(1.f / 3.f); + + for (band = hQmfTransposer->xOverQmf[stretch - 2]; + band < hQmfTransposer->xOverQmf[stretch - 1]; band++) { + FIXP_DBL gammaCenterReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaCenterImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaCenter_e[2] = {0, 0}; + + FIXP_DBL gammaVecReal_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}, + gammaVecImag_m[2] = {(FIXP_DBL)0, (FIXP_DBL)0}; + INT gammaVec_e[2] = {0, 0}; + + FIXP_DBL wingain = (FIXP_DBL)0; + + gammaCenter_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaCenter_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + /* interpolation filters for 3rd order */ + sourceband = 2 * band / stretch - qmfOffset; + FDK_ASSERT(sourceband >= 0); + + /* maximum gammaCenter_e == 20 */ + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], &gammaCenter_e[0], + stretch, stretch - 2); + + if (stretch == 4) { + r = band - 2 * (band / 2); + sourceband += (r == 0) ? -1 : 1; + pSlotStretch = slot_stretch4; + factor = FL2FXCONST_DBL(2.f / 3.f); + pFilt = filt_dummy; + } else if (stretch == 2) { + r = 0; + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch2; + factor = FL2FXCONST_DBL(1.f / 3.f); + pFilt = filt_dummy; + } else { + r = 2 * band - 3 * (2 * band / 3); + sourceband = 2 * band / stretch - qmfOffset; + pSlotStretch = slot_stretch3; + factor = FL2FXCONST_DBL(1.4142f / 3.0f); + pFilt = filt_stretch3; + } + + if (r == 2) { + calculateCenterFIXP( + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband + 1], + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband + 1], + &gammaCenterReal_m[1], &gammaCenterImag_m[1], &gammaCenter_e[1], + stretch, stretch - 2); + + factor = FL2FXCONST_DBL(1.4142f / 6.0f); + } + + if (r == 2) { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband + 1]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband + 1]; + gammaVec_e[0] = gammaVec_e[1] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + + tmpRealF = gammaVecReal_m[1]; + + gammaVecReal_m[1] = + (fMult(gammaVecReal_m[1], hintReal_F[sourceband % 4][2]) - + fMult(gammaVecImag_m[1], + hintReal_F[(sourceband + 3) % 4][2])) >> + 1; + gammaVecImag_m[1] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][2]) + + fMult(gammaVecImag_m[1], hintReal_F[sourceband % 4][2])) >> + 1; + + tmpRealF = + hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband + 1]; + tmpImagF = + hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband + 1]; + + gammaVecReal_m[1] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][2]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][2])) >> + 1; + gammaVecImag_m[1] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][2]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][2])) >> + 1; + gammaVec_e[1]++; + } + + addHighBandPart(gammaVecReal_m[1], gammaVecImag_m[1], gammaVec_e[1], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[1], gammaCenterImag_m[1], + gammaCenter_e[1], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } else { + for (k = start; k < stop; k++) { + gammaVecReal_m[0] = + hQmfTransposer->qmfInBufReal_F[pSlotStretch[k]][sourceband]; + gammaVecImag_m[0] = + hQmfTransposer->qmfInBufImag_F[pSlotStretch[k]][sourceband]; + gammaVec_e[0] = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + if (pFilt[k] == 1) { + FIXP_DBL tmpRealF = gammaVecReal_m[0], tmpImagF; + gammaVecReal_m[0] = + (fMult(gammaVecReal_m[0], hintReal_F[sourceband % 4][1]) - + fMult(gammaVecImag_m[0], + hintReal_F[(sourceband + 3) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] = + (fMult(tmpRealF, hintReal_F[(sourceband + 3) % 4][1]) + + fMult(gammaVecImag_m[0], hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + + tmpRealF = hQmfTransposer + ->qmfInBufReal_F[pSlotStretch[k] + 1][sourceband]; + tmpImagF = hQmfTransposer + ->qmfInBufImag_F[pSlotStretch[k] + 1][sourceband]; + + gammaVecReal_m[0] += + (fMult(tmpRealF, hintReal_F[sourceband % 4][1]) - + fMult(tmpImagF, hintReal_F[(sourceband + 1) % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVecImag_m[0] += + (fMult(tmpRealF, hintReal_F[(sourceband + 1) % 4][1]) + + fMult(tmpImagF, hintReal_F[sourceband % 4][1])) >> + 1; /* sum should be <= 1 because of sin/cos multiplication */ + gammaVec_e[0]++; + } + + addHighBandPart(gammaVecReal_m[0], gammaVecImag_m[0], gammaVec_e[0], + factor, gammaCenterReal_m[0], gammaCenterImag_m[0], + gammaCenter_e[0], stretch, scale_factor_hbe, + &hQmfTransposer->qmfHBEBufReal_F[k][band], + &hQmfTransposer->qmfHBEBufImag_F[k][band]); + } + } + + /* pitchInBins is given with the resolution of a 768 bins FFT and we + * need 64 QMF units so factor 768/64 = 12 */ + if (pitchInBins >= pmin * (1 + bSbr41)) { + int tr, ti1, ti2, mTr = 0, ts1 = 0, ts2 = 0, mVal_e = 0, temp_e = 0; + int sqmag0_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL mVal_F = FL2FXCONST_DBL(0.f), sqmag0_F, sqmag1_F, sqmag2_F, + temp_F, f1_F; /* all equal exponent */ + sign = -1; + + sourceband = 2 * band / stretch - qmfOffset; /* consistent with the + already computed for + stretch = 3,4. */ + FDK_ASSERT(sourceband >= 0); + + FIXP_DBL sqmag0R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][sourceband]; + FIXP_DBL sqmag0I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][sourceband]; + scaleUp(&sqmag0R_F, &sqmag0I_F, &sqmag0_e); + + sqmag0_F = fPow2Div2(sqmag0R_F); + sqmag0_F += fPow2Div2(sqmag0I_F); + sqmag0_e = 2 * sqmag0_e + 1; + + for (tr = 1; tr < stretch; tr++) { + int sqmag1_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + int sqmag2_e = + SCALE2EXP(-hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + + FIXP_DBL tmp_band = band_F[band]; + FIXP_DBL tr_p = + fMult(p_F[pitchInBins] >> bSbr41, tr_str[tr - 1]); /* scale 7 */ + f1_F = + fMult(tmp_band - tr_p, stretchfac[stretch - 2]); /* scale 7 */ + ti1 = (INT)(f1_F >> (DFRACT_BITS - 1 - 7)) - qmfOffset; + ti2 = (INT)(((f1_F) + ((p_F[pitchInBins] >> bSbr41) >> 2)) >> + (DFRACT_BITS - 1 - 7)) - + qmfOffset; + + if (ti1 >= 0 && ti2 < 2 * hQmfTransposer->synthSize) { + FIXP_DBL sqmag1R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti1]; + FIXP_DBL sqmag1I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti1]; + scaleUp(&sqmag1R_F, &sqmag1I_F, &sqmag1_e); + sqmag1_F = fPow2Div2(sqmag1R_F); + sqmag1_F += fPow2Div2(sqmag1I_F); + sqmag1_e = 2 * sqmag1_e + 1; + + FIXP_DBL sqmag2R_F = + hQmfTransposer->qmfInBufReal_F[slotOffset][ti2]; + FIXP_DBL sqmag2I_F = + hQmfTransposer->qmfInBufImag_F[slotOffset][ti2]; + scaleUp(&sqmag2R_F, &sqmag2I_F, &sqmag2_e); + sqmag2_F = fPow2Div2(sqmag2R_F); + sqmag2_F += fPow2Div2(sqmag2I_F); + sqmag2_e = 2 * sqmag2_e + 1; + + int shift1 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag1_e, 31); + int shift2 = fMin(fMax(sqmag1_e, sqmag2_e) - sqmag2_e, 31); + + temp_F = fMin((sqmag1_F >> shift1), (sqmag2_F >> shift2)); + temp_e = fMax(sqmag1_e, sqmag2_e); + + int shift3 = fMin(fMax(temp_e, mVal_e) - temp_e, 31); + int shift4 = fMin(fMax(temp_e, mVal_e) - mVal_e, 31); + + if ((temp_F >> shift3) > (mVal_F >> shift4)) { + mVal_F = temp_F; + mVal_e = temp_e; /* equals sqmag2_e + shift2 */ + mTr = tr; + ts1 = ti1; + ts2 = ti2; + } + } + } + + int shift1 = fMin(fMax(sqmag0_e, mVal_e) - sqmag0_e, 31); + int shift2 = fMin(fMax(sqmag0_e, mVal_e) - mVal_e, 31); + + if ((mVal_F >> shift2) > (sqmag0_F >> shift1) && ts1 >= 0 && + ts2 < 2 * hQmfTransposer->synthSize) { + INT gammaOut_e[2]; + FIXP_DBL gammaOutReal_m[2], gammaOutImag_m[2]; + FIXP_DBL tmpReal_m = (FIXP_DBL)0, tmpImag_m = (FIXP_DBL)0; + + int Tcenter, Tvec; + + Tcenter = stretch - mTr; /* default phase power parameters */ + Tvec = mTr; + switch (stretch) /* 2 tap block creation design depends on stretch + order */ + { + case 2: + wingain = + FL2FXCONST_DBL(5.f / 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[0]) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer->qmfInBufReal_F[slotOffset - 1 + k][ts2]; + gammaVecImag_m[k] = + hQmfTransposer->qmfInBufImag_F[slotOffset - 1 + k][ts2]; + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 4: + wingain = + FL2FXCONST_DBL(6.f / 12.f); /* sum of taps divided by two */ + if (hQmfTransposer->bXProducts[2]) { + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts2]; + } + } else if (mTr == 2) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + (k - 1)][ts2]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + (k - 1)][ts2]; + } + } else /* (mTr == 3) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + for (k = 0; k < 2; k++) { + gammaVecReal_m[k] = + hQmfTransposer + ->qmfInBufReal_F[slotOffset + 2 * (k - 1)][ts1]; + gammaVecImag_m[k] = + hQmfTransposer + ->qmfInBufImag_F[slotOffset + 2 * (k - 1)][ts1]; + } + } + + gammaCenter_e[0] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + } + break; + + case 3: + wingain = FL2FXCONST_DBL(5.6568f / + 12.f); /* sum of taps divided by two */ + + if (hQmfTransposer->bXProducts[1]) { + FIXP_DBL tmpReal_F, tmpImag_F; + if (mTr == 1) { + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts2]; + + gammaVecReal_m[0] = + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts2 + 3) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts2]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts2]; + + gammaVecReal_m[0] += + (fMult(factors[ts2 % 4], tmpReal_F) - + fMult(factors[(ts2 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts2 + 1) % 4], tmpReal_F) + + fMult(factors[ts2 % 4], tmpImag_F)) >> + 1; + + } else /* (mTr == 2) */ + { + sign = 1; + Tcenter = mTr; /* opposite phase power parameters as ts2 is + center */ + Tvec = stretch - mTr; + + gammaCenterReal_m[0] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts2]; + gammaCenterImag_m[0] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts2]; + gammaVecReal_m[1] = + hQmfTransposer->qmfInBufReal_F[slotOffset][ts1]; + gammaVecImag_m[1] = + hQmfTransposer->qmfInBufImag_F[slotOffset][ts1]; + + addrshift = -2; + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + slotOffset][ts1]; + + gammaVecReal_m[0] = + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 3) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] = + (fMult(factors[(ts1 + 3) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + + tmpReal_F = + hQmfTransposer + ->qmfInBufReal_F[addrshift + 1 + slotOffset][ts1]; + tmpImag_F = + hQmfTransposer + ->qmfInBufImag_F[addrshift + 1 + slotOffset][ts1]; + + gammaVecReal_m[0] += + (fMult(factors[ts1 % 4], tmpReal_F) - + fMult(factors[(ts1 + 1) % 4], tmpImag_F)) >> + 1; + gammaVecImag_m[0] += + (fMult(factors[(ts1 + 1) % 4], tmpReal_F) + + fMult(factors[ts1 % 4], tmpImag_F)) >> + 1; + } + + gammaCenter_e[0] = gammaVec_e[1] = SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor); + gammaVec_e[0] = + SCALE2EXP( + -hQmfTransposer->HBEAnalysiscQMF.outScalefactor) + + 1; + } + break; + default: + FDK_ASSERT(0); + break; + } /* stretch cases */ + + /* parameter controlled phase modification parts */ + /* maximum *_e == 20 */ + calculateCenterFIXP(gammaCenterReal_m[0], gammaCenterImag_m[0], + &gammaCenterReal_m[0], &gammaCenterImag_m[0], + &gammaCenter_e[0], stretch, Tcenter - 1); + calculateCenterFIXP(gammaVecReal_m[0], gammaVecImag_m[0], + &gammaVecReal_m[0], &gammaVecImag_m[0], + &gammaVec_e[0], stretch, Tvec - 1); + calculateCenterFIXP(gammaVecReal_m[1], gammaVecImag_m[1], + &gammaVecReal_m[1], &gammaVecImag_m[1], + &gammaVec_e[1], stretch, Tvec - 1); + + /* Final multiplication of prepared parts */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterReal_m[0]) - + fMultDiv2(gammaVecImag_m[k], gammaCenterImag_m[0]); + gammaOutImag_m[k] = + fMultDiv2(gammaVecReal_m[k], gammaCenterImag_m[0]) + + fMultDiv2(gammaVecImag_m[k], gammaCenterReal_m[0]); + gammaOut_e[k] = gammaCenter_e[0] + gammaVec_e[k] + 1; + } + + scaleUp(&gammaOutReal_m[0], &gammaOutImag_m[0], &gammaOut_e[0]); + scaleUp(&gammaOutReal_m[1], &gammaOutImag_m[1], &gammaOut_e[1]); + FDK_ASSERT(gammaOut_e[0] >= 0); + FDK_ASSERT(gammaOut_e[0] < 32); + + tmpReal_m = gammaOutReal_m[0]; + tmpImag_m = gammaOutImag_m[0]; + + INT modstretch4 = ((stretch == 4) && (mTr == 2)); + + FIXP_DBL cos_twid = twid_m_new[stretch - 2 - modstretch4][0]; + FIXP_DBL sin_twid = sign * twid_m_new[stretch - 2 - modstretch4][1]; + + gammaOutReal_m[0] = + fMult(tmpReal_m, cos_twid) - + fMult(tmpImag_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + gammaOutImag_m[0] = + fMult(tmpImag_m, cos_twid) + + fMult(tmpReal_m, sin_twid); /* sum should be <= 1 because of + sin/cos multiplication */ + + /* wingain */ + for (k = 0; k < 2; k++) { + gammaOutReal_m[k] = (fMult(gammaOutReal_m[k], wingain) << 1); + gammaOutImag_m[k] = (fMult(gammaOutImag_m[k], wingain) << 1); + } + + gammaOutReal_m[1] >>= 1; + gammaOutImag_m[1] >>= 1; + gammaOut_e[0] += 2; + gammaOut_e[1] += 2; + + /* OLA including window scaling by wingain/3 */ + for (k = 0; k < 2; k++) /* need k=1 to correspond to + grainModImag[slotOffset] -> out to + j*2+(slotOffset-offset) */ + { + hQmfTransposer->qmfHBEBufReal_F[(k + slotOffset - 1)][band] += + gammaOutReal_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + hQmfTransposer->qmfHBEBufImag_F[(k + slotOffset - 1)][band] += + gammaOutImag_m[k] >> (scale_factor_hbe - gammaOut_e[k]); + } + } /* mVal > qThrQMF * qThrQMF * sqmag0 && ts1 > 0 && ts2 < 64 */ + } /* p >= pmin */ + } /* for band */ + } /* for stretch */ + + for (i = 0; i < QMF_WIN_LEN - 1; i++) { + FDKmemcpy(hQmfTransposer->qmfInBufReal_F[i], + hQmfTransposer->qmfInBufReal_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + FDKmemcpy(hQmfTransposer->qmfInBufImag_F[i], + hQmfTransposer->qmfInBufImag_F[i + 1], + sizeof(FIXP_DBL) * hQmfTransposer->HBEAnalysiscQMF.no_channels); + } + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (2 * j >= offset) { + /* copy first two slots of internal buffer to output */ + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j - offset + i] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } else { + for (i = 0; i < 2; i++) { + FDKmemcpy(&ppQmfBufferOutReal_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy(&ppQmfBufferOutImag_F[2 * j + i + ov_len] + [hQmfTransposer->xOverQmf[0]], + &hQmfTransposer + ->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } + } + } + + /* move slots up */ + for (i = 0; i < HBE_MAX_OUT_SLOTS - 2; i++) { + FDKmemcpy( + &hQmfTransposer->qmfHBEBufReal_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufReal_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemcpy( + &hQmfTransposer->qmfHBEBufImag_F[i][hQmfTransposer->xOverQmf[0]], + &hQmfTransposer->qmfHBEBufImag_F[i + 2][hQmfTransposer->xOverQmf[0]], + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + + /* finally set last two slot to zero */ + for (i = 0; i < 2; i++) { + FDKmemset(&hQmfTransposer->qmfHBEBufReal_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + FDKmemset(&hQmfTransposer->qmfHBEBufImag_F[HBE_MAX_OUT_SLOTS - 1 - i] + [hQmfTransposer->xOverQmf[0]], + 0, + (QMF_SYNTH_CHANNELS - hQmfTransposer->xOverQmf[0]) * + sizeof(FIXP_DBL)); + } + } /* qmfVocoderColsIn */ + + if (keepStatesSyncedMode != KEEP_STATES_SYNCED_NOOUT) { + if (keepStatesSyncedMode == KEEP_STATES_SYNCED_OUTDIFF) { + for (i = 0; i < ov_len + LPC_ORDER; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i][band]; + + ppQmfBufferOutReal_F[i][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } else { + for (i = offset; i < hQmfTransposer->noCols; i++) { + for (band = hQmfTransposer->startBand; band < hQmfTransposer->stopBand; + band++) { + FIXP_DBL tmpR = ppQmfBufferOutReal_F[i + ov_len][band]; + FIXP_DBL tmpI = ppQmfBufferOutImag_F[i + ov_len][band]; + + ppQmfBufferOutReal_F[i + ov_len][band] = + fMult(tmpR, cos_F[band]) - + fMult(tmpI, (-cos_F[64 - band - 1])); /* sum should be <= 1 + because of sin/cos + multiplication */ + ppQmfBufferOutImag_F[i + ov_len][band] = + fMult(tmpR, (-cos_F[64 - band - 1])) + + fMult(tmpI, cos_F[band]); /* sum should by <= 1 because of sin/cos + multiplication */ + } + } + } + } + + *scale_hb = EXP2SCALE(scale_factor_hbe); +} + +int* GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer) + return hQmfTransposer->xOverQmf; + else + return NULL; +} + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer) { + if (hQmfTransposer != NULL) + return hQmfTransposer->bSbr41; + else + return 0; +} diff --git a/fdk-aac/libSBRdec/src/hbe.h b/fdk-aac/libSBRdec/src/hbe.h new file mode 100644 index 0000000..fdffe1e --- /dev/null +++ b/fdk-aac/libSBRdec/src/hbe.h @@ -0,0 +1,200 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef HBE_H +#define HBE_H + +#include "sbrdecoder.h" + +#ifndef QMF_SYNTH_CHANNELS +#define QMF_SYNTH_CHANNELS (64) +#endif + +#define HBE_QMF_FILTER_STATE_ANA_SIZE (400) +#define HBE_QMF_FILTER_STATE_SYN_SIZE (200) + +#ifndef MAX_NUM_PATCHES_HBE +#define MAX_NUM_PATCHES_HBE (6) +#endif +#define MAX_STRETCH_HBE (4) + +typedef enum { + KEEP_STATES_SYNCED_OFF = 0, /*!< normal QMF transposer behaviour */ + KEEP_STATES_SYNCED_NORMAL = 1, /*!< QMF transposer called for syncing of + states the last 8/14 slots are calculated in + case next frame is HBE */ + KEEP_STATES_SYNCED_OUTDIFF = + 2, /*!< QMF transposer behaviour as in normal case, but the calculated + slots are directly written to overlap area of buffer; only used in + resetSbrDec function */ + KEEP_STATES_SYNCED_NOOUT = + 3 /*!< QMF transposer is called for syncing of states only, not output + is generated at all; only used in resetSbrDec function */ +} KEEP_STATES_SYNCED_MODE; + +struct hbeTransposer { + int xOverQmf[MAX_NUM_PATCHES_HBE]; + + int maxStretch; + int timeDomainWinLen; + int qmfInBufSize; + int qmfOutBufSize; + int noCols; + int noChannels; + int startBand; + int stopBand; + int bSbr41; + + INT_PCM *inBuf_F; + FIXP_DBL **qmfInBufReal_F; + FIXP_DBL **qmfInBufImag_F; + + FIXP_DBL *qmfBufferCodecTempSlot_F; + + QMF_FILTER_BANK HBEAnalysiscQMF; + QMF_FILTER_BANK HBESynthesisQMF; + + FIXP_DBL const *synthesisQmfPreModCos_F; + FIXP_DBL const *synthesisQmfPreModSin_F; + + FIXP_QAS anaQmfStates[HBE_QMF_FILTER_STATE_ANA_SIZE]; + FIXP_QSS synQmfStates[HBE_QMF_FILTER_STATE_SYN_SIZE]; + + FIXP_DBL **qmfHBEBufReal_F; + FIXP_DBL **qmfHBEBufImag_F; + + int bXProducts[MAX_STRETCH_HBE]; + + int kstart; + int synthSize; + + int highband_exp[2]; + int target_exp[2]; +}; + +typedef struct hbeTransposer *HANDLE_HBE_TRANSPOSER; + +SBR_ERROR QmfTransposerCreate(HANDLE_HBE_TRANSPOSER *hQmfTransposer, + const int frameSize, int bDisableCrossProducts, + int bSbr41); + +SBR_ERROR QmfTransposerReInit(HANDLE_HBE_TRANSPOSER hQmfTransposer, + UCHAR *FreqBandTable[2], UCHAR NSfb[2]); + +void QmfTransposerClose(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +void QmfTransposerApply(HANDLE_HBE_TRANSPOSER hQmfTransposer, + FIXP_DBL **qmfBufferCodecReal, + FIXP_DBL **qmfBufferCodecImag, int nColsIn, + FIXP_DBL **ppQmfBufferOutReal_F, + FIXP_DBL **ppQmfBufferOutImag_F, + FIXP_DBL lpcFilterStatesReal[2 + (3 * (4))][(64)], + FIXP_DBL lpcFilterStatesImag[2 + (3 * (4))][(64)], + int pitchInBins, int scale_lb, int scale_hbe, + int *scale_hb, int timeStep, int firstSlotOffsset, + int ov_len, + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode); + +int *GetxOverBandQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); + +int Get41SbrQmfTransposer(HANDLE_HBE_TRANSPOSER hQmfTransposer); +#endif /* HBE_H */ diff --git a/fdk-aac/libSBRdec/src/huff_dec.cpp b/fdk-aac/libSBRdec/src/huff_dec.cpp new file mode 100644 index 0000000..90c9541 --- /dev/null +++ b/fdk-aac/libSBRdec/src/huff_dec.cpp @@ -0,0 +1,137 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Huffman Decoder +*/ + +#include "huff_dec.h" + +/***************************************************************************/ +/*! + \brief Decodes one huffman code word + + Reads bits from the bitstream until a valid codeword is found. + The table entries are interpreted either as index to the next entry + or - if negative - as the codeword. + + \return decoded value + + \author + +****************************************************************************/ +int DecodeHuffmanCW(Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBs) /*!< Handle to Bitbuffer */ +{ + SCHAR index = 0; + int value, bit; + + while (index >= 0) { + bit = FDKreadBits(hBs, 1); + index = h[index][bit]; + } + + value = index + 64; /* Add offset */ + + return value; +} diff --git a/fdk-aac/libSBRdec/src/huff_dec.h b/fdk-aac/libSBRdec/src/huff_dec.h new file mode 100644 index 0000000..9aa62b4 --- /dev/null +++ b/fdk-aac/libSBRdec/src/huff_dec.h @@ -0,0 +1,117 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Huffman Decoder +*/ +#ifndef HUFF_DEC_H +#define HUFF_DEC_H + +#include "sbrdecoder.h" +#include "FDK_bitstream.h" + +typedef const SCHAR (*Huffman)[2]; + +int DecodeHuffmanCW(Huffman h, HANDLE_FDK_BITSTREAM hBitBuf); + +#endif diff --git a/fdk-aac/libSBRdec/src/lpp_tran.cpp b/fdk-aac/libSBRdec/src/lpp_tran.cpp new file mode 100644 index 0000000..2ef07eb --- /dev/null +++ b/fdk-aac/libSBRdec/src/lpp_tran.cpp @@ -0,0 +1,1471 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Low Power Profile Transposer + This module provides the transposer. The main entry point is lppTransposer(). + The function generates high frequency content by copying data from the low + band (provided by core codec) into the high band. This process is also + referred to as "patching". The function also implements spectral whitening by + means of inverse filtering based on LPC coefficients. + + Together with the QMF filterbank the transposer can be tested using a supplied + test program. See main_audio.cpp for details. This module does use fractional + arithmetic and the accuracy of the computations has an impact on the overall + sound quality. The module also needs to take into account the different + scaling of spectral data. + + \sa lppTransposer(), main_audio.cpp, sbr_scale.h, \ref documentationOverview +*/ + +#ifdef __ANDROID__ +#include "log/log.h" +#endif + +#include "lpp_tran.h" + +#include "sbr_ram.h" +#include "sbr_rom.h" + +#include "genericStds.h" +#include "autocorr2nd.h" + +#include "HFgen_preFlat.h" + +#if defined(__arm__) +#include "arm/lpp_tran_arm.cpp" +#endif + +#define LPC_SCALE_FACTOR 2 + +/*! + * + * \brief Get bandwidth expansion factor from filtering level + * + * Returns a filter parameter (bandwidth expansion factor) depending on + * the desired filtering level signalled in the bitstream. + * When switching the filtering level from LOW to OFF, an additional + * level is being inserted to achieve a smooth transition. + */ + +static FIXP_DBL mapInvfMode(INVF_MODE mode, INVF_MODE prevMode, + WHITENING_FACTORS whFactors) { + switch (mode) { + case INVF_LOW_LEVEL: + if (prevMode == INVF_OFF) + return whFactors.transitionLevel; + else + return whFactors.lowLevel; + + case INVF_MID_LEVEL: + return whFactors.midLevel; + + case INVF_HIGH_LEVEL: + return whFactors.highLevel; + + default: + if (prevMode == INVF_LOW_LEVEL) + return whFactors.transitionLevel; + else + return whFactors.off; + } +} + +/*! + * + * \brief Perform inverse filtering level emphasis + * + * Retrieve bandwidth expansion factor and apply smoothing for each filter band + * + */ + +static void inverseFilteringLevelEmphasis( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev, /*!< Previous inverse filtering modes */ + FIXP_DBL *bwVector /*!< Resulting filtering levels */ +) { + for (int i = 0; i < nInvfBands; i++) { + FIXP_DBL accu; + FIXP_DBL bwTmp = mapInvfMode(sbr_invf_mode[i], sbr_invf_mode_prev[i], + hLppTrans->pSettings->whFactors); + + if (bwTmp < hLppTrans->bwVectorOld[i]) { + accu = fMultDiv2(FL2FXCONST_DBL(0.75f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.25f), hLppTrans->bwVectorOld[i]); + } else { + accu = fMultDiv2(FL2FXCONST_DBL(0.90625f), bwTmp) + + fMultDiv2(FL2FXCONST_DBL(0.09375f), hLppTrans->bwVectorOld[i]); + } + + if (accu> 1) { + bwVector[i] = FL2FXCONST_DBL(0.0f); + } else { + bwVector[i] = fixMin(accu << 1, FL2FXCONST_DBL(0.99609375f)); + } + } +} + +/* Resulting autocorrelation determinant exponent */ +#define ACDET_EXP \ + (2 * (DFRACT_BITS + sbrScaleFactor->lb_scale + 10 - ac.det_scale)) +#define AC_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR) +#define ALPHA_EXP (-sbrScaleFactor->lb_scale + LPC_SCALE_FACTOR + 1) +/* Resulting transposed QMF values exponent 16 bit normalized samplebits + * assumed. */ +#define QMFOUT_EXP ((SAMPLE_BITS - 15) - sbrScaleFactor->lb_scale) + +static inline void calc_qmfBufferReal(FIXP_DBL **qmfBufferReal, + const FIXP_DBL *const lowBandReal, + const int startSample, + const int stopSample, const UCHAR hiBand, + const int dynamicScale, const int descale, + const FIXP_SGL a0r, const FIXP_SGL a1r) { + FIXP_DBL accu1, accu2; + int i; + + for (i = 0; i < stopSample - startSample; i++) { + accu1 = fMultDiv2(a1r, lowBandReal[i]); + accu1 = (fMultDiv2(a0r, lowBandReal[i + 1]) + accu1); + accu1 = accu1 >> dynamicScale; + + accu1 <<= 1; + accu2 = (lowBandReal[i + 2] >> descale); + qmfBufferReal[i + startSample][hiBand] = accu1 + accu2; + } +} + +/*! + * + * \brief Perform transposition by patching of subband samples. + * This function serves as the main entry point into the module. The function + * determines the areas for the patching process (these are the source range as + * well as the target range) and implements spectral whitening by means of + * inverse filtering. The function autoCorrelation2nd() is an auxiliary function + * for calculating the LPC coefficients for the filtering. The actual + * calculation of the LPC coefficients and the implementation of the filtering + * are done as part of lppTransposer(). + * + * Note that the filtering is done on all available QMF subsamples, whereas the + * patching is only done on those QMF subsamples that will be used in the next + * QMF synthesis. The filtering is also implemented before the patching includes + * further dependencies on parameters from the SBR data. + * + */ + +void lppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + + FIXP_DBL *degreeAlias, /*!< Vector for results of aliasing estimation */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int useLP, const int fPreWhitening, const int v_k_master0, + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex[MAX_NUM_PATCHES]; + FIXP_DBL bwVector[MAX_NUM_PATCHES]; /*!< pole moving factors */ + FIXP_DBL preWhiteningGains[(64) / 2]; + int preWhiteningGains_exp[(64) / 2]; + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + int patch; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + FIXP_DBL k1, k1_below = 0, k1_below2 = 0; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comLowBandScale; + int ovLowBandShift; + int lowBandShift; + /* int ovHighBandShift;*/ + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + FDK_ASSERT((lastSlotOffs * timeStep) <= pSettings->overlap); + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + if (pSettings->noOfPatches > 0) { + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + int targetStopBand = + patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + if (!useLP) { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + } else { + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + } + } + } +#ifdef __ANDROID__ + else { + // Safetynet logging + android_errorWriteLog(0x534e4554, "112160868"); + } +#endif + + /* init bwIndex for each patch */ + FDKmemclear(bwIndex, sizeof(bwIndex)); + + /* + Calc common low band scale factor + */ + comLowBandScale = + fixMin(sbrScaleFactor->ov_lb_scale, sbrScaleFactor->lb_scale); + + ovLowBandShift = sbrScaleFactor->ov_lb_scale - comLowBandScale; + lowBandShift = sbrScaleFactor->lb_scale - comLowBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + if (fPreWhitening) { + sbrDecoder_calculateGainVec( + qmfBufferReal, qmfBufferImag, + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->ov_lb_scale, /* convert scale to exponent */ + DFRACT_BITS - 1 - 16 - + sbrScaleFactor->lb_scale, /* convert scale to exponent */ + pSettings->overlap, preWhiteningGains, preWhiteningGains_exp, + v_k_master0, startSample, stopSample); + } + + /* outer loop over bands to do analysis only once for each band */ + + if (!useLP) { + start = pSettings->lbStartPatching; + stop = pSettings->lbStopPatching; + } else { + start = fixMax(1, pSettings->lbStartPatching - 2); + stop = patchParam[0].targetStartBand; + } + + for (loBand = start; loBand < stop; loBand++) { + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL *plowBandReal = lowBandReal; + FIXP_DBL **pqmfBufferReal = + qmfBufferReal + firstSlotOffs * timeStep /* + pSettings->overlap */; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL *plowBandImag = lowBandImag; + FIXP_DBL **pqmfBufferImag = + qmfBufferImag + firstSlotOffs * timeStep /* + pSettings->overlap */; + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for (i = 0; + i < LPC_ORDER + firstSlotOffs * timeStep /*+pSettings->overlap*/; + i++) { + *plowBandReal++ = hLppTrans->lpcFilterStatesRealLegSBR[i][loBand]; + if (!useLP) + *plowBandImag++ = hLppTrans->lpcFilterStatesImagLegSBR[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + if (!useLP) { + for (i = 0; + i < pSettings->nCols + pSettings->overlap - firstSlotOffs * timeStep; + i++) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandImag++ = (*pqmfBufferImag++)[loBand]; + } + } else { + /* pSettings->overlap is always even */ + FDK_ASSERT((pSettings->overlap & 1) == 0); + for (i = 0; i < ((pSettings->nCols + pSettings->overlap - + firstSlotOffs * timeStep) >> + 1); + i++) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + if (pSettings->nCols & 1) { + *plowBandReal++ = (*pqmfBufferReal++)[loBand]; + } + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + if (!useLP) { + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + } + dynamicScale = fixMax( + 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */ + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + + if (!useLP) { + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols, dynamicScale - lowBandShift); + } + + if (!useLP) { + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + } else { + acDetScale += + autoCorr2nd_real(&ac, lowBandReal + LPC_ORDER, autoCorrLength); + } + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comLowBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } + + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp, absTmp, absDet; + + absDet = fixp_abs(ac.det); + + if (!useLP) { + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + } else { + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + (fMultDiv2(ac.r02r, ac.r11r) >> (LPC_SCALE_FACTOR - 1)); + } + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphar[1] = -alphar[1]; + } + } + } + + if (!useLP) { + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> + scale)) { + resetLPCCoeffs = 1; + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphai[1] = -alphai[1]; + } + } + } + } + } + + alphar[0] = FL2FXCONST_SGL(0.0f); + if (!useLP) alphai[0] = FL2FXCONST_SGL(0.0f); + + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { + /* ac.r11r is always >=0 */ + FIXP_DBL tmp, absTmp; + + if (!useLP) { + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + } else { + if (ac.r01r >= FL2FXCONST_DBL(0.0f)) + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); + else + tmp = -((-ac.r01r) >> (LPC_SCALE_FACTOR + 1)) + + fMultDiv2(alphar[1], ac.r12r); + } + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphar[0] = -alphar[0]; + } + + if (!useLP) { + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphai[0] = -alphai[0]; + } + } + } + + if (!useLP) { + /* Now check the quadratic criteria */ + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) + resetLPCCoeffs = 1; + } + + if (resetLPCCoeffs) { + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + if (!useLP) { + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + } + + if (useLP) { + /* Aliasing detection */ + if (ac.r11r == FL2FXCONST_DBL(0.0f)) { + k1 = FL2FXCONST_DBL(0.0f); + } else { + if (fixp_abs(ac.r01r) >= fixp_abs(ac.r11r)) { + if (fMultDiv2(ac.r01r, ac.r11r) < FL2FX_DBL(0.0f)) { + k1 = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_SGL(1.0f)*/; + } else { + /* Since this value is squared later, it must not ever become -1.0f. + */ + k1 = (FIXP_DBL)(MINVAL_DBL + 1) /*FL2FXCONST_SGL(-1.0f)*/; + } + } else { + INT scale; + FIXP_DBL result = + fDivNorm(fixp_abs(ac.r01r), fixp_abs(ac.r11r), &scale); + k1 = scaleValue(result, scale); + + if (!((ac.r01r < FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f)))) { + k1 = -k1; + } + } + } + if ((loBand > 1) && (loBand < v_k_master0)) { + /* Check if the gain should be locked */ + FIXP_DBL deg = + /*FL2FXCONST_DBL(1.0f)*/ (FIXP_DBL)MAXVAL_DBL - fPow2(k1_below); + degreeAlias[loBand] = FL2FXCONST_DBL(0.0f); + if (((loBand & 1) == 0) && (k1 < FL2FXCONST_DBL(0.0f))) { + if (k1_below < FL2FXCONST_DBL(0.0f)) { /* 2-Ch Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand - 1] = deg; + } + } else if (k1_below2 > + FL2FXCONST_DBL(0.0f)) { /* 3-Ch Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + if (((loBand & 1) == 1) && (k1 > FL2FXCONST_DBL(0.0f))) { + if (k1_below > FL2FXCONST_DBL(0.0f)) { /* 2-CH Aliasing Detection */ + degreeAlias[loBand] = (FIXP_DBL)MAXVAL_DBL /*FL2FXCONST_DBL(1.0f)*/; + if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand - 1] = deg; + } + } else if (k1_below2 < + FL2FXCONST_DBL(0.0f)) { /* 3-CH Aliasing Detection */ + degreeAlias[loBand] = deg; + } + } + } + /* remember k1 values of the 2 QMF channels below the current channel */ + k1_below2 = k1_below; + k1_below = k1; + } + + patch = 0; + + while (patch < pSettings->noOfPatches) { /* inner loop over every patch */ + + int hiBand = loBand + patchParam[patch].targetBandOffs; + + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand + //|| hiBand >= hLppTrans->pSettings->noChannels + ) { + /* Lowband not in current patch - proceed */ + patch++; + continue; + } + + FDK_ASSERT(hiBand < (64)); + + /* bwIndex[patch] is already initialized with value from previous band + * inside this patch */ + while (hiBand >= pSettings->bwBorders[bwIndex[patch]] && + bwIndex[patch] < MAX_NUM_PATCHES - 1) { + bwIndex[patch]++; + } + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex[patch]]); + + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + + if (!useLP) a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + if (!useLP) a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + if (bw <= FL2FXCONST_SGL(0.0f)) { + if (!useLP) { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + accu1 = lowBandReal[LPC_ORDER + i] >> descale; + accu2 = lowBandImag[LPC_ORDER + i] >> descale; + if (fPreWhitening) { + accu1 = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + accu2 = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; + } + } else { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][hiBand] = lowBandReal[LPC_ORDER + i] >> descale; + } + } + } else { /* bw <= 0 */ + + if (!useLP) { + int descale = + fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); +#ifdef FUNCTION_LPPTRANSPOSER_func1 + lppTransposer_func1( + lowBandReal + LPC_ORDER + startSample, + lowBandImag + LPC_ORDER + startSample, + qmfBufferReal + startSample, qmfBufferImag + startSample, + stopSample - startSample, (int)hiBand, dynamicScale, descale, a0r, + a0i, a1r, a1i, fPreWhitening, preWhiteningGains[loBand], + preWhiteningGains_exp[loBand] + 1); +#else + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + + accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + + accu1 = (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1); + accu2 = (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1); + if (fPreWhitening) { + accu1 = scaleValueSaturate( + fMultDiv2(accu1, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + accu2 = scaleValueSaturate( + fMultDiv2(accu2, preWhiteningGains[loBand]), + preWhiteningGains_exp[loBand] + 1); + } + qmfBufferReal[i][hiBand] = accu1; + qmfBufferImag[i][hiBand] = accu2; + } +#endif + } else { + FDK_ASSERT(dynamicScale >= 0); + calc_qmfBufferReal( + qmfBufferReal, &(lowBandReal[LPC_ORDER + startSample - 2]), + startSample, stopSample, hiBand, dynamicScale, + fMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)), a0r, + a1r); + } + } /* bw <= 0 */ + + patch++; + + } /* inner loop over patches */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + } /* outer loop over bands (loBand) */ + + if (useLP) { + for (loBand = pSettings->lbStartPatching; + loBand < pSettings->lbStopPatching; loBand++) { + patch = 0; + while (patch < pSettings->noOfPatches) { + UCHAR hiBand = loBand + patchParam[patch].targetBandOffs; + + if (loBand < patchParam[patch].sourceStartBand || + loBand >= patchParam[patch].sourceStopBand || + hiBand >= (64) /* Highband out of range (biterror) */ + ) { + /* Lowband not in current patch or highband out of range (might be + * caused by biterrors)- proceed */ + patch++; + continue; + } + + if (hiBand != patchParam[patch].targetStartBand) + degreeAlias[hiBand] = degreeAlias[loBand]; + + patch++; + } + } /* end for loop */ + } + + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comLowBandScale - (LPC_SCALE_FACTOR); +} + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +) { + INT bwIndex; + FIXP_DBL bwVector[MAX_NUM_PATCHES_HBE]; /*!< pole moving factors */ + + int i; + int loBand, start, stop; + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + FIXP_SGL alphar[LPC_ORDER], a0r, a1r; + FIXP_SGL alphai[LPC_ORDER], a0i = 0, a1i = 0; + FIXP_SGL bw = FL2FXCONST_SGL(0.0f); + + int autoCorrLength; + + ACORR_COEFS ac; + int startSample; + int stopSample; + int stopSampleClear; + + int comBandScale; + int ovLowBandShift; + int lowBandShift; + /* int ovHighBandShift;*/ + + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + startSample = firstSlotOffs * timeStep; + stopSample = pSettings->nCols + lastSlotOffs * timeStep; + + inverseFilteringLevelEmphasis(hLppTrans, nInvfBands, sbr_invf_mode, + sbr_invf_mode_prev, bwVector); + + stopSampleClear = stopSample; + + autoCorrLength = pSettings->nCols + pSettings->overlap; + + if (pSettings->noOfPatches > 0) { + /* Set upper subbands to zero: + This is required in case that the patches do not cover the complete + highband (because the last patch would be too short). Possible + optimization: Clearing bands up to usb would be sufficient here. */ + int targetStopBand = + patchParam[pSettings->noOfPatches - 1].targetStartBand + + patchParam[pSettings->noOfPatches - 1].numBandsInPatch; + + int memSize = ((64) - targetStopBand) * sizeof(FIXP_DBL); + + for (i = startSample; i < stopSampleClear; i++) { + FDKmemclear(&qmfBufferReal[i][targetStopBand], memSize); + FDKmemclear(&qmfBufferImag[i][targetStopBand], memSize); + } + } +#ifdef __ANDROID__ + else { + // Safetynet logging + android_errorWriteLog(0x534e4554, "112160868"); + } +#endif + + /* + Calc common low band scale factor + */ + comBandScale = sbrScaleFactor->hb_scale; + + ovLowBandShift = sbrScaleFactor->hb_scale - comBandScale; + lowBandShift = sbrScaleFactor->hb_scale - comBandScale; + /* ovHighBandShift = firstSlotOffs == 0 ? ovLowBandShift:0;*/ + + /* outer loop over bands to do analysis only once for each band */ + + start = hQmfTransposer->startBand; + stop = hQmfTransposer->stopBand; + + for (loBand = start; loBand < stop; loBand++) { + bwIndex = 0; + + FIXP_DBL lowBandReal[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + FIXP_DBL lowBandImag[(((1024) / (32) * (4) / 2) + (3 * (4))) + LPC_ORDER]; + + int resetLPCCoeffs = 0; + int dynamicScale = DFRACT_BITS - 1 - LPC_SCALE_FACTOR; + int acDetScale = 0; /* scaling of autocorrelation determinant */ + + for (i = 0; i < LPC_ORDER; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + for (; i < LPC_ORDER + firstSlotOffs * timeStep; i++) { + lowBandReal[i] = hLppTrans->lpcFilterStatesRealHBE[i][loBand]; + lowBandImag[i] = hLppTrans->lpcFilterStatesImagHBE[i][loBand]; + } + + /* + Take old slope length qmf slot source values out of (overlap)qmf buffer + */ + for (i = firstSlotOffs * timeStep; + i < pSettings->nCols + pSettings->overlap; i++) { + lowBandReal[i + LPC_ORDER] = qmfBufferReal[i][loBand]; + lowBandImag[i + LPC_ORDER] = qmfBufferImag[i][loBand]; + } + + /* store unmodified values to buffer */ + for (i = 0; i < LPC_ORDER + pSettings->overlap; i++) { + hLppTrans->lpcFilterStatesRealHBE[i][loBand] = + qmfBufferReal[pSettings->nCols - LPC_ORDER + i][loBand]; + hLppTrans->lpcFilterStatesImagHBE[i][loBand] = + qmfBufferImag[pSettings->nCols - LPC_ORDER + i][loBand]; + } + + /* + Determine dynamic scaling value. + */ + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandReal, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandReal[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(lowBandImag, LPC_ORDER + pSettings->overlap) + + ovLowBandShift); + dynamicScale = + fixMin(dynamicScale, + getScalefactor(&lowBandImag[LPC_ORDER + pSettings->overlap], + pSettings->nCols) + + lowBandShift); + + dynamicScale = fixMax( + 0, dynamicScale - 1); /* one additional bit headroom to prevent -1.0 */ + + /* + Scale temporal QMF buffer. + */ + scaleValues(&lowBandReal[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandReal[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + scaleValues(&lowBandImag[0], LPC_ORDER + pSettings->overlap, + dynamicScale - ovLowBandShift); + scaleValues(&lowBandImag[LPC_ORDER + pSettings->overlap], pSettings->nCols, + dynamicScale - lowBandShift); + + acDetScale += autoCorr2nd_cplx(&ac, lowBandReal + LPC_ORDER, + lowBandImag + LPC_ORDER, autoCorrLength); + + /* Examine dynamic of determinant in autocorrelation. */ + acDetScale += 2 * (comBandScale + dynamicScale); + acDetScale *= 2; /* two times reflection coefficent scaling */ + acDetScale += ac.det_scale; /* ac scaling of determinant */ + + /* In case of determinant < 10^-38, resetLPCCoeffs=1 has to be enforced. */ + if (acDetScale > 126) { + resetLPCCoeffs = 1; + } + + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + + if (ac.det != FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp, absTmp, absDet; + + absDet = fixp_abs(ac.det); + + tmp = (fMultDiv2(ac.r01r, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) - + ((fMultDiv2(ac.r01i, ac.r12i) + fMultDiv2(ac.r02r, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && (result >= (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphar[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphar[1] = -alphar[1]; + } + } + } + + tmp = (fMultDiv2(ac.r01i, ac.r12r) >> (LPC_SCALE_FACTOR - 1)) + + ((fMultDiv2(ac.r01r, ac.r12i) - + (FIXP_DBL)fMultDiv2(ac.r02i, ac.r11r)) >> + (LPC_SCALE_FACTOR - 1)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, absDet, &scale); + scale = scale + ac.det_scale; + + if ((scale > 0) && + (result >= /*FL2FXCONST_DBL(1.f)*/ (FIXP_DBL)MAXVAL_DBL >> scale)) { + resetLPCCoeffs = 1; + } else { + alphai[1] = FX_DBL2FX_SGL(scaleValue(result, scale)); + if ((tmp < FL2FX_DBL(0.0f)) ^ (ac.det < FL2FX_DBL(0.0f))) { + alphai[1] = -alphai[1]; + } + } + } + } + + alphar[0] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + + if (ac.r11r != FL2FXCONST_DBL(0.0f)) { + /* ac.r11r is always >=0 */ + FIXP_DBL tmp, absTmp; + + tmp = (ac.r01r >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphar[1], ac.r12r) + fMultDiv2(alphai[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is first filter coeff >= 1(4) + */ + + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphar[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) + alphar[0] = -alphar[0]; + } + + tmp = (ac.r01i >> (LPC_SCALE_FACTOR + 1)) + + (fMultDiv2(alphai[1], ac.r12r) - fMultDiv2(alphar[1], ac.r12i)); + + absTmp = fixp_abs(tmp); + + /* + Quick check: is second filter coeff >= 1(4) + */ + if (absTmp >= (ac.r11r >> 1)) { + resetLPCCoeffs = 1; + } else { + INT scale; + FIXP_DBL result = fDivNorm(absTmp, fixp_abs(ac.r11r), &scale); + alphai[0] = FX_DBL2FX_SGL(scaleValue(result, scale + 1)); + if ((tmp > FL2FX_DBL(0.0f)) ^ (ac.r11r < FL2FX_DBL(0.0f))) { + alphai[0] = -alphai[0]; + } + } + } + + /* Now check the quadratic criteria */ + if ((fMultDiv2(alphar[0], alphar[0]) + fMultDiv2(alphai[0], alphai[0])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + if ((fMultDiv2(alphar[1], alphar[1]) + fMultDiv2(alphai[1], alphai[1])) >= + FL2FXCONST_DBL(0.5f)) { + resetLPCCoeffs = 1; + } + + if (resetLPCCoeffs) { + alphar[0] = FL2FXCONST_SGL(0.0f); + alphar[1] = FL2FXCONST_SGL(0.0f); + alphai[0] = FL2FXCONST_SGL(0.0f); + alphai[1] = FL2FXCONST_SGL(0.0f); + } + + while (bwIndex < MAX_NUM_PATCHES - 1 && + loBand >= pSettings->bwBorders[bwIndex]) { + bwIndex++; + } + + /* + Filter Step 2: add the left slope with the current filter to the buffer + pure source values are already in there + */ + bw = FX_DBL2FX_SGL(bwVector[bwIndex]); + + a0r = FX_DBL2FX_SGL( + fMult(bw, alphar[0])); /* Apply current bandwidth expansion factor */ + a0i = FX_DBL2FX_SGL(fMult(bw, alphai[0])); + bw = FX_DBL2FX_SGL(fPow2(bw)); + a1r = FX_DBL2FX_SGL(fMult(bw, alphar[1])); + a1i = FX_DBL2FX_SGL(fMult(bw, alphai[1])); + + /* + Filter Step 3: insert the middle part which won't be windowed + */ + if (bw <= FL2FXCONST_SGL(0.0f)) { + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + for (i = startSample; i < stopSample; i++) { + qmfBufferReal[i][loBand] = lowBandReal[LPC_ORDER + i] >> descale; + qmfBufferImag[i][loBand] = lowBandImag[LPC_ORDER + i] >> descale; + } + } else { /* bw <= 0 */ + + int descale = fixMin(DFRACT_BITS - 1, (LPC_SCALE_FACTOR + dynamicScale)); + + for (i = startSample; i < stopSample; i++) { + FIXP_DBL accu1, accu2; + + accu1 = (fMultDiv2(a0r, lowBandReal[LPC_ORDER + i - 1]) - + fMultDiv2(a0i, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1r, lowBandReal[LPC_ORDER + i - 2]) - + fMultDiv2(a1i, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + accu2 = (fMultDiv2(a0i, lowBandReal[LPC_ORDER + i - 1]) + + fMultDiv2(a0r, lowBandImag[LPC_ORDER + i - 1]) + + fMultDiv2(a1i, lowBandReal[LPC_ORDER + i - 2]) + + fMultDiv2(a1r, lowBandImag[LPC_ORDER + i - 2])) >> + dynamicScale; + + qmfBufferReal[i][loBand] = + (lowBandReal[LPC_ORDER + i] >> descale) + (accu1 << 1); + qmfBufferImag[i][loBand] = + (lowBandImag[LPC_ORDER + i] >> descale) + (accu2 << 1); + } + } /* bw <= 0 */ + + /* + * store the unmodified filter coefficients if there is + * an overlapping envelope + *****************************************************************/ + + } /* outer loop over bands (loBand) */ + + for (i = 0; i < nInvfBands; i++) { + hLppTrans->bwVectorOld[i] = bwVector[i]; + } + + /* + set high band scale factor + */ + sbrScaleFactor->hb_scale = comBandScale - (LPC_SCALE_FACTOR); +} + +/*! + * + * \brief Initialize one low power transposer instance + * + * + */ +SBR_ERROR +createLppTransposer( + HANDLE_SBR_LPP_TRANS hs, /*!< Handle of low power transposer */ + TRANSPOSER_SETTINGS *pSettings, /*!< Pointer to settings */ + const int highBandStartSb, /*!< ? */ + UCHAR *v_k_master, /*!< Master table */ + const int numMaster, /*!< Valid entries in master table */ + const int usb, /*!< Highband area stop subband */ + const int timeSlots, /*!< Number of time slots */ + const int nCols, /*!< Number of colums (codec qmf bank) */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + const int noNoiseBands, /*!< Number of noise bands */ + UINT fs, /*!< Sample Frequency */ + const int chan, /*!< Channel number */ + const int overlap) { + /* FB inverse filtering settings */ + hs->pSettings = pSettings; + + pSettings->nCols = nCols; + pSettings->overlap = overlap; + + switch (timeSlots) { + case 15: + case 16: + break; + + default: + return SBRDEC_UNSUPPORTED_CONFIG; /* Unimplemented */ + } + + if (chan == 0) { + /* Init common data only once */ + hs->pSettings->nCols = nCols; + + return resetLppTransposer(hs, highBandStartSb, v_k_master, numMaster, + noiseBandTable, noNoiseBands, usb, fs); + } + return SBRDEC_OK; +} + +static int findClosestEntry(UCHAR goalSb, UCHAR *v_k_master, UCHAR numMaster, + UCHAR direction) { + int index; + + if (goalSb <= v_k_master[0]) return v_k_master[0]; + + if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; + + if (direction) { + index = 0; + while (v_k_master[index] < goalSb) { + index++; + } + } else { + index = numMaster; + while (v_k_master[index] > goalSb) { + index--; + } + } + + return v_k_master[index]; +} + +/*! + * + * \brief Reset memory for one lpp transposer instance + * + * \return SBRDEC_OK on success, SBRDEC_UNSUPPORTED_CONFIG on error + */ +SBR_ERROR +resetLppTransposer( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + UCHAR highBandStartSb, /*!< High band area: start subband */ + UCHAR *v_k_master, /*!< Master table */ + UCHAR numMaster, /*!< Valid entries in master table */ + UCHAR *noiseBandTable, /*!< Mapping of SBR noise bands to QMF bands */ + UCHAR noNoiseBands, /*!< Number of noise bands */ + UCHAR usb, /*!< High band area: stop subband */ + UINT fs /*!< SBR output sampling frequency */ +) { + TRANSPOSER_SETTINGS *pSettings = hLppTrans->pSettings; + PATCH_PARAM *patchParam = pSettings->patchParam; + + int i, patch; + int targetStopBand; + int sourceStartBand; + int patchDistance; + int numBandsInPatch; + + int lsb = v_k_master[0]; /* Start subband expressed in "non-critical" sampling + terms*/ + int xoverOffset = highBandStartSb - + lsb; /* Calculate distance in QMF bands between k0 and kx */ + int startFreqHz; + + int desiredBorder; + + usb = fixMin(usb, v_k_master[numMaster]); /* Avoid endless loops (compare with + float code). */ + + /* + * Plausibility check + */ + + if (pSettings->nCols == 64) { + if (lsb < 4) { + /* 4:1 SBR Requirement k0 >= 4 missed! */ + return SBRDEC_UNSUPPORTED_CONFIG; + } + } else if (lsb - SHIFT_START_SB < 4) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* + * Initialize the patching parameter + */ + /* ISO/IEC 14496-3 (Figure 4.48): goalSb = round( 2.048e6 / fs ) */ + desiredBorder = (((2048000 * 2) / fs) + 1) >> 1; + + desiredBorder = findClosestEntry(desiredBorder, v_k_master, numMaster, + 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = SHIFT_START_SB + xoverOffset; + targetStopBand = lsb + xoverOffset; /* upperBand */ + + /* Even (odd) numbered channel must be patched to even (odd) numbered channel + */ + patch = 0; + while (targetStopBand < usb) { + /* Too many patches? + Allow MAX_NUM_PATCHES+1 patches here. + we need to check later again, since patch might be the highest patch + AND contain less than 3 bands => actual number of patches will be reduced + by 1. + */ + if (patch > MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + patchParam[patch].guardStartBand = targetStopBand; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = + desiredBorder - targetStopBand; /* Get the desired range of the patch */ + + if (numBandsInPatch >= lsb - sourceStartBand) { + /* Desired number bands are not available -> patch whole source range */ + patchDistance = + targetStopBand - sourceStartBand; /* Get the targetOffset */ + patchDistance = + patchDistance & ~1; /* Rounding off odd numbers and make all even */ + numBandsInPatch = + lsb - (targetStopBand - + patchDistance); /* Update number of bands to be patched */ + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, + v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + if (pSettings->nCols == 64) { + if (numBandsInPatch == 0 && sourceStartBand == SHIFT_START_SB) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + + /* Desired number bands are available -> get the minimal even patching + * distance */ + patchDistance = + numBandsInPatch + targetStopBand - lsb; /* Get minimal distance */ + patchDistance = (patchDistance + 1) & + ~1; /* Rounding up odd numbers and make all even */ + + if (numBandsInPatch > 0) { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = + patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + patch++; + } + + /* All patches but first */ + sourceStartBand = SHIFT_START_SB; + + /* Check if we are close to desiredBorder */ + if (desiredBorder - targetStopBand < 3) /* MPEG doc */ + { + desiredBorder = usb; + } + } + + patch--; + + /* If highest patch contains less than three subband: skip it */ + if ((patch > 0) && (patchParam[patch].numBandsInPatch < 3)) { + patch--; + targetStopBand = + patchParam[patch].targetStartBand + patchParam[patch].numBandsInPatch; + } + + /* now check if we don't have one too many */ + if (patch >= MAX_NUM_PATCHES) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + pSettings->noOfPatches = patch + 1; + + /* Check lowest and highest source subband */ + pSettings->lbStartPatching = targetStopBand; + pSettings->lbStopPatching = 0; + for (patch = 0; patch < pSettings->noOfPatches; patch++) { + pSettings->lbStartPatching = + fixMin(pSettings->lbStartPatching, patchParam[patch].sourceStartBand); + pSettings->lbStopPatching = + fixMax(pSettings->lbStopPatching, patchParam[patch].sourceStopBand); + } + + for (i = 0; i < noNoiseBands; i++) { + pSettings->bwBorders[i] = noiseBandTable[i + 1]; + } + for (; i < MAX_NUM_NOISE_VALUES; i++) { + pSettings->bwBorders[i] = 255; + } + + /* + * Choose whitening factors + */ + + startFreqHz = + ((lsb + xoverOffset) * fs) >> 7; /* Shift does a division by 2*(64) */ + + for (i = 1; i < NUM_WHFACTOR_TABLE_ENTRIES; i++) { + if (startFreqHz < FDK_sbrDecoder_sbr_whFactorsIndex[i]) break; + } + i--; + + pSettings->whFactors.off = FDK_sbrDecoder_sbr_whFactorsTable[i][0]; + pSettings->whFactors.transitionLevel = + FDK_sbrDecoder_sbr_whFactorsTable[i][1]; + pSettings->whFactors.lowLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][2]; + pSettings->whFactors.midLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][3]; + pSettings->whFactors.highLevel = FDK_sbrDecoder_sbr_whFactorsTable[i][4]; + + return SBRDEC_OK; +} diff --git a/fdk-aac/libSBRdec/src/lpp_tran.h b/fdk-aac/libSBRdec/src/lpp_tran.h new file mode 100644 index 0000000..51b4395 --- /dev/null +++ b/fdk-aac/libSBRdec/src/lpp_tran.h @@ -0,0 +1,275 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Low Power Profile Transposer +*/ + +#ifndef LPP_TRAN_H +#define LPP_TRAN_H + +#include "sbrdecoder.h" +#include "hbe.h" +#include "qmf.h" + +/* + Common +*/ +#define QMF_OUT_SCALE 8 + +/* + Frequency scales +*/ + +/* + Env-Adjust +*/ +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NOISE_ENVELOPES * MAX_NOISE_COEFFS) +#define MAX_NUM_LIMITERS 12 + +/* Set MAX_ENVELOPES to the largest value of all supported BSFORMATs + by overriding MAX_ENVELOPES in the correct order: */ +#define MAX_ENVELOPES_LEGACY 5 +#define MAX_ENVELOPES_USAC 8 +#define MAX_ENVELOPES MAX_ENVELOPES_USAC + +#define MAX_FREQ_COEFFS_DUAL_RATE 48 +#define MAX_FREQ_COEFFS_QUAD_RATE 56 +#define MAX_FREQ_COEFFS MAX_FREQ_COEFFS_QUAD_RATE + +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) + +#define MAX_GAIN_EXP 34 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_EXP) + example: 34=99dB */ +#define MAX_GAIN_CONCEAL_EXP 1 +/* Maximum gain will be sqrt(0.5 * 2^MAX_GAIN_CONCEAL_EXP) in concealment case + * (0dB) */ + +/* + LPP Transposer +*/ +#define LPC_ORDER 2 + +#define MAX_INVF_BANDS MAX_NOISE_COEFFS + +#define MAX_NUM_PATCHES 6 +#define SHIFT_START_SB 1 /*!< lowest subband of source range */ + +typedef enum { + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} INVF_MODE; + +/** parameter set for one single patch */ +typedef struct { + UCHAR sourceStartBand; /*!< first band in lowbands where to take the samples + from */ + UCHAR + sourceStopBand; /*!< first band in lowbands which is not included in the + patch anymore */ + UCHAR guardStartBand; /*!< first band in highbands to be filled with zeros in + order to reduce interferences between patches */ + UCHAR + targetStartBand; /*!< first band in highbands to be filled with whitened + lowband signal */ + UCHAR targetBandOffs; /*!< difference between 'startTargetBand' and + 'startSourceBand' */ + UCHAR numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + +/** whitening factors for different levels of whitening + need to be initialized corresponding to crossover frequency */ +typedef struct { + FIXP_DBL off; /*!< bw factor for signal OFF */ + FIXP_DBL transitionLevel; + FIXP_DBL lowLevel; /*!< bw factor for signal LOW_LEVEL */ + FIXP_DBL midLevel; /*!< bw factor for signal MID_LEVEL */ + FIXP_DBL highLevel; /*!< bw factor for signal HIGH_LEVEL */ +} WHITENING_FACTORS; + +/*! The transposer settings are calculated on a header reset and are shared by + * both channels. */ +typedef struct { + UCHAR nCols; /*!< number subsamples of a codec frame */ + UCHAR noOfPatches; /*!< number of patches */ + UCHAR lbStartPatching; /*!< first band of lowbands that will be patched */ + UCHAR lbStopPatching; /*!< first band that won't be patched anymore*/ + UCHAR bwBorders[MAX_NUM_NOISE_VALUES]; /*!< spectral bands with different + inverse filtering levels */ + + PATCH_PARAM + patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + WHITENING_FACTORS + whFactors; /*!< the pole moving factors for certain + whitening levels as indicated in the bitstream + depending on the crossover frequency */ + UCHAR overlap; /*!< Overlap size */ +} TRANSPOSER_SETTINGS; + +typedef struct { + TRANSPOSER_SETTINGS *pSettings; /*!< Common settings for both channels */ + FIXP_DBL + bwVectorOld[MAX_NUM_PATCHES]; /*!< pole moving factors of past frame */ + FIXP_DBL lpcFilterStatesRealLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ + + FIXP_DBL lpcFilterStatesImagLegSBR[LPC_ORDER + (3 * (4))][( + 32)]; /*!< pointer array to save filter states */ + + FIXP_DBL lpcFilterStatesRealHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ + FIXP_DBL lpcFilterStatesImagHBE[LPC_ORDER + (3 * (4))][( + 64)]; /*!< pointer array to save filter states */ +} SBR_LPP_TRANS; + +typedef SBR_LPP_TRANS *HANDLE_SBR_LPP_TRANS; + +void lppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + QMF_SCALE_FACTOR *sbrScaleFactor, FIXP_DBL **qmfBufferReal, + + FIXP_DBL *degreeAlias, FIXP_DBL **qmfBufferImag, + const int useLP, const int fPreWhitening, + const int v_k_master0, const int timeStep, + const int firstSlotOffset, const int lastSlotOffset, + const int nInvfBands, INVF_MODE *sbr_invf_mode, + INVF_MODE *sbr_invf_mode_prev); + +void lppTransposerHBE( + HANDLE_SBR_LPP_TRANS hLppTrans, /*!< Handle of lpp transposer */ + HANDLE_HBE_TRANSPOSER hQmfTransposer, + QMF_SCALE_FACTOR *sbrScaleFactor, /*!< Scaling factors */ + FIXP_DBL **qmfBufferReal, /*!< Pointer to pointer to real part of subband + samples (source) */ + FIXP_DBL **qmfBufferImag, /*!< Pointer to pointer to imaginary part of + subband samples (source) */ + const int timeStep, /*!< Time step of envelope */ + const int firstSlotOffs, /*!< Start position in time */ + const int lastSlotOffs, /*!< Number of overlap-slots into next frame */ + const int nInvfBands, /*!< Number of bands for inverse filtering */ + INVF_MODE *sbr_invf_mode, /*!< Current inverse filtering modes */ + INVF_MODE *sbr_invf_mode_prev /*!< Previous inverse filtering modes */ +); + +SBR_ERROR +createLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, + TRANSPOSER_SETTINGS *pSettings, const int highBandStartSb, + UCHAR *v_k_master, const int numMaster, const int usb, + const int timeSlots, const int nCols, UCHAR *noiseBandTable, + const int noNoiseBands, UINT fs, const int chan, + const int overlap); + +SBR_ERROR +resetLppTransposer(HANDLE_SBR_LPP_TRANS hLppTrans, UCHAR highBandStartSb, + UCHAR *v_k_master, UCHAR numMaster, UCHAR *noiseBandTable, + UCHAR noNoiseBands, UCHAR usb, UINT fs); + +#endif /* LPP_TRAN_H */ diff --git a/fdk-aac/libSBRdec/src/psbitdec.cpp b/fdk-aac/libSBRdec/src/psbitdec.cpp new file mode 100644 index 0000000..82bb65b --- /dev/null +++ b/fdk-aac/libSBRdec/src/psbitdec.cpp @@ -0,0 +1,594 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "psbitdec.h" + +#include "sbr_rom.h" +#include "huff_dec.h" + +/* PS dec privat functions */ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); + +/***************************************************************************/ +/*! + \brief huffman decoding by codebook table + + \return index of huffman codebook table + +****************************************************************************/ +static SCHAR decode_huff_cw( + Huffman h, /*!< pointer to huffman codebook table */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< Handle to Bitbuffer */ + int *length) /*!< length of huffman codeword (or NULL) */ +{ + UCHAR bit = 0; + SCHAR index = 0; + UCHAR bitCount = 0; + + while (index >= 0) { + bit = FDKreadBits(hBitBuf, 1); + bitCount++; + index = h[index][bit]; + } + if (length) { + *length = bitCount; + } + return (index + 64); /* Add offset */ +} + +/***************************************************************************/ +/*! + \brief helper function - limiting of value to min/max values + + \return limited value + +****************************************************************************/ + +static SCHAR limitMinMax(SCHAR i, SCHAR min, SCHAR max) { + if (i < min) + return min; + else if (i > max) + return max; + else + return i; +} + +/***************************************************************************/ +/*! + \brief Decodes delta values in-place and updates + data buffers according to quantization classes. + + When delta coded in frequency the first element is deltacode from zero. + aIndex buffer is decoded from delta values to actual values. + + \return none + +****************************************************************************/ +static void deltaDecodeArray( + SCHAR enable, SCHAR *aIndex, /*!< ICC/IID parameters */ + SCHAR *aPrevFrameIndex, /*!< ICC/IID parameters of previous frame */ + SCHAR DtDf, UCHAR nrElements, /*!< as conveyed in bitstream */ + /*!< output array size: nrElements*stride */ + UCHAR stride, /*!< 1=dflt, 2=half freq. resolution */ + SCHAR minIdx, SCHAR maxIdx) { + int i; + + /* Delta decode */ + if (enable == 1) { + if (DtDf == 0) { /* Delta coded in freq */ + aIndex[0] = 0 + aIndex[0]; + aIndex[0] = limitMinMax(aIndex[0], minIdx, maxIdx); + for (i = 1; i < nrElements; i++) { + aIndex[i] = aIndex[i - 1] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); + } + } else { /* Delta time */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = aPrevFrameIndex[i * stride] + aIndex[i]; + aIndex[i] = limitMinMax(aIndex[i], minIdx, maxIdx); + } + } + } else { /* No data is sent, set index to zero */ + for (i = 0; i < nrElements; i++) { + aIndex[i] = 0; + } + } + if (stride == 2) { + for (i = nrElements * stride - 1; i > 0; i--) { + aIndex[i] = aIndex[i >> 1]; + } + } +} + +/***************************************************************************/ +/*! + \brief Mapping of ICC/IID parameters to 20 stereo bands + + \return none + +****************************************************************************/ +static void map34IndexTo20(SCHAR *aIndex, /*!< decoded ICC/IID parameters */ + UCHAR noBins) /*!< number of stereo bands */ +{ + aIndex[0] = (2 * aIndex[0] + aIndex[1]) / 3; + aIndex[1] = (aIndex[1] + 2 * aIndex[2]) / 3; + aIndex[2] = (2 * aIndex[3] + aIndex[4]) / 3; + aIndex[3] = (aIndex[4] + 2 * aIndex[5]) / 3; + aIndex[4] = (aIndex[6] + aIndex[7]) / 2; + aIndex[5] = (aIndex[8] + aIndex[9]) / 2; + aIndex[6] = aIndex[10]; + aIndex[7] = aIndex[11]; + aIndex[8] = (aIndex[12] + aIndex[13]) / 2; + aIndex[9] = (aIndex[14] + aIndex[15]) / 2; + aIndex[10] = aIndex[16]; + /* For IPD/OPD it stops here */ + + if (noBins == NO_HI_RES_BINS) { + aIndex[11] = aIndex[17]; + aIndex[12] = aIndex[18]; + aIndex[13] = aIndex[19]; + aIndex[14] = (aIndex[20] + aIndex[21]) / 2; + aIndex[15] = (aIndex[22] + aIndex[23]) / 2; + aIndex[16] = (aIndex[24] + aIndex[25]) / 2; + aIndex[17] = (aIndex[26] + aIndex[27]) / 2; + aIndex[18] = (aIndex[28] + aIndex[29] + aIndex[30] + aIndex[31]) / 4; + aIndex[19] = (aIndex[32] + aIndex[33]) / 2; + } +} + +/***************************************************************************/ +/*! + \brief Decodes delta coded IID, ICC, IPD and OPD indices + + \return PS processing flag. If set to 1 + +****************************************************************************/ +int DecodePs(struct PS_DEC *h_ps_d, /*!< PS handle */ + const UCHAR frameError, /*!< Flag telling that frame had errors */ + PS_DEC_COEFFICIENTS *pScratch) { + MPEG_PS_BS_DATA *pBsData; + UCHAR gr, env; + int bPsHeaderValid, bPsDataAvail; + + /* Assign Scratch */ + h_ps_d->specificTo.mpeg.pCoef = pScratch; + + /* Shortcuts to avoid deferencing and keep the code readable */ + pBsData = &h_ps_d->bsData[h_ps_d->processSlot].mpeg; + bPsHeaderValid = pBsData->bPsHeaderValid; + bPsDataAvail = + (h_ps_d->bPsDataAvail[h_ps_d->processSlot] == ppt_mpeg) ? 1 : 0; + + /*************************************************************************************** + * Decide whether to process or to conceal PS data or not. */ + + if ((h_ps_d->psDecodedPrv && !frameError && !bPsDataAvail) || + (!h_ps_d->psDecodedPrv && + (frameError || !bPsDataAvail || !bPsHeaderValid))) { + /* Don't apply PS processing. + * Declare current PS header and bitstream data invalid. */ + pBsData->bPsHeaderValid = 0; + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + return (0); + } + + if (frameError || + !bPsHeaderValid) { /* no new PS data available (e.g. frame loss) */ + /* => keep latest data constant (i.e. FIX with noEnv=0) */ + pBsData->noEnv = 0; + } + + /*************************************************************************************** + * Decode bitstream payload or prepare parameter for concealment: + */ + for (env = 0; env < pBsData->noEnv; env++) { + SCHAR *aPrevIidIndex; + SCHAR *aPrevIccIndex; + + UCHAR noIidSteps = pBsData->bFineIidQ ? NO_IID_STEPS_FINE : NO_IID_STEPS; + + if (env == 0) { + aPrevIidIndex = h_ps_d->specificTo.mpeg.aIidPrevFrameIndex; + aPrevIccIndex = h_ps_d->specificTo.mpeg.aIccPrevFrameIndex; + } else { + aPrevIidIndex = pBsData->aaIidIndex[env - 1]; + aPrevIccIndex = pBsData->aaIccIndex[env - 1]; + } + + deltaDecodeArray(pBsData->bEnableIid, pBsData->aaIidIndex[env], + aPrevIidIndex, pBsData->abIidDtFlag[env], + FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid], + (pBsData->freqResIid) ? 1 : 2, -noIidSteps, noIidSteps); + + deltaDecodeArray(pBsData->bEnableIcc, pBsData->aaIccIndex[env], + aPrevIccIndex, pBsData->abIccDtFlag[env], + FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc], + (pBsData->freqResIcc) ? 1 : 2, 0, NO_ICC_STEPS - 1); + } /* for (env=0; envnoEnv; env++) */ + + /* handling of FIX noEnv=0 */ + if (pBsData->noEnv == 0) { + /* set noEnv=1, keep last parameters or force 0 if not enabled */ + pBsData->noEnv = 1; + + if (pBsData->bEnableIid) { + pBsData->bFineIidQ = h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ; + pBsData->freqResIid = h_ps_d->specificTo.mpeg.prevFreqResIid; + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr]; + } + } else { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv - 1][gr] = 0; + } + } + + if (pBsData->bEnableIcc) { + pBsData->freqResIcc = h_ps_d->specificTo.mpeg.prevFreqResIcc; + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr]; + } + } else { + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv - 1][gr] = 0; + } + } + } + + /* Update previous frame Iid quantization */ + h_ps_d->specificTo.mpeg.bPrevFrameFineIidQ = pBsData->bFineIidQ; + + /* Update previous frequency resolution for IID */ + h_ps_d->specificTo.mpeg.prevFreqResIid = pBsData->freqResIid; + + /* Update previous frequency resolution for ICC */ + h_ps_d->specificTo.mpeg.prevFreqResIcc = pBsData->freqResIcc; + + /* Update previous frame index buffers */ + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIidPrevFrameIndex[gr] = + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + h_ps_d->specificTo.mpeg.aIccPrevFrameIndex[gr] = + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; + } + + /* PS data from bitstream (if avail) was decoded now */ + h_ps_d->bPsDataAvail[h_ps_d->processSlot] = ppt_none; + + /* handling of env borders for FIX & VAR */ + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->aEnvStartStop[0] = 0; + for (env = 1; env < pBsData->noEnv; env++) { + pBsData->aEnvStartStop[env] = + (env * h_ps_d->noSubSamples) / pBsData->noEnv; + } + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + /* 1024 (32 slots) env borders: 0, 8, 16, 24, 32 */ + /* 960 (30 slots) env borders: 0, 7, 15, 22, 30 */ + } else { /* if (h_ps_d->bFrameClass == 0) */ + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->aEnvStartStop[0] = 0; + + /* handle case aEnvStartStop[noEnv]aEnvStartStop[pBsData->noEnv] < h_ps_d->noSubSamples) { + for (gr = 0; gr < NO_HI_RES_IID_BINS; gr++) { + pBsData->aaIidIndex[pBsData->noEnv][gr] = + pBsData->aaIidIndex[pBsData->noEnv - 1][gr]; + } + for (gr = 0; gr < NO_HI_RES_ICC_BINS; gr++) { + pBsData->aaIccIndex[pBsData->noEnv][gr] = + pBsData->aaIccIndex[pBsData->noEnv - 1][gr]; + } + pBsData->noEnv++; + pBsData->aEnvStartStop[pBsData->noEnv] = h_ps_d->noSubSamples; + } + + /* enforce strictly monotonic increasing borders */ + for (env = 1; env < pBsData->noEnv; env++) { + UCHAR thr; + thr = (UCHAR)h_ps_d->noSubSamples - (pBsData->noEnv - env); + if (pBsData->aEnvStartStop[env] > thr) { + pBsData->aEnvStartStop[env] = thr; + } else { + thr = pBsData->aEnvStartStop[env - 1] + 1; + if (pBsData->aEnvStartStop[env] < thr) { + pBsData->aEnvStartStop[env] = thr; + } + } + } + } /* if (h_ps_d->bFrameClass == 0) ... else */ + + /* copy data prior to possible 20<->34 in-place mapping */ + for (env = 0; env < pBsData->noEnv; env++) { + UCHAR i; + for (i = 0; i < NO_HI_RES_IID_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][i] = + pBsData->aaIidIndex[env][i]; + } + for (i = 0; i < NO_HI_RES_ICC_BINS; i++) { + h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][i] = + pBsData->aaIccIndex[env][i]; + } + } + + /* MPEG baseline PS */ + /* Baseline version of PS always uses the hybrid filter structure with 20 + * stereo bands. */ + /* If ICC/IID parameters for 34 stereo bands are decoded they have to be + * mapped to 20 */ + /* stereo bands. */ + /* Additionaly the IPD/OPD parameters won't be used. */ + + for (env = 0; env < pBsData->noEnv; env++) { + if (pBsData->freqResIid == 2) + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env], + NO_HI_RES_IID_BINS); + if (pBsData->freqResIcc == 2) + map34IndexTo20(h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env], + NO_HI_RES_ICC_BINS); + + /* IPD/OPD is disabled in baseline version and thus was removed here */ + } + + return (1); +} + +/***************************************************************************/ +/*! + + \brief Reads parametric stereo data from bitstream + + \return + +****************************************************************************/ +unsigned int ReadPsData( + HANDLE_PS_DEC h_ps_d, /*!< handle to struct PS_DEC */ + HANDLE_FDK_BITSTREAM hBitBuf, /*!< handle to struct BIT_BUF */ + int nBitsLeft /*!< max number of bits available */ +) { + MPEG_PS_BS_DATA *pBsData; + + UCHAR gr, env; + SCHAR dtFlag; + INT startbits; + Huffman CurrentTable; + SCHAR bEnableHeader; + + if (!h_ps_d) return 0; + + pBsData = &h_ps_d->bsData[h_ps_d->bsReadSlot].mpeg; + + if (h_ps_d->bsReadSlot != h_ps_d->bsLastSlot) { + /* Copy last header data */ + FDKmemcpy(pBsData, &h_ps_d->bsData[h_ps_d->bsLastSlot].mpeg, + sizeof(MPEG_PS_BS_DATA)); + } + + startbits = (INT)FDKgetValidBits(hBitBuf); + + bEnableHeader = (SCHAR)FDKreadBits(hBitBuf, 1); + + /* Read header */ + if (bEnableHeader) { + pBsData->bPsHeaderValid = 1; + pBsData->bEnableIid = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bEnableIid) { + pBsData->modeIid = (UCHAR)FDKreadBits(hBitBuf, 3); + } + + pBsData->bEnableIcc = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bEnableIcc) { + pBsData->modeIcc = (UCHAR)FDKreadBits(hBitBuf, 3); + } + + pBsData->bEnableExt = (UCHAR)FDKreadBits(hBitBuf, 1); + } + + pBsData->bFrameClass = (UCHAR)FDKreadBits(hBitBuf, 1); + if (pBsData->bFrameClass == 0) { + /* FIX_BORDERS NoEnv=0,1,2,4 */ + pBsData->noEnv = + FDK_sbrDecoder_aFixNoEnvDecode[(UCHAR)FDKreadBits(hBitBuf, 2)]; + /* all additional handling of env borders is now in DecodePs() */ + } else { + /* VAR_BORDERS NoEnv=1,2,3,4 */ + pBsData->noEnv = 1 + (UCHAR)FDKreadBits(hBitBuf, 2); + for (env = 1; env < pBsData->noEnv + 1; env++) + pBsData->aEnvStartStop[env] = ((UCHAR)FDKreadBits(hBitBuf, 5)) + 1; + /* all additional handling of env borders is now in DecodePs() */ + } + + /* verify that IID & ICC modes (quant grid, freq res) are supported */ + if ((pBsData->modeIid > 5) || (pBsData->modeIcc > 5)) { + /* no useful PS data could be read from bitstream */ + h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_none; + /* discard all remaining bits */ + nBitsLeft -= startbits - (INT)FDKgetValidBits(hBitBuf); + while (nBitsLeft > 0) { + int i = nBitsLeft; + if (i > 8) { + i = 8; + } + FDKreadBits(hBitBuf, i); + nBitsLeft -= i; + } + return (UINT)(startbits - (INT)FDKgetValidBits(hBitBuf)); + } + + if (pBsData->modeIid > 2) { + pBsData->freqResIid = pBsData->modeIid - 3; + pBsData->bFineIidQ = 1; + } else { + pBsData->freqResIid = pBsData->modeIid; + pBsData->bFineIidQ = 0; + } + + if (pBsData->modeIcc > 2) { + pBsData->freqResIcc = pBsData->modeIcc - 3; + } else { + pBsData->freqResIcc = pBsData->modeIcc; + } + + /* Extract IID data */ + if (pBsData->bEnableIid) { + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); + if (!dtFlag) { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIidFreqDecode; + } else { + if (pBsData->bFineIidQ) + CurrentTable = (Huffman)&aBookPsIidFineTimeDecode; + else + CurrentTable = (Huffman)&aBookPsIidTimeDecode; + } + + for (gr = 0; gr < FDK_sbrDecoder_aNoIidBins[pBsData->freqResIid]; gr++) + pBsData->aaIidIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); + pBsData->abIidDtFlag[env] = dtFlag; + } + } + + /* Extract ICC data */ + if (pBsData->bEnableIcc) { + for (env = 0; env < pBsData->noEnv; env++) { + dtFlag = (SCHAR)FDKreadBits(hBitBuf, 1); + if (!dtFlag) + CurrentTable = (Huffman)&aBookPsIccFreqDecode; + else + CurrentTable = (Huffman)&aBookPsIccTimeDecode; + + for (gr = 0; gr < FDK_sbrDecoder_aNoIccBins[pBsData->freqResIcc]; gr++) + pBsData->aaIccIndex[env][gr] = + decode_huff_cw(CurrentTable, hBitBuf, NULL); + pBsData->abIccDtFlag[env] = dtFlag; + } + } + + if (pBsData->bEnableExt) { + /*! + Decoders that support only the baseline version of the PS tool are allowed + to ignore the IPD/OPD data, but according header data has to be parsed. + ISO/IEC 14496-3 Subpart 8 Annex 4 + */ + + int cnt = FDKreadBits(hBitBuf, PS_EXTENSION_SIZE_BITS); + if (cnt == (1 << PS_EXTENSION_SIZE_BITS) - 1) { + cnt += FDKreadBits(hBitBuf, PS_EXTENSION_ESC_COUNT_BITS); + } + while (cnt--) FDKreadBits(hBitBuf, 8); + } + + /* new PS data was read from bitstream */ + h_ps_d->bPsDataAvail[h_ps_d->bsReadSlot] = ppt_mpeg; + + return (startbits - (INT)FDKgetValidBits(hBitBuf)); +} diff --git a/fdk-aac/libSBRdec/src/psbitdec.h b/fdk-aac/libSBRdec/src/psbitdec.h new file mode 100644 index 0000000..f0fc43a --- /dev/null +++ b/fdk-aac/libSBRdec/src/psbitdec.h @@ -0,0 +1,116 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef PSBITDEC_H +#define PSBITDEC_H + +#include "sbrdecoder.h" + +#include "psdec.h" + +unsigned int ReadPsData(struct PS_DEC *h_ps_d, HANDLE_FDK_BITSTREAM hBs, + int nBitsLeft); + +int DecodePs(struct PS_DEC *h_ps_d, const UCHAR frameError, + PS_DEC_COEFFICIENTS *pCoef); + +#endif /* PSBITDEC_H */ diff --git a/fdk-aac/libSBRdec/src/psdec.cpp b/fdk-aac/libSBRdec/src/psdec.cpp new file mode 100644 index 0000000..b31b310 --- /dev/null +++ b/fdk-aac/libSBRdec/src/psdec.cpp @@ -0,0 +1,722 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder +*/ + +#include "psdec.h" + +#include "FDK_bitbuffer.h" + +#include "sbr_rom.h" +#include "sbr_ram.h" + +#include "FDK_tools_rom.h" + +#include "genericStds.h" + +#include "FDK_trigFcts.h" + +/********************************************************************/ +/* MLQUAL DEFINES */ +/********************************************************************/ + +#define FRACT_ZERO FRACT_BITS - 1 +/********************************************************************/ + +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d); + +/***** HELPERS *****/ + +/***************************************************************************/ +/*! + \brief Creates one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, /*!< pointer to the module state */ + int aacSamplesPerFrame) { + SBR_ERROR errorInfo = SBRDEC_OK; + HANDLE_PS_DEC h_ps_d; + int i; + + if (*h_PS_DEC == NULL) { + /* Get ps dec ram */ + h_ps_d = GetRam_ps_dec(); + if (h_ps_d == NULL) { + goto bail; + } + } else { + /* Reset an open instance */ + h_ps_d = *h_PS_DEC; + } + + /* + * Create Analysis Hybrid filterbank. + */ + FDKhybridAnalysisOpen(&h_ps_d->specificTo.mpeg.hybridAnalysis, + h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx, + sizeof(h_ps_d->specificTo.mpeg.pHybridAnaStatesLFdmx), + NULL, 0); + + /* initialisation */ + switch (aacSamplesPerFrame) { + case 960: + h_ps_d->noSubSamples = 30; /* col */ + break; + case 1024: + h_ps_d->noSubSamples = 32; /* col */ + break; + default: + h_ps_d->noSubSamples = -1; + break; + } + + if (h_ps_d->noSubSamples > MAX_NUM_COL || h_ps_d->noSubSamples <= 0) { + goto bail; + } + h_ps_d->noChannels = NO_QMF_CHANNELS; /* row */ + + h_ps_d->psDecodedPrv = 0; + h_ps_d->procFrameBased = -1; + for (i = 0; i < (1) + 1; i++) { + h_ps_d->bPsDataAvail[i] = ppt_none; + } + { + int error; + error = FDKdecorrelateOpen(&(h_ps_d->specificTo.mpeg.apDecor), + h_ps_d->specificTo.mpeg.decorrBufferCplx, + (2 * ((825) + (373)))); + if (error) goto bail; + } + + for (i = 0; i < (1) + 1; i++) { + FDKmemclear(&h_ps_d->bsData[i].mpeg, sizeof(MPEG_PS_BS_DATA)); + } + + errorInfo = ResetPsDec(h_ps_d); + + if (errorInfo != SBRDEC_OK) goto bail; + + *h_PS_DEC = h_ps_d; + + return 0; + +bail: + if (h_ps_d != NULL) { + DeletePsDec(&h_ps_d); + } + + return -1; +} /*END CreatePsDec */ + +/***************************************************************************/ +/*! + \brief Delete one instance of the PS_DEC struct + + \return Error info + +****************************************************************************/ +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC) /*!< pointer to the module state */ +{ + if (*h_PS_DEC == NULL) { + return -1; + } + + { + HANDLE_PS_DEC h_ps_d = *h_PS_DEC; + FDKdecorrelateClose(&(h_ps_d->specificTo.mpeg.apDecor)); + } + + FreeRam_ps_dec(h_PS_DEC); + + return 0; +} /*END DeletePsDec */ + +/***************************************************************************/ +/*! + \brief resets some values of the PS handle to default states + + \return + +****************************************************************************/ +SBR_ERROR ResetPsDec(HANDLE_PS_DEC h_ps_d) /*!< pointer to the module state */ +{ + SBR_ERROR errorInfo = SBRDEC_OK; + INT i; + + /* explicitly init state variables to safe values (until first ps header + * arrives) */ + + h_ps_d->specificTo.mpeg.lastUsb = 0; + + /* + * Initialize Analysis Hybrid filterbank. + */ + FDKhybridAnalysisInit(&h_ps_d->specificTo.mpeg.hybridAnalysis, THREE_TO_TEN, + NO_QMF_BANDS_HYBRID20, NO_QMF_BANDS_HYBRID20, 1); + + /* + * Initialize Synthesis Hybrid filterbank. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisInit(&h_ps_d->specificTo.mpeg.hybridSynthesis[i], + THREE_TO_TEN, NO_QMF_CHANNELS, NO_QMF_CHANNELS); + } + { + INT error; + error = FDKdecorrelateInit(&h_ps_d->specificTo.mpeg.apDecor, 71, DECORR_PS, + DUCKER_AUTOMATIC, 0, 0, 0, 0, 1, /* isLegacyPS */ + 1); + if (error) return SBRDEC_NOT_INITIALIZED; + } + + for (i = 0; i < NO_IID_GROUPS; i++) { + h_ps_d->specificTo.mpeg.h11rPrev[i] = FL2FXCONST_DBL(0.5f); + h_ps_d->specificTo.mpeg.h12rPrev[i] = FL2FXCONST_DBL(0.5f); + } + + FDKmemclear(h_ps_d->specificTo.mpeg.h21rPrev, + sizeof(h_ps_d->specificTo.mpeg.h21rPrev)); + FDKmemclear(h_ps_d->specificTo.mpeg.h22rPrev, + sizeof(h_ps_d->specificTo.mpeg.h22rPrev)); + + return errorInfo; +} + +/***************************************************************************/ +/*! + \brief Feed delaylines when parametric stereo is switched on. + \return +****************************************************************************/ +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand) { + if (h_ps_d->procFrameBased == + 1) /* If we have switched from frame to slot based processing */ + { /* fill hybrid delay buffer. */ + int i, j; + + for (i = 0; i < HYBRID_FILTER_DELAY; i++) { + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL hybridOutputData[2][NO_SUB_QMF_CHANNELS]; + + for (j = 0; j < NO_QMF_BANDS_HYBRID20; j++) { + qmfInputData[0][j] = + scaleValue(rIntBufferLeft[i][j], scaleFactorLowBand); + qmfInputData[1][j] = + scaleValue(iIntBufferLeft[i][j], scaleFactorLowBand); + } + + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], + hybridOutputData[0], hybridOutputData[1]); + } + h_ps_d->procFrameBased = 0; /* switch to slot based processing. */ + + } /* procFrameBased==1 */ +} + +void initSlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + int env, int usb) { + INT group = 0; + INT bin = 0; + INT noIidSteps, noFactors; + + FIXP_SGL invL; + FIXP_DBL ScaleL, ScaleR; + FIXP_DBL Alpha, Beta, AlphasValue; + FIXP_DBL h11r, h12r, h21r, h22r; + + const FIXP_DBL *PScaleFactors; + + if (h_ps_d->bsData[h_ps_d->processSlot].mpeg.bFineIidQ) { + PScaleFactors = ScaleFactorsFine; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS_FINE; + noFactors = NO_IID_LEVELS_FINE; + } else { + PScaleFactors = ScaleFactors; /* values are shiftet right by one */ + noIidSteps = NO_IID_STEPS; + noFactors = NO_IID_LEVELS; + } + + /* dequantize and decode */ + for (group = 0; group < NO_IID_GROUPS; group++) { + bin = bins2groupMap20[group]; + + /*! +

type 'A' rotation

+ mixing procedure R_a, used in baseline version
+ + Scale-factor vectors c1 and c2 are precalculated in initPsTables () and + stored in scaleFactors[] and scaleFactorsFine[] = pScaleFactors []. From the + linearized IID parameters (intensity differences), two scale factors are + calculated. They are used to obtain the coefficients h11... h22. + */ + + /* ScaleR and ScaleL are scaled by 1 shift right */ + + ScaleL = ScaleR = 0; + if (noIidSteps + h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][bin] >= 0 && noIidSteps + h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][bin] < noFactors) + ScaleR = PScaleFactors[noIidSteps + h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; + if (noIidSteps - h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][bin] >= 0 && noIidSteps - h_ps_d->specificTo.mpeg.pCoef->aaIidIndexMapped[env][bin] < noFactors) + ScaleL = PScaleFactors[noIidSteps - h_ps_d->specificTo.mpeg.pCoef + ->aaIidIndexMapped[env][bin]]; + + AlphasValue = 0; + if (h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin] >= 0) + AlphasValue = Alphas[h_ps_d->specificTo.mpeg.pCoef->aaIccIndexMapped[env][bin]]; + Beta = fMult( + fMult(AlphasValue, + (ScaleR - ScaleL)), + FIXP_SQRT05); + Alpha = + AlphasValue >> 1; + + /* Alpha and Beta are now both scaled by 2 shifts right */ + + /* calculate the coefficients h11... h22 from scale-factors and ICC + * parameters */ + + /* h values are scaled by 1 shift right */ + { + FIXP_DBL trigData[4]; + + inline_fixp_cos_sin(Beta + Alpha, Beta - Alpha, 2, trigData); + h11r = fMult(ScaleL, trigData[0]); + h12r = fMult(ScaleR, trigData[2]); + h21r = fMult(ScaleL, trigData[1]); + h22r = fMult(ScaleR, trigData[3]); + } + /*****************************************************************************************/ + /* Interpolation of the matrices H11... H22: */ + /* */ + /* H11(k,n) = H11(k,n[e]) + (n-n[e]) * (H11(k,n[e+1] - H11(k,n[e])) / + * (n[e+1] - n[e]) */ + /* ... */ + /*****************************************************************************************/ + + /* invL = 1/(length of envelope) */ + invL = FX_DBL2FX_SGL(GetInvInt( + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env + 1] - + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env])); + + h_ps_d->specificTo.mpeg.pCoef->H11r[group] = + h_ps_d->specificTo.mpeg.h11rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H12r[group] = + h_ps_d->specificTo.mpeg.h12rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H21r[group] = + h_ps_d->specificTo.mpeg.h21rPrev[group]; + h_ps_d->specificTo.mpeg.pCoef->H22r[group] = + h_ps_d->specificTo.mpeg.h22rPrev[group]; + + h_ps_d->specificTo.mpeg.pCoef->DeltaH11r[group] = + fMult(h11r - h_ps_d->specificTo.mpeg.pCoef->H11r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH12r[group] = + fMult(h12r - h_ps_d->specificTo.mpeg.pCoef->H12r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH21r[group] = + fMult(h21r - h_ps_d->specificTo.mpeg.pCoef->H21r[group], invL); + h_ps_d->specificTo.mpeg.pCoef->DeltaH22r[group] = + fMult(h22r - h_ps_d->specificTo.mpeg.pCoef->H22r[group], invL); + + /* update prev coefficients for interpolation in next envelope */ + + h_ps_d->specificTo.mpeg.h11rPrev[group] = h11r; + h_ps_d->specificTo.mpeg.h12rPrev[group] = h12r; + h_ps_d->specificTo.mpeg.h21rPrev[group] = h21r; + h_ps_d->specificTo.mpeg.h22rPrev[group] = h22r; + + } /* group loop */ +} + +static const UCHAR groupTable[NO_IID_GROUPS + 1] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static void applySlotBasedRotation( + HANDLE_PS_DEC h_ps_d, /*!< pointer to the module state */ + + FIXP_DBL *mHybridRealLeft, /*!< hybrid values real left */ + FIXP_DBL *mHybridImagLeft, /*!< hybrid values imag left */ + + FIXP_DBL *mHybridRealRight, /*!< hybrid values real right */ + FIXP_DBL *mHybridImagRight /*!< hybrid values imag right */ +) { + INT group; + INT subband; + + /**********************************************************************************************/ + /*! +

Mapping

+ + The number of stereo bands that is actually used depends on the number of + availble parameters for IID and ICC:
 nr. of IID para.| nr. of ICC para.
+  | nr. of Stereo bands
+   ----------------|------------------|-------------------
+     10,20         |     10,20        |        20
+     10,20         |     34           |        34
+     34            |     10,20        |        34
+     34            |     34           |        34
+  
+ In the case the number of parameters for IIS and ICC differs from the number + of stereo bands, a mapping from the lower number to the higher number of + parameters is applied. Index mapping of IID and ICC parameters is already done + in psbitdec.cpp. Further mapping is not needed here in baseline version. + **********************************************************************************************/ + + /************************************************************************************************/ + /*! +

Mixing

+ + To generate the QMF subband signals for the subband samples n = n[e]+1 ,,, + n_[e+1] the parameters at position n[e] and n[e+1] are required as well as the + subband domain signals s_k(n) and d_k(n) for n = n[e]+1... n_[e+1]. n[e] + represents the start position for envelope e. The border positions n[e] are + handled in DecodePS(). + + The stereo sub subband signals are constructed as: +
+  l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n)
+  r_k(n) = H21(k,n) s_k(n) + H22(k,n) d_k(n)
+  
+ In order to obtain the matrices H11(k,n)... H22 (k,n), the vectors h11(b)... + h22(b) need to be calculated first (b: parameter index). Depending on ICC mode + either mixing procedure R_a or R_b is used for that. For both procedures, the + parameters for parameter position n[e+1] is used. + ************************************************************************************************/ + + /************************************************************************************************/ + /*! +

Phase parameters

+ With disabled phase parameters (which is the case in baseline version), the + H-matrices are just calculated by: + +
+  H11(k,n[e+1] = h11(b(k))
+  (...)
+  b(k): parameter index according to mapping table
+  
+ +

Processing of the samples in the sub subbands

+ this loop includes the interpolation of the coefficients Hxx + ************************************************************************************************/ + + /******************************************************/ + /* construct stereo sub subband signals according to: */ + /* */ + /* l_k(n) = H11(k,n) s_k(n) + H21(k,n) d_k(n) */ + /* r_k(n) = H12(k,n) s_k(n) + H22(k,n) d_k(n) */ + /******************************************************/ + PS_DEC_COEFFICIENTS *pCoef = h_ps_d->specificTo.mpeg.pCoef; + + for (group = 0; group < NO_IID_GROUPS; group++) { + pCoef->H11r[group] += pCoef->DeltaH11r[group]; + pCoef->H12r[group] += pCoef->DeltaH12r[group]; + pCoef->H21r[group] += pCoef->DeltaH21r[group]; + pCoef->H22r[group] += pCoef->DeltaH22r[group]; + + const int start = groupTable[group]; + const int stop = groupTable[group + 1]; + for (subband = start; subband < stop; subband++) { + FIXP_DBL tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridRealLeft[subband]), + pCoef->H21r[group], mHybridRealRight[subband]); + FIXP_DBL tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridRealLeft[subband]), + pCoef->H22r[group], mHybridRealRight[subband]); + mHybridRealLeft[subband] = tmpLeft; + mHybridRealRight[subband] = tmpRight; + + tmpLeft = + fMultAdd(fMultDiv2(pCoef->H11r[group], mHybridImagLeft[subband]), + pCoef->H21r[group], mHybridImagRight[subband]); + tmpRight = + fMultAdd(fMultDiv2(pCoef->H12r[group], mHybridImagLeft[subband]), + pCoef->H22r[group], mHybridImagRight[subband]); + mHybridImagLeft[subband] = tmpLeft; + mHybridImagRight[subband] = tmpRight; + } /* subband */ + } +} + +/***************************************************************************/ +/*! + \brief Applies IID, ICC, IPD and OPD parameters to the current frame. + + \return none + +****************************************************************************/ +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /*!< handle PS_DEC*/ + FIXP_DBL **rIntBufferLeft, /*!< real bands left qmf channel (38x64) */ + FIXP_DBL **iIntBufferLeft, /*!< imag bands left qmf channel (38x64) */ + FIXP_DBL *rIntBufferRight, /*!< real bands right qmf channel (38x64) */ + FIXP_DBL *iIntBufferRight, /*!< imag bands right qmf channel (38x64) */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb) { +/*! +The 64-band QMF representation of the monaural signal generated by the SBR tool +is used as input of the PS tool. After the PS processing, the outputs of the +left and right hybrid synthesis filterbanks are used to generate the stereo +output signal. + +
+
+           -------------            ----------            -------------
+          | Hybrid      | M_n[k,m] |          | L_n[k,m] | Hybrid      | l[n]
+ m[n] --->| analysis    |--------->|          |--------->| synthesis   |----->
+           -------------           | Stereo   |           -------------
+                 |                 | recon-   |
+                 |                 | stuction |
+                \|/                |          |
+           -------------           |          |
+          | De-         | D_n[k,m] |          |
+          | correlation |--------->|          |
+           -------------           |          |           -------------
+                                   |          | R_n[k,m] | Hybrid      | r[n]
+                                   |          |--------->| synthesis   |----->
+ IID, ICC ------------------------>|          |          | filter bank |
+(IPD, OPD)                          ----------            -------------
+
+m[n]:      QMF represantation of the mono input
+M_n[k,m]:  (sub-)sub-band domain signals of the mono input
+D_n[k,m]:  decorrelated (sub-)sub-band domain signals
+L_n[k,m]:  (sub-)sub-band domain signals of the left output
+R_n[k,m]:  (sub-)sub-band domain signals of the right output
+l[n],r[n]: left/right output signals
+
+
+*/ +#define NO_HYBRID_DATA_BANDS (71) + + int i; + FIXP_DBL qmfInputData[2][NO_QMF_BANDS_HYBRID20]; + FIXP_DBL *hybridData[2][2]; + C_ALLOC_SCRATCH_START(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); + + hybridData[0][0] = + pHybridData + 0 * NO_HYBRID_DATA_BANDS; /* left real hybrid data */ + hybridData[0][1] = + pHybridData + 1 * NO_HYBRID_DATA_BANDS; /* left imag hybrid data */ + hybridData[1][0] = + pHybridData + 2 * NO_HYBRID_DATA_BANDS; /* right real hybrid data */ + hybridData[1][1] = + pHybridData + 3 * NO_HYBRID_DATA_BANDS; /* right imag hybrid data */ + + /*! + Hybrid analysis filterbank: + The lower 3 (5) of the 64 QMF subbands are further split to provide better + frequency resolution. for PS processing. For the 10 and 20 stereo bands + configuration, the QMF band H_0(w) is split up into 8 (sub-) sub-bands and the + QMF bands H_1(w) and H_2(w) are spit into 2 (sub-) 4th. (See figures 8.20 + and 8.22 of ISO/IEC 14496-3:2001/FDAM 2:2004(E) ) + */ + + /* + * Hybrid analysis. + */ + + /* Get qmf input data and apply descaling */ + for (i = 0; i < NO_QMF_BANDS_HYBRID20; i++) { + qmfInputData[0][i] = scaleValue(rIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + qmfInputData[1][i] = scaleValue(iIntBufferLeft[HYBRID_FILTER_DELAY][i], + scaleFactorLowBand_no_ov); + } + + /* LF - part */ + FDKhybridAnalysisApply(&h_ps_d->specificTo.mpeg.hybridAnalysis, + qmfInputData[0], qmfInputData[1], hybridData[0][0], + hybridData[0][1]); + + /* HF - part */ + /* bands up to lsb */ + scaleValues(&hybridData[0][0][NO_SUB_QMF_CHANNELS - 2], + &rIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + scaleValues(&hybridData[0][1][NO_SUB_QMF_CHANNELS - 2], + &iIntBufferLeft[0][NO_QMF_BANDS_HYBRID20], + lsb - NO_QMF_BANDS_HYBRID20, scaleFactorLowBand); + + /* bands from lsb to usb */ + scaleValues(&hybridData[0][0][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + scaleValues(&hybridData[0][1][lsb + (NO_SUB_QMF_CHANNELS - 2 - + NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][lsb], usb - lsb, scaleFactorHighBand); + + /* bands from usb to NO_SUB_QMF_CHANNELS which should be zero for non-overlap + slots but can be non-zero for overlap slots */ + FDKmemcpy( + &hybridData[0][0] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &rIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); + FDKmemcpy( + &hybridData[0][1] + [usb + (NO_SUB_QMF_CHANNELS - 2 - NO_QMF_BANDS_HYBRID20)], + &iIntBufferLeft[0][usb], sizeof(FIXP_DBL) * (NO_QMF_CHANNELS - usb)); + + /*! + Decorrelation: + By means of all-pass filtering and delaying, the (sub-)sub-band samples s_k(n) + are converted into de-correlated (sub-)sub-band samples d_k(n). + - k: frequency in hybrid spectrum + - n: time index + */ + + FDKdecorrelateApply(&h_ps_d->specificTo.mpeg.apDecor, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0], /* right imag hybrid data */ + 0 /* startHybBand */ + ); + + /*! + Stereo Processing: + The sets of (sub-)sub-band samples s_k(n) and d_k(n) are processed according + to the stereo cues which are defined per stereo band. + */ + + applySlotBasedRotation(h_ps_d, + &hybridData[0][0][0], /* left real hybrid data */ + &hybridData[0][1][0], /* left imag hybrid data */ + &hybridData[1][0][0], /* right real hybrid data */ + &hybridData[1][1][0] /* right imag hybrid data */ + ); + + /*! + Hybrid synthesis filterbank: + The stereo processed hybrid subband signals l_k(n) and r_k(n) are fed into the + hybrid synthesis filterbanks which are identical to the 64 complex synthesis + filterbank of the SBR tool. The input to the filterbank are slots of 64 QMF + samples. For each slot the filterbank outputs one block of 64 samples of one + reconstructed stereo channel. The hybrid synthesis filterbank is computed + seperatly for the left and right channel. + */ + + /* + * Hybrid synthesis. + */ + for (i = 0; i < 2; i++) { + FDKhybridSynthesisApply( + &h_ps_d->specificTo.mpeg.hybridSynthesis[i], + hybridData[i][0], /* real hybrid data */ + hybridData[i][1], /* imag hybrid data */ + (i == 0) ? rIntBufferLeft[0] + : rIntBufferRight, /* output real qmf buffer */ + (i == 0) ? iIntBufferLeft[0] + : iIntBufferRight /* output imag qmf buffer */ + ); + } + + /* free temporary hybrid qmf values of one timeslot */ + C_ALLOC_SCRATCH_END(pHybridData, FIXP_DBL, 4 * NO_HYBRID_DATA_BANDS); + +} /* END ApplyPsSlot */ diff --git a/fdk-aac/libSBRdec/src/psdec.h b/fdk-aac/libSBRdec/src/psdec.h new file mode 100644 index 0000000..029eac4 --- /dev/null +++ b/fdk-aac/libSBRdec/src/psdec.h @@ -0,0 +1,333 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef PSDEC_H +#define PSDEC_H + +#include "sbrdecoder.h" +#include "FDK_hybrid.h" + +#include "FDK_decorrelate.h" + +/* This PS decoder implements the baseline version. So it always uses the */ +/* hybrid filter structure for 20 stereo bands and does not implemet IPD/OPD */ +/* synthesis. The baseline version has to support the complete PS bitstream */ +/* syntax. But IPD/OPD data is ignored and set to 0. If 34 stereo band config */ +/* is used in the bitstream for IIS/ICC the decoded parameters are mapped to */ +/* 20 stereo bands. */ + +#include "FDK_bitstream.h" + +#define SCAL_HEADROOM (2) + +#define PS_EXTENSION_SIZE_BITS (4) +#define PS_EXTENSION_ESC_COUNT_BITS (8) + +#define NO_QMF_CHANNELS (64) +#define MAX_NUM_COL (32) + +#define NO_QMF_BANDS_HYBRID20 (3) +#define NO_SUB_QMF_CHANNELS (12) +#define HYBRID_FILTER_DELAY (6) + +#define MAX_NO_PS_ENV (4 + 1) /* +1 needed for VAR_BORDER */ + +#define NO_HI_RES_BINS (34) +#define NO_MID_RES_BINS (20) +#define NO_LOW_RES_BINS (10) + +#define NO_HI_RES_IID_BINS (NO_HI_RES_BINS) +#define NO_HI_RES_ICC_BINS (NO_HI_RES_BINS) + +#define NO_MID_RES_IID_BINS (NO_MID_RES_BINS) +#define NO_MID_RES_ICC_BINS (NO_MID_RES_BINS) + +#define NO_LOW_RES_IID_BINS (NO_LOW_RES_BINS) +#define NO_LOW_RES_ICC_BINS (NO_LOW_RES_BINS) + +#define SUBQMF_GROUPS (10) +#define QMF_GROUPS (12) + +//#define SUBQMF_GROUPS_HI_RES ( 32 ) +//#define QMF_GROUPS_HI_RES ( 18 ) + +#define NO_IID_GROUPS (SUBQMF_GROUPS + QMF_GROUPS) +//#define NO_IID_GROUPS_HI_RES ( SUBQMF_GROUPS_HI_RES + +// QMF_GROUPS_HI_RES ) + +#define NO_IID_STEPS (7) /* 1 .. + 7 */ +#define NO_IID_STEPS_FINE (15) /* 1 .. +15 */ +#define NO_ICC_STEPS (8) /* 0 .. + 7 */ + +#define NO_IID_LEVELS (2 * NO_IID_STEPS + 1) /* - 7 .. + 7 */ +#define NO_IID_LEVELS_FINE (2 * NO_IID_STEPS_FINE + 1) /* -15 .. +15 */ +#define NO_ICC_LEVELS (NO_ICC_STEPS) /* 0 .. + 7 */ + +#define FIXP_SQRT05 ((FIXP_DBL)0x5a827980) /* 1/SQRT2 */ + +struct PS_DEC_COEFFICIENTS { + FIXP_DBL H11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL H22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + FIXP_DBL + DeltaH11r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH12r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH21r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + FIXP_DBL + DeltaH22r[NO_IID_GROUPS]; /*!< coefficients of the sub-subband groups */ + + SCHAR + aaIidIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The mapped IID index for all + envelopes and all IID bins */ + SCHAR + aaIccIndexMapped[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The mapped ICC index for all + envelopes and all ICC bins */ +}; + +typedef enum { ppt_none = 0, ppt_mpeg = 1, ppt_drm = 2 } PS_PAYLOAD_TYPE; + +typedef struct { + UCHAR bPsHeaderValid; /*!< set if new header is available from bitstream */ + + UCHAR bEnableIid; /*!< One bit denoting the presence of IID parameters */ + UCHAR bEnableIcc; /*!< One bit denoting the presence of ICC parameters */ + UCHAR bEnableExt; /*!< The PS extension layer is enabled using the enable_ext + bit. If it is set to %1 the IPD and OPD parameters are + sent. If it is disabled, i.e. %0, the extension layer is + skipped. */ + + UCHAR + modeIid; /*!< The configuration of IID parameters (number of bands and + quantisation grid, iid_quant) is determined by iid_mode. */ + UCHAR modeIcc; /*!< The configuration of Inter-channel Coherence parameters + (number of bands and quantisation grid) is determined by + icc_mode. */ + + UCHAR freqResIid; /*!< 0=low, 1=mid or 2=high frequency resolution for iid */ + UCHAR freqResIcc; /*!< 0=low, 1=mid or 2=high frequency resolution for icc */ + + UCHAR bFineIidQ; /*!< Use fine Iid quantisation. */ + + UCHAR bFrameClass; /*!< The frame_class bit determines whether the parameter + positions of the current frame are uniformly spaced + accross the frame or they are defined using the + positions described by border_position. + */ + + UCHAR noEnv; /*!< The number of envelopes per frame */ + UCHAR aEnvStartStop[MAX_NO_PS_ENV + 1]; /*!< In case of variable parameter + spacing the parameter positions are + determined by border_position */ + + SCHAR abIidDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for IID, 0 + => freq */ + SCHAR abIccDtFlag[MAX_NO_PS_ENV]; /*!< Deltacoding time/freq flag for ICC, 0 + => freq */ + + SCHAR + aaIidIndex[MAX_NO_PS_ENV] + [NO_HI_RES_IID_BINS]; /*!< The IID index for all envelopes and + all IID bins */ + SCHAR + aaIccIndex[MAX_NO_PS_ENV] + [NO_HI_RES_ICC_BINS]; /*!< The ICC index for all envelopes and + all ICC bins */ + +} MPEG_PS_BS_DATA; + +struct PS_DEC { + SCHAR noSubSamples; + SCHAR noChannels; + + SCHAR procFrameBased; /*!< Helper to detected switching from frame based to + slot based processing + */ + + PS_PAYLOAD_TYPE + bPsDataAvail[(1) + 1]; /*!< set if new data available from bitstream */ + UCHAR psDecodedPrv; /*!< set if PS has been processed in the last frame */ + + /* helpers for frame delay line */ + UCHAR bsLastSlot; /*!< Index of last read slot. */ + UCHAR bsReadSlot; /*!< Index of current read slot for additional delay. */ + UCHAR processSlot; /*!< Index of current slot for processing (need for add. + delay). */ + + union { /* Bitstream data */ + MPEG_PS_BS_DATA + mpeg; /*!< Struct containing all MPEG specific PS data from bitstream. + */ + } bsData[(1) + 1]; + + shouldBeUnion { /* Static data */ + struct { + SCHAR aIidPrevFrameIndex[NO_HI_RES_IID_BINS]; /*!< The IID index for + previous frame */ + SCHAR aIccPrevFrameIndex[NO_HI_RES_ICC_BINS]; /*!< The ICC index for + previous frame */ + UCHAR + bPrevFrameFineIidQ; /*!< The IID quantization of the previous frame */ + UCHAR prevFreqResIid; /*!< Frequency resolution for IID of the previous + frame */ + UCHAR prevFreqResIcc; /*!< Frequency resolution for ICC of the previous + frame */ + UCHAR lastUsb; /*!< uppermost WMF delay band of last frame */ + + FIXP_DBL pHybridAnaStatesLFdmx + [2 * 13 * NO_QMF_BANDS_HYBRID20]; /*!< Memory used in hybrid analysis + for filter states. */ + FDK_ANA_HYB_FILTER hybridAnalysis; + FDK_SYN_HYB_FILTER hybridSynthesis[2]; + + DECORR_DEC apDecor; /*!< Decorrelator instance. */ + FIXP_DBL decorrBufferCplx[(2 * ((825) + (373)))]; + + FIXP_DBL h11rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h12rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h21rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + FIXP_DBL h22rPrev[NO_IID_GROUPS]; /*!< previous calculated h(xy) + coefficients */ + + PS_DEC_COEFFICIENTS + *pCoef; /*!< temporal coefficients are on reusable scratch memory */ + + } mpeg; + } + specificTo; +}; + +typedef struct PS_DEC *HANDLE_PS_DEC; + +int CreatePsDec(HANDLE_PS_DEC *h_PS_DEC, int aacSamplesPerFrame); + +int DeletePsDec(HANDLE_PS_DEC *h_PS_DEC); + +void PreparePsProcessing(HANDLE_PS_DEC h_ps_d, + const FIXP_DBL *const *const rIntBufferLeft, + const FIXP_DBL *const *const iIntBufferLeft, + const int scaleFactorLowBand); + +void initSlotBasedRotation(HANDLE_PS_DEC h_ps_d, int env, int usb); + +void ApplyPsSlot( + HANDLE_PS_DEC h_ps_d, /* parametric stereo decoder handle */ + FIXP_DBL **rIntBufferLeft, /* real values of left qmf timeslot */ + FIXP_DBL **iIntBufferLeft, /* imag values of left qmf timeslot */ + FIXP_DBL *rIntBufferRight, /* real values of right qmf timeslot */ + FIXP_DBL *iIntBufferRight, /* imag values of right qmf timeslot */ + const int scaleFactorLowBand_no_ov, const int scaleFactorLowBand, + const int scaleFactorHighBand, const int lsb, const int usb); + +#endif /* PSDEC_H */ diff --git a/fdk-aac/libSBRdec/src/psdec_drm.cpp b/fdk-aac/libSBRdec/src/psdec_drm.cpp new file mode 100644 index 0000000..6971f53 --- /dev/null +++ b/fdk-aac/libSBRdec/src/psdec_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder for Digital radio mondial +*/ + +#include "psdec_drm.h" diff --git a/fdk-aac/libSBRdec/src/psdec_drm.h b/fdk-aac/libSBRdec/src/psdec_drm.h new file mode 100644 index 0000000..5e2575d --- /dev/null +++ b/fdk-aac/libSBRdec/src/psdec_drm.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief parametric stereo decoder for digital radio mondial +*/ + +#ifndef PSDEC_DRM_H +#define PSDEC_DRM_H + +#include "sbrdecoder.h" + +#endif /* PSDEC_DRM_H */ diff --git a/fdk-aac/libSBRdec/src/psdecrom_drm.cpp b/fdk-aac/libSBRdec/src/psdecrom_drm.cpp new file mode 100644 index 0000000..2033a83 --- /dev/null +++ b/fdk-aac/libSBRdec/src/psdecrom_drm.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief rom tables for Drm parametric stereo decoder +*/ + +#include "psdec_drm.h" diff --git a/fdk-aac/libSBRdec/src/pvc_dec.cpp b/fdk-aac/libSBRdec/src/pvc_dec.cpp new file mode 100644 index 0000000..b477122 --- /dev/null +++ b/fdk-aac/libSBRdec/src/pvc_dec.cpp @@ -0,0 +1,683 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#include "pvc_dec.h" + +/* PVC interal definitions */ +#define PVC_DIVMODE_BITS 3 +#define PVC_NSMODE_BITS 1 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 +#define PVC_NQMFBAND 64 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NTAB1 3 +#define PVC_NTAB2 128 +#define PVC_ID_NBIT 7 + +/* Exponent of pPvcStaticData->Esg and predictedEsg in dB domain. + max(Esg) = 10*log10(2^15*2^15) = 90.30; + min(Esg) = 10*log10(0.1) = -10 + max of predicted Esg seems to be higher than 90dB but 7 Bit should be enough. +*/ +#define PVC_ESG_EXP 7 + +#define LOG10FAC 0.752574989159953f /* == 10/log2(10) * 2^-2 */ +#define LOG10FAC_INV 0.664385618977472f /* == log2(10)/10 * 2^1 */ + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_16[] = { + FX_DBL2FXCONST_SGL(0x14413695), FX_DBL2FXCONST_SGL(0x1434b6cb), + FX_DBL2FXCONST_SGL(0x140f27c7), FX_DBL2FXCONST_SGL(0x13d0591d), + FX_DBL2FXCONST_SGL(0x1377f502), FX_DBL2FXCONST_SGL(0x130577d6), + FX_DBL2FXCONST_SGL(0x12782266), FX_DBL2FXCONST_SGL(0x11cee459), + FX_DBL2FXCONST_SGL(0x11083a2a), FX_DBL2FXCONST_SGL(0x1021f5e9), + FX_DBL2FXCONST_SGL(0x0f18e17c), FX_DBL2FXCONST_SGL(0x0de814ca), + FX_DBL2FXCONST_SGL(0x0c87a568), FX_DBL2FXCONST_SGL(0x0ae9b167), + FX_DBL2FXCONST_SGL(0x08f24226), FX_DBL2FXCONST_SGL(0x06575ed5), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_12[] = { + FX_DBL2FXCONST_SGL(0x1aba6b3e), FX_DBL2FXCONST_SGL(0x1a9d164e), + FX_DBL2FXCONST_SGL(0x1a44d56d), FX_DBL2FXCONST_SGL(0x19b0d742), + FX_DBL2FXCONST_SGL(0x18df969a), FX_DBL2FXCONST_SGL(0x17ce91a0), + FX_DBL2FXCONST_SGL(0x1679c3fa), FX_DBL2FXCONST_SGL(0x14daabfc), + FX_DBL2FXCONST_SGL(0x12e65221), FX_DBL2FXCONST_SGL(0x1088d125), + FX_DBL2FXCONST_SGL(0x0d9907b3), FX_DBL2FXCONST_SGL(0x09a80e9d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_4[] = { + FX_DBL2FXCONST_SGL(0x4ad6ab0f), + FX_DBL2FXCONST_SGL(0x47ef0dbe), + FX_DBL2FXCONST_SGL(0x3eee7496), + FX_DBL2FXCONST_SGL(0x2e4bd29d), +}; + +RAM_ALIGN +LNK_SECTION_CONSTDATA +static const FIXP_SGL pvc_SC_3[] = { + FX_DBL2FXCONST_SGL(0x610dc761), + FX_DBL2FXCONST_SGL(0x5a519a3d), + FX_DBL2FXCONST_SGL(0x44a09e62), +}; + +static const UCHAR g_3a_pvcTab1_mode1[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE1] = + {{{0x4F, 0x5B, 0x57, 0x52, 0x4D, 0x65, 0x45, 0x57}, + {0xF3, 0x0F, 0x18, 0x20, 0x19, 0x4F, 0x3D, 0x23}, + {0x78, 0x57, 0x55, 0x50, 0x50, 0x20, 0x36, 0x37}}, + {{0x4C, 0x5F, 0x53, 0x37, 0x1E, 0xFD, 0x15, 0x0A}, + {0x05, 0x0E, 0x28, 0x41, 0x48, 0x6E, 0x54, 0x5B}, + {0x59, 0x47, 0x40, 0x40, 0x3D, 0x33, 0x3F, 0x39}}, + {{0x47, 0x5F, 0x57, 0x34, 0x3C, 0x2E, 0x2E, 0x31}, + {0xFA, 0x13, 0x23, 0x4E, 0x44, 0x7C, 0x34, 0x38}, + {0x63, 0x43, 0x41, 0x3D, 0x35, 0x19, 0x3D, 0x33}}}; + +static const UCHAR g_2a_pvcTab2_mode1[PVC_NTAB2][PVC_NBHIGH_MODE1] = { + {0xCB, 0xD1, 0xCC, 0xD2, 0xE2, 0xEB, 0xE7, 0xE8}, + {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80}, + {0x84, 0x8C, 0x88, 0x83, 0x90, 0x93, 0x86, 0x80}, + {0xD7, 0xD8, 0xC0, 0xC7, 0xCF, 0xE5, 0xF1, 0xF6}, + {0xA5, 0xA6, 0xAA, 0xA8, 0xB0, 0xB1, 0xB8, 0xB8}, + {0xD7, 0xCB, 0xC1, 0xC3, 0xC5, 0xC9, 0xC9, 0xCE}, + {0xCA, 0xB5, 0xB8, 0xB3, 0xAC, 0xB6, 0xBB, 0xB8}, + {0xC1, 0xC4, 0xC3, 0xC5, 0xC6, 0xCA, 0xCA, 0xCB}, + {0xE0, 0xE1, 0xD8, 0xCD, 0xCB, 0xCB, 0xCE, 0xCC}, + {0xDB, 0xE1, 0xDF, 0xDB, 0xDC, 0xD9, 0xD9, 0xD6}, + {0xE0, 0xDE, 0xDD, 0xDD, 0xE0, 0xE3, 0xE5, 0xE6}, + {0xCA, 0xD2, 0xCD, 0xCE, 0xD5, 0xDB, 0xD9, 0xDB}, + {0xD2, 0xE0, 0xDB, 0xD5, 0xDB, 0xDE, 0xE3, 0xE1}, + {0xE5, 0xDB, 0xD0, 0xD2, 0xD8, 0xDD, 0xDB, 0xDD}, + {0xC0, 0xB5, 0xBF, 0xDD, 0xE3, 0xDC, 0xDC, 0xE4}, + {0xDB, 0xCE, 0xC6, 0xCF, 0xCF, 0xD1, 0xD3, 0xD4}, + {0xC9, 0xD7, 0xDA, 0xE2, 0xE9, 0xE7, 0xDF, 0xDC}, + {0x0A, 0x07, 0x0A, 0x08, 0x19, 0x24, 0x1F, 0x22}, + {0x1E, 0x1F, 0x11, 0x0E, 0x22, 0x2D, 0x33, 0x32}, + {0xF0, 0xDA, 0xDC, 0x18, 0x1F, 0x19, 0x0A, 0x1E}, + {0x09, 0xF8, 0xE6, 0x05, 0x19, 0x11, 0x0E, 0x0B}, + {0x09, 0x10, 0x0E, 0xE6, 0xF4, 0x20, 0x22, 0xFA}, + {0xF2, 0xE5, 0xF8, 0x0E, 0x18, 0x15, 0x0D, 0x10}, + {0x15, 0x13, 0x16, 0x0A, 0x0D, 0x1F, 0x1D, 0x1B}, + {0xFA, 0xFF, 0xFE, 0xFF, 0x09, 0x11, 0x03, 0x0B}, + {0xFE, 0xFA, 0xF2, 0xF8, 0x0C, 0x1E, 0x11, 0x12}, + {0xFA, 0xF8, 0x0B, 0x17, 0x1D, 0x17, 0x0E, 0x16}, + {0x00, 0xF3, 0xFD, 0x0A, 0x1C, 0x17, 0xFD, 0x08}, + {0xEA, 0xEA, 0x03, 0x12, 0x1E, 0x14, 0x09, 0x04}, + {0x02, 0xFE, 0x04, 0xFB, 0x0C, 0x0E, 0x07, 0x02}, + {0xF6, 0x02, 0x07, 0x0B, 0x17, 0x17, 0x01, 0xFF}, + {0xF5, 0xFB, 0xFE, 0x04, 0x12, 0x14, 0x0C, 0x0D}, + {0x10, 0x10, 0x0E, 0x04, 0x07, 0x11, 0x0F, 0x13}, + {0x0C, 0x0F, 0xFB, 0xF2, 0x0A, 0x12, 0x09, 0x0D}, + {0x0D, 0x1D, 0xF1, 0xF4, 0x2A, 0x06, 0x3B, 0x32}, + {0xFC, 0x08, 0x06, 0x02, 0x0E, 0x17, 0x08, 0x0E}, + {0x07, 0x02, 0xEE, 0xEE, 0x2B, 0xF6, 0x23, 0x13}, + {0x04, 0x02, 0x05, 0x08, 0x0B, 0x0E, 0xFB, 0xFB}, + {0x00, 0x04, 0x10, 0x18, 0x22, 0x25, 0x1D, 0x1F}, + {0xFB, 0x0D, 0x07, 0x00, 0x0C, 0x0F, 0xFC, 0x02}, + {0x00, 0x00, 0x00, 0x01, 0x05, 0x07, 0x03, 0x05}, + {0x04, 0x05, 0x08, 0x13, 0xFF, 0xEB, 0x0C, 0x06}, + {0x05, 0x13, 0x0E, 0x0B, 0x12, 0x15, 0x09, 0x0A}, + {0x09, 0x03, 0x09, 0x05, 0x12, 0x16, 0x11, 0x12}, + {0x14, 0x1A, 0x06, 0x01, 0x10, 0x11, 0xFE, 0x02}, + {0x01, 0x0B, 0x0B, 0x0C, 0x18, 0x21, 0x10, 0x13}, + {0x12, 0x0D, 0x0A, 0x10, 0x1C, 0x1D, 0x0D, 0x10}, + {0x03, 0x09, 0x14, 0x15, 0x1B, 0x1A, 0x01, 0xFF}, + {0x08, 0x12, 0x13, 0x0E, 0x16, 0x1D, 0x14, 0x1B}, + {0x07, 0x15, 0x1C, 0x1B, 0x20, 0x21, 0x11, 0x0E}, + {0x12, 0x18, 0x19, 0x17, 0x20, 0x25, 0x1A, 0x1E}, + {0x0C, 0x1A, 0x1D, 0x22, 0x2F, 0x33, 0x27, 0x28}, + {0x0E, 0x1A, 0x17, 0x10, 0x0A, 0x0E, 0xFF, 0x06}, + {0x1A, 0x1C, 0x18, 0x14, 0x1A, 0x16, 0x0A, 0x0E}, + {0x1E, 0x27, 0x25, 0x26, 0x27, 0x2A, 0x21, 0x21}, + {0xF1, 0x0A, 0x16, 0x1C, 0x28, 0x25, 0x15, 0x19}, + {0x08, 0x12, 0x09, 0x08, 0x16, 0x17, 0xEF, 0xF6}, + {0x0C, 0x0B, 0x00, 0xFC, 0x04, 0x09, 0xFC, 0x03}, + {0xFB, 0xF1, 0xF8, 0x26, 0x24, 0x18, 0x1D, 0x20}, + {0xF9, 0x01, 0x0C, 0x0F, 0x07, 0x08, 0x06, 0x07}, + {0x07, 0x06, 0x08, 0x04, 0x07, 0x0D, 0x07, 0x09}, + {0xFE, 0x01, 0x06, 0x05, 0x13, 0x1B, 0x14, 0x19}, + {0x09, 0x0C, 0x0E, 0x01, 0x08, 0x05, 0xFB, 0xFD}, + {0x07, 0x06, 0x03, 0x0A, 0x16, 0x12, 0x04, 0x07}, + {0x04, 0x01, 0x00, 0x04, 0x1F, 0x20, 0x0E, 0x0A}, + {0x03, 0xFF, 0xF6, 0xFB, 0x15, 0x1A, 0x00, 0x03}, + {0xFC, 0x18, 0x0B, 0x2D, 0x35, 0x23, 0x12, 0x09}, + {0x02, 0xFE, 0x01, 0xFF, 0x0C, 0x11, 0x0D, 0x0F}, + {0xFA, 0xE9, 0xD9, 0xFF, 0x0D, 0x05, 0x0D, 0x10}, + {0xF1, 0xE0, 0xF0, 0x01, 0x06, 0x06, 0x06, 0x10}, + {0xE9, 0xD4, 0xD7, 0x0F, 0x14, 0x0B, 0x0D, 0x16}, + {0x00, 0xFF, 0xEE, 0xE5, 0xFF, 0x08, 0x02, 0xF9}, + {0xE0, 0xDA, 0xE5, 0xFE, 0x09, 0x02, 0xF9, 0x04}, + {0xE0, 0xE2, 0xF4, 0x09, 0x13, 0x0C, 0x0D, 0x09}, + {0xFC, 0x02, 0x04, 0xFF, 0x00, 0xFF, 0xF8, 0xF7}, + {0xFE, 0xFB, 0xED, 0xF2, 0xFE, 0xFE, 0x08, 0x0C}, + {0xF3, 0xEF, 0xD0, 0xE3, 0x05, 0x11, 0xFD, 0xFF}, + {0xFA, 0xEF, 0xEA, 0xFE, 0x0D, 0x0E, 0xFE, 0x02}, + {0xF7, 0xFB, 0xDB, 0xDF, 0x14, 0xDD, 0x07, 0xFE}, + {0xFE, 0x08, 0x00, 0xDB, 0xE5, 0x1A, 0x13, 0xED}, + {0xF9, 0xFE, 0xFF, 0xF4, 0xF3, 0x00, 0x05, 0x02}, + {0xEF, 0xDE, 0xD8, 0xEB, 0xEA, 0xF5, 0x0E, 0x19}, + {0xFB, 0xFC, 0xFA, 0xEC, 0xEB, 0xED, 0xEE, 0xE8}, + {0xEE, 0xFC, 0xFD, 0x00, 0x04, 0xFC, 0xF0, 0xF5}, + {0x00, 0xFA, 0xF4, 0xF1, 0xF5, 0xFA, 0xFB, 0xF9}, + {0xEB, 0xF0, 0xDF, 0xE3, 0xEF, 0x07, 0x02, 0x05}, + {0xF7, 0xF0, 0xE6, 0xE7, 0x06, 0x15, 0x06, 0x0C}, + {0xF1, 0xE4, 0xD8, 0xEA, 0x06, 0xF2, 0x07, 0x09}, + {0xFF, 0xFE, 0xFE, 0xF9, 0xFF, 0xFF, 0x02, 0xF9}, + {0xDD, 0xF4, 0xF0, 0xF1, 0xFF, 0xFF, 0xEA, 0xF1}, + {0xF0, 0xF1, 0xFD, 0x03, 0x03, 0xFE, 0x00, 0x05}, + {0xF1, 0xF6, 0xE0, 0xDF, 0xF5, 0x01, 0xF4, 0xF8}, + {0x02, 0x03, 0xE5, 0xDC, 0xE7, 0xFD, 0x02, 0x08}, + {0xEC, 0xF1, 0xF5, 0xEC, 0xF2, 0xF8, 0xF6, 0xEE}, + {0xF3, 0xF4, 0xF6, 0xF4, 0xF5, 0xF1, 0xE7, 0xEA}, + {0xF7, 0xF3, 0xEC, 0xEA, 0xEF, 0xF0, 0xEE, 0xF1}, + {0xEB, 0xF6, 0xFB, 0xFA, 0xEF, 0xF3, 0xF3, 0xF7}, + {0x01, 0x03, 0xF1, 0xF6, 0x05, 0xF8, 0xE1, 0xEB}, + {0xF5, 0xF6, 0xF6, 0xF4, 0xFB, 0xFB, 0xFF, 0x00}, + {0xF8, 0x01, 0xFB, 0xFA, 0xFF, 0x03, 0xFE, 0x04}, + {0x04, 0xFB, 0x03, 0xFD, 0xF5, 0xF7, 0xF6, 0xFB}, + {0x06, 0x09, 0xFB, 0xF4, 0xF9, 0xFA, 0xFC, 0xFF}, + {0xF5, 0xF6, 0xF1, 0xEE, 0xF5, 0xF8, 0xF5, 0xF9}, + {0xF5, 0xF9, 0xFA, 0xFC, 0x07, 0x09, 0x01, 0xFB}, + {0xD7, 0xE9, 0xE8, 0xEC, 0x00, 0x0C, 0xFE, 0xF1}, + {0xEC, 0x04, 0xE9, 0xDF, 0x03, 0xE8, 0x00, 0xFA}, + {0xE6, 0xE2, 0xFF, 0x0A, 0x13, 0x01, 0x00, 0xF7}, + {0xF1, 0xFA, 0xF7, 0xF5, 0x01, 0x06, 0x05, 0x0A}, + {0xF6, 0xF6, 0xFC, 0xF6, 0xE8, 0x11, 0xF2, 0xFE}, + {0xFE, 0x08, 0x05, 0x12, 0xFD, 0xD0, 0x0E, 0x07}, + {0xF1, 0xFE, 0xF7, 0xF2, 0xFB, 0x02, 0xFA, 0xF8}, + {0xF4, 0xEA, 0xEC, 0xF3, 0xFE, 0x01, 0xF7, 0xF6}, + {0xFF, 0xFA, 0xFB, 0xF9, 0xFF, 0x01, 0x04, 0x03}, + {0x00, 0xF9, 0xF4, 0xFC, 0x05, 0xFC, 0xF7, 0xFB}, + {0xF8, 0xFF, 0xEF, 0xEC, 0xFB, 0x04, 0xF8, 0x03}, + {0xEB, 0xF1, 0xED, 0xF4, 0x02, 0x0E, 0x0B, 0x04}, + {0xF7, 0x01, 0xF8, 0xF4, 0xF8, 0xEF, 0xF8, 0x04}, + {0xEB, 0xF0, 0xF7, 0xFC, 0x10, 0x0D, 0xF8, 0xF8}, + {0xE8, 0xFE, 0xEE, 0xE8, 0xED, 0xF7, 0xF5, 0xF8}, + {0xED, 0xEB, 0xE9, 0xEA, 0xF2, 0xF5, 0xF4, 0xF9}, + {0xEA, 0xF2, 0xEF, 0xEE, 0xF9, 0xFE, 0xFD, 0x02}, + {0xFA, 0xFD, 0x02, 0x0D, 0xFA, 0xE4, 0x0F, 0x01}, + {0xFF, 0x08, 0x05, 0xF6, 0xF7, 0xFB, 0xF1, 0xF1}, + {0xF4, 0xEC, 0xEE, 0xF6, 0xEE, 0xEE, 0xF8, 0x06}, + {0xE8, 0xFA, 0xF8, 0xE8, 0xF8, 0xE9, 0xEE, 0xF9}, + {0xE5, 0xE9, 0xF0, 0x00, 0x00, 0xEF, 0xF3, 0xF8}, + {0xF7, 0xFB, 0xFB, 0xF7, 0xF9, 0xF9, 0xF5, 0xF0}, + {0xFD, 0xFF, 0xF2, 0xEE, 0xF2, 0xF5, 0xF1, 0xF3}}; + +static const UCHAR g_3a_pvcTab1_mode2[PVC_NTAB1][PVC_NBLOW][PVC_NBHIGH_MODE2] = + {{{0x11, 0x27, 0x0F, 0xFD, 0x04, 0xFC}, + {0x00, 0xBE, 0xE3, 0xF4, 0xDB, 0xF0}, + {0x09, 0x1E, 0x18, 0x1A, 0x21, 0x1B}}, + {{0x16, 0x28, 0x2B, 0x29, 0x25, 0x32}, + {0xF2, 0xE9, 0xE4, 0xE5, 0xE2, 0xD4}, + {0x0E, 0x0B, 0x0C, 0x0D, 0x0D, 0x0E}}, + {{0x2E, 0x3C, 0x20, 0x16, 0x1B, 0x1A}, + {0xE4, 0xC6, 0xE5, 0xF4, 0xDC, 0xDC}, + {0x0F, 0x1B, 0x18, 0x14, 0x1E, 0x1A}}}; + +static const UCHAR g_2a_pvcTab2_mode2[PVC_NTAB2][PVC_NBHIGH_MODE2] = { + {0x26, 0x25, 0x11, 0x0C, 0xFA, 0x15}, {0x1B, 0x18, 0x11, 0x0E, 0x0E, 0x0E}, + {0x12, 0x10, 0x10, 0x10, 0x11, 0x10}, {0x1E, 0x24, 0x19, 0x15, 0x14, 0x12}, + {0x24, 0x16, 0x12, 0x13, 0x15, 0x1C}, {0xEA, 0xED, 0xEB, 0xEA, 0xEC, 0xEB}, + {0xFC, 0xFD, 0xFD, 0xFC, 0xFE, 0xFE}, {0x0F, 0x0C, 0x0B, 0x0A, 0x0B, 0x0B}, + {0x22, 0x0B, 0x16, 0x18, 0x13, 0x19}, {0x1C, 0x14, 0x1D, 0x20, 0x19, 0x1A}, + {0x10, 0x08, 0x00, 0xFF, 0x02, 0x05}, {0x06, 0x07, 0x05, 0x03, 0x05, 0x04}, + {0x2A, 0x1F, 0x12, 0x12, 0x11, 0x18}, {0x19, 0x19, 0x02, 0x04, 0x00, 0x04}, + {0x18, 0x17, 0x17, 0x15, 0x16, 0x15}, {0x21, 0x1E, 0x1B, 0x19, 0x1C, 0x1B}, + {0x3C, 0x35, 0x20, 0x1D, 0x30, 0x34}, {0x3A, 0x1F, 0x37, 0x38, 0x33, 0x31}, + {0x37, 0x34, 0x25, 0x27, 0x35, 0x34}, {0x34, 0x2E, 0x32, 0x31, 0x34, 0x31}, + {0x36, 0x33, 0x2F, 0x2F, 0x32, 0x2F}, {0x35, 0x20, 0x2F, 0x32, 0x2F, 0x2C}, + {0x2E, 0x2B, 0x2F, 0x34, 0x36, 0x30}, {0x3F, 0x39, 0x30, 0x28, 0x29, 0x29}, + {0x3C, 0x30, 0x32, 0x37, 0x39, 0x36}, {0x37, 0x36, 0x30, 0x2B, 0x26, 0x24}, + {0x44, 0x38, 0x2F, 0x2D, 0x2D, 0x2D}, {0x38, 0x2B, 0x2C, 0x2C, 0x30, 0x2D}, + {0x37, 0x36, 0x2F, 0x23, 0x2D, 0x32}, {0x3C, 0x39, 0x29, 0x2E, 0x38, 0x37}, + {0x3B, 0x3A, 0x35, 0x32, 0x31, 0x2D}, {0x32, 0x31, 0x2F, 0x2C, 0x2D, 0x28}, + {0x2C, 0x31, 0x32, 0x30, 0x32, 0x2D}, {0x35, 0x34, 0x34, 0x34, 0x35, 0x33}, + {0x34, 0x38, 0x3B, 0x3C, 0x3E, 0x3A}, {0x3E, 0x3C, 0x3B, 0x3A, 0x3C, 0x39}, + {0x3D, 0x41, 0x46, 0x41, 0x3D, 0x38}, {0x44, 0x41, 0x40, 0x3E, 0x3F, 0x3A}, + {0x47, 0x47, 0x47, 0x42, 0x44, 0x40}, {0x4C, 0x4A, 0x4A, 0x46, 0x49, 0x45}, + {0x53, 0x52, 0x52, 0x4C, 0x4E, 0x49}, {0x41, 0x3D, 0x39, 0x2C, 0x2E, 0x2E}, + {0x2D, 0x37, 0x36, 0x30, 0x28, 0x36}, {0x3B, 0x32, 0x2E, 0x2D, 0x2D, 0x29}, + {0x40, 0x39, 0x36, 0x35, 0x36, 0x32}, {0x30, 0x2D, 0x2D, 0x2E, 0x31, 0x30}, + {0x38, 0x3D, 0x3B, 0x37, 0x35, 0x34}, {0x44, 0x3D, 0x3C, 0x38, 0x37, 0x33}, + {0x3A, 0x36, 0x37, 0x37, 0x39, 0x36}, {0x32, 0x36, 0x37, 0x30, 0x2E, 0x2A}, + {0x3C, 0x33, 0x33, 0x31, 0x33, 0x30}, {0x30, 0x31, 0x36, 0x37, 0x38, 0x34}, + {0x26, 0x27, 0x2E, 0x29, 0x1C, 0x16}, {0x14, 0x15, 0x1F, 0x17, 0x15, 0x1C}, + {0x38, 0x2D, 0x18, 0x13, 0x1E, 0x2B}, {0x30, 0x22, 0x17, 0x1A, 0x26, 0x2B}, + {0x24, 0x20, 0x1F, 0x10, 0x0C, 0x11}, {0x27, 0x1F, 0x13, 0x17, 0x24, 0x2A}, + {0x2F, 0x13, 0x18, 0x13, 0x2A, 0x32}, {0x31, 0x1E, 0x1E, 0x1E, 0x21, 0x28}, + {0x2A, 0x12, 0x19, 0x17, 0x16, 0x24}, {0x27, 0x0F, 0x16, 0x1D, 0x17, 0x1C}, + {0x2F, 0x26, 0x25, 0x22, 0x20, 0x22}, {0x1E, 0x1B, 0x1E, 0x18, 0x1E, 0x24}, + {0x31, 0x26, 0x0E, 0x15, 0x15, 0x25}, {0x2D, 0x22, 0x1E, 0x14, 0x10, 0x22}, + {0x25, 0x1B, 0x18, 0x11, 0x13, 0x1F}, {0x2F, 0x1B, 0x13, 0x1B, 0x18, 0x22}, + {0x21, 0x24, 0x1D, 0x1C, 0x1D, 0x1B}, {0x23, 0x1E, 0x28, 0x29, 0x27, 0x25}, + {0x2E, 0x2A, 0x1D, 0x17, 0x26, 0x2D}, {0x31, 0x2C, 0x1A, 0x0E, 0x1A, 0x24}, + {0x26, 0x16, 0x20, 0x1D, 0x14, 0x1E}, {0x29, 0x20, 0x1B, 0x1B, 0x17, 0x17}, + {0x1D, 0x06, 0x1A, 0x1E, 0x1B, 0x1D}, {0x2B, 0x23, 0x1F, 0x1F, 0x1D, 0x1C}, + {0x27, 0x1A, 0x0C, 0x0E, 0x0F, 0x1A}, {0x29, 0x1D, 0x1E, 0x22, 0x22, 0x24}, + {0x20, 0x21, 0x1B, 0x18, 0x13, 0x21}, {0x27, 0x0E, 0x10, 0x14, 0x10, 0x1A}, + {0x26, 0x24, 0x25, 0x25, 0x26, 0x28}, {0x1A, 0x24, 0x25, 0x29, 0x26, 0x24}, + {0x1D, 0x1D, 0x15, 0x12, 0x0F, 0x18}, {0x1E, 0x14, 0x13, 0x12, 0x14, 0x18}, + {0x16, 0x13, 0x13, 0x1A, 0x1B, 0x1D}, {0x20, 0x27, 0x22, 0x24, 0x1A, 0x19}, + {0x1F, 0x17, 0x19, 0x18, 0x17, 0x18}, {0x20, 0x1B, 0x1C, 0x1C, 0x1B, 0x1A}, + {0x23, 0x19, 0x1D, 0x1F, 0x1E, 0x21}, {0x26, 0x1F, 0x1D, 0x1B, 0x19, 0x1A}, + {0x23, 0x1E, 0x1F, 0x20, 0x1F, 0x1E}, {0x29, 0x20, 0x22, 0x20, 0x20, 0x1F}, + {0x26, 0x23, 0x21, 0x22, 0x23, 0x23}, {0x29, 0x1F, 0x24, 0x25, 0x26, 0x29}, + {0x2B, 0x22, 0x25, 0x27, 0x23, 0x21}, {0x29, 0x21, 0x19, 0x0E, 0x22, 0x2D}, + {0x32, 0x29, 0x1F, 0x1C, 0x1B, 0x21}, {0x1E, 0x1A, 0x1E, 0x24, 0x25, 0x25}, + {0x24, 0x1D, 0x21, 0x22, 0x22, 0x25}, {0x2C, 0x25, 0x21, 0x22, 0x23, 0x25}, + {0x24, 0x1E, 0x21, 0x26, 0x2B, 0x2C}, {0x28, 0x24, 0x1B, 0x1F, 0x28, 0x2D}, + {0x23, 0x13, 0x16, 0x22, 0x22, 0x29}, {0x1B, 0x23, 0x1C, 0x20, 0x14, 0x0D}, + {0x1E, 0x16, 0x1A, 0x1E, 0x1C, 0x1D}, {0x2B, 0x1C, 0x1D, 0x20, 0x1B, 0x1C}, + {0x1C, 0x1B, 0x23, 0x1F, 0x19, 0x1E}, {0x21, 0x23, 0x26, 0x20, 0x20, 0x22}, + {0x1D, 0x0B, 0x19, 0x1E, 0x11, 0x19}, {0x18, 0x17, 0x16, 0x17, 0x14, 0x16}, + {0x16, 0x19, 0x1C, 0x20, 0x21, 0x22}, {0x30, 0x1E, 0x22, 0x24, 0x25, 0x26}, + {0x1B, 0x1F, 0x17, 0x1D, 0x1E, 0x21}, {0x32, 0x2B, 0x27, 0x1F, 0x1B, 0x1A}, + {0x28, 0x20, 0x1A, 0x1B, 0x1F, 0x23}, {0x32, 0x21, 0x20, 0x21, 0x1D, 0x1F}, + {0x22, 0x18, 0x12, 0x15, 0x1B, 0x20}, {0x27, 0x27, 0x2A, 0x24, 0x21, 0x21}, + {0x1E, 0x0F, 0x0D, 0x1A, 0x1D, 0x23}, {0x28, 0x25, 0x27, 0x21, 0x17, 0x25}, + {0x2B, 0x27, 0x23, 0x19, 0x13, 0x14}, {0x25, 0x2B, 0x22, 0x22, 0x20, 0x21}, + {0x27, 0x1B, 0x16, 0x17, 0x0F, 0x15}, {0x29, 0x26, 0x23, 0x15, 0x1E, 0x28}, + {0x24, 0x1C, 0x19, 0x1A, 0x18, 0x19}, {0x2D, 0x15, 0x27, 0x2B, 0x24, 0x23}, + {0x2C, 0x12, 0x1F, 0x23, 0x1F, 0x20}, {0x25, 0x0F, 0x22, 0x27, 0x1F, 0x21}}; + +static const UCHAR g_a_pvcTab1_dp_mode1[PVC_NTAB1 - 1] = {17, 68}; +static const UCHAR g_a_pvcTab1_dp_mode2[PVC_NTAB1 - 1] = {16, 52}; +/* fractional exponent which corresponds to Q representation value */ +static const SCHAR g_a_scalingCoef_mode1[PVC_NBLOW + 1] = { + -1, -1, 0, 6}; /* { 8, 8, 7, 1 }; Q scaling */ +static const SCHAR g_a_scalingCoef_mode2[PVC_NBLOW + 1] = { + 0, 0, 1, 7}; /* { 7, 7, 6, 0 }; Q scaling */ + +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID) { + int lbw, hbw, i, temp; + pPvcDynamicData->pvc_mode = pvcMode; + pPvcDynamicData->kx = kx; + pPvcDynamicData->RATE = RATE; + + switch (pvcMode) { + case 0: + /* legacy SBR, nothing to do */ + return 0; + case 1: + pPvcDynamicData->nbHigh = 8; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode1; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode1; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode1; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode1; + hbw = 8 / RATE; + break; + case 2: + pPvcDynamicData->nbHigh = 6; + pPvcDynamicData->pPVCTab1 = (const UCHAR *)g_3a_pvcTab1_mode2; + pPvcDynamicData->pPVCTab2 = (const UCHAR *)g_2a_pvcTab2_mode2; + pPvcDynamicData->pPVCTab1_dp = g_a_pvcTab1_dp_mode2; + pPvcDynamicData->pScalingCoef = g_a_scalingCoef_mode2; + hbw = 12 / RATE; + break; + default: + /* invalid pvcMode */ + return 1; + } + + pPvcDynamicData->pvcBorder0 = pvcBorder0; + UCHAR pvcBorder0_last = pPvcStaticData->pvcBorder0; + pPvcStaticData->pvcBorder0 = pvcBorder0; + pPvcDynamicData->pPvcID = pPvcID; + + pPvcDynamicData->ns = ns; + switch (ns) { + case 16: + pPvcDynamicData->pSCcoeffs = pvc_SC_16; + break; + case 12: + pPvcDynamicData->pSCcoeffs = pvc_SC_12; + break; + case 4: + pPvcDynamicData->pSCcoeffs = pvc_SC_4; + break; + case 3: + pPvcDynamicData->pSCcoeffs = pvc_SC_3; + break; + default: + return 1; + } + + /* in the lower part of Esg-array there are previous values of Esg (from last + call to this function In case of an previous legay-SBR frame, or if there + was a change in cross-over FQ the value of first PVC SBR timeslot is + propagated to prev-values in order to have reasonable values for + smooth-filtering + */ + if ((pPvcStaticData->pvc_mode_last == 0) || (pPvcStaticData->kx_last != kx)) { + pPvcDynamicData->pastEsgSlotsAvail = 0; + } else { + pPvcDynamicData->pastEsgSlotsAvail = PVC_NS_MAX - pvcBorder0_last; + } + + lbw = 8 / RATE; + + temp = kx; + for (i = PVC_NBLOW; i >= 0; i--) { + pPvcDynamicData->sg_offset_low[i] = temp; + temp -= lbw; + } + + temp = 0; + for (i = 0; i <= pPvcDynamicData->nbHigh; i++) { + pPvcDynamicData->sg_offset_high_kx[i] = temp; + temp += hbw; + } + + return 0; +} + +/* call if pvcMode = 1,2 */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, + const int qmfExponentCurrent) { + int t; + FIXP_DBL *predictedEsgSlot; + int RATE = pPvcDynamicData->RATE; + int pvcBorder0 = pPvcDynamicData->pvcBorder0; + + for (t = pvcBorder0; t < PVC_NTIMESLOT; t++) { + int *pPredEsg_exp = &pPvcDynamicData->predEsg_exp[t]; + predictedEsgSlot = pPvcDynamicData->predEsg[t]; + + pvcDecodeTimeSlot( + pPvcStaticData, pPvcDynamicData, &qmfBufferReal[t * RATE], + &qmfBufferImag[t * RATE], + (t * RATE < overlap) ? qmfExponentOverlap : qmfExponentCurrent, + pvcBorder0, t, predictedEsgSlot, pPredEsg_exp); + } + + return; +} + +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp) { + int i, band, ksg, ksg_start = 0; + int RATE = pPvcDynamicData->RATE; + int Esg_index = pPvcStaticData->Esg_slot_index; + const SCHAR *sg_borders = pPvcDynamicData->sg_offset_low; + FIXP_DBL *pEsg = pPvcStaticData->Esg[Esg_index]; + FIXP_DBL E[PVC_NBLOW] = {0}; + + /* Subband grouping in QMF subbands below SBR range */ + /* Within one timeslot ( i = [0...(RATE-1)] QMF subsamples) calculate energy + E(ib,t) and group them to Esg(ksg,t). Then transfer values to logarithmical + domain and store them for time domain smoothing. (7.5.6.3 Subband grouping + in QMF subbands below SBR range) + */ + for (ksg = 0; sg_borders[ksg] < 0; ksg++) { + pEsg[ksg] = FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + ksg_start++; + } + + for (i = 0; i < RATE; i++) { + FIXP_DBL *qmfR, *qmfI; + qmfR = qmfSlotReal[i]; + qmfI = qmfSlotImag[i]; + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + for (band = sg_borders[ksg]; band < sg_borders[ksg + 1]; band++) { + /* The division by 8 == (RATE*lbw) is required algorithmically */ + E[ksg] += (fPow2Div2(qmfR[band]) + fPow2Div2(qmfI[band])) >> 2; + } + } + } + for (ksg = ksg_start; ksg < PVC_NBLOW; ksg++) { + if (E[ksg] > (FIXP_DBL)0) { + /* 10/log2(10) = 0.752574989159953 * 2^2 */ + int exp_log; + FIXP_DBL nrg = CalcLog2(E[ksg], 2 * qmfExponent, &exp_log); + nrg = fMult(nrg, FL2FXCONST_SGL(LOG10FAC)); + nrg = scaleValue(nrg, exp_log - PVC_ESG_EXP + 2); + pEsg[ksg] = fMax(nrg, FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP))); + } else { + pEsg[ksg] = + FL2FXCONST_DBL(-10.0 / (1 << PVC_ESG_EXP)); /* 10*log10(0.1) */ + } + } + + /* Time domain smoothing of subband-grouped energy */ + { + int idx = pPvcStaticData->Esg_slot_index; + FIXP_DBL *pEsg_filt; + FIXP_SGL SCcoeff; + + E[0] = E[1] = E[2] = (FIXP_DBL)0; + for (i = 0; i < pPvcDynamicData->ns; i++) { + SCcoeff = pPvcDynamicData->pSCcoeffs[i]; + pEsg_filt = pPvcStaticData->Esg[idx]; + /* Div2 is compensated by scaling of coeff table */ + E[0] = fMultAddDiv2(E[0], pEsg_filt[0], SCcoeff); + E[1] = fMultAddDiv2(E[1], pEsg_filt[1], SCcoeff); + E[2] = fMultAddDiv2(E[2], pEsg_filt[2], SCcoeff); + if (i >= pPvcDynamicData->pastEsgSlotsAvail) { + /* if past Esg values are not available use the ones from the last valid + * slot */ + continue; + } + if (idx > 0) { + idx--; + } else { + idx += PVC_NS_MAX - 1; + } + } + } + + /* SBR envelope scalefactor prediction */ + { + int E_high_exp[PVC_NBHIGH_MAX]; + int E_high_exp_max = 0; + int pvcTab1ID; + int pvcTab2ID = (int)pPvcDynamicData->pPvcID[timeSlotNumber]; + const UCHAR *pTab1, *pTab2; + if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[0]) { + pvcTab1ID = 0; + } else if (pvcTab2ID < pPvcDynamicData->pPVCTab1_dp[1]) { + pvcTab1ID = 1; + } else { + pvcTab1ID = 2; + } + pTab1 = &(pPvcDynamicData + ->pPVCTab1[pvcTab1ID * PVC_NBLOW * pPvcDynamicData->nbHigh]); + pTab2 = &(pPvcDynamicData->pPVCTab2[pvcTab2ID * pPvcDynamicData->nbHigh]); + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + FIXP_SGL predCoeff; + FIXP_DBL accu; + int predCoeff_exp, kb; + E_high_exp[ksg] = 0; + + /* residual part */ + accu = ((LONG)(SCHAR)*pTab2++) << (DFRACT_BITS - 8 - PVC_ESG_EXP + + pPvcDynamicData->pScalingCoef[3]); + + /* linear combination of lower grouped energies part */ + for (kb = 0; kb < PVC_NBLOW; kb++) { + predCoeff = (FIXP_SGL)( + (SHORT)(SCHAR)pTab1[kb * pPvcDynamicData->nbHigh + ksg] << 8); + predCoeff_exp = pPvcDynamicData->pScalingCoef[kb] + + 1; /* +1 to compensate for Div2 */ + accu += fMultDiv2(E[kb], predCoeff) << predCoeff_exp; + } + /* convert back to linear domain */ + accu = fMult(accu, FL2FXCONST_SGL(LOG10FAC_INV)); + accu = f2Pow( + accu, PVC_ESG_EXP - 1, + &predCoeff_exp); /* -1 compensates for exponent of LOG10FAC_INV */ + predictedEsgSlot[ksg] = accu; + E_high_exp[ksg] = predCoeff_exp; + if (predCoeff_exp > E_high_exp_max) { + E_high_exp_max = predCoeff_exp; + } + } + + /* rescale output vector according to largest exponent */ + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + int scale = E_high_exp[ksg] - E_high_exp_max; + predictedEsgSlot[ksg] = scaleValue(predictedEsgSlot[ksg], scale); + } + *predictedEsg_exp = E_high_exp_max; + } + + pPvcStaticData->Esg_slot_index = + (pPvcStaticData->Esg_slot_index + 1) & (PVC_NS_MAX - 1); + pPvcDynamicData->pastEsgSlotsAvail = + fMin(pPvcDynamicData->pastEsgSlotsAvail + 1, PVC_NS_MAX - 1); + return; +} + +/* call if pvcMode = 0,1,2 */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData) { + pPvcStaticData->pvc_mode_last = pPvcDynamicData->pvc_mode; + pPvcStaticData->kx_last = pPvcDynamicData->kx; + + if (pPvcDynamicData->pvc_mode == 0) return; + + { + int t, max = -100; + for (t = pPvcDynamicData->pvcBorder0; t < PVC_NTIMESLOT; t++) { + if (pPvcDynamicData->predEsg_exp[t] > max) { + max = pPvcDynamicData->predEsg_exp[t]; + } + } + pPvcDynamicData->predEsg_expMax = max; + } + return; +} + +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp) { + int k = 0, ksg; + const FIXP_DBL *predEsg = pPvcDynamicData->predEsg[timeSlot]; + + for (ksg = 0; ksg < pPvcDynamicData->nbHigh; ksg++) { + for (; k < pPvcDynamicData->sg_offset_high_kx[ksg + 1]; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + } + ksg--; + for (; k < lengthOutputVector; k++) { + pOutput[k] = predEsg[ksg]; + pOutput_exp[k] = (SCHAR)pPvcDynamicData->predEsg_exp[timeSlot]; + } + + return; +} diff --git a/fdk-aac/libSBRdec/src/pvc_dec.h b/fdk-aac/libSBRdec/src/pvc_dec.h new file mode 100644 index 0000000..f5a467f --- /dev/null +++ b/fdk-aac/libSBRdec/src/pvc_dec.h @@ -0,0 +1,238 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Matthias Hildenbrand + + Description: Decode Predictive Vector Coding Data + +*******************************************************************************/ + +#ifndef PVC_DEC_H +#define PVC_DEC_H + +#include "common_fix.h" + +#define PVC_DIVMODE_BITS 3 +#define PVC_REUSEPVCID_BITS 1 +#define PVC_PVCID_BITS 7 +#define PVC_GRIDINFO_BITS 1 + +#define MAX_PVC_ENVELOPES 2 +#define PVC_NTIMESLOT 16 +#define PVC_NBLOW 3 /* max. number of grouped QMF subbands below SBR range */ + +#define PVC_NBHIGH_MODE1 8 +#define PVC_NBHIGH_MODE2 6 +#define PVC_NBHIGH_MAX (PVC_NBHIGH_MODE1) +#define PVC_NS_MAX 16 + +/** Data for each PVC instance which needs to be persistent accross SBR frames + */ +typedef struct { + UCHAR kx_last; /**< Xover frequency of last frame */ + UCHAR pvc_mode_last; /**< PVC mode of last frame */ + UCHAR Esg_slot_index; /**< Ring buffer index to current Esg time slot */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + FIXP_DBL Esg[PVC_NS_MAX][PVC_NBLOW]; /**< Esg(ksg,t) of current and 15 + previous time slots (ring buffer) in + logarithmical domain */ +} PVC_STATIC_DATA; + +/** Data for each PVC instance which is valid during one SBR frame */ +typedef struct { + UCHAR pvc_mode; /**< PVC mode 1 or 2, 0 means legacy SBR */ + UCHAR pvcBorder0; /**< Start SBR time slot of PVC frame */ + UCHAR kx; /**< Index of the first QMF subband in the SBR range */ + UCHAR RATE; /**< Number of QMF subband samples per time slot (2 or 4) */ + UCHAR ns; /**< Number of time slots for time-domain smoothing of Esg(ksg,t) */ + const UCHAR + *pPvcID; /**< Pointer to prediction coefficient matrix index table */ + UCHAR pastEsgSlotsAvail; /**< Number of past Esg(ksg,t) which are available + for smoothing filter */ + const FIXP_SGL *pSCcoeffs; /**< Pointer to smoothing window table */ + SCHAR + sg_offset_low[PVC_NBLOW + 1]; /**< Offset table for PVC grouping of SBR + subbands below SBR range */ + SCHAR sg_offset_high_kx[PVC_NBHIGH_MAX + 1]; /**< Offset table for PVC + grouping of SBR subbands in + SBR range (relativ to kx) */ + UCHAR nbHigh; /**< Number of grouped QMF subbands in the SBR range */ + const SCHAR *pScalingCoef; /**< Pointer to scaling coeff table */ + const UCHAR *pPVCTab1; /**< PVC mode 1 table */ + const UCHAR *pPVCTab2; /**< PVC mode 2 table */ + const UCHAR *pPVCTab1_dp; /**< Mapping of pvcID to PVC mode 1 table */ + FIXP_DBL predEsg[PVC_NTIMESLOT] + [PVC_NBHIGH_MAX]; /**< Predicted Energy in linear domain */ + int predEsg_exp[PVC_NTIMESLOT]; /**< Exponent of predicted Energy in linear + domain */ + int predEsg_expMax; /**< Maximum of predEsg_exp[] */ +} PVC_DYNAMIC_DATA; + +/** + * \brief Initialize PVC data structures for current frame (call if pvcMode = + * 0,1,2) + * \param[in] pPvcStaticData Pointer to PVC persistent data + * \param[out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] pvcMode PVC mode 1 or 2, 0 means legacy SBR + * \param[in] ns Number of time slots for time-domain smoothing of Esg(ksg,t) + * \param[in] RATE Number of QMF subband samples per time slot (2 or 4) + * \param[in] kx Index of the first QMF subband in the SBR range + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] pPvcID Pointer to array of PvcIDs read from bitstream + */ +int pvcInitFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, const UCHAR pvcMode, + const UCHAR ns, const int RATE, const int kx, + const int pvcBorder0, const UCHAR *pPvcID); + +/** + * \brief Wrapper function for pvcDecodeTimeSlot() to decode PVC data of one + * frame (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] overlap Number of QMF overlap slots + * \param[in] qmfExponentOverlap Exponent of qmfBuffer (low part) of overlap + * slots + * \param[in] qmfExponentCurrent Exponent of qmfBuffer (low part) + */ +void pvcDecodeFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, FIXP_DBL **qmfBufferReal, + FIXP_DBL **qmfBufferImag, const int overlap, + const int qmfExponentOverlap, const int qmfExponentCurrent); + +/** + * \brief Decode PVC data for one SBR time slot (call if pvcMode = 1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] qmfBufferReal Pointer to array with real QMF subbands + * \param[in] qmfBufferImag Pointer to array with imag QMF subbands + * \param[in] qmfExponent Exponent of qmfBuffer of current time slot + * \param[in] pvcBorder0 Start SBR time slot of PVC frame + * \param[in] timeSlotNumber Number of current SBR time slot (0..15) + * \param[out] predictedEsgSlot Predicted Energy of current time slot + * \param[out] predictedEsg_exp Exponent of predicted Energy of current time + * slot + */ +void pvcDecodeTimeSlot(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData, + FIXP_DBL **qmfSlotReal, FIXP_DBL **qmfSlotImag, + const int qmfExponent, const int pvcBorder0, + const int timeSlotNumber, FIXP_DBL predictedEsgSlot[], + int *predictedEsg_exp); + +/** + * \brief Finish the current PVC frame (call if pvcMode = 0,1,2) + * \param[in,out] pPvcStaticData Pointer to PVC persistent data + * \param[in,out] pPvcDynamicData Pointer to PVC dynamic data + */ +void pvcEndFrame(PVC_STATIC_DATA *pPvcStaticData, + PVC_DYNAMIC_DATA *pPvcDynamicData); + +/** + * \brief Expand predicted PVC grouped energies to full QMF subband resolution + * \param[in] pPvcDynamicData Pointer to PVC dynamic data + * \param[in] timeSlot Number of current SBR time slot (0..15) + * \param[in] lengthOutputVector Lenght of output vector + * \param[out] pOutput Output array for predicted energies + * \param[out] pOutput_exp Exponent of predicted energies + */ +void expandPredEsg(const PVC_DYNAMIC_DATA *pPvcDynamicData, const int timeSlot, + const int lengthOutputVector, FIXP_DBL *pOutput, + SCHAR *pOutput_exp); + +#endif /* PVC_DEC_H*/ diff --git a/fdk-aac/libSBRdec/src/sbr_crc.cpp b/fdk-aac/libSBRdec/src/sbr_crc.cpp new file mode 100644 index 0000000..ba0fd05 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_crc.cpp @@ -0,0 +1,192 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief CRC check coutines +*/ + +#include "sbr_crc.h" + +#include "FDK_bitstream.h" +#include "transcendent.h" + +#define MAXCRCSTEP 16 +#define MAXCRCSTEP_LD 4 + +/*! + \brief crc calculation +*/ +static ULONG calcCRC(HANDLE_CRC hCrcBuf, ULONG bValue, int nBits) { + int i; + ULONG bMask = (1UL << (nBits - 1)); + + for (i = 0; i < nBits; i++, bMask >>= 1) { + USHORT flag = (hCrcBuf->crcState & hCrcBuf->crcMask) ? 1 : 0; + USHORT flag1 = (bMask & bValue) ? 1 : 0; + + flag ^= flag1; + hCrcBuf->crcState <<= 1; + if (flag) hCrcBuf->crcState ^= hCrcBuf->crcPoly; + } + + return (hCrcBuf->crcState); +} + +/*! + \brief crc +*/ +static int getCrc(HANDLE_FDK_BITSTREAM hBs, ULONG NrBits) { + int i; + CRC_BUFFER CrcBuf; + + CrcBuf.crcState = SBR_CRC_START; + CrcBuf.crcPoly = SBR_CRC_POLY; + CrcBuf.crcMask = SBR_CRC_MASK; + + int CrcStep = NrBits >> MAXCRCSTEP_LD; + + int CrcNrBitsRest = (NrBits - CrcStep * MAXCRCSTEP); + ULONG bValue; + + for (i = 0; i < CrcStep; i++) { + bValue = FDKreadBits(hBs, MAXCRCSTEP); + calcCRC(&CrcBuf, bValue, MAXCRCSTEP); + } + + bValue = FDKreadBits(hBs, CrcNrBitsRest); + calcCRC(&CrcBuf, bValue, CrcNrBitsRest); + + return (CrcBuf.crcState & SBR_CRC_RANGE); +} + +/*! + \brief crc interface + \return 1: CRC OK, 0: CRC check failure +*/ +int SbrCrcCheck(HANDLE_FDK_BITSTREAM hBs, /*!< handle to bit-buffer */ + LONG NrBits) /*!< max. CRC length */ +{ + int crcResult = 1; + ULONG NrCrcBits; + ULONG crcCheckResult; + LONG NrBitsAvailable; + ULONG crcCheckSum; + + crcCheckSum = FDKreadBits(hBs, 10); + + NrBitsAvailable = FDKgetValidBits(hBs); + if (NrBitsAvailable <= 0) { + return 0; + } + + NrCrcBits = fixMin((INT)NrBits, (INT)NrBitsAvailable); + + crcCheckResult = getCrc(hBs, NrCrcBits); + FDKpushBack(hBs, (NrBitsAvailable - FDKgetValidBits(hBs))); + + if (crcCheckResult != crcCheckSum) { + crcResult = 0; + } + + return (crcResult); +} diff --git a/fdk-aac/libSBRdec/src/sbr_crc.h b/fdk-aac/libSBRdec/src/sbr_crc.h new file mode 100644 index 0000000..9633717 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_crc.h @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief CRC checking routines +*/ +#ifndef SBR_CRC_H +#define SBR_CRC_H + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" + +/* some useful crc polynoms: + +crc5: x^5+x^4+x^2+x^1+1 +crc6: x^6+x^5+x^3+x^2+x+1 +crc7: x^7+x^6+x^2+1 +crc8: x^8+x^2+x+x+1 +*/ + +/* default SBR CRC */ /* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY 0x0233 +#define SBR_CRC_MASK 0x0200 +#define SBR_CRC_START 0x0000 +#define SBR_CRC_RANGE 0x03FF + +typedef struct { + USHORT crcState; + USHORT crcMask; + USHORT crcPoly; +} CRC_BUFFER; + +typedef CRC_BUFFER *HANDLE_CRC; + +int SbrCrcCheck(HANDLE_FDK_BITSTREAM hBitBuf, LONG NrCrcBits); + +#endif diff --git a/fdk-aac/libSBRdec/src/sbr_deb.cpp b/fdk-aac/libSBRdec/src/sbr_deb.cpp new file mode 100644 index 0000000..13cd211 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_deb.cpp @@ -0,0 +1,108 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Print selected debug messages +*/ + +#include "sbr_deb.h" diff --git a/fdk-aac/libSBRdec/src/sbr_deb.h b/fdk-aac/libSBRdec/src/sbr_deb.h new file mode 100644 index 0000000..97d572a --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_deb.h @@ -0,0 +1,113 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Debugging aids +*/ + +#ifndef SBR_DEB_H +#define SBR_DEB_H + +#include "sbrdecoder.h" + +#endif diff --git a/fdk-aac/libSBRdec/src/sbr_dec.cpp b/fdk-aac/libSBRdec/src/sbr_dec.cpp new file mode 100644 index 0000000..30611e7 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_dec.cpp @@ -0,0 +1,1480 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder + This module provides the actual decoder implementation. The SBR data (side + information) is already decoded. Only three functions are provided: + + \li 1.) createSbrDec(): One time initialization + \li 2.) resetSbrDec(): Called by sbr_Apply() when the information contained in + an SBR_HEADER_ELEMENT requires a reset and recalculation of important SBR + structures. \li 3.) sbr_dec(): The actual decoder. Calls the different tools + such as filterbanks, lppTransposer(), and calculateSbrEnvelope() [the envelope + adjuster]. + + \sa sbr_dec(), \ref documentationOverview +*/ + +#include "sbr_dec.h" + +#include "sbr_ram.h" +#include "env_extr.h" +#include "env_calc.h" +#include "scale.h" +#include "FDK_matrixCalloc.h" +#include "hbe.h" + +#include "genericStds.h" + +#include "sbrdec_drc.h" + +static void copyHarmonicSpectrum(int *xOverQmf, FIXP_DBL **qmfReal, + FIXP_DBL **qmfImag, int noCols, int overlap, + KEEP_STATES_SYNCED_MODE keepStatesSynced) { + int patchBands; + int patch, band, col, target, sourceBands, i; + int numPatches = 0; + int slotOffset = 0; + + FIXP_DBL **ppqmfReal = qmfReal + overlap; + FIXP_DBL **ppqmfImag = qmfImag + overlap; + + if (keepStatesSynced == KEEP_STATES_SYNCED_NORMAL) { + slotOffset = noCols - overlap - LPC_ORDER; + } + + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + ppqmfReal = qmfReal; + ppqmfImag = qmfImag; + } + + for (i = 1; i < MAX_NUM_PATCHES; i++) { + if (xOverQmf[i] != 0) { + numPatches++; + } + } + + for (patch = (MAX_STRETCH_HBE - 1); patch < numPatches; patch++) { + patchBands = xOverQmf[patch + 1] - xOverQmf[patch]; + target = xOverQmf[patch]; + sourceBands = xOverQmf[MAX_STRETCH_HBE - 1] - xOverQmf[MAX_STRETCH_HBE - 2]; + + while (patchBands > 0) { + int numBands = sourceBands; + int startBand = xOverQmf[MAX_STRETCH_HBE - 1] - 1; + if (target + numBands >= xOverQmf[patch + 1]) { + numBands = xOverQmf[patch + 1] - target; + } + if ((((target + numBands - 1) % 2) + + ((xOverQmf[MAX_STRETCH_HBE - 1] - 1) % 2)) % + 2) { + if (numBands == sourceBands) { + numBands--; + } else { + startBand--; + } + } + if (keepStatesSynced == KEEP_STATES_SYNCED_OUTDIFF) { + for (col = slotOffset; col < overlap + LPC_ORDER; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } else { + for (col = slotOffset; col < noCols; col++) { + i = 0; + for (band = numBands; band > 0; band--) { + if ((target + band - 1 < 64) && + (target + band - 1 < xOverQmf[patch + 1])) { + ppqmfReal[col][target + band - 1] = ppqmfReal[col][startBand - i]; + ppqmfImag[col][target + band - 1] = ppqmfImag[col][startBand - i]; + i++; + } + } + } + } + target += numBands; + patchBands -= numBands; + } + } +} + +/*! + \brief SBR decoder core function for one channel + + \image html BufferMgmtDetailed-1632.png + + Besides the filter states of the QMF filter bank and the LPC-states of + the LPP-Transposer, processing is mainly based on four buffers: + #timeIn, #timeOut, #WorkBuffer2 and #OverlapBuffer. The #WorkBuffer2 + is reused for all channels and might be used by the core decoder, a + static overlap buffer is required for each channel. Due to in-place + processing, #timeIn and #timeOut point to identical locations. + + The spectral data is organized in so-called slots. Each slot + contains 64 bands of complex data. The number of slots per frame + depends on the frame size. For mp3PRO, there are 18 slots per frame + and 6 slots per #OverlapBuffer. It is not necessary to have the slots + in located consecutive address ranges. + + To optimize memory usage and to minimize the number of memory + accesses, the memory management is organized as follows (slot numbers + based on mp3PRO): + + 1.) Input time domain signal is located in #timeIn. The last slots + (0..5) of the spectral data of the previous frame are located in the + #OverlapBuffer. In addition, #frameData of the current frame resides + in the upper part of #timeIn. + + 2.) During the cplxAnalysisQmfFiltering(), 32 samples from #timeIn are + transformed into a slot of up to 32 complex spectral low band values at a + time. The first spectral slot -- nr. 6 -- is written at slot number + zero of #WorkBuffer2. #WorkBuffer2 will be completely filled with + spectral data. + + 3.) LPP-Transposition in lppTransposer() is processed on 24 slots. During the + transposition, the high band part of the spectral data is replicated + based on the low band data. + + Envelope Adjustment is processed on the high band part of the spectral + data only by calculateSbrEnvelope(). + + 4.) The cplxSynthesisQmfFiltering() creates 64 time domain samples out + of a slot of 64 complex spectral values at a time. The first 6 slots + in #timeOut are filled from the results of spectral slots 0..5 in the + #OverlapBuffer. The consecutive slots in timeOut are now filled with + the results of spectral slots 6..17. + + 5.) The preprocessed slots 18..23 have to be stored in the + #OverlapBuffer. + +*/ + +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + const int strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize) { + int i, slot, reserve; + int saveLbScale; + int lastSlotOffs; + FIXP_DBL maxVal; + + /* temporary pointer / variable for QMF; + required as we want to use temporary buffer + creating one frame delay for HBE in LP mode */ + INT_PCM *pTimeInQmf = timeIn; + + /* Number of QMF timeslots in the overlap buffer: */ + int ov_len = hSbrDec->LppTrans.pSettings->overlap; + + /* Number of QMF slots per frame */ + int noCols = hHeaderData->numberTimeSlots * hHeaderData->timeStep; + + /* create pointer array for data to use for HBE and legacy sbr */ + FIXP_DBL *pLowBandReal[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + FIXP_DBL *pLowBandImag[(3 * 4) + 2 * ((1024) / (32) * (4) / 2)]; + + /* set pReal to where QMF analysis writes in case of legacy SBR */ + FIXP_DBL **pReal = pLowBandReal + ov_len; + FIXP_DBL **pImag = pLowBandImag + ov_len; + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < noCols + ov_len; i++) { + pLowBandReal[i] = hSbrDec->qmfDomainInCh->hQmfSlotsReal[i]; + pLowBandImag[i] = hSbrDec->qmfDomainInCh->hQmfSlotsImag[i]; + } + + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < noCols; i++) { + pLowBandReal[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + noCols + ov_len] = hSbrDec->hQmfHBESlotsImag[i]; + } + + /* shift scale values according to buffer */ + hSbrDec->scale_ov = hSbrDec->scale_lb; + hSbrDec->scale_lb = hSbrDec->scale_hbe; + + /* set pReal to where QMF analysis writes in case of HBE */ + pReal += noCols; + pImag += noCols; + if (flags & SBRDEC_SKIP_QMF_ANA) { + /* stereoCfgIndex3 with HBE */ + FDK_QmfDomain_QmfData2HBE(hSbrDec->qmfDomainInCh, + hSbrDec->hQmfHBESlotsReal, + hSbrDec->hQmfHBESlotsImag); + } else { + /* We have to move old hbe frame data to lb area of buffer */ + for (i = 0; i < noCols; i++) { + FDKmemcpy(pLowBandReal[ov_len + i], hSbrDec->hQmfHBESlotsReal[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + FDKmemcpy(pLowBandImag[ov_len + i], hSbrDec->hQmfHBESlotsImag[i], + hHeaderData->numberOfAnalysisBands * sizeof(FIXP_DBL)); + } + } + } + + /* + low band codec signal subband filtering + */ + + if (flags & SBRDEC_SKIP_QMF_ANA) { + if (!(flags & SBRDEC_USAC_HARMONICSBR)) /* stereoCfgIndex3 w/o HBE */ + FDK_QmfDomain_WorkBuffer2ProcChannel(hSbrDec->qmfDomainInCh); + } else { + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * (64)); + qmfAnalysisFiltering(&hSbrDec->qmfDomainInCh->fb, pReal, pImag, + &hSbrDec->qmfDomainInCh->scaling, pTimeInQmf, 0, 1, + qmfTemp); + + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * (64)); + } + + /* + Clear upper half of spectrum + */ + if (!((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0))) { + int nAnalysisBands = hHeaderData->numberOfAnalysisBands; + + if (!(flags & SBRDEC_LOW_POWER)) { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + FDKmemclear(&pLowBandImag[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } else { + for (slot = ov_len; slot < noCols + ov_len; slot++) { + FDKmemclear(&pLowBandReal[slot][nAnalysisBands], + ((64) - nAnalysisBands) * sizeof(FIXP_DBL)); + } + } + } + + /* + Shift spectral data left to gain accuracy in transposer and adjustor + */ + /* Range was increased from lsb to no_channels because in some cases (e.g. + USAC conf eSbr_4_Pvc.mp4 and some HBE cases) it could be observed that the + signal between lsb and no_channels is used for the patching process. + */ + maxVal = maxSubbandSample(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols); + + reserve = fixMax(0, CntLeadingZeros(maxVal) - 1); + reserve = fixMin(reserve, + DFRACT_BITS - 1 - hSbrDec->qmfDomainInCh->scaling.lb_scale); + + /* If all data is zero, lb_scale could become too large */ + rescaleSubbandSamples(pReal, (flags & SBRDEC_LOW_POWER) ? NULL : pImag, 0, + hSbrDec->qmfDomainInCh->fb.no_channels, 0, noCols, + reserve); + + hSbrDec->qmfDomainInCh->scaling.lb_scale += reserve; + + if ((flags & SBRDEC_USAC_HARMONICSBR)) { + /* actually this is our hbe_scale */ + hSbrDec->scale_hbe = hSbrDec->qmfDomainInCh->scaling.lb_scale; + /* the real lb_scale is stored in scale_lb from sbr */ + hSbrDec->qmfDomainInCh->scaling.lb_scale = hSbrDec->scale_lb; + } + /* + save low band scale, wavecoding or parametric stereo may modify it + */ + saveLbScale = hSbrDec->qmfDomainInCh->scaling.lb_scale; + + if (applyProcessing) { + UCHAR *borders = hFrameData->frameInfo.borders; + lastSlotOffs = borders[hFrameData->frameInfo.nEnvelopes] - + hHeaderData->numberTimeSlots; + + FIXP_DBL degreeAlias[(64)]; + PVC_DYNAMIC_DATA pvcDynamicData; + pvcInitFrame( + &hSbrDec->PvcStaticData, &pvcDynamicData, + (hHeaderData->frameErrorFlag ? 0 : hHeaderData->bs_info.pvc_mode), + hFrameData->ns, hHeaderData->timeStep, + hHeaderData->freqBandData.lowSubband, + hFrameData->frameInfo.pvcBorders[0], hFrameData->pvcID); + + if (!hHeaderData->frameErrorFlag && (hHeaderData->bs_info.pvc_mode > 0)) { + pvcDecodeFrame(&hSbrDec->PvcStaticData, &pvcDynamicData, pLowBandReal, + pLowBandImag, ov_len, + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale), + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale)); + } + pvcEndFrame(&hSbrDec->PvcStaticData, &pvcDynamicData); + + /* The transposer will override most values in degreeAlias[]. + The array needs to be cleared at least from lowSubband to highSubband + before. */ + if (flags & SBRDEC_LOW_POWER) + FDKmemclear(°reeAlias[hHeaderData->freqBandData.lowSubband], + (hHeaderData->freqBandData.highSubband - + hHeaderData->freqBandData.lowSubband) * + sizeof(FIXP_DBL)); + + /* + Inverse filtering of lowband and transposition into the SBR-frequency + range + */ + + { + KEEP_STATES_SYNCED_MODE keepStatesSyncedMode = + ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode != 0)) + ? KEEP_STATES_SYNCED_NORMAL + : KEEP_STATES_SYNCED_OFF; + + if (flags & SBRDEC_USAC_HARMONICSBR) { + if (flags & SBRDEC_QUAD_RATE) { + pReal -= 32; + pImag -= 32; + } + + if ((hSbrDec->savedStates == 0) && (hFrameData->sbrPatchingMode == 1)) { + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[noCols - LPC_ORDER - ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + } + + /* saving unmodified QMF states in case we are switching from legacy SBR + * to HBE */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + FDKmemcpy(hSbrDec->codecQMFBufferReal[i], pLowBandReal[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->codecQMFBufferImag[i], pLowBandImag[ov_len + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + + QmfTransposerApply( + hSbrDec->hHBE, pReal, pImag, noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hFrameData->sbrPitchInBins, hSbrDec->scale_lb, hSbrDec->scale_hbe, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + borders[0], ov_len, keepStatesSyncedMode); + + if (flags & SBRDEC_QUAD_RATE) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + copyHarmonicSpectrum(xOverQmf, pLowBandReal, pLowBandImag, noCols, + ov_len, keepStatesSyncedMode); + } + } + } + + if ((flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0)) { + hSbrDec->prev_frame_lSbr = 0; + hSbrDec->prev_frame_hbeSbr = 1; + + lppTransposerHBE( + &hSbrDec->LppTrans, hSbrDec->hHBE, &hSbrDec->qmfDomainInCh->scaling, + pLowBandReal, pLowBandImag, hHeaderData->timeStep, borders[0], + lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + + } else { + if (flags & SBRDEC_USAC_HARMONICSBR) { + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsReal[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagHBE[i], + hSbrDec->qmfDomainInCh + ->hQmfSlotsImag[hSbrDec->hHBE->noCols - LPC_ORDER + i], + (64) * sizeof(FIXP_DBL)); + } + } + { + hSbrDec->prev_frame_lSbr = 1; + hSbrDec->prev_frame_hbeSbr = 0; + } + + lppTransposer( + &hSbrDec->LppTrans, &hSbrDec->qmfDomainInCh->scaling, pLowBandReal, + degreeAlias, // only used if useLP = 1 + pLowBandImag, flags & SBRDEC_LOW_POWER, + hHeaderData->bs_info.sbr_preprocessing, + hHeaderData->freqBandData.v_k_master[0], hHeaderData->timeStep, + borders[0], lastSlotOffs, hHeaderData->freqBandData.nInvfBands, + hFrameData->sbr_invf_mode, hPrevFrameData->sbr_invf_mode); + } + + /* + Adjust envelope of current frame. + */ + + if ((hFrameData->sbrPatchingMode != + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode)) { + ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + (flags & SBRDEC_USAC_HARMONICSBR) && + (hFrameData->sbrPatchingMode == 0) + ? GetxOverBandQmfTransposer(hSbrDec->hHBE) + : NULL, + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = + hFrameData->sbrPatchingMode; + } + + calculateSbrEnvelope( + &hSbrDec->qmfDomainInCh->scaling, &hSbrDec->SbrCalculateEnvelope, + hHeaderData, hFrameData, &pvcDynamicData, pLowBandReal, pLowBandImag, + flags & SBRDEC_LOW_POWER, + + degreeAlias, flags, + (hHeaderData->frameErrorFlag || hPrevFrameData->frameErrorFlag)); + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + /* Avoid hard onsets of high band */ + if (hHeaderData->frameErrorFlag) { + if (hSbrDec->highBandFadeCnt < SBRDEC_MAX_HB_FADE_FRAMES) { + hSbrDec->highBandFadeCnt += 1; + } + } else { + if (hSbrDec->highBandFadeCnt > + 0) { /* Manipulate high band scale factor to get a smooth fade-in */ + hSbrDec->qmfDomainInCh->scaling.hb_scale += hSbrDec->highBandFadeCnt; + hSbrDec->qmfDomainInCh->scaling.hb_scale = + fMin(hSbrDec->qmfDomainInCh->scaling.hb_scale, DFRACT_BITS - 1); + hSbrDec->highBandFadeCnt -= 1; + } + } + +#endif + /* + Update hPrevFrameData (to be used in the next frame) + */ + for (i = 0; i < hHeaderData->freqBandData.nInvfBands; i++) { + hPrevFrameData->sbr_invf_mode[i] = hFrameData->sbr_invf_mode[i]; + } + hPrevFrameData->coupling = hFrameData->coupling; + hPrevFrameData->stopPos = borders[hFrameData->frameInfo.nEnvelopes]; + hPrevFrameData->ampRes = hFrameData->ampResolutionCurrentFrame; + hPrevFrameData->prevSbrPitchInBins = hFrameData->sbrPitchInBins; + /* could be done in extractFrameInfo_pvc() but hPrevFrameData is not + * available there */ + FDKmemcpy(&hPrevFrameData->prevFrameInfo, &hFrameData->frameInfo, + sizeof(FRAME_INFO)); + } else { + /* rescale from lsb to nAnalysisBands in order to compensate scaling with + * hb_scale in this area, done by synthesisFiltering*/ + int rescale; + int lsb; + int length; + + /* Reset hb_scale if no highband is present, because hb_scale is considered + * in the QMF-synthesis */ + hSbrDec->qmfDomainInCh->scaling.hb_scale = saveLbScale; + + rescale = hSbrDec->qmfDomainInCh->scaling.hb_scale - + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + length = (hSbrDec->qmfDomainInCh->fb.no_channels - lsb); + + if ((rescale < 0) && (length > 0)) { + if (!(flags & SBRDEC_LOW_POWER)) { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + scaleValues(&pLowBandImag[i][lsb], length, rescale); + } + } else { + for (i = 0; i < ov_len; i++) { + scaleValues(&pLowBandReal[i][lsb], length, rescale); + } + } + } + } + + if (!(flags & SBRDEC_USAC_HARMONICSBR)) { + int length = hSbrDec->qmfDomainInCh->fb.lsb; + if (flags & SBRDEC_SYNTAX_USAC) { + length = hSbrDec->qmfDomainInCh->fb.no_channels; + } + + /* in case of legacy sbr saving of filter states here */ + for (i = 0; i < LPC_ORDER + ov_len; i++) { + /* + Store the unmodified qmf Slots values (required for LPC filtering) + */ + if (!(flags & SBRDEC_LOW_POWER)) { + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + pLowBandImag[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } else + FDKmemcpy(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + pLowBandReal[noCols - LPC_ORDER + i], + length * sizeof(FIXP_DBL)); + } + } + + /* + Synthesis subband filtering. + */ + + if (!(flags & SBRDEC_PS_DECODED)) { + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + int outScalefactor = 0; + + if (h_ps_d != NULL) { + h_ps_d->procFrameBased = 1; /* we here do frame based processing */ + } + + sbrDecoder_drcApply(&hSbrDec->sbrDrcChannel, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + hSbrDec->qmfDomainOutCh->fb.no_col, &outScalefactor); + + qmfChangeOutScalefactor(&hSbrDec->qmfDomainOutCh->fb, outScalefactor); + + { + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + int save_usb = hSbrDec->qmfDomainOutCh->fb.usb; + +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + if (hSbrDec->qmfDomainOutCh->fb.usb < hFreq->ov_highSubband) { + /* we need to patch usb for this frame as overlap may contain higher + frequency range if headerchange occured; fb. usb is always limited + to maximum fb.no_channels; In case of wrongly decoded headers it + might be that ov_highSubband is higher than the number of synthesis + channels (fb.no_channels), which is forbidden, therefore we need to + limit ov_highSubband with fMin function to avoid not allowed usb in + synthesis filterbank. */ + hSbrDec->qmfDomainOutCh->fb.usb = + fMin((UINT)hFreq->ov_highSubband, + (UINT)hSbrDec->qmfDomainOutCh->fb.no_channels); + } + { + qmfSynthesisFiltering( + &hSbrDec->qmfDomainOutCh->fb, pLowBandReal, + (flags & SBRDEC_LOW_POWER) ? NULL : pLowBandImag, + &hSbrDec->qmfDomainInCh->scaling, + hSbrDec->LppTrans.pSettings->overlap, timeOut, strideOut, + qmfTemp); + } + /* restore saved value */ + hSbrDec->qmfDomainOutCh->fb.usb = save_usb; + hFreq->ov_highSubband = save_usb; +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(qmfTemp, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + } + } + + } else { /* (flags & SBRDEC_PS_DECODED) */ + INT sdiff; + INT scaleFactorHighBand, scaleFactorLowBand_ov, scaleFactorLowBand_no_ov; + + HANDLE_QMF_FILTER_BANK synQmf = &hSbrDec->qmfDomainOutCh->fb; + HANDLE_QMF_FILTER_BANK synQmfRight = &hSbrDecRight->qmfDomainOutCh->fb; + + /* adapt scaling */ + sdiff = hSbrDec->qmfDomainInCh->scaling.lb_scale - + reserve; /* Scaling difference */ + scaleFactorHighBand = sdiff - hSbrDec->qmfDomainInCh->scaling.hb_scale; + scaleFactorLowBand_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + scaleFactorLowBand_no_ov = sdiff - hSbrDec->qmfDomainInCh->scaling.lb_scale; + + /* Scale of low band overlapping QMF data */ + scaleFactorLowBand_ov = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_ov)); + /* Scale of low band current QMF data */ + scaleFactorLowBand_no_ov = fMin( + DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorLowBand_no_ov)); + /* Scale of current high band */ + scaleFactorHighBand = + fMin(DFRACT_BITS - 1, fMax(-(DFRACT_BITS - 1), scaleFactorHighBand)); + + if (h_ps_d->procFrameBased == 1) /* If we have switched from frame to slot + based processing copy filter states */ + { /* procFrameBased will be unset later */ + /* copy filter states from left to right */ + /* was ((640)-(64))*sizeof(FIXP_QSS) + flexible amount of synthesis bands needed for QMF based resampling + */ + FDK_ASSERT(hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis <= + QMF_MAX_SYNTHESIS_BANDS); + FDKmemcpy(synQmfRight->FilterStates, synQmf->FilterStates, + 9 * hSbrDec->qmfDomainInCh->pGlobalConf->nBandsSynthesis * + sizeof(FIXP_QSS)); + } + + /* Feed delaylines when parametric stereo is switched on. */ + PreparePsProcessing(h_ps_d, pLowBandReal, pLowBandImag, + scaleFactorLowBand_ov); + + /* use the same synthese qmf values for left and right channel */ + synQmfRight->no_col = synQmf->no_col; + synQmfRight->lsb = synQmf->lsb; + synQmfRight->usb = synQmf->usb; + + int env = 0; + + { +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, + 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_START(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + + int maxShift = 0; + + if (hSbrDec->sbrDrcChannel.enable != 0) { + if (hSbrDec->sbrDrcChannel.prevFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.prevFact_exp; + } + if (hSbrDec->sbrDrcChannel.currFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.currFact_exp; + } + if (hSbrDec->sbrDrcChannel.nextFact_exp > maxShift) { + maxShift = hSbrDec->sbrDrcChannel.nextFact_exp; + } + } + + /* copy DRC data to right channel (with PS both channels use the same DRC + * gains) */ + FDKmemcpy(&hSbrDecRight->sbrDrcChannel, &hSbrDec->sbrDrcChannel, + sizeof(SBRDEC_DRC_CHANNEL)); + + for (i = 0; i < synQmf->no_col; i++) { /* ----- no_col loop ----- */ + + INT outScalefactorR, outScalefactorL; + + /* qmf timeslot of right channel */ + FIXP_DBL *rQmfReal = pWorkBuffer; + FIXP_DBL *rQmfImag = pWorkBuffer + synQmf->no_channels; + + { + if (i == + h_ps_d->bsData[h_ps_d->processSlot].mpeg.aEnvStartStop[env]) { + initSlotBasedRotation(h_ps_d, env, + hHeaderData->freqBandData.highSubband); + env++; + } + + ApplyPsSlot( + h_ps_d, /* parametric stereo decoder handle */ + (pLowBandReal + i), /* one timeslot of left/mono channel */ + (pLowBandImag + i), /* one timeslot of left/mono channel */ + rQmfReal, /* one timeslot or right channel */ + rQmfImag, /* one timeslot or right channel */ + scaleFactorLowBand_no_ov, + (i < hSbrDec->LppTrans.pSettings->overlap) + ? scaleFactorLowBand_ov + : scaleFactorLowBand_no_ov, + scaleFactorHighBand, synQmf->lsb, synQmf->usb); + + outScalefactorL = outScalefactorR = 1; /* psDiffScale! (MPEG-PS) */ + } + + sbrDecoder_drcApplySlot(/* right channel */ + &hSbrDecRight->sbrDrcChannel, rQmfReal, + rQmfImag, i, synQmfRight->no_col, maxShift); + + outScalefactorR += maxShift; + + sbrDecoder_drcApplySlot(/* left channel */ + &hSbrDec->sbrDrcChannel, *(pLowBandReal + i), + *(pLowBandImag + i), i, synQmf->no_col, + maxShift); + + outScalefactorL += maxShift; + + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + qmfSynthesisFilteringSlot( + synQmfRight, rQmfReal, /* QMF real buffer */ + rQmfImag, /* QMF imag buffer */ + outScalefactorL, outScalefactorL, + timeOutRight + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + + qmfSynthesisFilteringSlot( + synQmf, *(pLowBandReal + i), /* QMF real buffer */ + *(pLowBandImag + i), /* QMF imag buffer */ + outScalefactorR, outScalefactorR, + timeOut + (i * synQmf->no_channels * strideOut), strideOut, + pWorkBuffer); + } + } /* no_col loop i */ +#if (QMF_MAX_SYNTHESIS_BANDS <= 64) + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#else + C_AALLOC_STACK_END(pWorkBuffer, FIXP_DBL, 2 * QMF_MAX_SYNTHESIS_BANDS); +#endif + } + } + + sbrDecoder_drcUpdateChannel(&hSbrDec->sbrDrcChannel); + + /* + Update overlap buffer + Even bands above usb are copied to avoid outdated spectral data in case + the stop frequency raises. + */ + + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + { + FDK_QmfDomain_SaveOverlap(hSbrDec->qmfDomainInCh, 0); + FDK_ASSERT(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale == saveLbScale); + } + } + + hSbrDec->savedStates = 0; + + /* Save current frame status */ + hPrevFrameData->frameErrorFlag = hHeaderData->frameErrorFlag; + hSbrDec->applySbrProc_old = applyProcessing; + +} /* sbr_dec() */ + +/*! + \brief Creates sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +createSbrDec(SBR_CHANNEL *hSbrChannel, + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + TRANSPOSER_SETTINGS *pSettings, + const int downsampleFac, /*!< Downsampling factor */ + const UINT qmfFlags, /*!< flags -> 1: HQ/LP selector, 2: CLDFB */ + const UINT flags, const int overlap, + int chan, /*!< Channel for which to assign buffers etc. */ + int codecFrameSize) + +{ + SBR_ERROR err = SBRDEC_OK; + int timeSlots = + hHeaderData->numberTimeSlots; /* Number of SBR slots per frame */ + int noCols = + timeSlots * hHeaderData->timeStep; /* Number of QMF slots per frame */ + HANDLE_SBR_DEC hs = &(hSbrChannel->SbrDec); + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + hs->highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + +#endif + hs->scale_hbe = 15; + hs->scale_lb = 15; + hs->scale_ov = 15; + + hs->prev_frame_lSbr = 0; + hs->prev_frame_hbeSbr = 0; + + hs->codecFrameSize = codecFrameSize; + + /* + create envelope calculator + */ + err = createSbrEnvelopeCalc(&hs->SbrCalculateEnvelope, hHeaderData, chan, + flags); + if (err != SBRDEC_OK) { + return err; + } + + initSbrPrevFrameData(&hSbrChannel->prevFrameData, timeSlots); + + /* + create transposer + */ + err = createLppTransposer( + &hs->LppTrans, pSettings, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.highSubband, timeSlots, noCols, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->sbrProcSmplRate, chan, + overlap); + if (err != SBRDEC_OK) { + return err; + } + + if (flags & SBRDEC_USAC_HARMONICSBR) { + int noChannels, bSbr41 = flags & SBRDEC_QUAD_RATE ? 1 : 0; + + noChannels = + QMF_SYNTH_CHANNELS / + ((bSbr41 + 1) * 2); /* 32 for (32:64 and 24:64) and 16 for 16:64 */ + + /* shared memory between hbeLightTimeDelayBuffer and hQmfHBESlotsReal if + * SBRDEC_HBE_ENABLE */ + hSbrChannel->SbrDec.tmp_memory = (FIXP_DBL **)fdkCallocMatrix2D_aligned( + noCols, noChannels, sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.tmp_memory == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.hQmfHBESlotsReal = hSbrChannel->SbrDec.tmp_memory; + hSbrChannel->SbrDec.hQmfHBESlotsImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.hQmfHBESlotsImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + /* buffers containing unmodified qmf data; required when switching from + * legacy SBR to HBE */ + /* buffer can be used as LPCFilterstates buffer because legacy SBR needs + * exactly these values for LPC filtering */ + hSbrChannel->SbrDec.codecQMFBufferReal = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferReal == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + hSbrChannel->SbrDec.codecQMFBufferImag = + (FIXP_DBL **)fdkCallocMatrix2D_aligned(noCols, noChannels, + sizeof(FIXP_DBL)); + if (hSbrChannel->SbrDec.codecQMFBufferImag == NULL) { + return SBRDEC_MEM_ALLOC_FAILED; + } + + err = QmfTransposerCreate(&hs->hHBE, codecFrameSize, 0, bSbr41); + if (err != SBRDEC_OK) { + return err; + } + } + + return err; +} + +/*! + \brief Delete sbr decoder structure + \return errorCode, 0 if successful +*/ +int deleteSbrDec(SBR_CHANNEL *hSbrChannel) { + HANDLE_SBR_DEC hs = &hSbrChannel->SbrDec; + + deleteSbrEnvelopeCalc(&hs->SbrCalculateEnvelope); + + if (hs->tmp_memory != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->tmp_memory); + } + + /* modify here */ + FDK_FREE_MEMORY_2D_ALIGNED(hs->hQmfHBESlotsImag); + + if (hs->hHBE != NULL) QmfTransposerClose(hs->hHBE); + + if (hs->codecQMFBufferReal != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferReal); + } + + if (hs->codecQMFBufferImag != NULL) { + FDK_FREE_MEMORY_2D_ALIGNED(hs->codecQMFBufferImag); + } + + return 0; +} + +/*! + \brief resets sbr decoder structure + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData) { + SBR_ERROR sbrError = SBRDEC_OK; + int i; + FIXP_DBL *pLowBandReal[128]; + FIXP_DBL *pLowBandImag[128]; + int useLP = flags & SBRDEC_LOW_POWER; + + int old_lsb = hSbrDec->qmfDomainInCh->fb.lsb; + int old_usb = hSbrDec->qmfDomainInCh->fb.usb; + int new_lsb = hHeaderData->freqBandData.lowSubband; + /* int new_usb = hHeaderData->freqBandData.highSubband; */ + int l, startBand, stopBand, startSlot, size; + + FIXP_DBL **OverlapBufferReal = hSbrDec->qmfDomainInCh->hQmfSlotsReal; + FIXP_DBL **OverlapBufferImag = hSbrDec->qmfDomainInCh->hQmfSlotsImag; + + /* in case the previous frame was not active in terms of SBR processing, the + full band from 0 to no_channels was rescaled and not overwritten. Thats why + the scaling factor lb_scale can be seen as assigned to all bands from 0 to + no_channels in the previous frame. The same states for the current frame if + the current frame is not active in terms of SBR processing + */ + int applySbrProc = (hHeaderData->syncState == SBR_ACTIVE || + (hHeaderData->frameErrorFlag == 0 && + hHeaderData->syncState == SBR_HEADER)); + int applySbrProc_old = hSbrDec->applySbrProc_old; + + if (!applySbrProc) { + new_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + } + if (!applySbrProc_old) { + old_lsb = (hSbrDec->qmfDomainInCh->fb).no_channels; + old_usb = old_lsb; + } + + resetSbrEnvelopeCalc(&hSbrDec->SbrCalculateEnvelope); + + /* Change lsb and usb */ + /* Synthesis */ + FDK_ASSERT(hSbrDec->qmfDomainOutCh != NULL); + hSbrDec->qmfDomainOutCh->fb.lsb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.lowSubband); + hSbrDec->qmfDomainOutCh->fb.usb = + fixMin((INT)hSbrDec->qmfDomainOutCh->fb.no_channels, + (INT)hHeaderData->freqBandData.highSubband); + /* Analysis */ + FDK_ASSERT(hSbrDec->qmfDomainInCh != NULL); + hSbrDec->qmfDomainInCh->fb.lsb = hSbrDec->qmfDomainOutCh->fb.lsb; + hSbrDec->qmfDomainInCh->fb.usb = hSbrDec->qmfDomainOutCh->fb.usb; + + /* + The following initialization of spectral data in the overlap buffer + is required for dynamic x-over or a change of the start-freq for 2 reasons: + + 1. If the lowband gets _wider_, unadjusted data would remain + + 2. If the lowband becomes _smaller_, the highest bands of the old lowband + must be cleared because the whitening would be affected + */ + startBand = old_lsb; + stopBand = new_lsb; + startSlot = fMax(0, hHeaderData->timeStep * (hPrevFrameData->stopPos - + hHeaderData->numberTimeSlots)); + size = fMax(0, stopBand - startBand); + + /* in case of USAC we don't want to zero out the memory, as this can lead to + holes in the spectrum; fix shall only be applied for USAC not for MPEG-4 + SBR, in this case setting zero remains */ + if (!(flags & SBRDEC_SYNTAX_USAC)) { + /* keep already adjusted data in the x-over-area */ + if (!useLP) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + FDKmemclear(&OverlapBufferImag[l][startBand], size * sizeof(FIXP_DBL)); + } + } else { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + FDKmemclear(&OverlapBufferReal[l][startBand], size * sizeof(FIXP_DBL)); + } + } + + /* + reset LPC filter states + */ + startBand = fixMin(old_lsb, new_lsb); + stopBand = fixMax(old_lsb, new_lsb); + size = fixMax(0, stopBand - startBand); + + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[0][startBand], + size * sizeof(FIXP_DBL)); + FDKmemclear(&hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[1][startBand], + size * sizeof(FIXP_DBL)); + } + } + + if (startSlot != 0) { + int source_exp, target_exp, delta_exp, target_lsb, target_usb, reserve; + FIXP_DBL maxVal; + + /* + Rescale already processed spectral data between old and new x-over + frequency. This must be done because of the separate scalefactors for + lowband and highband. + */ + + /* We have four relevant transitions to cover: + 1. old_usb is lower than new_lsb; old SBR area is completely below new SBR + area. + -> entire old area was highband and belongs to lowband now + and has to be rescaled. + 2. old_lsb is higher than new_usb; new SBR area is completely below old SBR + area. + -> old area between new_lsb and old_lsb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + 3. old_lsb is lower and old_usb is higher than new_lsb; old and new SBR + areas overlap. + -> old area between old_lsb and new_lsb was highband and belongs to + lowband now and has to be rescaled to match new lowband scale. + 4. new_lsb is lower and new_usb_is higher than old_lsb; old and new SBR + areas overlap. + -> old area between new_lsb and old_usb was lowband and belongs to + highband now and has to be rescaled to match new highband scale. + */ + + if (new_lsb > old_lsb) { + /* case 1 and 3 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + + startBand = old_lsb; + + if (new_lsb >= old_usb) { + /* case 1 */ + stopBand = old_usb; + } else { + /* case 3 */ + stopBand = new_lsb; + } + + target_lsb = 0; + target_usb = old_lsb; + } else { + /* case 2 and 4 */ + source_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale); + target_exp = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_hb_scale); + + startBand = new_lsb; + stopBand = old_lsb; + + target_lsb = old_lsb; + target_usb = old_usb; + } + + maxVal = + maxSubbandSample(OverlapBufferReal, (useLP) ? NULL : OverlapBufferImag, + startBand, stopBand, 0, startSlot); + + reserve = ((LONG)maxVal != 0 ? CntLeadingZeros(maxVal) - 1 : 0); + reserve = fixMin( + reserve, + DFRACT_BITS - 1 - + EXP2SCALE( + source_exp)); /* what is this line for, why do we need it? */ + + /* process only if x-over-area is not dominant after rescale; + otherwise I'm not sure if all buffers are scaled correctly; + */ + if (target_exp - (source_exp - reserve) >= 0) { + rescaleSubbandSamples(OverlapBufferReal, + (useLP) ? NULL : OverlapBufferImag, startBand, + stopBand, 0, startSlot, reserve); + source_exp -= reserve; + } + + delta_exp = target_exp - source_exp; + + if (delta_exp < 0) { /* x-over-area is dominant */ + startBand = target_lsb; + stopBand = target_usb; + delta_exp = -delta_exp; + + if (new_lsb > old_lsb) { + /* The lowband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = EXP2SCALE(source_exp); + } else { + /* The highband has to be rescaled */ + hSbrDec->qmfDomainInCh->scaling.ov_hb_scale = EXP2SCALE(source_exp); + } + } + + FDK_ASSERT(startBand <= stopBand); + + if (!useLP) { + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + -delta_exp); + } + } else + for (l = 0; l < startSlot; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + -delta_exp); + } + } /* startSlot != 0 */ + + /* + Initialize transposer and limiter + */ + sbrError = resetLppTransposer( + &hSbrDec->LppTrans, hHeaderData->freqBandData.lowSubband, + hHeaderData->freqBandData.v_k_master, hHeaderData->freqBandData.numMaster, + hHeaderData->freqBandData.freqBandTableNoise, + hHeaderData->freqBandData.nNfb, hHeaderData->freqBandData.highSubband, + hHeaderData->sbrProcSmplRate); + if (sbrError != SBRDEC_OK) return sbrError; + + hSbrDec->savedStates = 0; + + if ((flags & SBRDEC_USAC_HARMONICSBR) && applySbrProc) { + sbrError = QmfTransposerReInit(hSbrDec->hHBE, + hHeaderData->freqBandData.freqBandTable, + hHeaderData->freqBandData.nSfb); + if (sbrError != SBRDEC_OK) return sbrError; + + /* copy saved states from previous frame to legacy SBR lpc filterstate + * buffer */ + for (i = 0; i < LPC_ORDER + hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - LPC_ORDER - + hSbrDec->LppTrans.pSettings->overlap + i], + hSbrDec->hHBE->noChannels * sizeof(FIXP_DBL)); + } + hSbrDec->savedStates = 1; + + { + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + pLowBandReal[i] = hSbrDec->LppTrans.lpcFilterStatesRealHBE[i]; + pLowBandImag[i] = hSbrDec->LppTrans.lpcFilterStatesImagHBE[i]; + } + + /* map QMF buffer to pointer array (Overlap + Frame)*/ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferReal[i]; + pLowBandImag[i + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->codecQMFBufferImag[i]; + } + + if (flags & SBRDEC_QUAD_RATE) { + if (hFrameData->sbrPatchingMode == 0) { + int *xOverQmf = GetxOverBandQmfTransposer(hSbrDec->hHBE); + + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols / 2; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols / 2 + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + + copyHarmonicSpectrum( + xOverQmf, pLowBandReal, pLowBandImag, hSbrDec->hHBE->noCols, + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + } else { + /* in case of harmonic SBR and no HBE_LP map additional buffer for + one more frame to pointer arry */ + for (i = 0; i < hSbrDec->hHBE->noCols; i++) { + pLowBandReal[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsReal[i]; + pLowBandImag[i + hSbrDec->hHBE->noCols + + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER] = + hSbrDec->hQmfHBESlotsImag[i]; + } + + if (hFrameData->sbrPatchingMode == 0) { + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + 0 /* not required for keeping states updated in this frame*/, + hSbrDec->scale_lb, hSbrDec->scale_lb, + &hSbrDec->qmfDomainInCh->scaling.hb_scale, hHeaderData->timeStep, + hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_NOOUT); + } + + QmfTransposerApply( + hSbrDec->hHBE, + pLowBandReal + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + pLowBandImag + hSbrDec->LppTrans.pSettings->overlap + + hSbrDec->hHBE->noCols + LPC_ORDER, + hSbrDec->hHBE->noCols, pLowBandReal, pLowBandImag, + hSbrDec->LppTrans.lpcFilterStatesRealHBE, + hSbrDec->LppTrans.lpcFilterStatesImagHBE, + hPrevFrameData->prevSbrPitchInBins, hSbrDec->scale_lb, + hSbrDec->scale_hbe, &hSbrDec->qmfDomainInCh->scaling.hb_scale, + hHeaderData->timeStep, hFrameData->frameInfo.borders[0], + hSbrDec->LppTrans.pSettings->overlap, KEEP_STATES_SYNCED_OUTDIFF); + } + + if (hFrameData->sbrPatchingMode == 0) { + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->LppTrans.lpcFilterStatesRealHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + FDKmemcpy(hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->LppTrans.lpcFilterStatesImagHBE[i + LPC_ORDER], + (64) * sizeof(FIXP_DBL)); + } + + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + /* + Store the unmodified qmf Slots values for upper part of spectrum + (required for LPC filtering) required if next frame is a HBE frame + */ + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsReal[i], + hSbrDec->codecQMFBufferReal[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + FDKmemcpy( + hSbrDec->qmfDomainInCh->hQmfSlotsImag[i], + hSbrDec->codecQMFBufferImag[hSbrDec->hHBE->noCols - + hSbrDec->LppTrans.pSettings->overlap + + i], + new_lsb * sizeof(FIXP_DBL)); + } + } + } + } + + { + int adapt_lb = 0, diff = 0, + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + + if ((hSbrDec->qmfDomainInCh->scaling.ov_lb_scale != + hSbrDec->qmfDomainInCh->scaling.lb_scale) && + startSlot != 0) { + /* we need to adapt spectrum to have equal scale factor, always larger + * than zero */ + diff = SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.ov_lb_scale) - + SCALE2EXP(hSbrDec->qmfDomainInCh->scaling.lb_scale); + + if (diff > 0) { + adapt_lb = 1; + diff = -diff; + new_scale = hSbrDec->qmfDomainInCh->scaling.ov_lb_scale; + } + + stopBand = new_lsb; + } + + if (hFrameData->sbrPatchingMode == 1) { + /* scale states from LegSBR filterstates buffer */ + for (i = 0; i < hSbrDec->LppTrans.pSettings->overlap + LPC_ORDER; i++) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesRealLegSBR[i], new_lsb, + diff); + if (!useLP) { + scaleValues(hSbrDec->LppTrans.lpcFilterStatesImagLegSBR[i], new_lsb, + diff); + } + } + + if (flags & SBRDEC_SYNTAX_USAC) { + /* get missing states between old and new x_over from LegSBR + * filterstates buffer */ + /* in case of legacy SBR we leave these values zeroed out */ + for (i = startSlot; i < hSbrDec->LppTrans.pSettings->overlap; i++) { + FDKmemcpy(&OverlapBufferReal[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesRealLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + if (!useLP) { + FDKmemcpy(&OverlapBufferImag[i][old_lsb], + &hSbrDec->LppTrans + .lpcFilterStatesImagLegSBR[LPC_ORDER + i][old_lsb], + fMax(new_lsb - old_lsb, 0) * sizeof(FIXP_DBL)); + } + } + } + + if (new_lsb > old_lsb) { + stopBand = old_lsb; + } + } + if ((adapt_lb == 1) && (stopBand > startBand)) { + for (l = startSlot; l < hSbrDec->LppTrans.pSettings->overlap; l++) { + scaleValues(OverlapBufferReal[l] + startBand, stopBand - startBand, + diff); + if (!useLP) { + scaleValues(OverlapBufferImag[l] + startBand, stopBand - startBand, + diff); + } + } + } + hSbrDec->qmfDomainInCh->scaling.ov_lb_scale = new_scale; + } + + sbrError = ResetLimiterBands(hHeaderData->freqBandData.limiterBandTable, + &hHeaderData->freqBandData.noLimiterBands, + hHeaderData->freqBandData.freqBandTable[0], + hHeaderData->freqBandData.nSfb[0], + hSbrDec->LppTrans.pSettings->patchParam, + hSbrDec->LppTrans.pSettings->noOfPatches, + hHeaderData->bs_data.limiterBands, + hFrameData->sbrPatchingMode, + GetxOverBandQmfTransposer(hSbrDec->hHBE), + Get41SbrQmfTransposer(hSbrDec->hHBE)); + + hSbrDec->SbrCalculateEnvelope.sbrPatchingMode = hFrameData->sbrPatchingMode; + + return sbrError; +} diff --git a/fdk-aac/libSBRdec/src/sbr_dec.h b/fdk-aac/libSBRdec/src/sbr_dec.h new file mode 100644 index 0000000..156da03 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_dec.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr decoder +*/ +#ifndef SBR_DEC_H +#define SBR_DEC_H + +#include "sbrdecoder.h" + +#include "lpp_tran.h" +#include "qmf.h" +#include "env_calc.h" +#include "FDK_audio.h" + +#include "sbrdec_drc.h" + +#include "pvc_dec.h" + +#include "hbe.h" + +enum SBRDEC_QMF_SKIP { + qmfSkipNothing = 0, + qmfSkipAnalysis = 1 << 0, + qmfSkipSynthesis = 1 << 1 +}; + +typedef struct { + SBR_CALCULATE_ENVELOPE SbrCalculateEnvelope; + SBR_LPP_TRANS LppTrans; + PVC_STATIC_DATA PvcStaticData; + + /* do scale handling in sbr an not in qmf */ + SHORT scale_ov; + SHORT scale_lb; + SHORT scale_hbe; + + SHORT prev_frame_lSbr; + SHORT prev_frame_hbeSbr; + + int codecFrameSize; + + HANDLE_HBE_TRANSPOSER hHBE; + + HANDLE_FDK_QMF_DOMAIN_IN qmfDomainInCh; + HANDLE_FDK_QMF_DOMAIN_OUT qmfDomainOutCh; + + SBRDEC_DRC_CHANNEL sbrDrcChannel; + +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + INT highBandFadeCnt; /* counter for fading in high-band signal smoothly */ + +#endif + FIXP_DBL **tmp_memory; /* shared memory between hbeLightTimeDelayBuffer and + hQmfHBESlotsReal */ + + FIXP_DBL **hQmfHBESlotsReal; + FIXP_DBL **hQmfHBESlotsImag; + + FIXP_DBL **codecQMFBufferReal; + FIXP_DBL **codecQMFBufferImag; + UCHAR savedStates; + int applySbrProc_old; +} SBR_DEC; + +typedef SBR_DEC *HANDLE_SBR_DEC; + +typedef struct { + SBR_FRAME_DATA frameData[(1) + 1]; + SBR_PREV_FRAME_DATA prevFrameData; + SBR_DEC SbrDec; +} SBR_CHANNEL; + +typedef SBR_CHANNEL *HANDLE_SBR_CHANNEL; + +void sbr_dec( + HANDLE_SBR_DEC hSbrDec, /*!< handle to Decoder channel */ + INT_PCM *timeIn, /*!< pointer to input time signal */ + INT_PCM *timeOut, /*!< pointer to output time signal */ + HANDLE_SBR_DEC hSbrDecRight, /*!< handle to Decoder channel right */ + INT_PCM *timeOutRight, /*!< pointer to output time signal */ + INT strideOut, /*!< Time data traversal strideOut */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Static control data */ + HANDLE_SBR_FRAME_DATA hFrameData, /*!< Control data of current frame */ + HANDLE_SBR_PREV_FRAME_DATA + hPrevFrameData, /*!< Some control data of last frame */ + const int applyProcessing, /*!< Flag for SBR operation */ + HANDLE_PS_DEC h_ps_d, const UINT flags, const int codecFrameSize); + +SBR_ERROR +createSbrDec(SBR_CHANNEL *hSbrChannel, HANDLE_SBR_HEADER_DATA hHeaderData, + TRANSPOSER_SETTINGS *pSettings, const int downsampleFac, + const UINT qmfFlags, const UINT flags, const int overlap, int chan, + int codecFrameSize); + +int deleteSbrDec(SBR_CHANNEL *hSbrChannel); + +SBR_ERROR +resetSbrDec(HANDLE_SBR_DEC hSbrDec, HANDLE_SBR_HEADER_DATA hHeaderData, + HANDLE_SBR_PREV_FRAME_DATA hPrevFrameData, const int downsampleFac, + const UINT flags, HANDLE_SBR_FRAME_DATA hFrameData); + +#endif diff --git a/fdk-aac/libSBRdec/src/sbr_ram.cpp b/fdk-aac/libSBRdec/src/sbr_ram.cpp new file mode 100644 index 0000000..8b35fd2 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_ram.cpp @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + + This module declares all static and dynamic memory spaces +*/ + +#include "sbr_ram.h" + +#define WORKBUFFER1_TAG 2 +#define WORKBUFFER2_TAG 3 + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the decoder +*/ +/* @{ */ + +/*! SBR Decoder main structure */ +C_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE, 1) +/*! SBR Decoder element data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecElement, SBR_DECODER_ELEMENT, 1, (8)) +/*! SBR Decoder individual channel data
+ Dimension: (8) */ +C_ALLOC_MEM2(Ram_SbrDecChannel, SBR_CHANNEL, 1, (8) + 1) + +/*! Static Data of PS */ + +C_ALLOC_MEM(Ram_ps_dec, struct PS_DEC, 1) + +/* @} */ + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core decoder +
+ Depending on the mode set by DONT_USE_CORE_WORKBUFFER, workbuffers are + defined additionally to the CoreWorkbuffer. +
+ The size of WorkBuffers is ((1024) / (32) * (4) / 2)*(64) = 2048. +
+ WorkBuffer2 is a pointer to the CoreWorkBuffer wich is reused here in the SBR + part. In case of DONT_USE_CORE_WORKBUFFER, the CoreWorkbuffer is not used and + the according Workbuffer2 is defined locally in this file.
WorkBuffer1 is + reused in the AAC core (-> aacdecoder.cpp, aac_ram.cpp)
+ + Use of WorkBuffers: +
+
+    -------------------------------------------------------------
+    AAC core:
+
+      CoreWorkbuffer: spectral coefficients
+      WorkBuffer1:    CAacDecoderChannelInfo, CAacDecoderDynamicData
+
+    -------------------------------------------------------------
+    SBR part:
+      ----------------------------------------------
+      Low Power Mode (useLP=1 or LOW_POWER_SBR_ONLY), see assignLcTimeSlots()
+
+        SLOT_BASED_PROTOTYPE_SYN_FILTER
+
+        WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | RealLeft       |                         | RealRight      |
+        |________________|                         |________________|
+
+      ----------------------------------------------
+      High Quality Mode (!LOW_POWER_SBR_ONLY and useLP=0), see
+  assignHqTimeSlots()
+
+         SLOTBASED_PS
+
+         WorkBuffer1                                WorkBuffer2(=CoreWorkbuffer)
+         ________________                           ________________
+        | Real/Imag      |  interleaved            | Real/Imag      |
+  interleaved
+        |________________|  first half actual ch   |________________|  second
+  half actual ch
+
+    -------------------------------------------------------------
+
+  
+ +*/ diff --git a/fdk-aac/libSBRdec/src/sbr_ram.h b/fdk-aac/libSBRdec/src/sbr_ram.h new file mode 100644 index 0000000..e00f8b5 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_ram.h @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Memory layout +*/ +#ifndef SBR_RAM_H +#define SBR_RAM_H + +#include "sbrdecoder.h" + +#include "env_extr.h" +#include "sbr_dec.h" + +#define SBRDEC_MAX_CH_PER_ELEMENT (2) + +#define FRAME_OK (0) +#define FRAME_ERROR (1) +#define FRAME_ERROR_ALLSLOTS (2) + +typedef struct { + SBR_CHANNEL *pSbrChannel[SBRDEC_MAX_CH_PER_ELEMENT]; + TRANSPOSER_SETTINGS + transposerSettings; /* Common transport settings for each individual + channel of an element */ + HANDLE_FDK_BITSTREAM hBs; + + MP4_ELEMENT_ID + elementID; /* Element ID set during initialization. Can be used for + concealment */ + int nChannels; /* Number of elements output channels (=2 in case of PS) */ + + UCHAR frameErrorFlag[(1) + 1]; /* Frame error status (for every slot in the + delay line). Will be copied into header at + the very beginning of decodeElement() + routine. */ + + UCHAR useFrameSlot; /* Index which defines which slot will be decoded/filled + next (used with additional delay) */ + UCHAR useHeaderSlot[(1) + 1]; /* Index array that provides the link between + header and frame data (important when + processing with additional delay). */ +} SBR_DECODER_ELEMENT; + +struct SBR_DECODER_INSTANCE { + SBR_DECODER_ELEMENT *pSbrElement[(8)]; + SBR_HEADER_DATA sbrHeader[( + 8)][(1) + 1]; /* Sbr header for each individual channel of an element */ + + HANDLE_FDK_QMF_DOMAIN pQmfDomain; + + HANDLE_PS_DEC hParametricStereoDec; + + /* Global parameters */ + AUDIO_OBJECT_TYPE coreCodec; /* AOT of core codec */ + int numSbrElements; + int numSbrChannels; + INT sampleRateIn; /* SBR decoder input sampling rate; might be different than + the transposer input sampling rate. */ + INT sampleRateOut; /* Sampling rate of the SBR decoder output audio samples. + */ + USHORT codecFrameSize; + UCHAR synDownsampleFac; + INT downscaleFactor; + UCHAR numDelayFrames; /* The current number of additional delay frames used + for processing. */ + UCHAR harmonicSBR; + UCHAR + numFlushedFrames; /* The variable counts the number of frames which are + flushed consecutively. */ + + UINT flags; +}; + +H_ALLOC_MEM(Ram_SbrDecElement, SBR_DECODER_ELEMENT) +H_ALLOC_MEM(Ram_SbrDecChannel, SBR_CHANNEL) +H_ALLOC_MEM(Ram_SbrDecoder, struct SBR_DECODER_INSTANCE) + +H_ALLOC_MEM(Ram_sbr_QmfStatesSynthesis, FIXP_QSS) +H_ALLOC_MEM(Ram_sbr_OverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(Ram_sbr_HBEOverlapBuffer, FIXP_DBL) + +H_ALLOC_MEM(Ram_ps_dec, PS_DEC) + +#endif /* SBR_RAM_H */ diff --git a/fdk-aac/libSBRdec/src/sbr_rom.cpp b/fdk-aac/libSBRdec/src/sbr_rom.cpp new file mode 100644 index 0000000..8a6688a --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbr_rom.cpp @@ -0,0 +1,1705 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Definition of constant tables + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbr_rom.h" + +/*! + \name StartStopBands + \brief Start and stop subbands of the highband. + + k_o = startMin + offset[bs_start_freq]; + startMin = {3000,4000,5000} * (128/FS_sbr) / FS_sbr < 32Khz, 32Khz <= FS_sbr < + 64KHz, 64KHz <= FS_sbr The stop subband can also be calculated to save memory + by defining #CALC_STOP_BAND. +*/ +//@{ +/* tables were created with ../addon/octave/sbr_start_freq_table.m */ +const UCHAR FDK_sbrDecoder_sbr_start_freq_16[][16] = { + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_22[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 30}, + {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_24[][16] = { + {11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_32[][16] = { + {10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 27, 29, 32}, + {2, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 24}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_40[][16] = { + {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 24, 26, 28, 30, 32}, + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 23, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_44[][16] = { + {8, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 21, 23, 25, 28, 32}, + {2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19, 22, 26}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_48[][16] = { + {7, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24, 27, 31}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_64[][16] = { + {6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 19, 21, 23, 26, 30}, + {1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_88[][16] = { + {5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 20, 23, 27, 31}, + {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_192[16] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 14, 16, 19, 23, 27}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_176[16] = { + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 20, 24, 28}; +const UCHAR FDK_sbrDecoder_sbr_start_freq_128[16] = { + 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 21, 25}; + +//@} + +/*! + \name Whitening + \brief Coefficients for spectral whitening in the transposer +*/ +//@{ +/*! Assignment of whitening tuning depending on the crossover frequency */ +const USHORT FDK_sbrDecoder_sbr_whFactorsIndex[NUM_WHFACTOR_TABLE_ENTRIES] = { + 0, 5000, 6000, 6500, 7000, 7500, 8000, 9000, 10000}; + +/*! + \brief Whithening levels tuning table + + With the current tuning, there are some redundant entries: + + \li NUM_WHFACTOR_TABLE_ENTRIES can be reduced by 3, + \li the first coloumn can be eliminated. + +*/ +const FIXP_DBL + FDK_sbrDecoder_sbr_whFactorsTable[NUM_WHFACTOR_TABLE_ENTRIES][6] = { + /* OFF_LEVEL, TRANSITION_LEVEL, LOW_LEVEL, MID_LEVEL, HIGH_LEVEL */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* < 5000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 5000 < 6000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6000 < 6500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 6500 < 7000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7000 < 7500 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 7500 < 8000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 8000 < 9000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* 9000 < 10000 */ + {FL2FXCONST_DBL(0.00f), FL2FXCONST_DBL(0.6f), FL2FXCONST_DBL(0.75f), + FL2FXCONST_DBL(0.90f), FL2FXCONST_DBL(0.98f)}, /* > 10000 */ +}; + +//@} + +/*! + \name EnvAdj + \brief Constants and tables used for envelope adjustment +*/ +//@{ + +/*! Mantissas of gain limits */ +const FIXP_SGL FDK_sbrDecoder_sbr_limGains_m[4] = { + FL2FXCONST_SGL(0.5011932025f), /*!< -3 dB. Gain limit when limiterGains in + frameData is 0 */ + FL2FXCONST_SGL( + 0.5f), /*!< 0 dB. Gain limit when limiterGains in frameData is 1 */ + FL2FXCONST_SGL(0.9976346258f), /*!< +3 dB. Gain limit when limiterGains in + frameData is 2 */ + FL2FXCONST_SGL(0.6776263578f) /*!< Inf. Gain limit when limiterGains in + frameData is 3 */ +}; + +/*! Exponents of gain limits */ +const UCHAR FDK_sbrDecoder_sbr_limGains_e[4] = {0, 1, 1, 67}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_SGL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4[4] = { + FL2FXCONST_SGL(1.0f / 4.0f), FL2FXCONST_SGL(1.2f / 4.0f), + FL2FXCONST_SGL(2.0f / 4.0f), FL2FXCONST_SGL(3.0f / 4.0f)}; + +/*! Constants for calculating the number of limiter bands */ +const FIXP_DBL FDK_sbrDecoder_sbr_limiterBandsPerOctaveDiv4_DBL[4] = { + FL2FXCONST_DBL(1.0f / 4.0f), FL2FXCONST_DBL(1.2f / 4.0f), + FL2FXCONST_DBL(2.0f / 4.0f), FL2FXCONST_DBL(3.0f / 4.0f)}; + +/*! Ratio of old gains and noise levels for the first 4 timeslots of an envelope + */ +const FIXP_SGL FDK_sbrDecoder_sbr_smoothFilter[4] = { + FL2FXCONST_SGL(0.66666666666666f), FL2FXCONST_SGL(0.36516383427084f), + FL2FXCONST_SGL(0.14699433520835f), FL2FXCONST_SGL(0.03183050093751f)}; + +/*! Real and imaginary part of random noise which will be modulated + to the desired level. An accuracy of 13 bits is sufficient for these + random numbers. +*/ +const FIXP_SGL FDK_sbrDecoder_sbr_randomPhase[SBR_NF_NO_RANDOM_VAL][2] = { + {FL2FXCONST_SGL(-0.99948153278296f / 8.0), + FL2FXCONST_SGL(-0.59483417516607f / 8.0)}, + {FL2FXCONST_SGL(0.97113454393991f / 8.0), + FL2FXCONST_SGL(-0.67528515225647f / 8.0)}, + {FL2FXCONST_SGL(0.14130051758487f / 8.0), + FL2FXCONST_SGL(-0.95090983575689f / 8.0)}, + {FL2FXCONST_SGL(-0.47005496701697f / 8.0), + FL2FXCONST_SGL(-0.37340549728647f / 8.0)}, + {FL2FXCONST_SGL(0.80705063769351f / 8.0), + FL2FXCONST_SGL(0.29653668284408f / 8.0)}, + {FL2FXCONST_SGL(-0.38981478896926f / 8.0), + FL2FXCONST_SGL(0.89572605717087f / 8.0)}, + {FL2FXCONST_SGL(-0.01053049862020f / 8.0), + FL2FXCONST_SGL(-0.66959058036166f / 8.0)}, + {FL2FXCONST_SGL(-0.91266367957293f / 8.0), + FL2FXCONST_SGL(-0.11522938140034f / 8.0)}, + {FL2FXCONST_SGL(0.54840422910309f / 8.0), + FL2FXCONST_SGL(0.75221367176302f / 8.0)}, + {FL2FXCONST_SGL(0.40009252867955f / 8.0), + FL2FXCONST_SGL(-0.98929400334421f / 8.0)}, + {FL2FXCONST_SGL(-0.99867974711855f / 8.0), + FL2FXCONST_SGL(-0.88147068645358f / 8.0)}, + {FL2FXCONST_SGL(-0.95531076805040f / 8.0), + FL2FXCONST_SGL(0.90908757154593f / 8.0)}, + {FL2FXCONST_SGL(-0.45725933317144f / 8.0), + FL2FXCONST_SGL(-0.56716323646760f / 8.0)}, + {FL2FXCONST_SGL(-0.72929675029275f / 8.0), + FL2FXCONST_SGL(-0.98008272727324f / 8.0)}, + {FL2FXCONST_SGL(0.75622801399036f / 8.0), + FL2FXCONST_SGL(0.20950329995549f / 8.0)}, + {FL2FXCONST_SGL(0.07069442601050f / 8.0), + FL2FXCONST_SGL(-0.78247898470706f / 8.0)}, + {FL2FXCONST_SGL(0.74496252926055f / 8.0), + FL2FXCONST_SGL(-0.91169004445807f / 8.0)}, + {FL2FXCONST_SGL(-0.96440182703856f / 8.0), + FL2FXCONST_SGL(-0.94739918296622f / 8.0)}, + {FL2FXCONST_SGL(0.30424629369539f / 8.0), + FL2FXCONST_SGL(-0.49438267012479f / 8.0)}, + {FL2FXCONST_SGL(0.66565033746925f / 8.0), + FL2FXCONST_SGL(0.64652935542491f / 8.0)}, + {FL2FXCONST_SGL(0.91697008020594f / 8.0), + FL2FXCONST_SGL(0.17514097332009f / 8.0)}, + {FL2FXCONST_SGL(-0.70774918760427f / 8.0), + FL2FXCONST_SGL(0.52548653416543f / 8.0)}, + {FL2FXCONST_SGL(-0.70051415345560f / 8.0), + FL2FXCONST_SGL(-0.45340028808763f / 8.0)}, + {FL2FXCONST_SGL(-0.99496513054797f / 8.0), + FL2FXCONST_SGL(-0.90071908066973f / 8.0)}, + {FL2FXCONST_SGL(0.98164490790123f / 8.0), + FL2FXCONST_SGL(-0.77463155528697f / 8.0)}, + {FL2FXCONST_SGL(-0.54671580548181f / 8.0), + FL2FXCONST_SGL(-0.02570928536004f / 8.0)}, + {FL2FXCONST_SGL(-0.01689629065389f / 8.0), + FL2FXCONST_SGL(0.00287506445732f / 8.0)}, + {FL2FXCONST_SGL(-0.86110349531986f / 8.0), + FL2FXCONST_SGL(0.42548583726477f / 8.0)}, + {FL2FXCONST_SGL(-0.98892980586032f / 8.0), + FL2FXCONST_SGL(-0.87881132267556f / 8.0)}, + {FL2FXCONST_SGL(0.51756627678691f / 8.0), + FL2FXCONST_SGL(0.66926784710139f / 8.0)}, + {FL2FXCONST_SGL(-0.99635026409640f / 8.0), + FL2FXCONST_SGL(-0.58107730574765f / 8.0)}, + {FL2FXCONST_SGL(-0.99969370862163f / 8.0), + FL2FXCONST_SGL(0.98369989360250f / 8.0)}, + {FL2FXCONST_SGL(0.55266258627194f / 8.0), + FL2FXCONST_SGL(0.59449057465591f / 8.0)}, + {FL2FXCONST_SGL(0.34581177741673f / 8.0), + FL2FXCONST_SGL(0.94879421061866f / 8.0)}, + {FL2FXCONST_SGL(0.62664209577999f / 8.0), + FL2FXCONST_SGL(-0.74402970906471f / 8.0)}, + {FL2FXCONST_SGL(-0.77149701404973f / 8.0), + FL2FXCONST_SGL(-0.33883658042801f / 8.0)}, + {FL2FXCONST_SGL(-0.91592244254432f / 8.0), + FL2FXCONST_SGL(0.03687901376713f / 8.0)}, + {FL2FXCONST_SGL(-0.76285492357887f / 8.0), + FL2FXCONST_SGL(-0.91371867919124f / 8.0)}, + {FL2FXCONST_SGL(0.79788337195331f / 8.0), + FL2FXCONST_SGL(-0.93180971199849f / 8.0)}, + {FL2FXCONST_SGL(0.54473080610200f / 8.0), + FL2FXCONST_SGL(-0.11919206037186f / 8.0)}, + {FL2FXCONST_SGL(-0.85639281671058f / 8.0), + FL2FXCONST_SGL(0.42429854760451f / 8.0)}, + {FL2FXCONST_SGL(-0.92882402971423f / 8.0), + FL2FXCONST_SGL(0.27871809078609f / 8.0)}, + {FL2FXCONST_SGL(-0.11708371046774f / 8.0), + FL2FXCONST_SGL(-0.99800843444966f / 8.0)}, + {FL2FXCONST_SGL(0.21356749817493f / 8.0), + FL2FXCONST_SGL(-0.90716295627033f / 8.0)}, + {FL2FXCONST_SGL(-0.76191692573909f / 8.0), + FL2FXCONST_SGL(0.99768118356265f / 8.0)}, + {FL2FXCONST_SGL(0.98111043100884f / 8.0), + FL2FXCONST_SGL(-0.95854459734407f / 8.0)}, + {FL2FXCONST_SGL(-0.85913269895572f / 8.0), + FL2FXCONST_SGL(0.95766566168880f / 8.0)}, + {FL2FXCONST_SGL(-0.93307242253692f / 8.0), + FL2FXCONST_SGL(0.49431757696466f / 8.0)}, + {FL2FXCONST_SGL(0.30485754879632f / 8.0), + FL2FXCONST_SGL(-0.70540034357529f / 8.0)}, + {FL2FXCONST_SGL(0.85289650925190f / 8.0), + FL2FXCONST_SGL(0.46766131791044f / 8.0)}, + {FL2FXCONST_SGL(0.91328082618125f / 8.0), + FL2FXCONST_SGL(-0.99839597361769f / 8.0)}, + {FL2FXCONST_SGL(-0.05890199924154f / 8.0), + FL2FXCONST_SGL(0.70741827819497f / 8.0)}, + {FL2FXCONST_SGL(0.28398686150148f / 8.0), + FL2FXCONST_SGL(0.34633555702188f / 8.0)}, + {FL2FXCONST_SGL(0.95258164539612f / 8.0), + FL2FXCONST_SGL(-0.54893416026939f / 8.0)}, + {FL2FXCONST_SGL(-0.78566324168507f / 8.0), + FL2FXCONST_SGL(-0.75568541079691f / 8.0)}, + {FL2FXCONST_SGL(-0.95789495447877f / 8.0), + FL2FXCONST_SGL(-0.20423194696966f / 8.0)}, + {FL2FXCONST_SGL(0.82411158711197f / 8.0), + FL2FXCONST_SGL(0.96654618432562f / 8.0)}, + {FL2FXCONST_SGL(-0.65185446735885f / 8.0), + FL2FXCONST_SGL(-0.88734990773289f / 8.0)}, + {FL2FXCONST_SGL(-0.93643603134666f / 8.0), + FL2FXCONST_SGL(0.99870790442385f / 8.0)}, + {FL2FXCONST_SGL(0.91427159529618f / 8.0), + FL2FXCONST_SGL(-0.98290505544444f / 8.0)}, + {FL2FXCONST_SGL(-0.70395684036886f / 8.0), + FL2FXCONST_SGL(0.58796798221039f / 8.0)}, + {FL2FXCONST_SGL(0.00563771969365f / 8.0), + FL2FXCONST_SGL(0.61768196727244f / 8.0)}, + {FL2FXCONST_SGL(0.89065051931895f / 8.0), + FL2FXCONST_SGL(0.52783352697585f / 8.0)}, + {FL2FXCONST_SGL(-0.68683707712762f / 8.0), + FL2FXCONST_SGL(0.80806944710339f / 8.0)}, + {FL2FXCONST_SGL(0.72165342518718f / 8.0), + FL2FXCONST_SGL(-0.69259857349564f / 8.0)}, + {FL2FXCONST_SGL(-0.62928247730667f / 8.0), + FL2FXCONST_SGL(0.13627037407335f / 8.0)}, + {FL2FXCONST_SGL(0.29938434065514f / 8.0), + FL2FXCONST_SGL(-0.46051329682246f / 8.0)}, + {FL2FXCONST_SGL(-0.91781958879280f / 8.0), + FL2FXCONST_SGL(-0.74012716684186f / 8.0)}, + {FL2FXCONST_SGL(0.99298717043688f / 8.0), + FL2FXCONST_SGL(0.40816610075661f / 8.0)}, + {FL2FXCONST_SGL(0.82368298622748f / 8.0), + FL2FXCONST_SGL(-0.74036047190173f / 8.0)}, + {FL2FXCONST_SGL(-0.98512833386833f / 8.0), + FL2FXCONST_SGL(-0.99972330709594f / 8.0)}, + {FL2FXCONST_SGL(-0.95915368242257f / 8.0), + FL2FXCONST_SGL(-0.99237800466040f / 8.0)}, + {FL2FXCONST_SGL(-0.21411126572790f / 8.0), + FL2FXCONST_SGL(-0.93424819052545f / 8.0)}, + {FL2FXCONST_SGL(-0.68821476106884f / 8.0), + FL2FXCONST_SGL(-0.26892306315457f / 8.0)}, + {FL2FXCONST_SGL(0.91851997982317f / 8.0), + FL2FXCONST_SGL(0.09358228901785f / 8.0)}, + {FL2FXCONST_SGL(-0.96062769559127f / 8.0), + FL2FXCONST_SGL(0.36099095133739f / 8.0)}, + {FL2FXCONST_SGL(0.51646184922287f / 8.0), + FL2FXCONST_SGL(-0.71373332873917f / 8.0)}, + {FL2FXCONST_SGL(0.61130721139669f / 8.0), + FL2FXCONST_SGL(0.46950141175917f / 8.0)}, + {FL2FXCONST_SGL(0.47336129371299f / 8.0), + FL2FXCONST_SGL(-0.27333178296162f / 8.0)}, + {FL2FXCONST_SGL(0.90998308703519f / 8.0), + FL2FXCONST_SGL(0.96715662938132f / 8.0)}, + {FL2FXCONST_SGL(0.44844799194357f / 8.0), + FL2FXCONST_SGL(0.99211574628306f / 8.0)}, + {FL2FXCONST_SGL(0.66614891079092f / 8.0), + FL2FXCONST_SGL(0.96590176169121f / 8.0)}, + {FL2FXCONST_SGL(0.74922239129237f / 8.0), + FL2FXCONST_SGL(-0.89879858826087f / 8.0)}, + {FL2FXCONST_SGL(-0.99571588506485f / 8.0), + FL2FXCONST_SGL(0.52785521494349f / 8.0)}, + {FL2FXCONST_SGL(0.97401082477563f / 8.0), + FL2FXCONST_SGL(-0.16855870075190f / 8.0)}, + {FL2FXCONST_SGL(0.72683747733879f / 8.0), + FL2FXCONST_SGL(-0.48060774432251f / 8.0)}, + {FL2FXCONST_SGL(0.95432193457128f / 8.0), + FL2FXCONST_SGL(0.68849603408441f / 8.0)}, + {FL2FXCONST_SGL(-0.72962208425191f / 8.0), + FL2FXCONST_SGL(-0.76608443420917f / 8.0)}, + {FL2FXCONST_SGL(-0.85359479233537f / 8.0), + FL2FXCONST_SGL(0.88738125901579f / 8.0)}, + {FL2FXCONST_SGL(-0.81412430338535f / 8.0), + FL2FXCONST_SGL(-0.97480768049637f / 8.0)}, + {FL2FXCONST_SGL(-0.87930772356786f / 8.0), + FL2FXCONST_SGL(0.74748307690436f / 8.0)}, + {FL2FXCONST_SGL(-0.71573331064977f / 8.0), + FL2FXCONST_SGL(-0.98570608178923f / 8.0)}, + {FL2FXCONST_SGL(0.83524300028228f / 8.0), + FL2FXCONST_SGL(0.83702537075163f / 8.0)}, + {FL2FXCONST_SGL(-0.48086065601423f / 8.0), + FL2FXCONST_SGL(-0.98848504923531f / 8.0)}, + {FL2FXCONST_SGL(0.97139128574778f / 8.0), + FL2FXCONST_SGL(0.80093621198236f / 8.0)}, + {FL2FXCONST_SGL(0.51992825347895f / 8.0), + FL2FXCONST_SGL(0.80247631400510f / 8.0)}, + {FL2FXCONST_SGL(-0.00848591195325f / 8.0), + FL2FXCONST_SGL(-0.76670128000486f / 8.0)}, + {FL2FXCONST_SGL(-0.70294374303036f / 8.0), + FL2FXCONST_SGL(0.55359910445577f / 8.0)}, + {FL2FXCONST_SGL(-0.95894428168140f / 8.0), + FL2FXCONST_SGL(-0.43265504344783f / 8.0)}, + {FL2FXCONST_SGL(0.97079252950321f / 8.0), + FL2FXCONST_SGL(0.09325857238682f / 8.0)}, + {FL2FXCONST_SGL(-0.92404293670797f / 8.0), + FL2FXCONST_SGL(0.85507704027855f / 8.0)}, + {FL2FXCONST_SGL(-0.69506469500450f / 8.0), + FL2FXCONST_SGL(0.98633412625459f / 8.0)}, + {FL2FXCONST_SGL(0.26559203620024f / 8.0), + FL2FXCONST_SGL(0.73314307966524f / 8.0)}, + {FL2FXCONST_SGL(0.28038443336943f / 8.0), + FL2FXCONST_SGL(0.14537913654427f / 8.0)}, + {FL2FXCONST_SGL(-0.74138124825523f / 8.0), + FL2FXCONST_SGL(0.99310339807762f / 8.0)}, + {FL2FXCONST_SGL(-0.01752795995444f / 8.0), + FL2FXCONST_SGL(-0.82616635284178f / 8.0)}, + {FL2FXCONST_SGL(-0.55126773094930f / 8.0), + FL2FXCONST_SGL(-0.98898543862153f / 8.0)}, + {FL2FXCONST_SGL(0.97960898850996f / 8.0), + FL2FXCONST_SGL(-0.94021446752851f / 8.0)}, + {FL2FXCONST_SGL(-0.99196309146936f / 8.0), + FL2FXCONST_SGL(0.67019017358456f / 8.0)}, + {FL2FXCONST_SGL(-0.67684928085260f / 8.0), + FL2FXCONST_SGL(0.12631491649378f / 8.0)}, + {FL2FXCONST_SGL(0.09140039465500f / 8.0), + FL2FXCONST_SGL(-0.20537731453108f / 8.0)}, + {FL2FXCONST_SGL(-0.71658965751996f / 8.0), + FL2FXCONST_SGL(-0.97788200391224f / 8.0)}, + {FL2FXCONST_SGL(0.81014640078925f / 8.0), + FL2FXCONST_SGL(0.53722648362443f / 8.0)}, + {FL2FXCONST_SGL(0.40616991671205f / 8.0), + FL2FXCONST_SGL(-0.26469008598449f / 8.0)}, + {FL2FXCONST_SGL(-0.67680188682972f / 8.0), + FL2FXCONST_SGL(0.94502052337695f / 8.0)}, + {FL2FXCONST_SGL(0.86849774348749f / 8.0), + FL2FXCONST_SGL(-0.18333598647899f / 8.0)}, + {FL2FXCONST_SGL(-0.99500381284851f / 8.0), + FL2FXCONST_SGL(-0.02634122068550f / 8.0)}, + {FL2FXCONST_SGL(0.84329189340667f / 8.0), + FL2FXCONST_SGL(0.10406957462213f / 8.0)}, + {FL2FXCONST_SGL(-0.09215968531446f / 8.0), + FL2FXCONST_SGL(0.69540012101253f / 8.0)}, + {FL2FXCONST_SGL(0.99956173327206f / 8.0), + FL2FXCONST_SGL(-0.12358542001404f / 8.0)}, + {FL2FXCONST_SGL(-0.79732779473535f / 8.0), + FL2FXCONST_SGL(-0.91582524736159f / 8.0)}, + {FL2FXCONST_SGL(0.96349973642406f / 8.0), + FL2FXCONST_SGL(0.96640458041000f / 8.0)}, + {FL2FXCONST_SGL(-0.79942778496547f / 8.0), + FL2FXCONST_SGL(0.64323902822857f / 8.0)}, + {FL2FXCONST_SGL(-0.11566039853896f / 8.0), + FL2FXCONST_SGL(0.28587846253726f / 8.0)}, + {FL2FXCONST_SGL(-0.39922954514662f / 8.0), + FL2FXCONST_SGL(0.94129601616966f / 8.0)}, + {FL2FXCONST_SGL(0.99089197565987f / 8.0), + FL2FXCONST_SGL(-0.92062625581587f / 8.0)}, + {FL2FXCONST_SGL(0.28631285179909f / 8.0), + FL2FXCONST_SGL(-0.91035047143603f / 8.0)}, + {FL2FXCONST_SGL(-0.83302725605608f / 8.0), + FL2FXCONST_SGL(-0.67330410892084f / 8.0)}, + {FL2FXCONST_SGL(0.95404443402072f / 8.0), + FL2FXCONST_SGL(0.49162765398743f / 8.0)}, + {FL2FXCONST_SGL(-0.06449863579434f / 8.0), + FL2FXCONST_SGL(0.03250560813135f / 8.0)}, + {FL2FXCONST_SGL(-0.99575054486311f / 8.0), + FL2FXCONST_SGL(0.42389784469507f / 8.0)}, + {FL2FXCONST_SGL(-0.65501142790847f / 8.0), + FL2FXCONST_SGL(0.82546114655624f / 8.0)}, + {FL2FXCONST_SGL(-0.81254441908887f / 8.0), + FL2FXCONST_SGL(-0.51627234660629f / 8.0)}, + {FL2FXCONST_SGL(-0.99646369485481f / 8.0), + FL2FXCONST_SGL(0.84490533520752f / 8.0)}, + {FL2FXCONST_SGL(0.00287840603348f / 8.0), + FL2FXCONST_SGL(0.64768261158166f / 8.0)}, + {FL2FXCONST_SGL(0.70176989408455f / 8.0), + FL2FXCONST_SGL(-0.20453028573322f / 8.0)}, + {FL2FXCONST_SGL(0.96361882270190f / 8.0), + FL2FXCONST_SGL(0.40706967140989f / 8.0)}, + {FL2FXCONST_SGL(-0.68883758192426f / 8.0), + FL2FXCONST_SGL(0.91338958840772f / 8.0)}, + {FL2FXCONST_SGL(-0.34875585502238f / 8.0), + FL2FXCONST_SGL(0.71472290693300f / 8.0)}, + {FL2FXCONST_SGL(0.91980081243087f / 8.0), + FL2FXCONST_SGL(0.66507455644919f / 8.0)}, + {FL2FXCONST_SGL(-0.99009048343881f / 8.0), + FL2FXCONST_SGL(0.85868021604848f / 8.0)}, + {FL2FXCONST_SGL(0.68865791458395f / 8.0), + FL2FXCONST_SGL(0.55660316809678f / 8.0)}, + {FL2FXCONST_SGL(-0.99484402129368f / 8.0), + FL2FXCONST_SGL(-0.20052559254934f / 8.0)}, + {FL2FXCONST_SGL(0.94214511408023f / 8.0), + FL2FXCONST_SGL(-0.99696425367461f / 8.0)}, + {FL2FXCONST_SGL(-0.67414626793544f / 8.0), + FL2FXCONST_SGL(0.49548221180078f / 8.0)}, + {FL2FXCONST_SGL(-0.47339353684664f / 8.0), + FL2FXCONST_SGL(-0.85904328834047f / 8.0)}, + {FL2FXCONST_SGL(0.14323651387360f / 8.0), + FL2FXCONST_SGL(-0.94145598222488f / 8.0)}, + {FL2FXCONST_SGL(-0.29268293575672f / 8.0), + FL2FXCONST_SGL(0.05759224927952f / 8.0)}, + {FL2FXCONST_SGL(0.43793861458754f / 8.0), + FL2FXCONST_SGL(-0.78904969892724f / 8.0)}, + {FL2FXCONST_SGL(-0.36345126374441f / 8.0), + FL2FXCONST_SGL(0.64874435357162f / 8.0)}, + {FL2FXCONST_SGL(-0.08750604656825f / 8.0), + FL2FXCONST_SGL(0.97686944362527f / 8.0)}, + {FL2FXCONST_SGL(-0.96495267812511f / 8.0), + FL2FXCONST_SGL(-0.53960305946511f / 8.0)}, + {FL2FXCONST_SGL(0.55526940659947f / 8.0), + FL2FXCONST_SGL(0.78891523734774f / 8.0)}, + {FL2FXCONST_SGL(0.73538215752630f / 8.0), + FL2FXCONST_SGL(0.96452072373404f / 8.0)}, + {FL2FXCONST_SGL(-0.30889773919437f / 8.0), + FL2FXCONST_SGL(-0.80664389776860f / 8.0)}, + {FL2FXCONST_SGL(0.03574995626194f / 8.0), + FL2FXCONST_SGL(-0.97325616900959f / 8.0)}, + {FL2FXCONST_SGL(0.98720684660488f / 8.0), + FL2FXCONST_SGL(0.48409133691962f / 8.0)}, + {FL2FXCONST_SGL(-0.81689296271203f / 8.0), + FL2FXCONST_SGL(-0.90827703628298f / 8.0)}, + {FL2FXCONST_SGL(0.67866860118215f / 8.0), + FL2FXCONST_SGL(0.81284503870856f / 8.0)}, + {FL2FXCONST_SGL(-0.15808569732583f / 8.0), + FL2FXCONST_SGL(0.85279555024382f / 8.0)}, + {FL2FXCONST_SGL(0.80723395114371f / 8.0), + FL2FXCONST_SGL(-0.24717418514605f / 8.0)}, + {FL2FXCONST_SGL(0.47788757329038f / 8.0), + FL2FXCONST_SGL(-0.46333147839295f / 8.0)}, + {FL2FXCONST_SGL(0.96367554763201f / 8.0), + FL2FXCONST_SGL(0.38486749303242f / 8.0)}, + {FL2FXCONST_SGL(-0.99143875716818f / 8.0), + FL2FXCONST_SGL(-0.24945277239809f / 8.0)}, + {FL2FXCONST_SGL(0.83081876925833f / 8.0), + FL2FXCONST_SGL(-0.94780851414763f / 8.0)}, + {FL2FXCONST_SGL(-0.58753191905341f / 8.0), + FL2FXCONST_SGL(0.01290772389163f / 8.0)}, + {FL2FXCONST_SGL(0.95538108220960f / 8.0), + FL2FXCONST_SGL(-0.85557052096538f / 8.0)}, + {FL2FXCONST_SGL(-0.96490920476211f / 8.0), + FL2FXCONST_SGL(-0.64020970923102f / 8.0)}, + {FL2FXCONST_SGL(-0.97327101028521f / 8.0), + FL2FXCONST_SGL(0.12378128133110f / 8.0)}, + {FL2FXCONST_SGL(0.91400366022124f / 8.0), + FL2FXCONST_SGL(0.57972471346930f / 8.0)}, + {FL2FXCONST_SGL(-0.99925837363824f / 8.0), + FL2FXCONST_SGL(0.71084847864067f / 8.0)}, + {FL2FXCONST_SGL(-0.86875903507313f / 8.0), + FL2FXCONST_SGL(-0.20291699203564f / 8.0)}, + {FL2FXCONST_SGL(-0.26240034795124f / 8.0), + FL2FXCONST_SGL(-0.68264554369108f / 8.0)}, + {FL2FXCONST_SGL(-0.24664412953388f / 8.0), + FL2FXCONST_SGL(-0.87642273115183f / 8.0)}, + {FL2FXCONST_SGL(0.02416275806869f / 8.0), + FL2FXCONST_SGL(0.27192914288905f / 8.0)}, + {FL2FXCONST_SGL(0.82068619590515f / 8.0), + FL2FXCONST_SGL(-0.85087787994476f / 8.0)}, + {FL2FXCONST_SGL(0.88547373760759f / 8.0), + FL2FXCONST_SGL(-0.89636802901469f / 8.0)}, + {FL2FXCONST_SGL(-0.18173078152226f / 8.0), + FL2FXCONST_SGL(-0.26152145156800f / 8.0)}, + {FL2FXCONST_SGL(0.09355476558534f / 8.0), + FL2FXCONST_SGL(0.54845123045604f / 8.0)}, + {FL2FXCONST_SGL(-0.54668414224090f / 8.0), + FL2FXCONST_SGL(0.95980774020221f / 8.0)}, + {FL2FXCONST_SGL(0.37050990604091f / 8.0), + FL2FXCONST_SGL(-0.59910140383171f / 8.0)}, + {FL2FXCONST_SGL(-0.70373594262891f / 8.0), + FL2FXCONST_SGL(0.91227665827081f / 8.0)}, + {FL2FXCONST_SGL(-0.34600785879594f / 8.0), + FL2FXCONST_SGL(-0.99441426144200f / 8.0)}, + {FL2FXCONST_SGL(-0.68774481731008f / 8.0), + FL2FXCONST_SGL(-0.30238837956299f / 8.0)}, + {FL2FXCONST_SGL(-0.26843291251234f / 8.0), + FL2FXCONST_SGL(0.83115668004362f / 8.0)}, + {FL2FXCONST_SGL(0.49072334613242f / 8.0), + FL2FXCONST_SGL(-0.45359708737775f / 8.0)}, + {FL2FXCONST_SGL(0.38975993093975f / 8.0), + FL2FXCONST_SGL(0.95515358099121f / 8.0)}, + {FL2FXCONST_SGL(-0.97757125224150f / 8.0), + FL2FXCONST_SGL(0.05305894580606f / 8.0)}, + {FL2FXCONST_SGL(-0.17325552859616f / 8.0), + FL2FXCONST_SGL(-0.92770672250494f / 8.0)}, + {FL2FXCONST_SGL(0.99948035025744f / 8.0), + FL2FXCONST_SGL(0.58285545563426f / 8.0)}, + {FL2FXCONST_SGL(-0.64946246527458f / 8.0), + FL2FXCONST_SGL(0.68645507104960f / 8.0)}, + {FL2FXCONST_SGL(-0.12016920576437f / 8.0), + FL2FXCONST_SGL(-0.57147322153312f / 8.0)}, + {FL2FXCONST_SGL(-0.58947456517751f / 8.0), + FL2FXCONST_SGL(-0.34847132454388f / 8.0)}, + {FL2FXCONST_SGL(-0.41815140454465f / 8.0), + FL2FXCONST_SGL(0.16276422358861f / 8.0)}, + {FL2FXCONST_SGL(0.99885650204884f / 8.0), + FL2FXCONST_SGL(0.11136095490444f / 8.0)}, + {FL2FXCONST_SGL(-0.56649614128386f / 8.0), + FL2FXCONST_SGL(-0.90494866361587f / 8.0)}, + {FL2FXCONST_SGL(0.94138021032330f / 8.0), + FL2FXCONST_SGL(0.35281916733018f / 8.0)}, + {FL2FXCONST_SGL(-0.75725076534641f / 8.0), + FL2FXCONST_SGL(0.53650549640587f / 8.0)}, + {FL2FXCONST_SGL(0.20541973692630f / 8.0), + FL2FXCONST_SGL(-0.94435144369918f / 8.0)}, + {FL2FXCONST_SGL(0.99980371023351f / 8.0), + FL2FXCONST_SGL(0.79835913565599f / 8.0)}, + {FL2FXCONST_SGL(0.29078277605775f / 8.0), + FL2FXCONST_SGL(0.35393777921520f / 8.0)}, + {FL2FXCONST_SGL(-0.62858772103030f / 8.0), + FL2FXCONST_SGL(0.38765693387102f / 8.0)}, + {FL2FXCONST_SGL(0.43440904467688f / 8.0), + FL2FXCONST_SGL(-0.98546330463232f / 8.0)}, + {FL2FXCONST_SGL(-0.98298583762390f / 8.0), + FL2FXCONST_SGL(0.21021524625209f / 8.0)}, + {FL2FXCONST_SGL(0.19513029146934f / 8.0), + FL2FXCONST_SGL(-0.94239832251867f / 8.0)}, + {FL2FXCONST_SGL(-0.95476662400101f / 8.0), + FL2FXCONST_SGL(0.98364554179143f / 8.0)}, + {FL2FXCONST_SGL(0.93379635304810f / 8.0), + FL2FXCONST_SGL(-0.70881994583682f / 8.0)}, + {FL2FXCONST_SGL(-0.85235410573336f / 8.0), + FL2FXCONST_SGL(-0.08342347966410f / 8.0)}, + {FL2FXCONST_SGL(-0.86425093011245f / 8.0), + FL2FXCONST_SGL(-0.45795025029466f / 8.0)}, + {FL2FXCONST_SGL(0.38879779059045f / 8.0), + FL2FXCONST_SGL(0.97274429344593f / 8.0)}, + {FL2FXCONST_SGL(0.92045124735495f / 8.0), + FL2FXCONST_SGL(-0.62433652524220f / 8.0)}, + {FL2FXCONST_SGL(0.89162532251878f / 8.0), + FL2FXCONST_SGL(0.54950955570563f / 8.0)}, + {FL2FXCONST_SGL(-0.36834336949252f / 8.0), + FL2FXCONST_SGL(0.96458298020975f / 8.0)}, + {FL2FXCONST_SGL(0.93891760988045f / 8.0), + FL2FXCONST_SGL(-0.89968353740388f / 8.0)}, + {FL2FXCONST_SGL(0.99267657565094f / 8.0), + FL2FXCONST_SGL(-0.03757034316958f / 8.0)}, + {FL2FXCONST_SGL(-0.94063471614176f / 8.0), + FL2FXCONST_SGL(0.41332338538963f / 8.0)}, + {FL2FXCONST_SGL(0.99740224117019f / 8.0), + FL2FXCONST_SGL(-0.16830494996370f / 8.0)}, + {FL2FXCONST_SGL(-0.35899413170555f / 8.0), + FL2FXCONST_SGL(-0.46633226649613f / 8.0)}, + {FL2FXCONST_SGL(0.05237237274947f / 8.0), + FL2FXCONST_SGL(-0.25640361602661f / 8.0)}, + {FL2FXCONST_SGL(0.36703583957424f / 8.0), + FL2FXCONST_SGL(-0.38653265641875f / 8.0)}, + {FL2FXCONST_SGL(0.91653180367913f / 8.0), + FL2FXCONST_SGL(-0.30587628726597f / 8.0)}, + {FL2FXCONST_SGL(0.69000803499316f / 8.0), + FL2FXCONST_SGL(0.90952171386132f / 8.0)}, + {FL2FXCONST_SGL(-0.38658751133527f / 8.0), + FL2FXCONST_SGL(0.99501571208985f / 8.0)}, + {FL2FXCONST_SGL(-0.29250814029851f / 8.0), + FL2FXCONST_SGL(0.37444994344615f / 8.0)}, + {FL2FXCONST_SGL(-0.60182204677608f / 8.0), + FL2FXCONST_SGL(0.86779651036123f / 8.0)}, + {FL2FXCONST_SGL(-0.97418588163217f / 8.0), + FL2FXCONST_SGL(0.96468523666475f / 8.0)}, + {FL2FXCONST_SGL(0.88461574003963f / 8.0), + FL2FXCONST_SGL(0.57508405276414f / 8.0)}, + {FL2FXCONST_SGL(0.05198933055162f / 8.0), + FL2FXCONST_SGL(0.21269661669964f / 8.0)}, + {FL2FXCONST_SGL(-0.53499621979720f / 8.0), + FL2FXCONST_SGL(0.97241553731237f / 8.0)}, + {FL2FXCONST_SGL(-0.49429560226497f / 8.0), + FL2FXCONST_SGL(0.98183865291903f / 8.0)}, + {FL2FXCONST_SGL(-0.98935142339139f / 8.0), + FL2FXCONST_SGL(-0.40249159006933f / 8.0)}, + {FL2FXCONST_SGL(-0.98081380091130f / 8.0), + FL2FXCONST_SGL(-0.72856895534041f / 8.0)}, + {FL2FXCONST_SGL(-0.27338148835532f / 8.0), + FL2FXCONST_SGL(0.99950922447209f / 8.0)}, + {FL2FXCONST_SGL(0.06310802338302f / 8.0), + FL2FXCONST_SGL(-0.54539587529618f / 8.0)}, + {FL2FXCONST_SGL(-0.20461677199539f / 8.0), + FL2FXCONST_SGL(-0.14209977628489f / 8.0)}, + {FL2FXCONST_SGL(0.66223843141647f / 8.0), + FL2FXCONST_SGL(0.72528579940326f / 8.0)}, + {FL2FXCONST_SGL(-0.84764345483665f / 8.0), + FL2FXCONST_SGL(0.02372316801261f / 8.0)}, + {FL2FXCONST_SGL(-0.89039863483811f / 8.0), + FL2FXCONST_SGL(0.88866581484602f / 8.0)}, + {FL2FXCONST_SGL(0.95903308477986f / 8.0), + FL2FXCONST_SGL(0.76744927173873f / 8.0)}, + {FL2FXCONST_SGL(0.73504123909879f / 8.0), + FL2FXCONST_SGL(-0.03747203173192f / 8.0)}, + {FL2FXCONST_SGL(-0.31744434966056f / 8.0), + FL2FXCONST_SGL(-0.36834111883652f / 8.0)}, + {FL2FXCONST_SGL(-0.34110827591623f / 8.0), + FL2FXCONST_SGL(0.40211222807691f / 8.0)}, + {FL2FXCONST_SGL(0.47803883714199f / 8.0), + FL2FXCONST_SGL(-0.39423219786288f / 8.0)}, + {FL2FXCONST_SGL(0.98299195879514f / 8.0), + FL2FXCONST_SGL(0.01989791390047f / 8.0)}, + {FL2FXCONST_SGL(-0.30963073129751f / 8.0), + FL2FXCONST_SGL(-0.18076720599336f / 8.0)}, + {FL2FXCONST_SGL(0.99992588229018f / 8.0), + FL2FXCONST_SGL(-0.26281872094289f / 8.0)}, + {FL2FXCONST_SGL(-0.93149731080767f / 8.0), + FL2FXCONST_SGL(-0.98313162570490f / 8.0)}, + {FL2FXCONST_SGL(0.99923472302773f / 8.0), + FL2FXCONST_SGL(-0.80142993767554f / 8.0)}, + {FL2FXCONST_SGL(-0.26024169633417f / 8.0), + FL2FXCONST_SGL(-0.75999759855752f / 8.0)}, + {FL2FXCONST_SGL(-0.35712514743563f / 8.0), + FL2FXCONST_SGL(0.19298963768574f / 8.0)}, + {FL2FXCONST_SGL(-0.99899084509530f / 8.0), + FL2FXCONST_SGL(0.74645156992493f / 8.0)}, + {FL2FXCONST_SGL(0.86557171579452f / 8.0), + FL2FXCONST_SGL(0.55593866696299f / 8.0)}, + {FL2FXCONST_SGL(0.33408042438752f / 8.0), + FL2FXCONST_SGL(0.86185953874709f / 8.0)}, + {FL2FXCONST_SGL(0.99010736374716f / 8.0), + FL2FXCONST_SGL(0.04602397576623f / 8.0)}, + {FL2FXCONST_SGL(-0.66694269691195f / 8.0), + FL2FXCONST_SGL(-0.91643611810148f / 8.0)}, + {FL2FXCONST_SGL(0.64016792079480f / 8.0), + FL2FXCONST_SGL(0.15649530836856f / 8.0)}, + {FL2FXCONST_SGL(0.99570534804836f / 8.0), + FL2FXCONST_SGL(0.45844586038111f / 8.0)}, + {FL2FXCONST_SGL(-0.63431466947340f / 8.0), + FL2FXCONST_SGL(0.21079116459234f / 8.0)}, + {FL2FXCONST_SGL(-0.07706847005931f / 8.0), + FL2FXCONST_SGL(-0.89581437101329f / 8.0)}, + {FL2FXCONST_SGL(0.98590090577724f / 8.0), + FL2FXCONST_SGL(0.88241721133981f / 8.0)}, + {FL2FXCONST_SGL(0.80099335254678f / 8.0), + FL2FXCONST_SGL(-0.36851896710853f / 8.0)}, + {FL2FXCONST_SGL(0.78368131392666f / 8.0), + FL2FXCONST_SGL(0.45506999802597f / 8.0)}, + {FL2FXCONST_SGL(0.08707806671691f / 8.0), + FL2FXCONST_SGL(0.80938994918745f / 8.0)}, + {FL2FXCONST_SGL(-0.86811883080712f / 8.0), + FL2FXCONST_SGL(0.39347308654705f / 8.0)}, + {FL2FXCONST_SGL(-0.39466529740375f / 8.0), + FL2FXCONST_SGL(-0.66809432114456f / 8.0)}, + {FL2FXCONST_SGL(0.97875325649683f / 8.0), + FL2FXCONST_SGL(-0.72467840967746f / 8.0)}, + {FL2FXCONST_SGL(-0.95038560288864f / 8.0), + FL2FXCONST_SGL(0.89563219587625f / 8.0)}, + {FL2FXCONST_SGL(0.17005239424212f / 8.0), + FL2FXCONST_SGL(0.54683053962658f / 8.0)}, + {FL2FXCONST_SGL(-0.76910792026848f / 8.0), + FL2FXCONST_SGL(-0.96226617549298f / 8.0)}, + {FL2FXCONST_SGL(0.99743281016846f / 8.0), + FL2FXCONST_SGL(0.42697157037567f / 8.0)}, + {FL2FXCONST_SGL(0.95437383549973f / 8.0), + FL2FXCONST_SGL(0.97002324109952f / 8.0)}, + {FL2FXCONST_SGL(0.99578905365569f / 8.0), + FL2FXCONST_SGL(-0.54106826257356f / 8.0)}, + {FL2FXCONST_SGL(0.28058259829990f / 8.0), + FL2FXCONST_SGL(-0.85361420634036f / 8.0)}, + {FL2FXCONST_SGL(0.85256524470573f / 8.0), + FL2FXCONST_SGL(-0.64567607735589f / 8.0)}, + {FL2FXCONST_SGL(-0.50608540105128f / 8.0), + FL2FXCONST_SGL(-0.65846015480300f / 8.0)}, + {FL2FXCONST_SGL(-0.97210735183243f / 8.0), + FL2FXCONST_SGL(-0.23095213067791f / 8.0)}, + {FL2FXCONST_SGL(0.95424048234441f / 8.0), + FL2FXCONST_SGL(-0.99240147091219f / 8.0)}, + {FL2FXCONST_SGL(-0.96926570524023f / 8.0), + FL2FXCONST_SGL(0.73775654896574f / 8.0)}, + {FL2FXCONST_SGL(0.30872163214726f / 8.0), + FL2FXCONST_SGL(0.41514960556126f / 8.0)}, + {FL2FXCONST_SGL(-0.24523839572639f / 8.0), + FL2FXCONST_SGL(0.63206633394807f / 8.0)}, + {FL2FXCONST_SGL(-0.33813265086024f / 8.0), + FL2FXCONST_SGL(-0.38661779441897f / 8.0)}, + {FL2FXCONST_SGL(-0.05826828420146f / 8.0), + FL2FXCONST_SGL(-0.06940774188029f / 8.0)}, + {FL2FXCONST_SGL(-0.22898461455054f / 8.0), + FL2FXCONST_SGL(0.97054853316316f / 8.0)}, + {FL2FXCONST_SGL(-0.18509915019881f / 8.0), + FL2FXCONST_SGL(0.47565762892084f / 8.0)}, + {FL2FXCONST_SGL(-0.10488238045009f / 8.0), + FL2FXCONST_SGL(-0.87769947402394f / 8.0)}, + {FL2FXCONST_SGL(-0.71886586182037f / 8.0), + FL2FXCONST_SGL(0.78030982480538f / 8.0)}, + {FL2FXCONST_SGL(0.99793873738654f / 8.0), + FL2FXCONST_SGL(0.90041310491497f / 8.0)}, + {FL2FXCONST_SGL(0.57563307626120f / 8.0), + FL2FXCONST_SGL(-0.91034337352097f / 8.0)}, + {FL2FXCONST_SGL(0.28909646383717f / 8.0), + FL2FXCONST_SGL(0.96307783970534f / 8.0)}, + {FL2FXCONST_SGL(0.42188998312520f / 8.0), + FL2FXCONST_SGL(0.48148651230437f / 8.0)}, + {FL2FXCONST_SGL(0.93335049681047f / 8.0), + FL2FXCONST_SGL(-0.43537023883588f / 8.0)}, + {FL2FXCONST_SGL(-0.97087374418267f / 8.0), + FL2FXCONST_SGL(0.86636445711364f / 8.0)}, + {FL2FXCONST_SGL(0.36722871286923f / 8.0), + FL2FXCONST_SGL(0.65291654172961f / 8.0)}, + {FL2FXCONST_SGL(-0.81093025665696f / 8.0), + FL2FXCONST_SGL(0.08778370229363f / 8.0)}, + {FL2FXCONST_SGL(-0.26240603062237f / 8.0), + FL2FXCONST_SGL(-0.92774095379098f / 8.0)}, + {FL2FXCONST_SGL(0.83996497984604f / 8.0), + FL2FXCONST_SGL(0.55839849139647f / 8.0)}, + {FL2FXCONST_SGL(-0.99909615720225f / 8.0), + FL2FXCONST_SGL(-0.96024605713970f / 8.0)}, + {FL2FXCONST_SGL(0.74649464155061f / 8.0), + FL2FXCONST_SGL(0.12144893606462f / 8.0)}, + {FL2FXCONST_SGL(-0.74774595569805f / 8.0), + FL2FXCONST_SGL(-0.26898062008959f / 8.0)}, + {FL2FXCONST_SGL(0.95781667469567f / 8.0), + FL2FXCONST_SGL(-0.79047927052628f / 8.0)}, + {FL2FXCONST_SGL(0.95472308713099f / 8.0), + FL2FXCONST_SGL(-0.08588776019550f / 8.0)}, + {FL2FXCONST_SGL(0.48708332746299f / 8.0), + FL2FXCONST_SGL(0.99999041579432f / 8.0)}, + {FL2FXCONST_SGL(0.46332038247497f / 8.0), + FL2FXCONST_SGL(0.10964126185063f / 8.0)}, + {FL2FXCONST_SGL(-0.76497004940162f / 8.0), + FL2FXCONST_SGL(0.89210929242238f / 8.0)}, + {FL2FXCONST_SGL(0.57397389364339f / 8.0), + FL2FXCONST_SGL(0.35289703373760f / 8.0)}, + {FL2FXCONST_SGL(0.75374316974495f / 8.0), + FL2FXCONST_SGL(0.96705214651335f / 8.0)}, + {FL2FXCONST_SGL(-0.59174397685714f / 8.0), + FL2FXCONST_SGL(-0.89405370422752f / 8.0)}, + {FL2FXCONST_SGL(0.75087906691890f / 8.0), + FL2FXCONST_SGL(-0.29612672982396f / 8.0)}, + {FL2FXCONST_SGL(-0.98607857336230f / 8.0), + FL2FXCONST_SGL(0.25034911730023f / 8.0)}, + {FL2FXCONST_SGL(-0.40761056640505f / 8.0), + FL2FXCONST_SGL(-0.90045573444695f / 8.0)}, + {FL2FXCONST_SGL(0.66929266740477f / 8.0), + FL2FXCONST_SGL(0.98629493401748f / 8.0)}, + {FL2FXCONST_SGL(-0.97463695257310f / 8.0), + FL2FXCONST_SGL(-0.00190223301301f / 8.0)}, + {FL2FXCONST_SGL(0.90145509409859f / 8.0), + FL2FXCONST_SGL(0.99781390365446f / 8.0)}, + {FL2FXCONST_SGL(-0.87259289048043f / 8.0), + FL2FXCONST_SGL(0.99233587353666f / 8.0)}, + {FL2FXCONST_SGL(-0.91529461447692f / 8.0), + FL2FXCONST_SGL(-0.15698707534206f / 8.0)}, + {FL2FXCONST_SGL(-0.03305738840705f / 8.0), + FL2FXCONST_SGL(-0.37205262859764f / 8.0)}, + {FL2FXCONST_SGL(0.07223051368337f / 8.0), + FL2FXCONST_SGL(-0.88805001733626f / 8.0)}, + {FL2FXCONST_SGL(0.99498012188353f / 8.0), + FL2FXCONST_SGL(0.97094358113387f / 8.0)}, + {FL2FXCONST_SGL(-0.74904939500519f / 8.0), + FL2FXCONST_SGL(0.99985483641521f / 8.0)}, + {FL2FXCONST_SGL(0.04585228574211f / 8.0), + FL2FXCONST_SGL(0.99812337444082f / 8.0)}, + {FL2FXCONST_SGL(-0.89054954257993f / 8.0), + FL2FXCONST_SGL(-0.31791913188064f / 8.0)}, + {FL2FXCONST_SGL(-0.83782144651251f / 8.0), + FL2FXCONST_SGL(0.97637632547466f / 8.0)}, + {FL2FXCONST_SGL(0.33454804933804f / 8.0), + FL2FXCONST_SGL(-0.86231516800408f / 8.0)}, + {FL2FXCONST_SGL(-0.99707579362824f / 8.0), + FL2FXCONST_SGL(0.93237990079441f / 8.0)}, + {FL2FXCONST_SGL(-0.22827527843994f / 8.0), + FL2FXCONST_SGL(0.18874759397997f / 8.0)}, + {FL2FXCONST_SGL(0.67248046289143f / 8.0), + FL2FXCONST_SGL(-0.03646211390569f / 8.0)}, + {FL2FXCONST_SGL(-0.05146538187944f / 8.0), + FL2FXCONST_SGL(-0.92599700120679f / 8.0)}, + {FL2FXCONST_SGL(0.99947295749905f / 8.0), + FL2FXCONST_SGL(0.93625229707912f / 8.0)}, + {FL2FXCONST_SGL(0.66951124390363f / 8.0), + FL2FXCONST_SGL(0.98905825623893f / 8.0)}, + {FL2FXCONST_SGL(-0.99602956559179f / 8.0), + FL2FXCONST_SGL(-0.44654715757688f / 8.0)}, + {FL2FXCONST_SGL(0.82104905483590f / 8.0), + FL2FXCONST_SGL(0.99540741724928f / 8.0)}, + {FL2FXCONST_SGL(0.99186510988782f / 8.0), + FL2FXCONST_SGL(0.72023001312947f / 8.0)}, + {FL2FXCONST_SGL(-0.65284592392918f / 8.0), + FL2FXCONST_SGL(0.52186723253637f / 8.0)}, + {FL2FXCONST_SGL(0.93885443798188f / 8.0), + FL2FXCONST_SGL(-0.74895312615259f / 8.0)}, + {FL2FXCONST_SGL(0.96735248738388f / 8.0), + FL2FXCONST_SGL(0.90891816978629f / 8.0)}, + {FL2FXCONST_SGL(-0.22225968841114f / 8.0), + FL2FXCONST_SGL(0.57124029781228f / 8.0)}, + {FL2FXCONST_SGL(-0.44132783753414f / 8.0), + FL2FXCONST_SGL(-0.92688840659280f / 8.0)}, + {FL2FXCONST_SGL(-0.85694974219574f / 8.0), + FL2FXCONST_SGL(0.88844532719844f / 8.0)}, + {FL2FXCONST_SGL(0.91783042091762f / 8.0), + FL2FXCONST_SGL(-0.46356892383970f / 8.0)}, + {FL2FXCONST_SGL(0.72556974415690f / 8.0), + FL2FXCONST_SGL(-0.99899555770747f / 8.0)}, + {FL2FXCONST_SGL(-0.99711581834508f / 8.0), + FL2FXCONST_SGL(0.58211560180426f / 8.0)}, + {FL2FXCONST_SGL(0.77638976371966f / 8.0), + FL2FXCONST_SGL(0.94321834873819f / 8.0)}, + {FL2FXCONST_SGL(0.07717324253925f / 8.0), + FL2FXCONST_SGL(0.58638399856595f / 8.0)}, + {FL2FXCONST_SGL(-0.56049829194163f / 8.0), + FL2FXCONST_SGL(0.82522301569036f / 8.0)}, + {FL2FXCONST_SGL(0.98398893639988f / 8.0), + FL2FXCONST_SGL(0.39467440420569f / 8.0)}, + {FL2FXCONST_SGL(0.47546946844938f / 8.0), + FL2FXCONST_SGL(0.68613044836811f / 8.0)}, + {FL2FXCONST_SGL(0.65675089314631f / 8.0), + FL2FXCONST_SGL(0.18331637134880f / 8.0)}, + {FL2FXCONST_SGL(0.03273375457980f / 8.0), + FL2FXCONST_SGL(-0.74933109564108f / 8.0)}, + {FL2FXCONST_SGL(-0.38684144784738f / 8.0), + FL2FXCONST_SGL(0.51337349030406f / 8.0)}, + {FL2FXCONST_SGL(-0.97346267944545f / 8.0), + FL2FXCONST_SGL(-0.96549364384098f / 8.0)}, + {FL2FXCONST_SGL(-0.53282156061942f / 8.0), + FL2FXCONST_SGL(-0.91423265091354f / 8.0)}, + {FL2FXCONST_SGL(0.99817310731176f / 8.0), + FL2FXCONST_SGL(0.61133572482148f / 8.0)}, + {FL2FXCONST_SGL(-0.50254500772635f / 8.0), + FL2FXCONST_SGL(-0.88829338134294f / 8.0)}, + {FL2FXCONST_SGL(0.01995873238855f / 8.0), + FL2FXCONST_SGL(0.85223515096765f / 8.0)}, + {FL2FXCONST_SGL(0.99930381973804f / 8.0), + FL2FXCONST_SGL(0.94578896296649f / 8.0)}, + {FL2FXCONST_SGL(0.82907767600783f / 8.0), + FL2FXCONST_SGL(-0.06323442598128f / 8.0)}, + {FL2FXCONST_SGL(-0.58660709669728f / 8.0), + FL2FXCONST_SGL(0.96840773806582f / 8.0)}, + {FL2FXCONST_SGL(-0.17573736667267f / 8.0), + FL2FXCONST_SGL(-0.48166920859485f / 8.0)}, + {FL2FXCONST_SGL(0.83434292401346f / 8.0), + FL2FXCONST_SGL(-0.13023450646997f / 8.0)}, + {FL2FXCONST_SGL(0.05946491307025f / 8.0), + FL2FXCONST_SGL(0.20511047074866f / 8.0)}, + {FL2FXCONST_SGL(0.81505484574602f / 8.0), + FL2FXCONST_SGL(-0.94685947861369f / 8.0)}, + {FL2FXCONST_SGL(-0.44976380954860f / 8.0), + FL2FXCONST_SGL(0.40894572671545f / 8.0)}, + {FL2FXCONST_SGL(-0.89746474625671f / 8.0), + FL2FXCONST_SGL(0.99846578838537f / 8.0)}, + {FL2FXCONST_SGL(0.39677256130792f / 8.0), + FL2FXCONST_SGL(-0.74854668609359f / 8.0)}, + {FL2FXCONST_SGL(-0.07588948563079f / 8.0), + FL2FXCONST_SGL(0.74096214084170f / 8.0)}, + {FL2FXCONST_SGL(0.76343198951445f / 8.0), + FL2FXCONST_SGL(0.41746629422634f / 8.0)}, + {FL2FXCONST_SGL(-0.74490104699626f / 8.0), + FL2FXCONST_SGL(0.94725911744610f / 8.0)}, + {FL2FXCONST_SGL(0.64880119792759f / 8.0), + FL2FXCONST_SGL(0.41336660830571f / 8.0)}, + {FL2FXCONST_SGL(0.62319537462542f / 8.0), + FL2FXCONST_SGL(-0.93098313552599f / 8.0)}, + {FL2FXCONST_SGL(0.42215817594807f / 8.0), + FL2FXCONST_SGL(-0.07712787385208f / 8.0)}, + {FL2FXCONST_SGL(0.02704554141885f / 8.0), + FL2FXCONST_SGL(-0.05417518053666f / 8.0)}, + {FL2FXCONST_SGL(0.80001773566818f / 8.0), + FL2FXCONST_SGL(0.91542195141039f / 8.0)}, + {FL2FXCONST_SGL(-0.79351832348816f / 8.0), + FL2FXCONST_SGL(-0.36208897989136f / 8.0)}, + {FL2FXCONST_SGL(0.63872359151636f / 8.0), + FL2FXCONST_SGL(0.08128252493444f / 8.0)}, + {FL2FXCONST_SGL(0.52890520960295f / 8.0), + FL2FXCONST_SGL(0.60048872455592f / 8.0)}, + {FL2FXCONST_SGL(0.74238552914587f / 8.0), + FL2FXCONST_SGL(0.04491915291044f / 8.0)}, + {FL2FXCONST_SGL(0.99096131449250f / 8.0), + FL2FXCONST_SGL(-0.19451182854402f / 8.0)}, + {FL2FXCONST_SGL(-0.80412329643109f / 8.0), + FL2FXCONST_SGL(-0.88513818199457f / 8.0)}, + {FL2FXCONST_SGL(-0.64612616129736f / 8.0), + FL2FXCONST_SGL(0.72198674804544f / 8.0)}, + {FL2FXCONST_SGL(0.11657770663191f / 8.0), + FL2FXCONST_SGL(-0.83662833815041f / 8.0)}, + {FL2FXCONST_SGL(-0.95053182488101f / 8.0), + FL2FXCONST_SGL(-0.96939905138082f / 8.0)}, + {FL2FXCONST_SGL(-0.62228872928622f / 8.0), + FL2FXCONST_SGL(0.82767262846661f / 8.0)}, + {FL2FXCONST_SGL(0.03004475787316f / 8.0), + FL2FXCONST_SGL(-0.99738896333384f / 8.0)}, + {FL2FXCONST_SGL(-0.97987214341034f / 8.0), + FL2FXCONST_SGL(0.36526129686425f / 8.0)}, + {FL2FXCONST_SGL(-0.99986980746200f / 8.0), + FL2FXCONST_SGL(-0.36021610299715f / 8.0)}, + {FL2FXCONST_SGL(0.89110648599879f / 8.0), + FL2FXCONST_SGL(-0.97894250343044f / 8.0)}, + {FL2FXCONST_SGL(0.10407960510582f / 8.0), + FL2FXCONST_SGL(0.77357793811619f / 8.0)}, + {FL2FXCONST_SGL(0.95964737821728f / 8.0), + FL2FXCONST_SGL(-0.35435818285502f / 8.0)}, + {FL2FXCONST_SGL(0.50843233159162f / 8.0), + FL2FXCONST_SGL(0.96107691266205f / 8.0)}, + {FL2FXCONST_SGL(0.17006334670615f / 8.0), + FL2FXCONST_SGL(-0.76854025314829f / 8.0)}, + {FL2FXCONST_SGL(0.25872675063360f / 8.0), + FL2FXCONST_SGL(0.99893303933816f / 8.0)}, + {FL2FXCONST_SGL(-0.01115998681937f / 8.0), + FL2FXCONST_SGL(0.98496019742444f / 8.0)}, + {FL2FXCONST_SGL(-0.79598702973261f / 8.0), + FL2FXCONST_SGL(0.97138411318894f / 8.0)}, + {FL2FXCONST_SGL(-0.99264708948101f / 8.0), + FL2FXCONST_SGL(-0.99542822402536f / 8.0)}, + {FL2FXCONST_SGL(-0.99829663752818f / 8.0), + FL2FXCONST_SGL(0.01877138824311f / 8.0)}, + {FL2FXCONST_SGL(-0.70801016548184f / 8.0), + FL2FXCONST_SGL(0.33680685948117f / 8.0)}, + {FL2FXCONST_SGL(-0.70467057786826f / 8.0), + FL2FXCONST_SGL(0.93272777501857f / 8.0)}, + {FL2FXCONST_SGL(0.99846021905254f / 8.0), + FL2FXCONST_SGL(-0.98725746254433f / 8.0)}, + {FL2FXCONST_SGL(-0.63364968534650f / 8.0), + FL2FXCONST_SGL(-0.16473594423746f / 8.0)}, + {FL2FXCONST_SGL(-0.16258217500792f / 8.0), + FL2FXCONST_SGL(-0.95939125400802f / 8.0)}, + {FL2FXCONST_SGL(-0.43645594360633f / 8.0), + FL2FXCONST_SGL(-0.94805030113284f / 8.0)}, + {FL2FXCONST_SGL(-0.99848471702976f / 8.0), + FL2FXCONST_SGL(0.96245166923809f / 8.0)}, + {FL2FXCONST_SGL(-0.16796458968998f / 8.0), + FL2FXCONST_SGL(-0.98987511890470f / 8.0)}, + {FL2FXCONST_SGL(-0.87979225745213f / 8.0), + FL2FXCONST_SGL(-0.71725725041680f / 8.0)}, + {FL2FXCONST_SGL(0.44183099021786f / 8.0), + FL2FXCONST_SGL(-0.93568974498761f / 8.0)}, + {FL2FXCONST_SGL(0.93310180125532f / 8.0), + FL2FXCONST_SGL(-0.99913308068246f / 8.0)}, + {FL2FXCONST_SGL(-0.93941931782002f / 8.0), + FL2FXCONST_SGL(-0.56409379640356f / 8.0)}, + {FL2FXCONST_SGL(-0.88590003188677f / 8.0), + FL2FXCONST_SGL(0.47624600491382f / 8.0)}, + {FL2FXCONST_SGL(0.99971463703691f / 8.0), + FL2FXCONST_SGL(-0.83889954253462f / 8.0)}, + {FL2FXCONST_SGL(-0.75376385639978f / 8.0), + FL2FXCONST_SGL(0.00814643438625f / 8.0)}, + {FL2FXCONST_SGL(0.93887685615875f / 8.0), + FL2FXCONST_SGL(-0.11284528204636f / 8.0)}, + {FL2FXCONST_SGL(0.85126435782309f / 8.0), + FL2FXCONST_SGL(0.52349251543547f / 8.0)}, + {FL2FXCONST_SGL(0.39701421446381f / 8.0), + FL2FXCONST_SGL(0.81779634174316f / 8.0)}, + {FL2FXCONST_SGL(-0.37024464187437f / 8.0), + FL2FXCONST_SGL(-0.87071656222959f / 8.0)}, + {FL2FXCONST_SGL(-0.36024828242896f / 8.0), + FL2FXCONST_SGL(0.34655735648287f / 8.0)}, + {FL2FXCONST_SGL(-0.93388812549209f / 8.0), + FL2FXCONST_SGL(-0.84476541096429f / 8.0)}, + {FL2FXCONST_SGL(-0.65298804552119f / 8.0), + FL2FXCONST_SGL(-0.18439575450921f / 8.0)}, + {FL2FXCONST_SGL(0.11960319006843f / 8.0), + FL2FXCONST_SGL(0.99899346780168f / 8.0)}, + {FL2FXCONST_SGL(0.94292565553160f / 8.0), + FL2FXCONST_SGL(0.83163906518293f / 8.0)}, + {FL2FXCONST_SGL(0.75081145286948f / 8.0), + FL2FXCONST_SGL(-0.35533223142265f / 8.0)}, + {FL2FXCONST_SGL(0.56721979748394f / 8.0), + FL2FXCONST_SGL(-0.24076836414499f / 8.0)}, + {FL2FXCONST_SGL(0.46857766746029f / 8.0), + FL2FXCONST_SGL(-0.30140233457198f / 8.0)}, + {FL2FXCONST_SGL(0.97312313923635f / 8.0), + FL2FXCONST_SGL(-0.99548191630031f / 8.0)}, + {FL2FXCONST_SGL(-0.38299976567017f / 8.0), + FL2FXCONST_SGL(0.98516909715427f / 8.0)}, + {FL2FXCONST_SGL(0.41025800019463f / 8.0), + FL2FXCONST_SGL(0.02116736935734f / 8.0)}, + {FL2FXCONST_SGL(0.09638062008048f / 8.0), + FL2FXCONST_SGL(0.04411984381457f / 8.0)}, + {FL2FXCONST_SGL(-0.85283249275397f / 8.0), + FL2FXCONST_SGL(0.91475563922421f / 8.0)}, + {FL2FXCONST_SGL(0.88866808958124f / 8.0), + FL2FXCONST_SGL(-0.99735267083226f / 8.0)}, + {FL2FXCONST_SGL(-0.48202429536989f / 8.0), + FL2FXCONST_SGL(-0.96805608884164f / 8.0)}, + {FL2FXCONST_SGL(0.27572582416567f / 8.0), + FL2FXCONST_SGL(0.58634753335832f / 8.0)}, + {FL2FXCONST_SGL(-0.65889129659168f / 8.0), + FL2FXCONST_SGL(0.58835634138583f / 8.0)}, + {FL2FXCONST_SGL(0.98838086953732f / 8.0), + FL2FXCONST_SGL(0.99994349600236f / 8.0)}, + {FL2FXCONST_SGL(-0.20651349620689f / 8.0), + FL2FXCONST_SGL(0.54593044066355f / 8.0)}, + {FL2FXCONST_SGL(-0.62126416356920f / 8.0), + FL2FXCONST_SGL(-0.59893681700392f / 8.0)}, + {FL2FXCONST_SGL(0.20320105410437f / 8.0), + FL2FXCONST_SGL(-0.86879180355289f / 8.0)}, + {FL2FXCONST_SGL(-0.97790548600584f / 8.0), + FL2FXCONST_SGL(0.96290806999242f / 8.0)}, + {FL2FXCONST_SGL(0.11112534735126f / 8.0), + FL2FXCONST_SGL(0.21484763313301f / 8.0)}, + {FL2FXCONST_SGL(-0.41368337314182f / 8.0), + FL2FXCONST_SGL(0.28216837680365f / 8.0)}, + {FL2FXCONST_SGL(0.24133038992960f / 8.0), + FL2FXCONST_SGL(0.51294362630238f / 8.0)}, + {FL2FXCONST_SGL(-0.66393410674885f / 8.0), + FL2FXCONST_SGL(-0.08249679629081f / 8.0)}, + {FL2FXCONST_SGL(-0.53697829178752f / 8.0), + FL2FXCONST_SGL(-0.97649903936228f / 8.0)}, + {FL2FXCONST_SGL(-0.97224737889348f / 8.0), + FL2FXCONST_SGL(0.22081333579837f / 8.0)}, + {FL2FXCONST_SGL(0.87392477144549f / 8.0), + FL2FXCONST_SGL(-0.12796173740361f / 8.0)}, + {FL2FXCONST_SGL(0.19050361015753f / 8.0), + FL2FXCONST_SGL(0.01602615387195f / 8.0)}, + {FL2FXCONST_SGL(-0.46353441212724f / 8.0), + FL2FXCONST_SGL(-0.95249041539006f / 8.0)}, + {FL2FXCONST_SGL(-0.07064096339021f / 8.0), + FL2FXCONST_SGL(-0.94479803205886f / 8.0)}, + {FL2FXCONST_SGL(-0.92444085484466f / 8.0), + FL2FXCONST_SGL(-0.10457590187436f / 8.0)}, + {FL2FXCONST_SGL(-0.83822593578728f / 8.0), + FL2FXCONST_SGL(-0.01695043208885f / 8.0)}, + {FL2FXCONST_SGL(0.75214681811150f / 8.0), + FL2FXCONST_SGL(-0.99955681042665f / 8.0)}, + {FL2FXCONST_SGL(-0.42102998829339f / 8.0), + FL2FXCONST_SGL(0.99720941999394f / 8.0)}, + {FL2FXCONST_SGL(-0.72094786237696f / 8.0), + FL2FXCONST_SGL(-0.35008961934255f / 8.0)}, + {FL2FXCONST_SGL(0.78843311019251f / 8.0), + FL2FXCONST_SGL(0.52851398958271f / 8.0)}, + {FL2FXCONST_SGL(0.97394027897442f / 8.0), + FL2FXCONST_SGL(-0.26695944086561f / 8.0)}, + {FL2FXCONST_SGL(0.99206463477946f / 8.0), + FL2FXCONST_SGL(-0.57010120849429f / 8.0)}, + {FL2FXCONST_SGL(0.76789609461795f / 8.0), + FL2FXCONST_SGL(-0.76519356730966f / 8.0)}, + {FL2FXCONST_SGL(-0.82002421836409f / 8.0), + FL2FXCONST_SGL(-0.73530179553767f / 8.0)}, + {FL2FXCONST_SGL(0.81924990025724f / 8.0), + FL2FXCONST_SGL(0.99698425250579f / 8.0)}, + {FL2FXCONST_SGL(-0.26719850873357f / 8.0), + FL2FXCONST_SGL(0.68903369776193f / 8.0)}, + {FL2FXCONST_SGL(-0.43311260380975f / 8.0), + FL2FXCONST_SGL(0.85321815947490f / 8.0)}, + {FL2FXCONST_SGL(0.99194979673836f / 8.0), + FL2FXCONST_SGL(0.91876249766422f / 8.0)}, + {FL2FXCONST_SGL(-0.80692001248487f / 8.0), + FL2FXCONST_SGL(-0.32627540663214f / 8.0)}, + {FL2FXCONST_SGL(0.43080003649976f / 8.0), + FL2FXCONST_SGL(-0.21919095636638f / 8.0)}, + {FL2FXCONST_SGL(0.67709491937357f / 8.0), + FL2FXCONST_SGL(-0.95478075822906f / 8.0)}, + {FL2FXCONST_SGL(0.56151770568316f / 8.0), + FL2FXCONST_SGL(-0.70693811747778f / 8.0)}, + {FL2FXCONST_SGL(0.10831862810749f / 8.0), + FL2FXCONST_SGL(-0.08628837174592f / 8.0)}, + {FL2FXCONST_SGL(0.91229417540436f / 8.0), + FL2FXCONST_SGL(-0.65987351408410f / 8.0)}, + {FL2FXCONST_SGL(-0.48972893932274f / 8.0), + FL2FXCONST_SGL(0.56289246362686f / 8.0)}, + {FL2FXCONST_SGL(-0.89033658689697f / 8.0), + FL2FXCONST_SGL(-0.71656563987082f / 8.0)}, + {FL2FXCONST_SGL(0.65269447475094f / 8.0), + FL2FXCONST_SGL(0.65916004833932f / 8.0)}, + {FL2FXCONST_SGL(0.67439478141121f / 8.0), + FL2FXCONST_SGL(-0.81684380846796f / 8.0)}, + {FL2FXCONST_SGL(-0.47770832416973f / 8.0), + FL2FXCONST_SGL(-0.16789556203025f / 8.0)}, + {FL2FXCONST_SGL(-0.99715979260878f / 8.0), + FL2FXCONST_SGL(-0.93565784007648f / 8.0)}, + {FL2FXCONST_SGL(-0.90889593602546f / 8.0), + FL2FXCONST_SGL(0.62034397054380f / 8.0)}, + {FL2FXCONST_SGL(-0.06618622548177f / 8.0), + FL2FXCONST_SGL(-0.23812217221359f / 8.0)}, + {FL2FXCONST_SGL(0.99430266919728f / 8.0), + FL2FXCONST_SGL(0.18812555317553f / 8.0)}, + {FL2FXCONST_SGL(0.97686402381843f / 8.0), + FL2FXCONST_SGL(-0.28664534366620f / 8.0)}, + {FL2FXCONST_SGL(0.94813650221268f / 8.0), + FL2FXCONST_SGL(-0.97506640027128f / 8.0)}, + {FL2FXCONST_SGL(-0.95434497492853f / 8.0), + FL2FXCONST_SGL(-0.79607978501983f / 8.0)}, + {FL2FXCONST_SGL(-0.49104783137150f / 8.0), + FL2FXCONST_SGL(0.32895214359663f / 8.0)}, + {FL2FXCONST_SGL(0.99881175120751f / 8.0), + FL2FXCONST_SGL(0.88993983831354f / 8.0)}, + {FL2FXCONST_SGL(0.50449166760303f / 8.0), + FL2FXCONST_SGL(-0.85995072408434f / 8.0)}, + {FL2FXCONST_SGL(0.47162891065108f / 8.0), + FL2FXCONST_SGL(-0.18680204049569f / 8.0)}, + {FL2FXCONST_SGL(-0.62081581361840f / 8.0), + FL2FXCONST_SGL(0.75000676218956f / 8.0)}, + {FL2FXCONST_SGL(-0.43867015250812f / 8.0), + FL2FXCONST_SGL(0.99998069244322f / 8.0)}, + {FL2FXCONST_SGL(0.98630563232075f / 8.0), + FL2FXCONST_SGL(-0.53578899600662f / 8.0)}, + {FL2FXCONST_SGL(-0.61510362277374f / 8.0), + FL2FXCONST_SGL(-0.89515019899997f / 8.0)}, + {FL2FXCONST_SGL(-0.03841517601843f / 8.0), + FL2FXCONST_SGL(-0.69888815681179f / 8.0)}, + {FL2FXCONST_SGL(-0.30102157304644f / 8.0), + FL2FXCONST_SGL(-0.07667808922205f / 8.0)}, + {FL2FXCONST_SGL(0.41881284182683f / 8.0), + FL2FXCONST_SGL(0.02188098922282f / 8.0)}, + {FL2FXCONST_SGL(-0.86135454941237f / 8.0), + FL2FXCONST_SGL(0.98947480909359f / 8.0)}, + {FL2FXCONST_SGL(0.67226861393788f / 8.0), + FL2FXCONST_SGL(-0.13494389011014f / 8.0)}, + {FL2FXCONST_SGL(-0.70737398842068f / 8.0), + FL2FXCONST_SGL(-0.76547349325992f / 8.0)}, + {FL2FXCONST_SGL(0.94044946687963f / 8.0), + FL2FXCONST_SGL(0.09026201157416f / 8.0)}, + {FL2FXCONST_SGL(-0.82386352534327f / 8.0), + FL2FXCONST_SGL(0.08924768823676f / 8.0)}, + {FL2FXCONST_SGL(-0.32070666698656f / 8.0), + FL2FXCONST_SGL(0.50143421908753f / 8.0)}, + {FL2FXCONST_SGL(0.57593163224487f / 8.0), + FL2FXCONST_SGL(-0.98966422921509f / 8.0)}, + {FL2FXCONST_SGL(-0.36326018419965f / 8.0), + FL2FXCONST_SGL(0.07440243123228f / 8.0)}, + {FL2FXCONST_SGL(0.99979044674350f / 8.0), + FL2FXCONST_SGL(-0.14130287347405f / 8.0)}, + {FL2FXCONST_SGL(-0.92366023326932f / 8.0), + FL2FXCONST_SGL(-0.97979298068180f / 8.0)}, + {FL2FXCONST_SGL(-0.44607178518598f / 8.0), + FL2FXCONST_SGL(-0.54233252016394f / 8.0)}, + {FL2FXCONST_SGL(0.44226800932956f / 8.0), + FL2FXCONST_SGL(0.71326756742752f / 8.0)}, + {FL2FXCONST_SGL(0.03671907158312f / 8.0), + FL2FXCONST_SGL(0.63606389366675f / 8.0)}, + {FL2FXCONST_SGL(0.52175424682195f / 8.0), + FL2FXCONST_SGL(-0.85396826735705f / 8.0)}, + {FL2FXCONST_SGL(-0.94701139690956f / 8.0), + FL2FXCONST_SGL(-0.01826348194255f / 8.0)}, + {FL2FXCONST_SGL(-0.98759606946049f / 8.0), + FL2FXCONST_SGL(0.82288714303073f / 8.0)}, + {FL2FXCONST_SGL(0.87434794743625f / 8.0), + FL2FXCONST_SGL(0.89399495655433f / 8.0)}, + {FL2FXCONST_SGL(-0.93412041758744f / 8.0), + FL2FXCONST_SGL(0.41374052024363f / 8.0)}, + {FL2FXCONST_SGL(0.96063943315511f / 8.0), + FL2FXCONST_SGL(0.93116709541280f / 8.0)}, + {FL2FXCONST_SGL(0.97534253457837f / 8.0), + FL2FXCONST_SGL(0.86150930812689f / 8.0)}, + {FL2FXCONST_SGL(0.99642466504163f / 8.0), + FL2FXCONST_SGL(0.70190043427512f / 8.0)}, + {FL2FXCONST_SGL(-0.94705089665984f / 8.0), + FL2FXCONST_SGL(-0.29580042814306f / 8.0)}, + {FL2FXCONST_SGL(0.91599807087376f / 8.0), + FL2FXCONST_SGL(-0.98147830385781f / 8.0)}}; +//@} + +/* +static const FIXP_SGL harmonicPhase [2][4] = { + { 1.0, 0.0, -1.0, 0.0}, + { 0.0, 1.0, 0.0, -1.0} +}; +*/ + +/* tables for SBR and AAC LD */ +/* table for 8 time slot index */ +const int FDK_sbrDecoder_envelopeTable_8[8][5] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ {2, 0, 0, 1, -1}, + /*[|-T-|-----]*/ {2, 0, 0, 2, -1}, + /*[--|T-|----]*/ {3, 1, 1, 2, 4}, + /*[---|T-|---]*/ {3, 1, 1, 3, 5}, + /*[----|T-|--]*/ {3, 1, 1, 4, 6}, + /*[-----|T--|]*/ {2, 1, 1, 5, -1}, + /*[------|T-|]*/ {2, 1, 1, 6, -1}, + /*[-------|T|]*/ {2, 1, 1, 7, -1}, +}; + +/* table for 15 time slot index */ +const int FDK_sbrDecoder_envelopeTable_15[15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1}, + /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1}, +}; + +/* table for 16 time slot index */ +const int FDK_sbrDecoder_envelopeTable_16[16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1}, + /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1}, + /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1}, +}; + +/*! + \name FrameInfoDefaults + + Predefined envelope positions for the FIX-FIX case (static framing) +*/ +//@{ +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_15 = { + 0, 1, {0, 15, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 15, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_15 = { + 0, 2, {0, 8, 15, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_15 = { + 0, 4, {0, 4, 8, 12, 15, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 15}, {0, 0, 0}, + 0, 0}; +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_15 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 15}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 15}, + {0, 0, 0}, + 0, + 0}; +#endif + +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info1_16 = { + 0, 1, {0, 16, 0, 0, 0, 0}, {1, 0, 0, 0, 0}, -1, 1, {0, 16, 0}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info2_16 = { + 0, 2, {0, 8, 16, 0, 0, 0}, {1, 1, 0, 0, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info4_16 = { + 0, 4, {0, 4, 8, 12, 16, 0}, {1, 1, 1, 1, 0}, -1, 2, {0, 8, 16}, {0, 0, 0}, + 0, 0}; + +#if (MAX_ENVELOPES >= 8) +const FRAME_INFO FDK_sbrDecoder_sbr_frame_info8_16 = { + 0, + 8, + {0, 2, 4, 6, 8, 10, 12, 14, 16}, + {1, 1, 1, 1, 1, 1, 1, 1}, + -1, + 2, + {0, 8, 16}, + {0, 0, 0}, + 0, + 0}; +#endif + +//@} + +/*! + \name SBR_HuffmanTables + + SBR Huffman Table Overview: \n + \n + o envelope level, 1.5 dB: \n + 1) sbr_huffBook_EnvLevel10T[120][2] \n + 2) sbr_huffBook_EnvLevel10F[120][2] \n + \n + o envelope balance, 1.5 dB: \n + 3) sbr_huffBook_EnvBalance10T[48][2] \n + 4) sbr_huffBook_EnvBalance10F[48][2] \n + \n + o envelope level, 3.0 dB: \n + 5) sbr_huffBook_EnvLevel11T[62][2] \n + 6) sbr_huffBook_EnvLevel11F[62][2] \n + \n + o envelope balance, 3.0 dB: \n + 7) sbr_huffBook_EnvBalance11T[24][2] \n + 8) sbr_huffBook_EnvBalance11F[24][2] \n + \n + o noise level, 3.0 dB: \n + 9) sbr_huffBook_NoiseLevel11T[62][2] \n + -) (sbr_huffBook_EnvLevel11F[62][2] is used for freq dir)\n + \n + o noise balance, 3.0 dB: \n + 10) sbr_huffBook_NoiseBalance11T[24][2]\n + -) (sbr_huffBook_EnvBalance11F[24][2] is used for freq dir)\n + \n + (1.5 dB is never used for noise) + +*/ +//@{ +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10T[120][2] = { + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-62, -67}, {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, + {11, 12}, {-59, -70}, {13, 14}, {-58, -71}, {15, 16}, + {-57, -72}, {17, 18}, {-73, -56}, {19, 21}, {-74, 20}, + {-55, -75}, {22, 26}, {23, 24}, {-54, -76}, {-77, 25}, + {-53, -78}, {27, 34}, {28, 29}, {-52, -79}, {30, 31}, + {-80, -51}, {32, 33}, {-83, -82}, {-81, -50}, {35, 57}, + {36, 40}, {37, 38}, {-88, -84}, {-48, 39}, {-90, -85}, + {41, 46}, {42, 43}, {-49, -87}, {44, 45}, {-89, -86}, + {-124, -123}, {47, 50}, {48, 49}, {-122, -121}, {-120, -119}, + {51, 54}, {52, 53}, {-118, -117}, {-116, -115}, {55, 56}, + {-114, -113}, {-112, -111}, {58, 89}, {59, 74}, {60, 67}, + {61, 64}, {62, 63}, {-110, -109}, {-108, -107}, {65, 66}, + {-106, -105}, {-104, -103}, {68, 71}, {69, 70}, {-102, -101}, + {-100, -99}, {72, 73}, {-98, -97}, {-96, -95}, {75, 82}, + {76, 79}, {77, 78}, {-94, -93}, {-92, -91}, {80, 81}, + {-47, -46}, {-45, -44}, {83, 86}, {84, 85}, {-43, -42}, + {-41, -40}, {87, 88}, {-39, -38}, {-37, -36}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-35, -34}, {-33, -32}, + {96, 97}, {-31, -30}, {-29, -28}, {99, 102}, {100, 101}, + {-27, -26}, {-25, -24}, {103, 104}, {-23, -22}, {-21, -20}, + {106, 113}, {107, 110}, {108, 109}, {-19, -18}, {-17, -16}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel10F[120][2] = { + {1, 2}, {-64, -65}, {3, 4}, {-63, -66}, {5, 6}, + {-67, -62}, {7, 8}, {-68, -61}, {9, 10}, {-69, -60}, + {11, 13}, {-70, 12}, {-59, -71}, {14, 16}, {-58, 15}, + {-72, -57}, {17, 19}, {-73, 18}, {-56, -74}, {20, 23}, + {21, 22}, {-55, -75}, {-54, -53}, {24, 27}, {25, 26}, + {-76, -52}, {-77, -51}, {28, 31}, {29, 30}, {-50, -78}, + {-79, -49}, {32, 36}, {33, 34}, {-48, -47}, {-80, 35}, + {-81, -82}, {37, 47}, {38, 41}, {39, 40}, {-83, -46}, + {-45, -84}, {42, 44}, {-85, 43}, {-44, -43}, {45, 46}, + {-88, -87}, {-86, -90}, {48, 66}, {49, 56}, {50, 53}, + {51, 52}, {-92, -42}, {-41, -39}, {54, 55}, {-105, -89}, + {-38, -37}, {57, 60}, {58, 59}, {-94, -91}, {-40, -36}, + {61, 63}, {-20, 62}, {-115, -110}, {64, 65}, {-108, -107}, + {-101, -97}, {67, 89}, {68, 75}, {69, 72}, {70, 71}, + {-95, -93}, {-34, -27}, {73, 74}, {-22, -17}, {-16, -124}, + {76, 82}, {77, 79}, {-123, 78}, {-122, -121}, {80, 81}, + {-120, -119}, {-118, -117}, {83, 86}, {84, 85}, {-116, -114}, + {-113, -112}, {87, 88}, {-111, -109}, {-106, -104}, {90, 105}, + {91, 98}, {92, 95}, {93, 94}, {-103, -102}, {-100, -99}, + {96, 97}, {-98, -96}, {-35, -33}, {99, 102}, {100, 101}, + {-32, -31}, {-30, -29}, {103, 104}, {-28, -26}, {-25, -24}, + {106, 113}, {107, 110}, {108, 109}, {-23, -21}, {-19, -18}, + {111, 112}, {-15, -14}, {-13, -12}, {114, 117}, {115, 116}, + {-11, -10}, {-9, -8}, {118, 119}, {-7, -6}, {-5, -4}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10T[48][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, + {-67, 7}, {-60, 8}, {-68, 9}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 28}, {15, 21}, {16, 18}, {-57, 17}, {-71, -56}, + {19, 20}, {-88, -87}, {-86, -85}, {22, 25}, {23, 24}, {-84, -83}, + {-82, -81}, {26, 27}, {-80, -79}, {-78, -77}, {29, 36}, {30, 33}, + {31, 32}, {-76, -75}, {-74, -73}, {34, 35}, {-72, -55}, {-54, -53}, + {37, 41}, {38, 39}, {-52, -51}, {-50, 40}, {-49, -48}, {42, 45}, + {43, 44}, {-47, -46}, {-45, -44}, {46, 47}, {-43, -42}, {-41, -40}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance10F[48][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {-70, 12}, + {-58, 13}, {14, 17}, {-71, 15}, {-57, 16}, {-56, -73}, {18, 32}, + {19, 25}, {20, 22}, {-72, 21}, {-88, -87}, {23, 24}, {-86, -85}, + {-84, -83}, {26, 29}, {27, 28}, {-82, -81}, {-80, -79}, {30, 31}, + {-78, -77}, {-76, -75}, {33, 40}, {34, 37}, {35, 36}, {-74, -55}, + {-54, -53}, {38, 39}, {-52, -51}, {-50, -49}, {41, 44}, {42, 43}, + {-48, -47}, {-46, -45}, {45, 46}, {-44, -43}, {-42, 47}, {-41, -40}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11T[62][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {10, 11}, {-69, -59}, {12, 14}, + {-70, 13}, {-71, -58}, {15, 18}, {16, 17}, {-72, -57}, {-73, -74}, + {19, 22}, {-56, 20}, {-55, 21}, {-54, -77}, {23, 31}, {24, 25}, + {-75, -76}, {26, 27}, {-78, -53}, {28, 29}, {-52, -95}, {-94, 30}, + {-93, -92}, {32, 47}, {33, 40}, {34, 37}, {35, 36}, {-91, -90}, + {-89, -88}, {38, 39}, {-87, -86}, {-85, -84}, {41, 44}, {42, 43}, + {-83, -82}, {-81, -80}, {45, 46}, {-79, -51}, {-50, -49}, {48, 55}, + {49, 52}, {50, 51}, {-48, -47}, {-46, -45}, {53, 54}, {-44, -43}, + {-42, -41}, {56, 59}, {57, 58}, {-40, -39}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvLevel11F[62][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 10}, {-60, -69}, {11, 12}, {-59, -70}, + {13, 14}, {-58, -71}, {15, 16}, {-57, -72}, {17, 19}, {-56, 18}, + {-55, -73}, {20, 24}, {21, 22}, {-74, -54}, {-53, 23}, {-75, -76}, + {25, 30}, {26, 27}, {-52, -51}, {28, 29}, {-77, -79}, {-50, -49}, + {31, 39}, {32, 35}, {33, 34}, {-78, -46}, {-82, -88}, {36, 37}, + {-83, -48}, {-47, 38}, {-86, -85}, {40, 47}, {41, 44}, {42, 43}, + {-80, -44}, {-43, -42}, {45, 46}, {-39, -87}, {-84, -40}, {48, 55}, + {49, 52}, {50, 51}, {-95, -94}, {-93, -92}, {53, 54}, {-91, -90}, + {-89, -81}, {56, 59}, {57, 58}, {-45, -41}, {-38, -37}, {60, 61}, + {-36, -35}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11T[24][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 16}, {11, 13}, {-69, 12}, + {-76, -75}, {14, 15}, {-74, -73}, {-72, -71}, {17, 20}, {18, 19}, + {-70, -59}, {-58, -57}, {21, 22}, {-56, -55}, {-54, 23}, {-53, -52}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_EnvBalance11F[24][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-61, 6}, + {-67, 7}, {-68, 8}, {-60, 9}, {10, 13}, {-69, 11}, {-59, 12}, + {-58, -76}, {14, 17}, {15, 16}, {-75, -74}, {-73, -72}, {18, 21}, + {19, 20}, {-71, -70}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseLevel11T[62][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {7, 8}, {-61, -68}, {9, 30}, {10, 15}, {-60, 11}, {-69, 12}, + {13, 14}, {-59, -53}, {-95, -94}, {16, 23}, {17, 20}, {18, 19}, + {-93, -92}, {-91, -90}, {21, 22}, {-89, -88}, {-87, -86}, {24, 27}, + {25, 26}, {-85, -84}, {-83, -82}, {28, 29}, {-81, -80}, {-79, -78}, + {31, 46}, {32, 39}, {33, 36}, {34, 35}, {-77, -76}, {-75, -74}, + {37, 38}, {-73, -72}, {-71, -70}, {40, 43}, {41, 42}, {-58, -57}, + {-56, -55}, {44, 45}, {-54, -52}, {-51, -50}, {47, 54}, {48, 51}, + {49, 50}, {-49, -48}, {-47, -46}, {52, 53}, {-45, -44}, {-43, -42}, + {55, 58}, {56, 57}, {-41, -40}, {-39, -38}, {59, 60}, {-37, -36}, + {-35, 61}, {-34, -33}}; + +const SCHAR FDK_sbrDecoder_sbr_huffBook_NoiseBalance11T[24][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {4, 9}, {-66, 5}, {-62, 6}, + {7, 8}, {-76, -75}, {-74, -73}, {10, 17}, {11, 14}, {12, 13}, + {-72, -71}, {-70, -69}, {15, 16}, {-68, -67}, {-61, -60}, {18, 21}, + {19, 20}, {-59, -58}, {-57, -56}, {22, 23}, {-55, -54}, {-53, -52}}; +//@} + +/*! + \name parametric stereo + \brief constants used by the parametric stereo part of the decoder + +*/ + +/* constants used in psbitdec.cpp */ + +/* FIX_BORDER can have 0, 1, 2, 4 envelopes */ +const UCHAR FDK_sbrDecoder_aFixNoEnvDecode[4] = {0, 1, 2, 4}; + +/* IID & ICC Huffman codebooks */ +const SCHAR aBookPsIidTimeDecode[28][2] = { + {-64, 1}, {-65, 2}, {-63, 3}, {-66, 4}, {-62, 5}, {-67, 6}, + {-61, 7}, {-68, 8}, {-60, 9}, {-69, 10}, {-59, 11}, {-70, 12}, + {-58, 13}, {-57, 14}, {-71, 15}, {16, 17}, {-56, -72}, {18, 21}, + {19, 20}, {-55, -78}, {-77, -76}, {22, 25}, {23, 24}, {-75, -74}, + {-73, -54}, {26, 27}, {-53, -52}, {-51, -50}}; + +const SCHAR aBookPsIidFreqDecode[28][2] = { + {-64, 1}, {2, 3}, {-63, -65}, {4, 5}, {-62, -66}, {6, 7}, + {-61, -67}, {8, 9}, {-68, -60}, {-59, 10}, {-69, 11}, {-58, 12}, + {-70, 13}, {-71, 14}, {-57, 15}, {16, 17}, {-56, -72}, {18, 19}, + {-55, -54}, {20, 21}, {-73, -53}, {22, 24}, {-74, 23}, {-75, -78}, + {25, 26}, {-77, -76}, {-52, 27}, {-51, -50}}; + +const SCHAR aBookPsIccTimeDecode[14][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-68, 9}, {-59, 10}, {-69, 11}, {-58, 12}, {-70, 13}, {-71, -57}}; + +const SCHAR aBookPsIccFreqDecode[14][2] = { + {-64, 1}, {-63, 2}, {-65, 3}, {-62, 4}, {-66, 5}, {-61, 6}, {-67, 7}, + {-60, 8}, {-59, 9}, {-68, 10}, {-58, 11}, {-69, 12}, {-57, 13}, {-70, -71}}; + +/* IID-fine Huffman codebooks */ + +const SCHAR aBookPsIidFineTimeDecode[60][2] = { + {1, -64}, {-63, 2}, {3, -65}, {4, 59}, {5, 7}, {6, -67}, + {-68, -60}, {-61, 8}, {9, 11}, {-59, 10}, {-70, -58}, {12, 41}, + {13, 20}, {14, -71}, {-55, 15}, {-53, 16}, {17, -77}, {18, 19}, + {-85, -84}, {-46, -45}, {-57, 21}, {22, 40}, {23, 29}, {-51, 24}, + {25, 26}, {-83, -82}, {27, 28}, {-90, -38}, {-92, -91}, {30, 37}, + {31, 34}, {32, 33}, {-35, -34}, {-37, -36}, {35, 36}, {-94, -93}, + {-89, -39}, {38, -79}, {39, -81}, {-88, -40}, {-74, -54}, {42, -69}, + {43, 44}, {-72, -56}, {45, 52}, {46, 50}, {47, -76}, {-49, 48}, + {-47, 49}, {-87, -41}, {-52, 51}, {-78, -50}, {53, -73}, {54, -75}, + {55, 57}, {56, -80}, {-86, -42}, {-48, 58}, {-44, -43}, {-66, -62}}; + +const SCHAR aBookPsIidFineFreqDecode[60][2] = { + {1, -64}, {2, 4}, {3, -65}, {-66, -62}, {-63, 5}, {6, 7}, + {-67, -61}, {8, 9}, {-68, -60}, {10, 11}, {-69, -59}, {12, 13}, + {-70, -58}, {14, 18}, {-57, 15}, {16, -72}, {-54, 17}, {-75, -53}, + {19, 37}, {-56, 20}, {21, -73}, {22, 29}, {23, -76}, {24, -78}, + {25, 28}, {26, 27}, {-85, -43}, {-83, -45}, {-81, -47}, {-52, 30}, + {-50, 31}, {32, -79}, {33, 34}, {-82, -46}, {35, 36}, {-90, -89}, + {-92, -91}, {38, -71}, {-55, 39}, {40, -74}, {41, 50}, {42, -77}, + {-49, 43}, {44, 47}, {45, 46}, {-86, -42}, {-88, -87}, {48, 49}, + {-39, -38}, {-41, -40}, {-51, 51}, {52, 59}, {53, 56}, {54, 55}, + {-35, -34}, {-37, -36}, {57, 58}, {-94, -93}, {-84, -44}, {-80, -48}}; + +/* constants used in psdec.cpp */ + +/* the values of the following 3 tables are shiftet right by 1 ! */ +const FIXP_DBL ScaleFactors[NO_IID_LEVELS] = { + + 0x5a5ded00, 0x59cd0400, 0x58c29680, 0x564c2e80, 0x52a3d480, + 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x24e9f640, 0x1b4a2940, 0x11b5c0a0, 0x0b4e2540, 0x0514ea90}; + +const FIXP_DBL ScaleFactorsFine[NO_IID_LEVELS_FINE] = { + + 0x5a825c00, 0x5a821c00, 0x5a815100, 0x5a7ed000, 0x5a76e600, 0x5a5ded00, + 0x5a39b880, 0x59f1fd00, 0x5964d680, 0x5852ca00, 0x564c2e80, 0x54174480, + 0x50ea7500, 0x4c8be080, 0x46df3080, 0x40000000, 0x384ba5c0, 0x304c2980, + 0x288dd240, 0x217a2900, 0x1b4a2940, 0x13c5ece0, 0x0e2b0090, 0x0a178ef0, + 0x072ab798, 0x0514ea90, 0x02dc5944, 0x019bf87c, 0x00e7b173, 0x00824b8b, + 0x00494568}; +const FIXP_DBL Alphas[NO_ICC_LEVELS] = { + + 0x00000000, 0x0b6b5be0, 0x12485f80, 0x1da2fa40, + 0x2637ebc0, 0x3243f6c0, 0x466b7480, 0x6487ed80}; + +const UCHAR bins2groupMap20[NO_IID_GROUPS] = { + 0, 0, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +const UCHAR FDK_sbrDecoder_aNoIidBins[3] = { + NO_LOW_RES_IID_BINS, NO_MID_RES_IID_BINS, NO_HI_RES_IID_BINS}; + +const UCHAR FDK_sbrDecoder_aNoIccBins[3] = { + NO_LOW_RES_ICC_BINS, NO_MID_RES_ICC_BINS, NO_HI_RES_ICC_BINS}; + +/************************************************************************/ +/*! + \brief Create lookup tables for some arithmetic functions + + The tables would normally be defined as const arrays, + but initialization at run time allows to specify their accuracy. +*/ +/************************************************************************/ + +/* 1/x-table: (example for INV_TABLE_BITS 8) + + The table covers an input range from 0.5 to 1.0 with a step size of 1/512, + starting at 0.5 + 1/512. + Each table entry corresponds to an input interval starting 1/1024 below the + exact value and ending 1/1024 above it. + + The table is actually a 0.5/x-table, so that the output range is again + 0.5...1.0 and the exponent of the result must be increased by 1. + + Input range Index in table result + ------------------------------------------------------------------- + 0.500000...0.500976 - 0.5 / 0.500000 = 1.000000 + 0.500976...0.502930 0 0.5 / 0.501953 = 0.996109 + 0.502930...0.500488 1 0.5 / 0.503906 = 0.992248 + ... + 0.999023...1.000000 255 0.5 / 1.000000 = 0.500000 + + for (i=0; iprevFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + for (band = 0; band < SBRDEC_MAX_DRC_BANDS; band++) { + hDrcData->currFact_mag[band] = FL2FXCONST_DBL(0.5f); + hDrcData->nextFact_mag[band] = FL2FXCONST_DBL(0.5f); + } + + hDrcData->prevFact_exp = 1; + hDrcData->currFact_exp = 1; + hDrcData->nextFact_exp = 1; + + hDrcData->numBandsCurr = 1; + hDrcData->numBandsNext = 1; + + hDrcData->winSequenceCurr = 0; + hDrcData->winSequenceNext = 0; + + hDrcData->drcInterpolationSchemeCurr = 0; + hDrcData->drcInterpolationSchemeNext = 0; + + hDrcData->enable = 0; +} + +/*! + \brief Swap DRC QMF scaling factors after they have been applied. + + \hDrcData Handle to DRC channel data. + + \return none +*/ +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData) { + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + /* swap previous data */ + FDKmemcpy(hDrcData->currFact_mag, hDrcData->nextFact_mag, + SBRDEC_MAX_DRC_BANDS * sizeof(FIXP_DBL)); + + hDrcData->currFact_exp = hDrcData->nextFact_exp; + + hDrcData->numBandsCurr = hDrcData->numBandsNext; + + FDKmemcpy(hDrcData->bandTopCurr, hDrcData->bandTopNext, + SBRDEC_MAX_DRC_BANDS * sizeof(USHORT)); + + hDrcData->drcInterpolationSchemeCurr = hDrcData->drcInterpolationSchemeNext; + + hDrcData->winSequenceCurr = hDrcData->winSequenceNext; +} + +/*! + \brief Apply DRC factors slot based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of one time slot. + \qmfImagSlot Pointer to the imaginary QMF data of one time slot. + \col Number of the time slot. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the time slot. + + \return None. +*/ +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift) { + const UCHAR *winBorderToColMap; + + int band, bottomMdct, topMdct, bin, useLP; + int indx = numQmfSubSamples - (numQmfSubSamples >> 1) - 10; /* l_border */ + int frameLenFlag = (numQmfSubSamples == 30) ? 1 : 0; + int frameSize = (frameLenFlag == 1) ? 960 : 1024; + + const FIXP_DBL *fact_mag = NULL; + INT fact_exp = 0; + UINT numBands = 0; + USHORT *bandTop = NULL; + int shortDrc = 0; + + FIXP_DBL alphaValue = FL2FXCONST_DBL(0.0f); + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable != 1) { + return; + } + + winBorderToColMap = winBorderToColMappingTab[frameLenFlag]; + + useLP = (qmfImagSlot == NULL) ? 1 : 0; + + col += indx; + bottomMdct = 0; + + /* get respective data and calc interpolation factor */ + if (col < (numQmfSubSamples >> 1)) { /* first half of current frame */ + if (hDrcData->winSequenceCurr != 2) { /* long window */ + int j = col + (numQmfSubSamples >> 1); + + if (hDrcData->drcInterpolationSchemeCurr == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeCurr]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } else if (col < numQmfSubSamples) { /* second half of current frame */ + if (hDrcData->winSequenceNext != 2) { /* next: long window */ + int j = col - (numQmfSubSamples >> 1); + + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } else { /* next: short windows */ + if (hDrcData->winSequenceCurr != 2) { /* current: long window */ + alphaValue = (FIXP_DBL)0; + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + } else { /* current: short windows */ + shortDrc = 1; + + fact_mag = hDrcData->currFact_mag; + fact_exp = hDrcData->currFact_exp; + numBands = hDrcData->numBandsCurr; + bandTop = hDrcData->bandTopCurr; + } + } + } else { /* first half of next frame */ + if (hDrcData->winSequenceNext != 2) { /* long window */ + int j = col - (numQmfSubSamples >> 1); + + if (hDrcData->drcInterpolationSchemeNext == 0) { + INT k = (frameLenFlag) ? 0x4444445 : 0x4000000; + + alphaValue = (FIXP_DBL)(j * k); + } else { + if (j >= (int)winBorderToColMap[hDrcData->drcInterpolationSchemeNext]) { + alphaValue = (FIXP_DBL)MAXVAL_DBL; + } + } + } else { /* short windows */ + shortDrc = 1; + } + + fact_mag = hDrcData->nextFact_mag; + fact_exp = hDrcData->nextFact_exp; + numBands = hDrcData->numBandsNext; + bandTop = hDrcData->bandTopNext; + + col -= numQmfSubSamples; + } + + /* process bands */ + for (band = 0; band < (int)numBands; band++) { + int bottomQmf, topQmf; + + FIXP_DBL drcFact_mag = (FIXP_DBL)MAXVAL_DBL; + + topMdct = (bandTop[band] + 1) << 2; + + if (!shortDrc) { /* long window */ + if (frameLenFlag) { + /* 960 framing */ + bottomQmf = fMultIfloor((FIXP_DBL)0x4444445, bottomMdct); + topQmf = fMultIfloor((FIXP_DBL)0x4444445, topMdct); + + topMdct = 30 * topQmf; + } else { + /* 1024 framing */ + topMdct &= ~0x1f; + + bottomQmf = bottomMdct >> 5; + topQmf = topMdct >> 5; + } + + if (band == ((int)numBands - 1)) { + topQmf = (64); + } + + for (bin = bottomQmf; bin < topQmf; bin++) { + FIXP_DBL drcFact1_mag = hDrcData->prevFact_mag[bin]; + FIXP_DBL drcFact2_mag = fact_mag[band]; + + /* normalize scale factors */ + if (hDrcData->prevFact_exp < maxShift) { + drcFact1_mag >>= maxShift - hDrcData->prevFact_exp; + } + if (fact_exp < maxShift) { + drcFact2_mag >>= maxShift - fact_exp; + } + + /* interpolate */ + if (alphaValue == (FIXP_DBL)0) { + drcFact_mag = drcFact1_mag; + } else if (alphaValue == (FIXP_DBL)MAXVAL_DBL) { + drcFact_mag = drcFact2_mag; + } else { + drcFact_mag = + fMult(alphaValue, drcFact2_mag) + + fMult(((FIXP_DBL)MAXVAL_DBL - alphaValue), drcFact1_mag); + } + + /* apply scaling */ + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + + /* save previous factors */ + if (col == (numQmfSubSamples >> 1) - 1) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + } else { /* short windows */ + unsigned startWinIdx, stopWinIdx; + int startCol, stopCol; + FIXP_DBL invFrameSizeDiv8 = + (frameLenFlag) ? (FIXP_DBL)0x1111112 : (FIXP_DBL)0x1000000; + + /* limit top at the frame borders */ + if (topMdct < 0) { + topMdct = 0; + } + if (topMdct >= frameSize) { + topMdct = frameSize - 1; + } + + if (frameLenFlag) { + /* 960 framing */ + topMdct = fMultIfloor((FIXP_DBL)0x78000000, + fMultIfloor((FIXP_DBL)0x22222223, topMdct) << 2); + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + + 1; /* winBorderToColMap table has offset of 1 */ + stopWinIdx = fMultIceil(invFrameSizeDiv8 - (FIXP_DBL)1, topMdct) + 1; + } else { + /* 1024 framing */ + topMdct &= ~0x03; + + startWinIdx = fMultIfloor(invFrameSizeDiv8, bottomMdct) + 1; + stopWinIdx = fMultIceil(invFrameSizeDiv8, topMdct) + 1; + } + + /* startCol is truncated to the nearest corresponding start subsample in + the QMF of the short window bottom is present in:*/ + startCol = (int)winBorderToColMap[startWinIdx]; + + /* stopCol is rounded upwards to the nearest corresponding stop subsample + in the QMF of the short window top is present in. */ + stopCol = (int)winBorderToColMap[stopWinIdx]; + + bottomQmf = fMultIfloor(invFrameSizeDiv8, + ((bottomMdct % (numQmfSubSamples << 2)) << 5)); + topQmf = fMultIfloor(invFrameSizeDiv8, + ((topMdct % (numQmfSubSamples << 2)) << 5)); + + /* extend last band */ + if (band == ((int)numBands - 1)) { + topQmf = (64); + stopCol = numQmfSubSamples; + stopWinIdx = 10; + } + + if (topQmf == 0) { + if (frameLenFlag) { + FIXP_DBL rem = fMult(invFrameSizeDiv8, + (FIXP_DBL)(topMdct << (DFRACT_BITS - 12))); + if ((LONG)rem & (LONG)0x1F) { + stopWinIdx -= 1; + stopCol = (int)winBorderToColMap[stopWinIdx]; + } + } + topQmf = (64); + } + + /* save previous factors */ + if (stopCol == numQmfSubSamples) { + int tmpBottom = bottomQmf; + + if ((int)winBorderToColMap[8] > startCol) { + tmpBottom = 0; /* band starts in previous short window */ + } + + for (bin = tmpBottom; bin < topQmf; bin++) { + hDrcData->prevFact_mag[bin] = fact_mag[band]; + } + } + + /* apply */ + if ((col >= startCol) && (col < stopCol)) { + if (col >= (int)winBorderToColMap[startWinIdx + 1]) { + bottomQmf = 0; /* band starts in previous short window */ + } + if (col < (int)winBorderToColMap[stopWinIdx - 1]) { + topQmf = (64); /* band ends in next short window */ + } + + drcFact_mag = fact_mag[band]; + + /* normalize scale factor */ + if (fact_exp < maxShift) { + drcFact_mag >>= maxShift - fact_exp; + } + + /* apply scaling */ + for (bin = bottomQmf; bin < topQmf; bin++) { + qmfRealSlot[bin] = fMult(qmfRealSlot[bin], drcFact_mag); + if (!useLP) { + qmfImagSlot[bin] = fMult(qmfImagSlot[bin], drcFact_mag); + } + } + } + } + + bottomMdct = topMdct; + } /* end of bands loop */ + + if (col == (numQmfSubSamples >> 1) - 1) { + hDrcData->prevFact_exp = fact_exp; + } +} + +/*! + \brief Apply DRC factors frame based. + + \hDrcData Handle to DRC channel data. + \qmfRealSlot Pointer to real valued QMF data of the whole frame. + \qmfImagSlot Pointer to the imaginary QMF data of the whole frame. + \numQmfSubSamples Total number of time slots for one frame. + \scaleFactor Pointer to the out scale factor of the frame. + + \return None. +*/ +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor) { + int col; + int maxShift = 0; + + if (hDrcData == NULL) { + return; + } + if (hDrcData->enable == 0) { + return; /* Avoid changing the scaleFactor even though the processing is + disabled. */ + } + + /* get max scale factor */ + if (hDrcData->prevFact_exp > maxShift) { + maxShift = hDrcData->prevFact_exp; + } + if (hDrcData->currFact_exp > maxShift) { + maxShift = hDrcData->currFact_exp; + } + if (hDrcData->nextFact_exp > maxShift) { + maxShift = hDrcData->nextFact_exp; + } + + for (col = 0; col < numQmfSubSamples; col++) { + FIXP_DBL *qmfSlotReal = QmfBufferReal[col]; + FIXP_DBL *qmfSlotImag = (QmfBufferImag == NULL) ? NULL : QmfBufferImag[col]; + + sbrDecoder_drcApplySlot(hDrcData, qmfSlotReal, qmfSlotImag, col, + numQmfSubSamples, maxShift); + } + + *scaleFactor += maxShift; +} diff --git a/fdk-aac/libSBRdec/src/sbrdec_drc.h b/fdk-aac/libSBRdec/src/sbrdec_drc.h new file mode 100644 index 0000000..2eb0e20 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbrdec_drc.h @@ -0,0 +1,149 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): Christian Griebel + + Description: Dynamic range control (DRC) decoder tool for SBR + +*******************************************************************************/ + +#ifndef SBRDEC_DRC_H +#define SBRDEC_DRC_H + +#include "sbrdecoder.h" + +#define SBRDEC_MAX_DRC_CHANNELS (8) +#define SBRDEC_MAX_DRC_BANDS (16) + +typedef struct { + FIXP_DBL prevFact_mag[(64)]; + INT prevFact_exp; + + FIXP_DBL currFact_mag[SBRDEC_MAX_DRC_BANDS]; + FIXP_DBL nextFact_mag[SBRDEC_MAX_DRC_BANDS]; + INT currFact_exp; + INT nextFact_exp; + + UINT numBandsCurr; + UINT numBandsNext; + USHORT bandTopCurr[SBRDEC_MAX_DRC_BANDS]; + USHORT bandTopNext[SBRDEC_MAX_DRC_BANDS]; + + SHORT drcInterpolationSchemeCurr; + SHORT drcInterpolationSchemeNext; + + SHORT enable; + + UCHAR winSequenceCurr; + UCHAR winSequenceNext; + +} SBRDEC_DRC_CHANNEL; + +typedef SBRDEC_DRC_CHANNEL *HANDLE_SBR_DRC_CHANNEL; + +void sbrDecoder_drcInitChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); + +void sbrDecoder_drcUpdateChannel(HANDLE_SBR_DRC_CHANNEL hDrcData); + +void sbrDecoder_drcApplySlot(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL *qmfRealSlot, FIXP_DBL *qmfImagSlot, + int col, int numQmfSubSamples, int maxShift); + +void sbrDecoder_drcApply(HANDLE_SBR_DRC_CHANNEL hDrcData, + FIXP_DBL **QmfBufferReal, FIXP_DBL **QmfBufferImag, + int numQmfSubSamples, int *scaleFactor); + +#endif /* SBRDEC_DRC_H */ diff --git a/fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp b/fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp new file mode 100644 index 0000000..165f94b --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbrdec_freq_sca.cpp @@ -0,0 +1,835 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Frequency scale calculation +*/ + +#include "sbrdec_freq_sca.h" + +#include "transcendent.h" +#include "sbr_rom.h" +#include "env_extr.h" + +#include "genericStds.h" /* need log() for debug-code only */ + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + +static int numberOfBands(FIXP_SGL bpo_div16, int start, int stop, int warpFlag); +static void CalcBands(UCHAR *diff, UCHAR start, UCHAR stop, UCHAR num_bands); +static SBR_ERROR modifyBands(UCHAR max_band, UCHAR *diff, UCHAR length); +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress); + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR getStartBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR startFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags) /*!< Info to SBR mode */ +{ + INT band; + UINT fsMapped = fs; + SBR_RATE rate = DUAL; + + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + if (headerDataFlags & SBRDEC_QUAD_RATE) { + rate = QUAD; + } + fsMapped = sbrdec_mapToStdSampleRate(fs, 1); + } + + FDK_ASSERT(2 * (rate + 1) <= (4)); + + switch (fsMapped) { + case 192000: + band = FDK_sbrDecoder_sbr_start_freq_192[startFreq]; + break; + case 176400: + band = FDK_sbrDecoder_sbr_start_freq_176[startFreq]; + break; + case 128000: + band = FDK_sbrDecoder_sbr_start_freq_128[startFreq]; + break; + case 96000: + case 88200: + band = FDK_sbrDecoder_sbr_start_freq_88[rate][startFreq]; + break; + case 64000: + band = FDK_sbrDecoder_sbr_start_freq_64[rate][startFreq]; + break; + case 48000: + band = FDK_sbrDecoder_sbr_start_freq_48[rate][startFreq]; + break; + case 44100: + band = FDK_sbrDecoder_sbr_start_freq_44[rate][startFreq]; + break; + case 40000: + band = FDK_sbrDecoder_sbr_start_freq_40[rate][startFreq]; + break; + case 32000: + band = FDK_sbrDecoder_sbr_start_freq_32[rate][startFreq]; + break; + case 24000: + band = FDK_sbrDecoder_sbr_start_freq_24[rate][startFreq]; + break; + case 22050: + band = FDK_sbrDecoder_sbr_start_freq_22[rate][startFreq]; + break; + case 16000: + band = FDK_sbrDecoder_sbr_start_freq_16[rate][startFreq]; + break; + default: + band = 255; + } + + return band; +} + +/*! + \brief Retrieve QMF-band where the SBR range starts + + Convert startFreq which was read from the bitstream into a + QMF-channel number. + + \return Number of start band +*/ +static UCHAR getStopBand( + UINT fs, /*!< Output sampling frequency */ + UCHAR stopFreq, /*!< Index to table of possible start bands */ + UINT headerDataFlags, /*!< Info to SBR mode */ + UCHAR k0) /*!< Start freq index */ +{ + UCHAR k2; + + if (stopFreq < 14) { + INT stopMin; + INT num = 2 * (64); + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + + if (headerDataFlags & SBRDEC_QUAD_RATE) { + num >>= 1; + } + + if (fs < 32000) { + stopMin = (((2 * 6000 * num) / fs) + 1) >> 1; + } else { + if (fs < 64000) { + stopMin = (((2 * 8000 * num) / fs) + 1) >> 1; + } else { + stopMin = (((2 * 10000 * num) / fs) + 1) >> 1; + } + } + + /* + Choose a stop band between k1 and 64 depending on stopFreq (0..13), + based on a logarithmic scale. + The vectors diff0 and diff1 are used temporarily here. + */ + CalcBands(diff0, stopMin, 64, 13); + shellsort(diff0, 13); + cumSum(stopMin, diff0, 13, diff1); + k2 = diff1[stopFreq]; + } else if (stopFreq == 14) + k2 = 2 * k0; + else + k2 = 3 * k0; + + /* Limit to Nyquist */ + if (k2 > (64)) k2 = (64); + + /* Range checks */ + /* 1 <= difference <= 48; 1 <= fs <= 96000 */ + { + UCHAR max_freq_coeffs = (headerDataFlags & SBRDEC_QUAD_RATE) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS; + if (((k2 - k0) > max_freq_coeffs) || (k2 <= k0)) { + return 255; + } + } + + if (headerDataFlags & SBRDEC_QUAD_RATE) { + return k2; /* skip other checks: (k2 - k0) must be <= + MAX_FREQ_COEFFS_QUAD_RATE for all fs */ + } + if (headerDataFlags & (SBRDEC_SYNTAX_USAC | SBRDEC_SYNTAX_RSVD50)) { + /* 1 <= difference <= 35; 42000 <= fs <= 96000 */ + if ((fs >= 42000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { + return 255; + } + /* 1 <= difference <= 32; 46009 <= fs <= 96000 */ + if ((fs >= 46009) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { + return 255; + } + } else { + /* 1 <= difference <= 35; fs == 44100 */ + if ((fs == 44100) && ((k2 - k0) > MAX_FREQ_COEFFS_FS44100)) { + return 255; + } + /* 1 <= difference <= 32; 48000 <= fs <= 96000 */ + if ((fs >= 48000) && ((k2 - k0) > MAX_FREQ_COEFFS_FS48000)) { + return 255; + } + } + + return k2; +} + +/*! + \brief Generates master frequency tables + + Frequency tables are calculated according to the selected domain + (linear/logarithmic) and granularity. + IEC 14496-3 4.6.18.3.2.1 + + \return errorCode, 0 if successful +*/ +SBR_ERROR +sbrdecUpdateFreqScale( + UCHAR *v_k_master, /*!< Master table to be created */ + UCHAR *numMaster, /*!< Number of entries in master table */ + UINT fs, /*!< SBR working sampling rate */ + HANDLE_SBR_HEADER_DATA hHeaderData, /*!< Control data from bitstream */ + UINT flags) { + FIXP_SGL bpo_div16; /* bands_per_octave divided by 16 */ + INT dk = 0; + + /* Internal variables */ + UCHAR k0, k2, i; + UCHAR num_bands0 = 0; + UCHAR num_bands1 = 0; + UCHAR diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + UCHAR *diff0 = diff_tot; + UCHAR *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; + + /* + Determine start band + */ + if (flags & SBRDEC_QUAD_RATE) { + fs >>= 1; + } + + k0 = getStartBand(fs, hHeaderData->bs_data.startFreq, flags); + if (k0 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* + Determine stop band + */ + k2 = getStopBand(fs, hHeaderData->bs_data.stopFreq, flags, k0); + if (k2 == 255) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (hHeaderData->bs_data.freqScale > 0) { /* Bark */ + INT k1; + + if (hHeaderData->bs_data.freqScale == 1) { + bpo_div16 = FL2FXCONST_SGL(12.0f / 16.0f); + } else if (hHeaderData->bs_data.freqScale == 2) { + bpo_div16 = FL2FXCONST_SGL(10.0f / 16.0f); + } else { + bpo_div16 = FL2FXCONST_SGL(8.0f / 16.0f); + } + + /* Ref: ISO/IEC 23003-3, Figure 12 - Flowchart calculation of fMaster for + * 4:1 system when bs_freq_scale > 0 */ + if (flags & SBRDEC_QUAD_RATE) { + if ((SHORT)k0 < (SHORT)(bpo_div16 >> ((FRACT_BITS - 1) - 4))) { + bpo_div16 = (FIXP_SGL)(k0 & (UCHAR)0xfe) + << ((FRACT_BITS - 1) - 4); /* bpo_div16 = floor(k0/2)*2 */ + } + } + + if (1000 * k2 > 2245 * k0) { /* Two or more regions */ + k1 = 2 * k0; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + num_bands1 = + numberOfBands(bpo_div16, k1, k2, hHeaderData->bs_data.alterScale); + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if (num_bands1 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + CalcBands(diff0, k0, k1, num_bands0); + shellsort(diff0, num_bands0); + if (diff0[0] == 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + + CalcBands(diff1, k1, k2, num_bands1); + shellsort(diff1, num_bands1); + if (diff0[num_bands0 - 1] > diff1[0]) { + SBR_ERROR err; + + err = modifyBands(diff0[num_bands0 - 1], diff1, num_bands1); + if (err) return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Add 2nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *numMaster = num_bands0 + num_bands1; /* Output nr of bands */ + + } else { /* Only one region */ + k1 = k2; + + num_bands0 = numberOfBands(bpo_div16, k0, k1, 0); + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + CalcBands(diff0, k0, k1, num_bands0); + shellsort(diff0, num_bands0); + if (diff0[0] == 0) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + cumSum(k0, diff0, num_bands0, v_k_master); + *numMaster = num_bands0; /* Output nr of bands */ + } + } else { /* Linear mode */ + if (hHeaderData->bs_data.alterScale == 0) { + dk = 1; + /* FLOOR to get to few number of bands (next lower even number) */ + num_bands0 = (k2 - k0) & 254; + } else { + dk = 2; + num_bands0 = (((k2 - k0) >> 1) + 1) & 254; /* ROUND to the closest fit */ + } + + if (num_bands0 < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + /* We must return already here because 'i' can become negative below. */ + } + + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; + + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; + + /* If linear scale wasn't achieved */ + /* and we got too wide SBR area */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } + + /* If linear scale wasn't achieved */ + /* and we got too small SBR area */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *numMaster = num_bands0; /* Output nr of bands */ + } + + if (*numMaster < 1) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Ref: ISO/IEC 23003-3 Cor.3, "In 7.5.5.2, add to the requirements:"*/ + if (flags & SBRDEC_QUAD_RATE) { + int k; + for (k = 1; k < *numMaster; k++) { + if (!(v_k_master[k] - v_k_master[k - 1] <= k0 - 2)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + } + + /* + Print out the calculated table + */ + + return SBRDEC_OK; +} + +/*! + \brief Calculate frequency ratio of one SBR band + + All SBR bands should span a constant frequency range in the logarithmic + domain. This function calculates the ratio of any SBR band's upper and lower + frequency. + + \return num_band-th root of k_start/k_stop +*/ +static FIXP_SGL calcFactorPerBand(int k_start, int k_stop, int num_bands) { + /* Scaled bandfactor and step 1 bit right to avoid overflow + * use double data type */ + FIXP_DBL bandfactor = FL2FXCONST_DBL(0.25f); /* Start value */ + FIXP_DBL step = FL2FXCONST_DBL(0.125f); /* Initial increment for factor */ + + int direction = 1; + + /* Because saturation can't be done in INT IIS, + * changed start and stop data type from FIXP_SGL to FIXP_DBL */ + FIXP_DBL start = k_start << (DFRACT_BITS - 8); + FIXP_DBL stop = k_stop << (DFRACT_BITS - 8); + + FIXP_DBL temp; + + int j, i = 0; + + while (step > FL2FXCONST_DBL(0.0f)) { + i++; + temp = stop; + + /* Calculate temp^num_bands: */ + for (j = 0; j < num_bands; j++) + // temp = fMult(temp,bandfactor); + temp = fMultDiv2(temp, bandfactor) << 2; + + if (temp < start) { /* Factor too strong, make it weaker */ + if (direction == 0) + /* Halfen step. Right shift is not done as fract because otherwise the + lowest bit cannot be cleared due to rounding */ + step = (FIXP_DBL)((LONG)step >> 1); + direction = 1; + bandfactor = bandfactor + step; + } else { /* Factor is too weak: make it stronger */ + if (direction == 1) step = (FIXP_DBL)((LONG)step >> 1); + direction = 0; + bandfactor = bandfactor - step; + } + + if (i > 100) { + step = FL2FXCONST_DBL(0.0f); + } + } + return FX_DBL2FX_SGL(bandfactor << 1); +} + +/*! + \brief Calculate number of SBR bands between start and stop band + + Given the number of bands per octave, this function calculates how many + bands fit in the given frequency range. + When the warpFlag is set, the 'band density' is decreased by a factor + of 1/1.3 + + \return number of bands +*/ +static int numberOfBands( + FIXP_SGL bpo_div16, /*!< Input: number of bands per octave divided by 16 */ + int start, /*!< First QMF band of SBR frequency range */ + int stop, /*!< Last QMF band of SBR frequency range + 1 */ + int warpFlag) /*!< Stretching flag */ +{ + FIXP_SGL num_bands_div128; + int num_bands; + + num_bands_div128 = + FX_DBL2FX_SGL(fMult(FDK_getNumOctavesDiv8(start, stop), bpo_div16)); + + if (warpFlag) { + /* Apply the warp factor of 1.3 to get wider bands. We use a value + of 32768/25200 instead of the exact value to avoid critical cases + of rounding. + */ + num_bands_div128 = FX_DBL2FX_SGL( + fMult(num_bands_div128, FL2FXCONST_SGL(25200.0 / 32768.0))); + } + + /* add scaled 1 for rounding to even numbers: */ + num_bands_div128 = num_bands_div128 + FL2FXCONST_SGL(1.0f / 128.0f); + /* scale back to right aligned integer and double the value: */ + num_bands = 2 * ((LONG)num_bands_div128 >> (FRACT_BITS - 7)); + + return (num_bands); +} + +/*! + \brief Calculate width of SBR bands + + Given the desired number of bands within the SBR frequency range, + this function calculates the width of each SBR band in QMF channels. + The bands get wider from start to stop (bark scale). +*/ +static void CalcBands(UCHAR *diff, /*!< Vector of widths to be calculated */ + UCHAR start, /*!< Lower end of subband range */ + UCHAR stop, /*!< Upper end of subband range */ + UCHAR num_bands) /*!< Desired number of bands */ +{ + int i; + int previous; + int current; + FIXP_SGL exact, temp; + FIXP_SGL bandfactor = calcFactorPerBand(start, stop, num_bands); + + previous = stop; /* Start with highest QMF channel */ + exact = (FIXP_SGL)( + stop << (FRACT_BITS - 8)); /* Shift left to gain some accuracy */ + + for (i = num_bands - 1; i >= 0; i--) { + /* Calculate border of next lower sbr band */ + exact = FX_DBL2FX_SGL(fMult(exact, bandfactor)); + + /* Add scaled 0.5 for rounding: + We use a value 128/256 instead of 0.5 to avoid some critical cases of + rounding. */ + temp = exact + FL2FXCONST_SGL(128.0 / 32768.0); + + /* scale back to right alinged integer: */ + current = (LONG)temp >> (FRACT_BITS - 8); + + /* Save width of band i */ + diff[i] = previous - current; + previous = current; + } +} + +/*! + \brief Calculate cumulated sum vector from delta vector +*/ +static void cumSum(UCHAR start_value, UCHAR *diff, UCHAR length, + UCHAR *start_adress) { + int i; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; +} + +/*! + \brief Adapt width of frequency bands in the second region + + If SBR spans more than 2 octaves, the upper part of a bark-frequency-scale + is calculated separately. This function tries to avoid that the second region + starts with a band smaller than the highest band of the first region. +*/ +static SBR_ERROR modifyBands(UCHAR max_band_previous, UCHAR *diff, + UCHAR length) { + int change = max_band_previous - diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) >> 1) + change = (diff[length - 1] - diff[0]) >> 1; + + diff[0] += change; + diff[length - 1] -= change; + shellsort(diff, length); + + return SBRDEC_OK; +} + +/*! + \brief Update high resolution frequency band table +*/ +static void sbrdecUpdateHiRes(UCHAR *h_hires, UCHAR *num_hires, + UCHAR *v_k_master, UCHAR num_bands, + UCHAR xover_band) { + UCHAR i; + + *num_hires = num_bands - xover_band; + + for (i = xover_band; i <= num_bands; i++) { + h_hires[i - xover_band] = v_k_master[i]; + } +} + +/*! + \brief Build low resolution table out of high resolution table +*/ +static void sbrdecUpdateLoRes(UCHAR *h_lores, UCHAR *num_lores, UCHAR *h_hires, + UCHAR num_hires) { + UCHAR i; + + if ((num_hires & 1) == 0) { + /* If even number of hires bands */ + *num_lores = num_hires >> 1; + /* Use every second lores=hires[0,2,4...] */ + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + } else { + /* Odd number of hires, which means xover is odd */ + *num_lores = (num_hires + 1) >> 1; + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0] = h_hires[0]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; + } + } +} + +/*! + \brief Derive a low-resolution frequency-table from the master frequency + table +*/ +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref) { + int step; + int i, j; + int org_length, result_length; + int v_index[MAX_FREQ_COEFFS >> 1]; + + /* init */ + org_length = num_Ref; + result_length = num_result; + + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) { + /* Create downsample vector */ + i++; + step = org_length / result_length; + org_length = org_length - step; + result_length--; + v_index[i] = v_index[i - 1] + step; + } + + for (j = 0; j <= i; j++) { + /* Use downsample vector to index LoResolution vector */ + v_result[j] = freqBandTableRef[v_index[j]]; + } +} + +/*! + \brief Sorting routine +*/ +void shellsort(UCHAR *in, UCHAR n) { + int i, j, v, w; + int inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc; i < n; i++) { + v = in[i]; + j = i; + while ((w = in[j - inc]) > v) { + in[j] = w; + j -= inc; + if (j < inc) break; + } + in[j] = v; + } + } while (inc > 1); +} + +/*! + \brief Reset frequency band tables + \return errorCode, 0 if successful +*/ +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags) { + SBR_ERROR err = SBRDEC_OK; + int k2, kx, lsb, usb; + int intTemp; + UCHAR nBandsLo, nBandsHi; + HANDLE_FREQ_BAND_DATA hFreq = &hHeaderData->freqBandData; + + /* Calculate master frequency function */ + err = sbrdecUpdateFreqScale(hFreq->v_k_master, &hFreq->numMaster, + hHeaderData->sbrProcSmplRate, hHeaderData, flags); + + if (err || (hHeaderData->bs_info.xover_band > hFreq->numMaster)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Derive Hiresolution from master frequency function */ + sbrdecUpdateHiRes(hFreq->freqBandTable[1], &nBandsHi, hFreq->v_k_master, + hFreq->numMaster, hHeaderData->bs_info.xover_band); + /* Derive Loresolution from Hiresolution */ + sbrdecUpdateLoRes(hFreq->freqBandTable[0], &nBandsLo, hFreq->freqBandTable[1], + nBandsHi); + + hFreq->nSfb[0] = nBandsLo; + hFreq->nSfb[1] = nBandsHi; + + /* Check index to freqBandTable[0] */ + if (!(nBandsLo > 0) || + (nBandsLo > (((hHeaderData->numberOfAnalysisBands == 16) + ? MAX_FREQ_COEFFS_QUAD_RATE + : MAX_FREQ_COEFFS_DUAL_RATE) >> + 1))) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + lsb = hFreq->freqBandTable[0][0]; + usb = hFreq->freqBandTable[0][nBandsLo]; + + /* Check for start frequency border k_x: + - ISO/IEC 14496-3 4.6.18.3.6 Requirements + - ISO/IEC 23003-3 7.5.5.2 Modifications and additions to the MPEG-4 SBR + tool + */ + /* Note that lsb > as hHeaderData->numberOfAnalysisBands is a valid SBR config + * for 24 band QMF analysis. */ + if ((lsb > ((flags & SBRDEC_QUAD_RATE) ? 16 : (32))) || (lsb >= usb)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Calculate number of noise bands */ + + k2 = hFreq->freqBandTable[1][nBandsHi]; + kx = hFreq->freqBandTable[1][0]; + + if (hHeaderData->bs_data.noise_bands == 0) { + hFreq->nNfb = 1; + } else /* Calculate no of noise bands 1,2 or 3 bands/octave */ + { + /* Fetch number of octaves divided by 32 */ + intTemp = (LONG)FDK_getNumOctavesDiv8(kx, k2) >> 2; + + /* Integer-Multiplication with number of bands: */ + intTemp = intTemp * hHeaderData->bs_data.noise_bands; + + /* Add scaled 0.5 for rounding: */ + intTemp = intTemp + (LONG)FL2FXCONST_SGL(0.5f / 32.0f); + + /* Convert to right-aligned integer: */ + intTemp = intTemp >> (FRACT_BITS - 1 /*sign*/ - 5 /* rescale */); + + if (intTemp == 0) intTemp = 1; + + hFreq->nNfb = intTemp; + } + + hFreq->nInvfBands = hFreq->nNfb; + + if (hFreq->nNfb > MAX_NOISE_COEFFS) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + /* Get noise bands */ + sbrdecDownSampleLoRes(hFreq->freqBandTableNoise, hFreq->nNfb, + hFreq->freqBandTable[0], nBandsLo); + + /* save old highband; required for overlap in usac + when headerchange occurs at XVAR and VARX frame; */ + hFreq->ov_highSubband = hFreq->highSubband; + + hFreq->lowSubband = lsb; + hFreq->highSubband = usb; + + return SBRDEC_OK; +} diff --git a/fdk-aac/libSBRdec/src/sbrdec_freq_sca.h b/fdk-aac/libSBRdec/src/sbrdec_freq_sca.h new file mode 100644 index 0000000..7e6b8e8 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbrdec_freq_sca.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Frequency scale prototypes +*/ +#ifndef SBRDEC_FREQ_SCA_H +#define SBRDEC_FREQ_SCA_H + +#include "sbrdecoder.h" +#include "env_extr.h" + +typedef enum { DUAL, QUAD } SBR_RATE; + +SBR_ERROR +sbrdecUpdateFreqScale(UCHAR *v_k_master, UCHAR *numMaster, UINT fs, + HANDLE_SBR_HEADER_DATA headerData, UINT flags); + +void sbrdecDownSampleLoRes(UCHAR *v_result, UCHAR num_result, + UCHAR *freqBandTableRef, UCHAR num_Ref); + +void shellsort(UCHAR *in, UCHAR n); + +SBR_ERROR +resetFreqBandTables(HANDLE_SBR_HEADER_DATA hHeaderData, const UINT flags); + +#endif diff --git a/fdk-aac/libSBRdec/src/sbrdecoder.cpp b/fdk-aac/libSBRdec/src/sbrdecoder.cpp new file mode 100644 index 0000000..4bc6f69 --- /dev/null +++ b/fdk-aac/libSBRdec/src/sbrdecoder.cpp @@ -0,0 +1,2023 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR decoder frontend + This module provides a frontend to the SBR decoder. The function openSBR() is + called for initialization. The function sbrDecoder_Apply() is called for each + frame. sbr_Apply() will call the required functions to decode the raw SBR data + (provided by env_extr.cpp), to decode the envelope data and noise floor levels + [decodeSbrData()], and to finally apply SBR to the current frame [sbr_dec()]. + + \sa sbrDecoder_Apply(), \ref documentationOverview +*/ + +/*! + \page documentationOverview Overview of important information resources and + source code documentation + + As part of this documentation you can find more extensive descriptions about + key concepts and algorithms at the following locations: + +

Programming

+ + \li Buffer management: sbrDecoder_Apply() and sbr_dec() + \li Internal scale factors to maximize SNR on fixed point processors: + #QMF_SCALE_FACTOR \li Special mantissa-exponent format: Created in + requantizeEnvelopeData() and used in calculateSbrEnvelope() + +

Algorithmic details

+ \li About the SBR data format: \ref SBR_HEADER_ELEMENT and \ref + SBR_STANDARD_ELEMENT \li Details about the bitstream decoder: env_extr.cpp \li + Details about the QMF filterbank and the provided polyphase implementation: + qmf_dec.cpp \li Details about the transposer: lpp_tran.cpp \li Details about + the envelope adjuster: env_calc.cpp + +*/ + +#include "sbrdecoder.h" + +#include "FDK_bitstream.h" + +#include "sbrdec_freq_sca.h" +#include "env_extr.h" +#include "sbr_dec.h" +#include "env_dec.h" +#include "sbr_crc.h" +#include "sbr_ram.h" +#include "sbr_rom.h" +#include "lpp_tran.h" +#include "transcendent.h" + +#include "FDK_crc.h" + +#include "sbrdec_drc.h" + +#include "psbitdec.h" + +/* Decoder library info */ +#define SBRDECODER_LIB_VL0 3 +#define SBRDECODER_LIB_VL1 0 +#define SBRDECODER_LIB_VL2 0 +#define SBRDECODER_LIB_TITLE "SBR Decoder" +#ifdef __ANDROID__ +#define SBRDECODER_LIB_BUILD_DATE "" +#define SBRDECODER_LIB_BUILD_TIME "" +#else +#define SBRDECODER_LIB_BUILD_DATE __DATE__ +#define SBRDECODER_LIB_BUILD_TIME __TIME__ +#endif + +static void setFrameErrorFlag(SBR_DECODER_ELEMENT *pSbrElement, UCHAR value) { + if (pSbrElement != NULL) { + switch (value) { + case FRAME_ERROR_ALLSLOTS: + FDKmemset(pSbrElement->frameErrorFlag, FRAME_ERROR, + sizeof(pSbrElement->frameErrorFlag)); + break; + default: + pSbrElement->frameErrorFlag[pSbrElement->useFrameSlot] = value; + } + } +} + +static UCHAR getHeaderSlot(UCHAR currentSlot, UCHAR hdrSlotUsage[(1) + 1]) { + UINT occupied = 0; + int s; + UCHAR slot = hdrSlotUsage[currentSlot]; + + FDK_ASSERT((1) + 1 < 32); + + for (s = 0; s < (1) + 1; s++) { + if ((hdrSlotUsage[s] == slot) && (s != slot)) { + occupied = 1; + break; + } + } + + if (occupied) { + occupied = 0; + + for (s = 0; s < (1) + 1; s++) { + occupied |= 1 << hdrSlotUsage[s]; + } + for (s = 0; s < (1) + 1; s++) { + if (!(occupied & 0x1)) { + slot = s; + break; + } + occupied >>= 1; + } + } + + return slot; +} + +static void copySbrHeader(HANDLE_SBR_HEADER_DATA hDst, + const HANDLE_SBR_HEADER_DATA hSrc) { + /* copy the whole header memory (including pointers) */ + FDKmemcpy(hDst, hSrc, sizeof(SBR_HEADER_DATA)); + + /* update pointers */ + hDst->freqBandData.freqBandTable[0] = hDst->freqBandData.freqBandTableLo; + hDst->freqBandData.freqBandTable[1] = hDst->freqBandData.freqBandTableHi; +} + +static int compareSbrHeader(const HANDLE_SBR_HEADER_DATA hHdr1, + const HANDLE_SBR_HEADER_DATA hHdr2) { + int result = 0; + + /* compare basic data */ + result |= (hHdr1->syncState != hHdr2->syncState) ? 1 : 0; + result |= (hHdr1->status != hHdr2->status) ? 1 : 0; + result |= (hHdr1->frameErrorFlag != hHdr2->frameErrorFlag) ? 1 : 0; + result |= (hHdr1->numberTimeSlots != hHdr2->numberTimeSlots) ? 1 : 0; + result |= + (hHdr1->numberOfAnalysisBands != hHdr2->numberOfAnalysisBands) ? 1 : 0; + result |= (hHdr1->timeStep != hHdr2->timeStep) ? 1 : 0; + result |= (hHdr1->sbrProcSmplRate != hHdr2->sbrProcSmplRate) ? 1 : 0; + + /* compare bitstream data */ + result |= + FDKmemcmp(&hHdr1->bs_data, &hHdr2->bs_data, sizeof(SBR_HEADER_DATA_BS)); + result |= + FDKmemcmp(&hHdr1->bs_dflt, &hHdr2->bs_dflt, sizeof(SBR_HEADER_DATA_BS)); + result |= FDKmemcmp(&hHdr1->bs_info, &hHdr2->bs_info, + sizeof(SBR_HEADER_DATA_BS_INFO)); + + /* compare frequency band data */ + result |= FDKmemcmp(&hHdr1->freqBandData, &hHdr2->freqBandData, + (8 + MAX_NUM_LIMITERS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableLo, + hHdr2->freqBandData.freqBandTableLo, + (MAX_FREQ_COEFFS / 2 + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableHi, + hHdr2->freqBandData.freqBandTableHi, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); + result |= FDKmemcmp(hHdr1->freqBandData.freqBandTableNoise, + hHdr2->freqBandData.freqBandTableNoise, + (MAX_NOISE_COEFFS + 1) * sizeof(UCHAR)); + result |= + FDKmemcmp(hHdr1->freqBandData.v_k_master, hHdr2->freqBandData.v_k_master, + (MAX_FREQ_COEFFS + 1) * sizeof(UCHAR)); + + return result; +} + +/*! + \brief Reset SBR decoder. + + Reset should only be called if SBR has been sucessfully detected by + an appropriate checkForPayload() function. + + \return Error code. +*/ +static SBR_ERROR sbrDecoder_ResetElement(HANDLE_SBRDECODER self, + int sampleRateIn, int sampleRateOut, + int samplesPerFrame, + const MP4_ELEMENT_ID elementID, + const int elementIndex, + const int overlap) { + SBR_ERROR sbrError = SBRDEC_OK; + HANDLE_SBR_HEADER_DATA hSbrHeader; + UINT qmfFlags = 0; + + int i, synDownsampleFac; + + /* USAC: assuming theoretical case 8 kHz output sample rate with 4:1 SBR */ + const int sbr_min_sample_rate_in = IS_USAC(self->coreCodec) ? 2000 : 6400; + + /* Check in/out samplerates */ + if (sampleRateIn < sbr_min_sample_rate_in || sampleRateIn > (96000)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (sampleRateOut > (96000)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + /* Set QMF mode flags */ + if (self->flags & SBRDEC_LOW_POWER) qmfFlags |= QMF_FLAG_LP; + + if (self->coreCodec == AOT_ER_AAC_ELD) { + if (self->flags & SBRDEC_LD_MPS_QMF) { + qmfFlags |= QMF_FLAG_MPSLDFB; + } else { + qmfFlags |= QMF_FLAG_CLDFB; + } + } + + /* Set downsampling factor for synthesis filter bank */ + if (sampleRateOut == 0) { + /* no single rate mode */ + sampleRateOut = + sampleRateIn + << 1; /* In case of implicit signalling, assume dual rate SBR */ + } + + if (sampleRateIn == sampleRateOut) { + synDownsampleFac = 2; + self->flags |= SBRDEC_DOWNSAMPLE; + } else { + synDownsampleFac = 1; + self->flags &= ~SBRDEC_DOWNSAMPLE; + } + + self->synDownsampleFac = synDownsampleFac; + self->sampleRateOut = sampleRateOut; + + { + for (i = 0; i < (1) + 1; i++) { + int setDflt; + hSbrHeader = &(self->sbrHeader[elementIndex][i]); + setDflt = ((hSbrHeader->syncState == SBR_NOT_INITIALIZED) || + (self->flags & SBRDEC_FORCE_RESET)) + ? 1 + : 0; + + /* init a default header such that we can at least do upsampling later */ + sbrError = initHeaderData(hSbrHeader, sampleRateIn, sampleRateOut, + self->downscaleFactor, samplesPerFrame, + self->flags, setDflt); + + /* Set synchState to UPSAMPLING in case it already is initialized */ + hSbrHeader->syncState = hSbrHeader->syncState > UPSAMPLING + ? UPSAMPLING + : hSbrHeader->syncState; + } + } + + if (sbrError != SBRDEC_OK) { + goto bail; + } + + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.flags_requested |= qmfFlags; + self->pQmfDomain->globalConf.nBandsAnalysis_requested = + self->sbrHeader[elementIndex][0].numberOfAnalysisBands; + self->pQmfDomain->globalConf.nBandsSynthesis_requested = + (synDownsampleFac == 1) ? 64 : 32; /* may be overwritten by MPS */ + self->pQmfDomain->globalConf.nBandsSynthesis_requested /= + self->downscaleFactor; + self->pQmfDomain->globalConf.nQmfTimeSlots_requested = + self->sbrHeader[elementIndex][0].numberTimeSlots * + self->sbrHeader[elementIndex][0].timeStep; + self->pQmfDomain->globalConf.nQmfOvTimeSlots_requested = overlap; + self->pQmfDomain->globalConf.nQmfProcBands_requested = 64; /* always 64 */ + self->pQmfDomain->globalConf.nQmfProcChannels_requested = + 1; /* may be overwritten by MPS */ + } + + /* Init SBR channels going to be assigned to a SBR element */ + { + int ch; + for (ch = 0; ch < self->pSbrElement[elementIndex]->nChannels; ch++) { + int headerIndex = + getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + /* and create sbrDec */ + sbrError = + createSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch], + &self->sbrHeader[elementIndex][headerIndex], + &self->pSbrElement[elementIndex]->transposerSettings, + synDownsampleFac, qmfFlags, self->flags, overlap, ch, + self->codecFrameSize); + + if (sbrError != SBRDEC_OK) { + goto bail; + } + } + } + + // FDKmemclear(sbr_OverlapBuffer, sizeof(sbr_OverlapBuffer)); + + if (self->numSbrElements == 1) { + switch (self->coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + if (CreatePsDec(&self->hParametricStereoDec, samplesPerFrame)) { + sbrError = SBRDEC_CREATE_ERROR; + goto bail; + } + break; + default: + break; + } + } + + /* Init frame delay slot handling */ + self->pSbrElement[elementIndex]->useFrameSlot = 0; + for (i = 0; i < ((1) + 1); i++) { + self->pSbrElement[elementIndex]->useHeaderSlot[i] = i; + } + +bail: + + return sbrError; +} + +/*! + \brief Assign QMF domain provided QMF channels to SBR channels. + + \return void +*/ +static void sbrDecoder_AssignQmfChannels2SbrChannels(HANDLE_SBRDECODER self) { + int ch, el, absCh_offset = 0; + for (el = 0; el < self->numSbrElements; el++) { + if (self->pSbrElement[el] != NULL) { + for (ch = 0; ch < self->pSbrElement[el]->nChannels; ch++) { + FDK_ASSERT(((absCh_offset + ch) < ((8) + (1))) && + ((absCh_offset + ch) < ((8) + (1)))); + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainInCh = + &self->pQmfDomain->QmfDomainIn[absCh_offset + ch]; + self->pSbrElement[el]->pSbrChannel[ch]->SbrDec.qmfDomainOutCh = + &self->pQmfDomain->QmfDomainOut[absCh_offset + ch]; + } + absCh_offset += self->pSbrElement[el]->nChannels; + } + } +} + +SBR_ERROR sbrDecoder_Open(HANDLE_SBRDECODER *pSelf, + HANDLE_FDK_QMF_DOMAIN pQmfDomain) { + HANDLE_SBRDECODER self = NULL; + SBR_ERROR sbrError = SBRDEC_OK; + int elIdx; + + if ((pSelf == NULL) || (pQmfDomain == NULL)) { + return SBRDEC_INVALID_ARGUMENT; + } + + /* Get memory for this instance */ + self = GetRam_SbrDecoder(); + if (self == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + + self->pQmfDomain = pQmfDomain; + + /* + Already zero because of calloc + self->numSbrElements = 0; + self->numSbrChannels = 0; + self->codecFrameSize = 0; + */ + + self->numDelayFrames = (1); /* set to the max value by default */ + + /* Initialize header sync state */ + for (elIdx = 0; elIdx < (8); elIdx += 1) { + int i; + for (i = 0; i < (1) + 1; i += 1) { + self->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } + + *pSelf = self; + +bail: + return sbrError; +} + +/** + * \brief determine if the given core codec AOT can be processed or not. + * \param coreCodec core codec audio object type. + * \return 1 if SBR can be processed, 0 if SBR cannot be processed/applied. + */ +static int sbrDecoder_isCoreCodecValid(AUDIO_OBJECT_TYPE coreCodec) { + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_ER_AAC_ELD: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + case AOT_USAC: + return 1; + default: + return 0; + } +} + +static void sbrDecoder_DestroyElement(HANDLE_SBRDECODER self, + const int elementIndex) { + if (self->pSbrElement[elementIndex] != NULL) { + int ch; + + for (ch = 0; ch < SBRDEC_MAX_CH_PER_ELEMENT; ch++) { + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] != NULL) { + deleteSbrDec(self->pSbrElement[elementIndex]->pSbrChannel[ch]); + FreeRam_SbrDecChannel( + &self->pSbrElement[elementIndex]->pSbrChannel[ch]); + self->numSbrChannels -= 1; + } + } + FreeRam_SbrDecElement(&self->pSbrElement[elementIndex]); + self->numSbrElements -= 1; + } +} + +SBR_ERROR sbrDecoder_InitElement( + HANDLE_SBRDECODER self, const int sampleRateIn, const int sampleRateOut, + const int samplesPerFrame, const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const int elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, const INT downscaleFactor) { + SBR_ERROR sbrError = SBRDEC_OK; + int chCnt = 0; + int nSbrElementsStart; + int nSbrChannelsStart; + if (self == NULL) { + return SBRDEC_INVALID_ARGUMENT; + } + + nSbrElementsStart = self->numSbrElements; + nSbrChannelsStart = self->numSbrChannels; + + /* Check core codec AOT */ + if (!sbrDecoder_isCoreCodecValid(coreCodec) || elementIndex >= (8)) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (elementID != ID_SCE && elementID != ID_CPE && elementID != ID_LFE) { + sbrError = SBRDEC_UNSUPPORTED_CONFIG; + goto bail; + } + + if (self->sampleRateIn == sampleRateIn && + self->codecFrameSize == samplesPerFrame && self->coreCodec == coreCodec && + self->pSbrElement[elementIndex] != NULL && + self->pSbrElement[elementIndex]->elementID == elementID && + !(self->flags & SBRDEC_FORCE_RESET) && + ((sampleRateOut == 0) ? 1 : (self->sampleRateOut == sampleRateOut)) && + ((harmonicSBR == 2) ? 1 + : (self->harmonicSBR == + harmonicSBR)) /* The value 2 signalizes that + harmonicSBR shall be ignored in + the config change detection */ + ) { + /* Nothing to do */ + return SBRDEC_OK; + } else { + if (configMode & AC_CM_DET_CFG_CHANGE) { + *configChanged = 1; + } + } + + /* reaching this point the SBR-decoder gets (re-)configured */ + + /* The flags field is used for all elements! */ + self->flags &= + (SBRDEC_FORCE_RESET | SBRDEC_FLUSH); /* Keep the global flags. They will + be reset after decoding. */ + self->flags |= (downscaleFactor > 1) ? SBRDEC_ELD_DOWNSCALE : 0; + self->flags |= (coreCodec == AOT_ER_AAC_ELD) ? SBRDEC_ELD_GRID : 0; + self->flags |= (coreCodec == AOT_ER_AAC_SCAL) ? SBRDEC_SYNTAX_SCAL : 0; + self->flags |= + (coreCodec == AOT_DRM_AAC) ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM : 0; + self->flags |= (coreCodec == AOT_DRM_SURROUND) + ? SBRDEC_SYNTAX_SCAL | SBRDEC_SYNTAX_DRM + : 0; + self->flags |= (coreCodec == AOT_USAC) ? SBRDEC_SYNTAX_USAC : 0; + /* Robustness: Take integer division rounding into consideration. E.g. 22050 + * Hz with 4:1 SBR => 5512 Hz core sampling rate. */ + self->flags |= (sampleRateIn == sampleRateOut / 4) ? SBRDEC_QUAD_RATE : 0; + self->flags |= (harmonicSBR == 1) ? SBRDEC_USAC_HARMONICSBR : 0; + + if (configMode & AC_CM_DET_CFG_CHANGE) { + return SBRDEC_OK; + } + + self->sampleRateIn = sampleRateIn; + self->codecFrameSize = samplesPerFrame; + self->coreCodec = coreCodec; + self->harmonicSBR = harmonicSBR; + self->downscaleFactor = downscaleFactor; + + /* Init SBR elements */ + { + int elChannels, ch; + + if (self->pSbrElement[elementIndex] == NULL) { + self->pSbrElement[elementIndex] = GetRam_SbrDecElement(elementIndex); + if (self->pSbrElement[elementIndex] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + self->numSbrElements++; + } else { + self->numSbrChannels -= self->pSbrElement[elementIndex]->nChannels; + } + + /* Save element ID for sanity checks and to have a fallback for concealment. + */ + self->pSbrElement[elementIndex]->elementID = elementID; + + /* Determine amount of channels for this element */ + switch (elementID) { + case ID_NONE: + case ID_CPE: + elChannels = 2; + break; + case ID_LFE: + case ID_SCE: + elChannels = 1; + break; + default: + elChannels = 0; + break; + } + + /* Handle case of Parametric Stereo */ + if (elementIndex == 0 && elementID == ID_SCE) { + switch (coreCodec) { + case AOT_AAC_LC: + case AOT_SBR: + case AOT_PS: + case AOT_ER_AAC_SCAL: + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + elChannels = 2; + break; + default: + break; + } + } + + /* Sanity check to avoid memory leaks */ + if (elChannels < self->pSbrElement[elementIndex]->nChannels) { + self->numSbrChannels += self->pSbrElement[elementIndex]->nChannels; + sbrError = SBRDEC_PARSE_ERROR; + goto bail; + } + + self->pSbrElement[elementIndex]->nChannels = elChannels; + + for (ch = 0; ch < elChannels; ch++) { + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + self->pSbrElement[elementIndex]->pSbrChannel[ch] = + GetRam_SbrDecChannel(chCnt); + if (self->pSbrElement[elementIndex]->pSbrChannel[ch] == NULL) { + sbrError = SBRDEC_MEM_ALLOC_FAILED; + goto bail; + } + } + self->numSbrChannels++; + + sbrDecoder_drcInitChannel(&self->pSbrElement[elementIndex] + ->pSbrChannel[ch] + ->SbrDec.sbrDrcChannel); + + chCnt++; + } + } + + if (!self->pQmfDomain->globalConf.qmfDomainExplicitConfig) { + self->pQmfDomain->globalConf.nInputChannels_requested = + self->numSbrChannels; + self->pQmfDomain->globalConf.nOutputChannels_requested = + fMax((INT)self->numSbrChannels, + (INT)self->pQmfDomain->globalConf.nOutputChannels_requested); + } + + /* Make sure each SBR channel has one QMF channel assigned even if + * numSbrChannels or element set-up has changed. */ + sbrDecoder_AssignQmfChannels2SbrChannels(self); + + /* clear error flags for all delay slots */ + FDKmemclear(self->pSbrElement[elementIndex]->frameErrorFlag, + ((1) + 1) * sizeof(UCHAR)); + + { + int overlap; + + if (coreCodec == AOT_ER_AAC_ELD) { + overlap = 0; + } else if (self->flags & SBRDEC_QUAD_RATE) { + overlap = (3 * 4); + } else { + overlap = (3 * 2); + } + /* Initialize this instance */ + sbrError = sbrDecoder_ResetElement(self, sampleRateIn, sampleRateOut, + samplesPerFrame, elementID, elementIndex, + overlap); + } + +bail: + if (sbrError != SBRDEC_OK) { + if ((nSbrElementsStart < self->numSbrElements) || + (nSbrChannelsStart < self->numSbrChannels)) { + /* Free the memory allocated for this element */ + sbrDecoder_DestroyElement(self, elementIndex); + } else if ((elementIndex < (8)) && + (self->pSbrElement[elementIndex] != + NULL)) { /* Set error flag to trigger concealment */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + } + } + + return sbrError; +} + +/** + * \brief Free config dependent SBR memory. + * \param self SBR decoder instance handle + */ +SBR_ERROR sbrDecoder_FreeMem(HANDLE_SBRDECODER *self) { + int i; + int elIdx; + + if (self != NULL && *self != NULL) { + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement(*self, i); + } + + for (elIdx = 0; elIdx < (8); elIdx += 1) { + for (i = 0; i < (1) + 1; i += 1) { + (*self)->sbrHeader[elIdx][i].syncState = SBR_NOT_INITIALIZED; + } + } + } + + return SBRDEC_OK; +} + +/** + * \brief Apply decoded SBR header for one element. + * \param self SBR decoder instance handle + * \param hSbrHeader SBR header handle to be processed. + * \param hSbrChannel pointer array to the SBR element channels corresponding to + * the SBR header. + * \param headerStatus header status value returned from SBR header parser. + * \param numElementChannels amount of channels for the SBR element whos header + * is to be processed. + */ +static SBR_ERROR sbrDecoder_HeaderUpdate(HANDLE_SBRDECODER self, + HANDLE_SBR_HEADER_DATA hSbrHeader, + SBR_HEADER_STATUS headerStatus, + HANDLE_SBR_CHANNEL hSbrChannel[], + const int numElementChannels) { + SBR_ERROR errorStatus = SBRDEC_OK; + + /* + change of control data, reset decoder + */ + errorStatus = resetFreqBandTables(hSbrHeader, self->flags); + + if (errorStatus == SBRDEC_OK) { + if (hSbrHeader->syncState == UPSAMPLING && headerStatus != HEADER_RESET) { +#if (SBRDEC_MAX_HB_FADE_FRAMES > 0) + int ch; + for (ch = 0; ch < numElementChannels; ch += 1) { + hSbrChannel[ch]->SbrDec.highBandFadeCnt = SBRDEC_MAX_HB_FADE_FRAMES; + } + +#endif + /* As the default header would limit the frequency range, + lowSubband and highSubband must be patched. */ + hSbrHeader->freqBandData.lowSubband = hSbrHeader->numberOfAnalysisBands; + hSbrHeader->freqBandData.highSubband = hSbrHeader->numberOfAnalysisBands; + } + + /* Trigger a reset before processing this slot */ + hSbrHeader->status |= SBRDEC_HDR_STAT_RESET; + } + + return errorStatus; +} + +INT sbrDecoder_Header(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + const INT sampleRateIn, const INT sampleRateOut, + const INT samplesPerFrame, + const AUDIO_OBJECT_TYPE coreCodec, + const MP4_ELEMENT_ID elementID, const INT elementIndex, + const UCHAR harmonicSBR, const UCHAR stereoConfigIndex, + const UCHAR configMode, UCHAR *configChanged, + const INT downscaleFactor) { + SBR_HEADER_STATUS headerStatus; + HANDLE_SBR_HEADER_DATA hSbrHeader; + SBR_ERROR sbrError = SBRDEC_OK; + int headerIndex; + UINT flagsSaved = + 0; /* flags should not be changed in AC_CM_DET_CFG_CHANGE - mode after + parsing */ + + if (self == NULL || elementIndex >= (8)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (!sbrDecoder_isCoreCodecValid(coreCodec)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + flagsSaved = self->flags; /* store */ + } + + sbrError = sbrDecoder_InitElement( + self, sampleRateIn, sampleRateOut, samplesPerFrame, coreCodec, elementID, + elementIndex, harmonicSBR, stereoConfigIndex, configMode, configChanged, + downscaleFactor); + + if ((sbrError != SBRDEC_OK) || (elementID == ID_LFE)) { + goto bail; + } + + if (configMode & AC_CM_DET_CFG_CHANGE) { + hSbrHeader = NULL; + } else { + headerIndex = getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + } + + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 0, configMode); + + if (coreCodec == AOT_USAC) { + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } + return sbrError; + } + + if (configMode & AC_CM_ALLOC_MEM) { + SBR_DECODER_ELEMENT *pSbrElement; + + pSbrElement = self->pSbrElement[elementIndex]; + + /* Sanity check */ + if (pSbrElement != NULL) { + if ((elementID == ID_CPE && pSbrElement->nChannels != 2) || + (elementID != ID_CPE && pSbrElement->nChannels != 1)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + if (headerStatus == HEADER_RESET) { + sbrError = sbrDecoder_HeaderUpdate(self, hSbrHeader, headerStatus, + pSbrElement->pSbrChannel, + pSbrElement->nChannels); + + if (sbrError == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } + /* else { + Since we already have overwritten the old SBR header the only way out + is UPSAMPLING! This will be prepared in the next step. + } */ + } + } + } +bail: + if (configMode & AC_CM_DET_CFG_CHANGE) { + self->flags = flagsSaved; /* restore */ + } + return sbrError; +} + +SBR_ERROR sbrDecoder_SetParam(HANDLE_SBRDECODER self, const SBRDEC_PARAM param, + const INT value) { + SBR_ERROR errorStatus = SBRDEC_OK; + + /* configure the subsystems */ + switch (param) { + case SBR_SYSTEM_BITSTREAM_DELAY: + if (value < 0 || value > (1)) { + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->numDelayFrames = (UCHAR)value; + } + break; + case SBR_QMF_MODE: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LOW_POWER; + } else { + self->flags &= ~SBRDEC_LOW_POWER; + } + } + break; + case SBR_LD_QMF_TIME_ALIGN: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_LD_MPS_QMF; + } else { + self->flags &= ~SBRDEC_LD_MPS_QMF; + } + } + break; + case SBR_FLUSH_DATA: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FLUSH; + } + } + break; + case SBR_CLEAR_HISTORY: + if (value != 0) { + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + self->flags |= SBRDEC_FORCE_RESET; + } + } + break; + case SBR_BS_INTERRUPTION: { + int elementIndex; + + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + break; + } + + /* Loop over SBR elements */ + for (elementIndex = 0; elementIndex < self->numSbrElements; + elementIndex++) { + if (self->pSbrElement[elementIndex] != NULL) { + HANDLE_SBR_HEADER_DATA hSbrHeader; + int headerIndex = + getHeaderSlot(self->pSbrElement[elementIndex]->useFrameSlot, + self->pSbrElement[elementIndex]->useHeaderSlot); + + hSbrHeader = &(self->sbrHeader[elementIndex][headerIndex]); + + /* Set sync state UPSAMPLING for the corresponding slot. + This switches off bitstream parsing until a new header arrives. */ + hSbrHeader->syncState = UPSAMPLING; + hSbrHeader->status |= SBRDEC_HDR_STAT_UPDATE; + } + } + } break; + + case SBR_SKIP_QMF: + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + } else { + if (value == 1) { + self->flags |= SBRDEC_SKIP_QMF_ANA; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_ANA; + } + if (value == 2) { + self->flags |= SBRDEC_SKIP_QMF_SYN; + } else { + self->flags &= ~SBRDEC_SKIP_QMF_SYN; + } + } + break; + default: + errorStatus = SBRDEC_SET_PARAM_FAIL; + break; + } /* switch(param) */ + + return (errorStatus); +} + +static SBRDEC_DRC_CHANNEL *sbrDecoder_drcGetChannel( + const HANDLE_SBRDECODER self, const INT channel) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int elementIndex, elChanIdx = 0, numCh = 0; + + for (elementIndex = 0; (elementIndex < (8)) && (numCh <= channel); + elementIndex++) { + SBR_DECODER_ELEMENT *pSbrElement = self->pSbrElement[elementIndex]; + int c, elChannels; + + elChanIdx = 0; + if (pSbrElement == NULL) break; + + /* Determine amount of channels for this element */ + switch (pSbrElement->elementID) { + case ID_CPE: + elChannels = 2; + break; + case ID_LFE: + case ID_SCE: + elChannels = 1; + break; + case ID_NONE: + default: + elChannels = 0; + break; + } + + /* Limit with actual allocated element channels */ + elChannels = fMin(elChannels, pSbrElement->nChannels); + + for (c = 0; (c < elChannels) && (numCh <= channel); c++) { + if (pSbrElement->pSbrChannel[elChanIdx] != NULL) { + numCh++; + elChanIdx++; + } + } + } + elementIndex -= 1; + elChanIdx -= 1; + + if (elChanIdx < 0 || elementIndex < 0) { + return NULL; + } + + if (self->pSbrElement[elementIndex] != NULL) { + if (self->pSbrElement[elementIndex]->pSbrChannel[elChanIdx] != NULL) { + pSbrDrcChannelData = &self->pSbrElement[elementIndex] + ->pSbrChannel[elChanIdx] + ->SbrDec.sbrDrcChannel; + } + } + + return (pSbrDrcChannelData); +} + +SBR_ERROR sbrDecoder_drcFeedChannel(HANDLE_SBRDECODER self, INT ch, + UINT numBands, FIXP_DBL *pNextFact_mag, + INT nextFact_exp, + SHORT drcInterpolationScheme, + UCHAR winSequence, USHORT *pBandTop) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + int band, isValidData = 0; + + if (self == NULL) { + return SBRDEC_NOT_INITIALIZED; + } + if (ch > (8) || pNextFact_mag == NULL) { + return SBRDEC_SET_PARAM_FAIL; + } + + /* Search for gain values different to 1.0f */ + for (band = 0; band < (int)numBands; band += 1) { + if (!((pNextFact_mag[band] == FL2FXCONST_DBL(0.5)) && + (nextFact_exp == 1)) && + !((pNextFact_mag[band] == (FIXP_DBL)MAXVAL_DBL) && + (nextFact_exp == 0))) { + isValidData = 1; + break; + } + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); + + if (pSbrDrcChannelData != NULL) { + if (pSbrDrcChannelData->enable || + isValidData) { /* Activate processing only with real and valid data */ + int i; + + pSbrDrcChannelData->enable = 1; + pSbrDrcChannelData->numBandsNext = numBands; + + pSbrDrcChannelData->winSequenceNext = winSequence; + pSbrDrcChannelData->drcInterpolationSchemeNext = drcInterpolationScheme; + pSbrDrcChannelData->nextFact_exp = nextFact_exp; + + for (i = 0; i < (int)numBands; i++) { + pSbrDrcChannelData->bandTopNext[i] = pBandTop[i]; + pSbrDrcChannelData->nextFact_mag[i] = pNextFact_mag[i]; + } + } + } + + return SBRDEC_OK; +} + +void sbrDecoder_drcDisable(HANDLE_SBRDECODER self, INT ch) { + SBRDEC_DRC_CHANNEL *pSbrDrcChannelData = NULL; + + if ((self == NULL) || (ch > (8)) || (self->numSbrElements == 0) || + (self->numSbrChannels == 0)) { + return; + } + + /* Find the right SBR channel */ + pSbrDrcChannelData = sbrDecoder_drcGetChannel(self, ch); + + if (pSbrDrcChannelData != NULL) { + sbrDecoder_drcInitChannel(pSbrDrcChannelData); + } +} + +SBR_ERROR sbrDecoder_Parse(HANDLE_SBRDECODER self, HANDLE_FDK_BITSTREAM hBs, + UCHAR *pDrmBsBuffer, USHORT drmBsBufferSize, + int *count, int bsPayLen, int crcFlag, + MP4_ELEMENT_ID prevElement, int elementIndex, + UINT acFlags, UINT acElFlags[]) { + SBR_DECODER_ELEMENT *hSbrElement = NULL; + HANDLE_SBR_HEADER_DATA hSbrHeader = NULL; + HANDLE_SBR_CHANNEL *pSbrChannel; + + SBR_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; + SBR_FRAME_DATA frameDataLeftCopy; + SBR_FRAME_DATA frameDataRightCopy; + + SBR_ERROR errorStatus = SBRDEC_OK; + SBR_HEADER_STATUS headerStatus = HEADER_NOT_PRESENT; + + INT startPos = FDKgetValidBits(hBs); + INT CRCLen = 0; + HANDLE_FDK_BITSTREAM hBsOriginal = hBs; + FDK_BITSTREAM bsBwd; + + FDK_CRCINFO crcInfo; + INT crcReg = 0; + USHORT drmSbrCrc = 0; + const int fGlobalIndependencyFlag = acFlags & AC_INDEP; + const int bs_pvc = acElFlags[elementIndex] & AC_EL_USAC_PVC; + const int bs_interTes = acElFlags[elementIndex] & AC_EL_USAC_ITES; + int stereo; + int fDoDecodeSbrData = 1; + + int lastSlot, lastHdrSlot = 0, thisHdrSlot = 0; + + if (*count <= 0) { + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + return SBRDEC_OK; + } + + /* SBR sanity checks */ + if (self == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } + + /* Reverse bits of DRM SBR payload */ + if ((self->flags & SBRDEC_SYNTAX_DRM) && *count > 0) { + int dataBytes, dataBits; + + FDK_ASSERT(drmBsBufferSize >= (512)); + dataBits = *count; + + if (dataBits > ((512) * 8)) { + /* do not flip more data than needed */ + dataBits = (512) * 8; + } + + dataBytes = (dataBits + 7) >> 3; + + int j; + + if ((j = (int)FDKgetValidBits(hBs)) != 8) { + FDKpushBiDirectional(hBs, (j - 8)); + } + + j = 0; + for (; dataBytes > 0; dataBytes--) { + int i; + UCHAR tmpByte; + UCHAR buffer = 0x00; + + tmpByte = (UCHAR)FDKreadBits(hBs, 8); + for (i = 0; i < 4; i++) { + int shift = 2 * i + 1; + buffer |= (tmpByte & (0x08 >> i)) << shift; + buffer |= (tmpByte & (0x10 << i)) >> shift; + } + pDrmBsBuffer[j++] = buffer; + FDKpushBack(hBs, 16); + } + + FDKinitBitStream(&bsBwd, pDrmBsBuffer, (512), dataBits, BS_READER); + + /* Use reversed data */ + hBs = &bsBwd; + bsPayLen = *count; + } + + /* Remember start position of SBR element */ + startPos = FDKgetValidBits(hBs); + + /* SBR sanity checks */ + if (self->pSbrElement[elementIndex] == NULL) { + errorStatus = SBRDEC_NOT_INITIALIZED; + goto bail; + } + hSbrElement = self->pSbrElement[elementIndex]; + + lastSlot = (hSbrElement->useFrameSlot > 0) ? hSbrElement->useFrameSlot - 1 + : self->numDelayFrames; + lastHdrSlot = hSbrElement->useHeaderSlot[lastSlot]; + thisHdrSlot = getHeaderSlot( + hSbrElement->useFrameSlot, + hSbrElement->useHeaderSlot); /* Get a free header slot not used by + frames not processed yet. */ + + /* Assign the free slot to store a new header if there is one. */ + hSbrHeader = &self->sbrHeader[elementIndex][thisHdrSlot]; + + pSbrChannel = hSbrElement->pSbrChannel; + stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + + hFrameDataLeft = &self->pSbrElement[elementIndex] + ->pSbrChannel[0] + ->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = &self->pSbrElement[elementIndex] + ->pSbrChannel[1] + ->frameData[hSbrElement->useFrameSlot]; + } + + /* store frameData; new parsed frameData possibly corrupted */ + FDKmemcpy(&frameDataLeftCopy, hFrameDataLeft, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(&frameDataRightCopy, hFrameDataRight, sizeof(SBR_FRAME_DATA)); + } + + /* reset PS flag; will be set after PS was found */ + self->flags &= ~SBRDEC_PS_DECODED; + + if (hSbrHeader->status & SBRDEC_HDR_STAT_UPDATE) { + /* Got a new header from extern (e.g. from an ASC) */ + headerStatus = HEADER_OK; + hSbrHeader->status &= ~SBRDEC_HDR_STAT_UPDATE; + } else if (thisHdrSlot != lastHdrSlot) { + /* Copy the last header into this slot otherwise the + header compare will trigger more HEADER_RESETs than needed. */ + copySbrHeader(hSbrHeader, &self->sbrHeader[elementIndex][lastHdrSlot]); + } + + /* + Check if bit stream data is valid and matches the element context + */ + if (((prevElement != ID_SCE) && (prevElement != ID_CPE)) || + prevElement != hSbrElement->elementID) { + /* In case of LFE we also land here, since there is no LFE SBR element (do + * upsampling only) */ + fDoDecodeSbrData = 0; + } + + if (fDoDecodeSbrData) { + if ((INT)FDKgetValidBits(hBs) <= 0) { + fDoDecodeSbrData = 0; + } + } + + /* + SBR CRC-check + */ + if (fDoDecodeSbrData) { + if (crcFlag) { + switch (self->coreCodec) { + case AOT_ER_AAC_ELD: + FDKpushFor(hBs, 10); + /* check sbrcrc later: we don't know the payload length now */ + break; + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + drmSbrCrc = (USHORT)FDKreadBits(hBs, 8); + /* Setup CRC decoder */ + FDKcrcInit(&crcInfo, 0x001d, 0xFFFF, 8); + /* Start CRC region */ + crcReg = FDKcrcStartReg(&crcInfo, hBs, 0); + break; + default: + CRCLen = bsPayLen - 10; /* change: 0 => i */ + if (CRCLen < 0) { + fDoDecodeSbrData = 0; + } else { + fDoDecodeSbrData = SbrCrcCheck(hBs, CRCLen); + } + break; + } + } + } /* if (fDoDecodeSbrData) */ + + /* + Read in the header data and issue a reset if change occured + */ + if (fDoDecodeSbrData) { + int sbrHeaderPresent; + + if (self->flags & (SBRDEC_SYNTAX_RSVD50 | SBRDEC_SYNTAX_USAC)) { + SBR_HEADER_DATA_BS_INFO newSbrInfo; + int sbrInfoPresent; + + if (bs_interTes) { + self->flags |= SBRDEC_USAC_ITES; + } else { + self->flags &= ~SBRDEC_USAC_ITES; + } + + if (fGlobalIndependencyFlag) { + self->flags |= SBRDEC_USAC_INDEP; + sbrInfoPresent = 1; + sbrHeaderPresent = 1; + } else { + self->flags &= ~SBRDEC_USAC_INDEP; + sbrInfoPresent = FDKreadBit(hBs); + if (sbrInfoPresent) { + sbrHeaderPresent = FDKreadBit(hBs); + } else { + sbrHeaderPresent = 0; + } + } + + if (sbrInfoPresent) { + newSbrInfo.ampResolution = FDKreadBit(hBs); + newSbrInfo.xover_band = FDKreadBits(hBs, 4); + newSbrInfo.sbr_preprocessing = FDKreadBit(hBs); + if (bs_pvc) { + newSbrInfo.pvc_mode = FDKreadBits(hBs, 2); + /* bs_pvc_mode: 0 -> no PVC, 1 -> PVC mode 1, 2 -> PVC mode 2, 3 -> + * reserved */ + if (newSbrInfo.pvc_mode > 2) { + headerStatus = HEADER_ERROR; + } + if (stereo && newSbrInfo.pvc_mode > 0) { + /* bs_pvc is always transmitted but pvc_mode is set to zero in case + * of stereo SBR. The config might be wrong but we cannot tell for + * sure. */ + newSbrInfo.pvc_mode = 0; + } + } else { + newSbrInfo.pvc_mode = 0; + } + if (headerStatus != HEADER_ERROR) { + if (FDKmemcmp(&hSbrHeader->bs_info, &newSbrInfo, + sizeof(SBR_HEADER_DATA_BS_INFO))) { + /* in case of ampResolution and preprocessing change no full reset + * required */ + /* HEADER reset would trigger HBE transposer reset which breaks + * eSbr_3_Eaa.mp4 */ + if ((hSbrHeader->bs_info.pvc_mode != newSbrInfo.pvc_mode) || + (hSbrHeader->bs_info.xover_band != newSbrInfo.xover_band)) { + headerStatus = HEADER_RESET; + } else { + headerStatus = HEADER_OK; + } + + hSbrHeader->bs_info = newSbrInfo; + } else { + headerStatus = HEADER_OK; + } + } + } + if (headerStatus == HEADER_ERROR) { + /* Corrupt SBR info data, do not decode and switch to UPSAMPLING */ + hSbrHeader->syncState = UPSAMPLING; + fDoDecodeSbrData = 0; + sbrHeaderPresent = 0; + } + + if (sbrHeaderPresent && fDoDecodeSbrData) { + int useDfltHeader; + + useDfltHeader = FDKreadBit(hBs); + + if (useDfltHeader) { + sbrHeaderPresent = 0; + if (FDKmemcmp(&hSbrHeader->bs_data, &hSbrHeader->bs_dflt, + sizeof(SBR_HEADER_DATA_BS)) || + hSbrHeader->syncState != SBR_ACTIVE) { + hSbrHeader->bs_data = hSbrHeader->bs_dflt; + headerStatus = HEADER_RESET; + } + } + } + } else { + sbrHeaderPresent = FDKreadBit(hBs); + } + + if (sbrHeaderPresent) { + headerStatus = sbrGetHeaderData(hSbrHeader, hBs, self->flags, 1, 0); + } + + if (headerStatus == HEADER_RESET) { + errorStatus = sbrDecoder_HeaderUpdate( + self, hSbrHeader, headerStatus, pSbrChannel, hSbrElement->nChannels); + + if (errorStatus == SBRDEC_OK) { + hSbrHeader->syncState = SBR_HEADER; + } else { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + headerStatus = HEADER_ERROR; + } + } + + if (errorStatus != SBRDEC_OK) { + fDoDecodeSbrData = 0; + } + } /* if (fDoDecodeSbrData) */ + + /* + Print debugging output only if state has changed + */ + + /* read frame data */ + if ((hSbrHeader->syncState >= SBR_HEADER) && fDoDecodeSbrData) { + int sbrFrameOk; + /* read the SBR element data */ + if (!stereo && (self->hParametricStereoDec != NULL)) { + /* update slot index for PS bitstream parsing */ + self->hParametricStereoDec->bsLastSlot = + self->hParametricStereoDec->bsReadSlot; + self->hParametricStereoDec->bsReadSlot = hSbrElement->useFrameSlot; + } + sbrFrameOk = sbrGetChannelElement( + hSbrHeader, hFrameDataLeft, (stereo) ? hFrameDataRight : NULL, + &pSbrChannel[0]->prevFrameData, + pSbrChannel[0]->SbrDec.PvcStaticData.pvc_mode_last, hBs, + (stereo) ? NULL : self->hParametricStereoDec, self->flags, + self->pSbrElement[elementIndex]->transposerSettings.overlap); + + if (!sbrFrameOk) { + fDoDecodeSbrData = 0; + } else { + INT valBits; + + if (bsPayLen > 0) { + valBits = bsPayLen - ((INT)startPos - (INT)FDKgetValidBits(hBs)); + } else { + valBits = (INT)FDKgetValidBits(hBs); + } + + if (crcFlag) { + switch (self->coreCodec) { + case AOT_ER_AAC_ELD: { + /* late crc check for eld */ + INT payloadbits = + (INT)startPos - (INT)FDKgetValidBits(hBs) - startPos; + INT crcLen = payloadbits - 10; + FDKpushBack(hBs, payloadbits); + fDoDecodeSbrData = SbrCrcCheck(hBs, crcLen); + FDKpushFor(hBs, crcLen); + } break; + case AOT_DRM_AAC: + case AOT_DRM_SURROUND: + /* End CRC region */ + FDKcrcEndReg(&crcInfo, hBs, crcReg); + /* Check CRC */ + if ((FDKcrcGetCRC(&crcInfo) ^ 0xFF) != drmSbrCrc) { + fDoDecodeSbrData = 0; + if (headerStatus != HEADER_NOT_PRESENT) { + headerStatus = HEADER_ERROR; + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + } + } + break; + default: + break; + } + } + + /* sanity check of remaining bits */ + if (valBits < 0) { + fDoDecodeSbrData = 0; + } else { + switch (self->coreCodec) { + case AOT_SBR: + case AOT_PS: + case AOT_AAC_LC: { + /* This sanity check is only meaningful with General Audio + * bitstreams */ + int alignBits = valBits & 0x7; + + if (valBits > alignBits) { + fDoDecodeSbrData = 0; + } + } break; + default: + /* No sanity check available */ + break; + } + } + } + } else { + /* The returned bit count will not be the actual payload size since we did + not parse the frame data. Return an error so that the caller can react + respectively. */ + errorStatus = SBRDEC_PARSE_ERROR; + } + + if (!fDoDecodeSbrData) { + /* Set error flag for this slot to trigger concealment */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_ERROR); + /* restore old frameData for concealment */ + FDKmemcpy(hFrameDataLeft, &frameDataLeftCopy, sizeof(SBR_FRAME_DATA)); + if (stereo) { + FDKmemcpy(hFrameDataRight, &frameDataRightCopy, sizeof(SBR_FRAME_DATA)); + } + errorStatus = SBRDEC_PARSE_ERROR; + } else { + /* Everything seems to be ok so clear the error flag */ + setFrameErrorFlag(self->pSbrElement[elementIndex], FRAME_OK); + } + + if (!stereo) { + /* Turn coupling off explicitely to avoid access to absent right frame data + that might occur with corrupt bitstreams. */ + hFrameDataLeft->coupling = COUPLING_OFF; + } + +bail: + + if (self != NULL) { + if (self->flags & SBRDEC_SYNTAX_DRM) { + hBs = hBsOriginal; + } + + if (errorStatus != SBRDEC_NOT_INITIALIZED) { + int useOldHdr = + ((headerStatus == HEADER_NOT_PRESENT) || + (headerStatus == HEADER_ERROR) || + (headerStatus == HEADER_RESET && errorStatus == SBRDEC_PARSE_ERROR)) + ? 1 + : 0; + + if (!useOldHdr && (thisHdrSlot != lastHdrSlot) && (hSbrHeader != NULL)) { + useOldHdr |= + (compareSbrHeader(hSbrHeader, + &self->sbrHeader[elementIndex][lastHdrSlot]) == 0) + ? 1 + : 0; + } + + if (hSbrElement != NULL) { + if (useOldHdr != 0) { + /* Use the old header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = lastHdrSlot; + } else { + /* Use the new header for this frame */ + hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot] = thisHdrSlot; + } + + /* Move frame pointer to the next slot which is up to be decoded/applied + * next */ + hSbrElement->useFrameSlot = + (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1); + } + } + } + + *count -= startPos - (INT)FDKgetValidBits(hBs); + + return errorStatus; +} + +/** + * \brief Render one SBR element into time domain signal. + * \param self SBR decoder handle + * \param timeData pointer to output buffer + * \param channelMapping pointer to UCHAR array where next 2 channel offsets are + * stored. + * \param elementIndex enumerating index of the SBR element to render. + * \param numInChannels number of channels from core coder. + * \param numOutChannels pointer to a location to return number of output + * channels. + * \param psPossible flag indicating if PS is possible or not. + * \return SBRDEC_OK if successfull, else error code + */ +static SBR_ERROR sbrDecoder_DecodeElement( + HANDLE_SBRDECODER self, QDOM_PCM *input, INT_PCM *timeData, + const int timeDataSize, const FDK_channelMapDescr *const mapDescr, + const int mapIdx, int channelIndex, const int elementIndex, + const int numInChannels, int *numOutChannels, const int psPossible) { + SBR_DECODER_ELEMENT *hSbrElement = self->pSbrElement[elementIndex]; + HANDLE_SBR_CHANNEL *pSbrChannel = + self->pSbrElement[elementIndex]->pSbrChannel; + HANDLE_SBR_HEADER_DATA hSbrHeader = + &self->sbrHeader[elementIndex] + [hSbrElement->useHeaderSlot[hSbrElement->useFrameSlot]]; + HANDLE_PS_DEC h_ps_d = self->hParametricStereoDec; + + /* get memory for frame data from scratch */ + SBR_FRAME_DATA *hFrameDataLeft = NULL; + SBR_FRAME_DATA *hFrameDataRight = NULL; + + SBR_ERROR errorStatus = SBRDEC_OK; + + INT strideOut, offset0 = 255, offset0_block = 0, offset1 = 255, + offset1_block = 0; + INT codecFrameSize = self->codecFrameSize; + + int stereo = (hSbrElement->elementID == ID_CPE) ? 1 : 0; + int numElementChannels = + hSbrElement + ->nChannels; /* Number of channels of the current SBR element */ + + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + + if (self->flags & SBRDEC_FLUSH) { + if (self->numFlushedFrames > self->numDelayFrames) { + int hdrIdx; + /* No valid SBR payload available, hence switch to upsampling (in all + * headers) */ + for (hdrIdx = 0; hdrIdx < ((1) + 1); hdrIdx += 1) { + self->sbrHeader[elementIndex][hdrIdx].syncState = UPSAMPLING; + } + } else { + /* Move frame pointer to the next slot which is up to be decoded/applied + * next */ + hSbrElement->useFrameSlot = + (hSbrElement->useFrameSlot + 1) % (self->numDelayFrames + 1); + /* Update header and frame data pointer because they have already been set + */ + hSbrHeader = + &self->sbrHeader[elementIndex] + [hSbrElement + ->useHeaderSlot[hSbrElement->useFrameSlot]]; + hFrameDataLeft = + &hSbrElement->pSbrChannel[0]->frameData[hSbrElement->useFrameSlot]; + if (stereo) { + hFrameDataRight = + &hSbrElement->pSbrChannel[1]->frameData[hSbrElement->useFrameSlot]; + } + } + } + + /* Update the header error flag */ + hSbrHeader->frameErrorFlag = + hSbrElement->frameErrorFlag[hSbrElement->useFrameSlot]; + + /* + Prepare filterbank for upsampling if no valid bit stream data is available. + */ + if (hSbrHeader->syncState == SBR_NOT_INITIALIZED) { + errorStatus = + initHeaderData(hSbrHeader, self->sampleRateIn, self->sampleRateOut, + self->downscaleFactor, codecFrameSize, self->flags, + 1 /* SET_DEFAULT_HDR */ + ); + + if (errorStatus != SBRDEC_OK) { + return errorStatus; + } + + hSbrHeader->syncState = UPSAMPLING; + + errorStatus = sbrDecoder_HeaderUpdate(self, hSbrHeader, HEADER_NOT_PRESENT, + pSbrChannel, hSbrElement->nChannels); + + if (errorStatus != SBRDEC_OK) { + hSbrHeader->syncState = SBR_NOT_INITIALIZED; + return errorStatus; + } + } + + /* reset */ + if (hSbrHeader->status & SBRDEC_HDR_STAT_RESET) { + int ch; + int applySbrProc = (hSbrHeader->syncState == SBR_ACTIVE || + (hSbrHeader->frameErrorFlag == 0 && + hSbrHeader->syncState == SBR_HEADER)); + for (ch = 0; ch < numElementChannels; ch++) { + SBR_ERROR errorStatusTmp = SBRDEC_OK; + + errorStatusTmp = resetSbrDec( + &pSbrChannel[ch]->SbrDec, hSbrHeader, &pSbrChannel[ch]->prevFrameData, + self->synDownsampleFac, self->flags, pSbrChannel[ch]->frameData); + + if (errorStatusTmp != SBRDEC_OK) { + hSbrHeader->syncState = UPSAMPLING; + } + } + if (applySbrProc) { + hSbrHeader->status &= ~SBRDEC_HDR_STAT_RESET; + } + } + + /* decoding */ + if ((hSbrHeader->syncState == SBR_ACTIVE) || + ((hSbrHeader->syncState == SBR_HEADER) && + (hSbrHeader->frameErrorFlag == 0))) { + errorStatus = SBRDEC_OK; + + decodeSbrData(hSbrHeader, hFrameDataLeft, &pSbrChannel[0]->prevFrameData, + (stereo) ? hFrameDataRight : NULL, + (stereo) ? &pSbrChannel[1]->prevFrameData : NULL); + + /* Now we have a full parameter set and can do parameter + based concealment instead of plain upsampling. */ + hSbrHeader->syncState = SBR_ACTIVE; + } + + if (timeDataSize < + hSbrHeader->numberTimeSlots * hSbrHeader->timeStep * + self->pQmfDomain->globalConf.nBandsSynthesis * + (psPossible ? fMax(2, numInChannels) : numInChannels)) { + return SBRDEC_OUTPUT_BUFFER_TOO_SMALL; + } + + { + self->flags &= ~SBRDEC_PS_DECODED; + C_ALLOC_SCRATCH_START(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) + + /* decode PS data if available */ + if (h_ps_d != NULL && psPossible && (hSbrHeader->syncState == SBR_ACTIVE)) { + int applyPs = 1; + + /* define which frame delay line slot to process */ + h_ps_d->processSlot = hSbrElement->useFrameSlot; + + applyPs = DecodePs(h_ps_d, hSbrHeader->frameErrorFlag, pPsScratch); + self->flags |= (applyPs) ? SBRDEC_PS_DECODED : 0; + } + + offset0 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex, mapIdx); + offset0_block = offset0 * codecFrameSize; + if (stereo || psPossible) { + /* the value of offset1 only matters if the condition is true, however if + it is not true channelIndex+1 may exceed the channel map resutling in an + error, though the value of offset1 is actually meaningless. This is + prevented here. */ + offset1 = FDK_chMapDescr_getMapValue(mapDescr, channelIndex + 1, mapIdx); + offset1_block = offset1 * codecFrameSize; + } + /* Set strides for reading and writing */ + if (psPossible) + strideOut = (numInChannels < 2) ? 2 : numInChannels; + else + strideOut = numInChannels; + + /* use same buffers for left and right channel and apply PS per timeslot */ + /* Process left channel */ + sbr_dec(&pSbrChannel[0]->SbrDec, input + offset0_block, timeData + offset0, + (self->flags & SBRDEC_PS_DECODED) ? &pSbrChannel[1]->SbrDec : NULL, + timeData + offset1, strideOut, hSbrHeader, hFrameDataLeft, + &pSbrChannel[0]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), h_ps_d, self->flags, + codecFrameSize); + + if (stereo) { + /* Process right channel */ + sbr_dec(&pSbrChannel[1]->SbrDec, input + offset1_block, + timeData + offset1, NULL, NULL, strideOut, hSbrHeader, + hFrameDataRight, &pSbrChannel[1]->prevFrameData, + (hSbrHeader->syncState == SBR_ACTIVE), NULL, self->flags, + codecFrameSize); + } + + C_ALLOC_SCRATCH_END(pPsScratch, struct PS_DEC_COEFFICIENTS, 1) + } + + if (h_ps_d != NULL) { + /* save PS status for next run */ + h_ps_d->psDecodedPrv = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; + } + + if (psPossible && !(self->flags & SBRDEC_SKIP_QMF_SYN)) { + FDK_ASSERT(strideOut > 1); + if (!(self->flags & SBRDEC_PS_DECODED)) { + /* A decoder which is able to decode PS has to produce a stereo output + * even if no PS data is available. */ + /* So copy left channel to right channel. */ + int copyFrameSize = + codecFrameSize * self->pQmfDomain->QmfDomainOut->fb.no_channels; + copyFrameSize /= self->pQmfDomain->QmfDomainIn->fb.no_channels; + INT_PCM *ptr; + INT i; + FDK_ASSERT(strideOut == 2); + + ptr = timeData; + for (i = copyFrameSize >> 1; i--;) { + INT_PCM tmp; /* This temporal variable is required because some + compilers can't do *ptr++ = *ptr++ correctly. */ + tmp = *ptr++; + *ptr++ = tmp; + tmp = *ptr++; + *ptr++ = tmp; + } + } + *numOutChannels = 2; /* Output minimum two channels when PS is enabled. */ + } + + return errorStatus; +} + +SBR_ERROR sbrDecoder_Apply(HANDLE_SBRDECODER self, INT_PCM *input, + INT_PCM *timeData, const int timeDataSize, + int *numChannels, int *sampleRate, + const FDK_channelMapDescr *const mapDescr, + const int mapIdx, const int coreDecodedOk, + UCHAR *psDecoded) { + SBR_ERROR errorStatus = SBRDEC_OK; + + int psPossible; + int sbrElementNum; + int numCoreChannels; + int numSbrChannels = 0; + + if ((self == NULL) || (timeData == NULL) || (numChannels == NULL) || + (sampleRate == NULL) || (psDecoded == NULL) || + !FDK_chMapDescr_isValid(mapDescr)) { + return SBRDEC_INVALID_ARGUMENT; + } + + psPossible = *psDecoded; + numCoreChannels = *numChannels; + if (numCoreChannels <= 0) { + return SBRDEC_INVALID_ARGUMENT; + } + + if (self->numSbrElements < 1) { + /* exit immediately to avoid access violations */ + return SBRDEC_NOT_INITIALIZED; + } + + /* Sanity check of allocated SBR elements. */ + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { + if (self->pSbrElement[sbrElementNum] == NULL) { + return SBRDEC_NOT_INITIALIZED; + } + } + + if (self->numSbrElements != 1 || self->pSbrElement[0]->elementID != ID_SCE) { + psPossible = 0; + } + + /* Make sure that even if no SBR data was found/parsed *psDecoded is returned + * 1 if psPossible was 0. */ + if (psPossible == 0) { + self->flags &= ~SBRDEC_PS_DECODED; + } + + /* replaces channel based reset inside sbr_dec() */ + if (((self->flags & SBRDEC_LOW_POWER) ? 1 : 0) != + ((self->pQmfDomain->globalConf.flags & QMF_FLAG_LP) ? 1 : 0)) { + if (self->flags & SBRDEC_LOW_POWER) { + self->pQmfDomain->globalConf.flags |= QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested |= QMF_FLAG_LP; + } else { + self->pQmfDomain->globalConf.flags &= ~QMF_FLAG_LP; + self->pQmfDomain->globalConf.flags_requested &= ~QMF_FLAG_LP; + } + if (FDK_QmfDomain_InitFilterBank(self->pQmfDomain, QMF_FLAG_KEEP_STATES)) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + } + if (self->numSbrChannels > self->pQmfDomain->globalConf.nInputChannels) { + return SBRDEC_UNSUPPORTED_CONFIG; + } + + if (self->flags & SBRDEC_FLUSH) { + /* flushing is signalized, hence increment the flush frame counter */ + self->numFlushedFrames++; + } else { + /* no flushing is signalized, hence reset the flush frame counter */ + self->numFlushedFrames = 0; + } + + /* Loop over SBR elements */ + for (sbrElementNum = 0; sbrElementNum < self->numSbrElements; + sbrElementNum++) { + int numElementChan; + + if (psPossible && + self->pSbrElement[sbrElementNum]->pSbrChannel[1] == NULL) { + /* Disable PS and try decoding SBR mono. */ + psPossible = 0; + } + + numElementChan = + (self->pSbrElement[sbrElementNum]->elementID == ID_CPE) ? 2 : 1; + + /* If core signal is bad then force upsampling */ + if (!coreDecodedOk) { + setFrameErrorFlag(self->pSbrElement[sbrElementNum], FRAME_ERROR_ALLSLOTS); + } + + errorStatus = sbrDecoder_DecodeElement( + self, input, timeData, timeDataSize, mapDescr, mapIdx, numSbrChannels, + sbrElementNum, + numCoreChannels, /* is correct even for USC SCI==2 case */ + &numElementChan, psPossible); + + if (errorStatus != SBRDEC_OK) { + goto bail; + } + + numSbrChannels += numElementChan; + + if (numSbrChannels >= numCoreChannels) { + break; + } + } + + /* Update numChannels and samplerate */ + /* Do not mess with output channels in case of USAC. numSbrChannels != + * numChannels for stereoConfigIndex == 2 */ + if (!(self->flags & SBRDEC_SYNTAX_USAC)) { + *numChannels = numSbrChannels; + } + *sampleRate = self->sampleRateOut; + *psDecoded = (self->flags & SBRDEC_PS_DECODED) ? 1 : 0; + + /* Clear reset and flush flag because everything seems to be done + * successfully. */ + self->flags &= ~SBRDEC_FORCE_RESET; + self->flags &= ~SBRDEC_FLUSH; + +bail: + + return errorStatus; +} + +SBR_ERROR sbrDecoder_Close(HANDLE_SBRDECODER *pSelf) { + HANDLE_SBRDECODER self = *pSelf; + int i; + + if (self != NULL) { + if (self->hParametricStereoDec != NULL) { + DeletePsDec(&self->hParametricStereoDec); + } + + for (i = 0; i < (8); i++) { + sbrDecoder_DestroyElement(self, i); + } + + FreeRam_SbrDecoder(pSelf); + } + + return SBRDEC_OK; +} + +INT sbrDecoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + info += i; + + info->module_id = FDK_SBRDEC; + info->version = + LIB_VERSION(SBRDECODER_LIB_VL0, SBRDECODER_LIB_VL1, SBRDECODER_LIB_VL2); + LIB_VERSION_STRING(info); + info->build_date = SBRDECODER_LIB_BUILD_DATE; + info->build_time = SBRDECODER_LIB_BUILD_TIME; + info->title = SBRDECODER_LIB_TITLE; + + /* Set flags */ + info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_LP | CAPF_SBR_PS_MPEG | + CAPF_SBR_DRM_BS | CAPF_SBR_CONCEALMENT | CAPF_SBR_DRC | + CAPF_SBR_ELD_DOWNSCALE | CAPF_SBR_HBEHQ; + /* End of flags */ + + return 0; +} + +UINT sbrDecoder_GetDelay(const HANDLE_SBRDECODER self) { + UINT outputDelay = 0; + + if (self != NULL) { + UINT flags = self->flags; + + /* See chapter 1.6.7.2 of ISO/IEC 14496-3 for the GA-SBR figures below. */ + + /* Are we initialized? */ + if ((self->numSbrChannels > 0) && (self->numSbrElements > 0)) { + /* Add QMF synthesis delay */ + if ((flags & SBRDEC_ELD_GRID) && IS_LOWDELAY(self->coreCodec)) { + /* Low delay SBR: */ + if (!(flags & SBRDEC_SKIP_QMF_SYN)) { + outputDelay += + (flags & SBRDEC_DOWNSAMPLE) ? 32 : 64; /* QMF synthesis */ + if (flags & SBRDEC_LD_MPS_QMF) { + outputDelay += 32; + } + } + } else if (!IS_USAC(self->coreCodec)) { + /* By the method of elimination this is the GA (AAC-LC, HE-AAC, ...) + * branch: */ + outputDelay += (flags & SBRDEC_DOWNSAMPLE) ? 481 : 962; + if (flags & SBRDEC_SKIP_QMF_SYN) { + outputDelay -= 257; /* QMF synthesis */ + } + } + } + } + + return (outputDelay); +} diff --git a/fdk-aac/libSBRdec/src/transcendent.h b/fdk-aac/libSBRdec/src/transcendent.h new file mode 100644 index 0000000..0e815c2 --- /dev/null +++ b/fdk-aac/libSBRdec/src/transcendent.h @@ -0,0 +1,372 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR decoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief FDK Fixed Point Arithmetic Library Interface +*/ + +#ifndef TRANSCENDENT_H +#define TRANSCENDENT_H + +#include "sbrdecoder.h" +#include "sbr_rom.h" + +/************************************************************************/ +/*! + \brief Get number of octaves between frequencies a and b + + The Result is scaled with 1/8. + The valid range for a and b is 1 to LOG_DUALIS_TABLE_SIZE. + + \return ld(a/b) / 8 +*/ +/************************************************************************/ +static inline FIXP_SGL FDK_getNumOctavesDiv8(INT a, /*!< lower band */ + INT b) /*!< upper band */ +{ + return ((SHORT)((LONG)(CalcLdInt(b) - CalcLdInt(a)) >> (FRACT_BITS - 3))); +} + +/************************************************************************/ +/*! + \brief Add two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+*/ +/************************************************************************/ +inline void FDK_add_MantExp(FIXP_SGL a_m, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_SGL b_m, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_SGL *ptrSum_m, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (FX_SGL2FX_DBL(b_m) >> shiftAbs) + : (FX_SGL2FX_DBL(a_m) >> shiftAbs); + otherMantissa = (shift > 0) ? FX_SGL2FX_DBL(a_m) : FX_SGL2FX_DBL(b_m); + *ptrSum_e = (shift > 0) ? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum_m = FX_DBL2FX_SGL(accu); +} + +inline void FDK_add_MantExp(FIXP_DBL a, /*!< Mantissa of 1st operand a */ + SCHAR a_e, /*!< Exponent of 1st operand a */ + FIXP_DBL b, /*!< Mantissa of 2nd operand b */ + SCHAR b_e, /*!< Exponent of 2nd operand b */ + FIXP_DBL *ptrSum, /*!< Mantissa of result */ + SCHAR *ptrSum_e) /*!< Exponent of result */ +{ + FIXP_DBL accu; + int shift; + int shiftAbs; + + FIXP_DBL shiftedMantissa; + FIXP_DBL otherMantissa; + + /* Equalize exponents of the summands. + For the smaller summand, the exponent is adapted and + for compensation, the mantissa is shifted right. */ + + shift = (int)(a_e - b_e); + + shiftAbs = (shift > 0) ? shift : -shift; + shiftAbs = (shiftAbs < DFRACT_BITS - 1) ? shiftAbs : DFRACT_BITS - 1; + shiftedMantissa = (shift > 0) ? (b >> shiftAbs) : (a >> shiftAbs); + otherMantissa = (shift > 0) ? a : b; + *ptrSum_e = (shift > 0) ? a_e : b_e; + + accu = (shiftedMantissa >> 1) + (otherMantissa >> 1); + /* shift by 1 bit to avoid overflow */ + + if ((accu >= (FL2FXCONST_DBL(0.5f) - (FIXP_DBL)1)) || + (accu <= FL2FXCONST_DBL(-0.5f))) + *ptrSum_e += 1; + else + accu = (shiftedMantissa + otherMantissa); + + *ptrSum = accu; +} + +/************************************************************************/ +/*! + \brief Divide two values given by mantissa and exponent. + + Mantissas are in fract format with values between 0 and 1.
+ The base for exponents is 2. Example: \f$ a = a\_m * 2^{a\_e} \f$
+ + For performance reasons, the division is based on a table lookup + which limits accuracy. +*/ +/************************************************************************/ +static inline void FDK_divide_MantExp( + FIXP_SGL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_SGL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_SGL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(FX_SGL2FX_DBL(b_m)); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (FRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS + 1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? FX_SGL2FX_DBL(a_m >> 1) : fMultDiv2(bInv_m, a_m); + + postShift = CntLeadingZeros(ratio_m) - 1; + + *ptrResult_m = FX_DBL2FX_SGL(ratio_m << postShift); + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +static inline void FDK_divide_MantExp( + FIXP_DBL a_m, /*!< Mantissa of dividend a */ + SCHAR a_e, /*!< Exponent of dividend a */ + FIXP_DBL b_m, /*!< Mantissa of divisor b */ + SCHAR b_e, /*!< Exponent of divisor b */ + FIXP_DBL *ptrResult_m, /*!< Mantissa of quotient a/b */ + SCHAR *ptrResult_e) /*!< Exponent of quotient a/b */ + +{ + int preShift, postShift, index, shift; + FIXP_DBL ratio_m; + FIXP_SGL bInv_m = FL2FXCONST_SGL(0.0f); + + preShift = CntLeadingZeros(b_m); + + /* + Shift b into the range from 0..INV_TABLE_SIZE-1, + + E.g. 10 bits must be skipped for INV_TABLE_BITS 8: + - leave 8 bits as index for table + - skip sign bit, + - skip first bit of mantissa, because this is always the same (>0.5) + + We are dealing with energies, so we need not care + about negative numbers + */ + + /* + The first interval has half width so the lowest bit of the index is + needed for a doubled resolution. + */ + shift = (DFRACT_BITS - 2 - INV_TABLE_BITS - preShift); + + index = (shift < 0) ? (LONG)b_m << (-shift) : (LONG)b_m >> shift; + + /* The index has INV_TABLE_BITS +1 valid bits here. Clear the other bits. */ + index &= (1 << (INV_TABLE_BITS + 1)) - 1; + + /* Remove offset of half an interval */ + index--; + + /* Now the lowest bit is shifted out */ + index = index >> 1; + + /* Fetch inversed mantissa from table: */ + bInv_m = (index < 0) ? bInv_m : FDK_sbrDecoder_invTable[index]; + + /* Multiply a with the inverse of b: */ + ratio_m = (index < 0) ? (a_m >> 1) : fMultDiv2(bInv_m, a_m); + + postShift = CntLeadingZeros(ratio_m) - 1; + + *ptrResult_m = ratio_m << postShift; + *ptrResult_e = a_e - b_e + 1 + preShift - postShift; +} + +/*! + \brief Calculate the squareroot of a number given by mantissa and exponent + + Mantissa is in fract 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. + + For performance reasons, the square root is based on a table lookup + which limits accuracy. +*/ +static inline void FDK_sqrt_MantExp( + FIXP_DBL *mantissa, /*!< Pointer to mantissa */ + SCHAR *exponent, const SCHAR *destScale) { + FIXP_DBL input_m = *mantissa; + int input_e = (int)*exponent; + FIXP_DBL result = FL2FXCONST_DBL(0.0f); + int result_e = -FRACT_BITS; + + /* Call lookup square root, which does internally normalization. */ + result = sqrtFixp_lookup(input_m, &input_e); + result_e = input_e; + + /* Write result */ + if (exponent == destScale) { + *mantissa = result; + *exponent = result_e; + } else { + int shift = result_e - *destScale; + *mantissa = (shift >= 0) ? result << (INT)fixMin(DFRACT_BITS - 1, shift) + : result >> (INT)fixMin(DFRACT_BITS - 1, -shift); + *exponent = *destScale; + } +} + +#endif diff --git a/fdk-aac/libSBRenc/include/sbr_encoder.h b/fdk-aac/libSBRenc/include/sbr_encoder.h new file mode 100644 index 0000000..d979ba6 --- /dev/null +++ b/fdk-aac/libSBRenc/include/sbr_encoder.h @@ -0,0 +1,483 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: SBR encoder top level processing prototype + +*******************************************************************************/ + +#ifndef SBR_ENCODER_H +#define SBR_ENCODER_H + +#include "common_fix.h" +#include "FDK_audio.h" + +#include "FDK_bitstream.h" + +/* core coder helpers */ +#define MAX_TRANS_FAC 8 +#define MAX_CODEC_FRAME_RATIO 2 +#define MAX_PAYLOAD_SIZE 256 + +typedef enum codecType { + CODEC_AAC = 0, + CODEC_AACLD = 1, + CODEC_UNSPECIFIED = 99 +} CODEC_TYPE; + +typedef struct { + INT bitRate; + INT nChannels; + INT sampleFreq; + INT transFac; + INT standardBitrate; +} CODEC_PARAM; + +typedef enum { + SBR_MONO, + SBR_LEFT_RIGHT, + SBR_COUPLING, + SBR_SWITCH_LRC +} SBR_STEREO_MODE; + +/* bitstream syntax flags */ +enum { + SBR_SYNTAX_LOW_DELAY = 0x0001, + SBR_SYNTAX_SCALABLE = 0x0002, + SBR_SYNTAX_CRC = 0x0004, + SBR_SYNTAX_DRM_CRC = 0x0008, + SBR_SYNTAX_ELD_REDUCED_DELAY = 0x0010 +}; + +typedef enum { FREQ_RES_LOW = 0, FREQ_RES_HIGH } FREQ_RES; + +typedef struct { + CODEC_TYPE coreCoder; /*!< LC or ELD */ + UINT bitrateFrom; /*!< inclusive */ + UINT bitrateTo; /*!< exclusive */ + + UINT sampleRate; /*!< */ + UCHAR numChannels; /*!< */ + + UCHAR startFreq; /*!< bs_start_freq */ + UCHAR startFreqSpeech; /*!< bs_start_freq for speech config flag */ + UCHAR stopFreq; /*!< bs_stop_freq */ + UCHAR stopFreqSpeech; /*!< bs_stop_freq for speech config flag */ + + UCHAR numNoiseBands; /*!< */ + UCHAR noiseFloorOffset; /*!< */ + SCHAR noiseMaxLevel; /*!< */ + SBR_STEREO_MODE stereoMode; /*!< */ + UCHAR freqScale; /*!< */ +} sbrTuningTable_t; + +typedef struct sbrConfiguration { + /* + core coder dependent configurations + */ + CODEC_PARAM + codecSettings; /*!< Core coder settings. To be set from core coder. */ + INT SendHeaderDataTime; /*!< SBR header send update frequency in ms. */ + INT useWaveCoding; /*!< Flag: usage of wavecoding tool. */ + INT crcSbr; /*!< Flag: usage of SBR-CRC. */ + INT dynBwSupported; /*!< Flag: support for dynamic bandwidth in this + combination. */ + INT parametricCoding; /*!< Flag: usage of parametric coding tool. */ + INT downSampleFactor; /*!< Sampling rate relation between the SBR and the core + encoder. */ + FREQ_RES freq_res_fixfix[2]; /*!< Frequency resolution of envelopes in frame + class FIXFIX, for non-split case and split + case */ + UCHAR fResTransIsLow; /*!< Frequency resolution of envelopes in transient + frames: low (0) or variable (1) */ + + /* + core coder dependent tuning parameters + */ + INT tran_thr; /*!< SBR transient detector threshold (* 100). */ + INT noiseFloorOffset; /*!< Noise floor offset. */ + UINT useSpeechConfig; /*!< Flag: adapt tuning parameters according to speech. + */ + + /* + core coder independent configurations + */ + INT sbrFrameSize; /*!< SBR frame size in samples. Will be calculated from core + coder settings. */ + INT sbr_data_extra; /*!< Flag usage of data extra. */ + INT amp_res; /*!< Amplitude resolution. */ + INT ana_max_level; /*!< Noise insertion maximum level. */ + INT tran_fc; /*!< Transient detector start frequency. */ + INT tran_det_mode; /*!< Transient detector mode. */ + INT spread; /*!< Flag: usage of SBR spread. */ + INT stat; /*!< Flag: usage of static framing. */ + INT e; /*!< Number of envelopes when static framing is chosen. */ + SBR_STEREO_MODE stereoMode; /*!< SBR stereo mode. */ + INT deltaTAcrossFrames; /*!< Flag: allow time-delta coding. */ + FIXP_DBL dF_edge_1stEnv; /*!< Extra fraction delta-F coding is allowed to be + more expensive. */ + FIXP_DBL dF_edge_incr; /*!< Increment dF_edge_1stEnv this much if dT-coding + was used this frame. */ + INT sbr_invf_mode; /*!< Inverse filtering mode. */ + INT sbr_xpos_mode; /*!< Transposer mode. */ + INT sbr_xpos_ctrl; /*!< Transposer control. */ + INT sbr_xpos_level; /*!< Transposer 3rd order level. */ + INT startFreq; /*!< The start frequency table index. */ + INT stopFreq; /*!< The stop frequency table index. */ + INT useSaPan; /*!< Flag: usage of SAPAN stereo. */ + INT dynBwEnabled; /*!< Flag: usage of dynamic bandwidth. */ + INT bParametricStereo; /*!< Flag: usage of parametric stereo coding tool. */ + + /* + header_extra1 configuration + */ + UCHAR freqScale; /*!< Frequency grouping. */ + INT alterScale; /*!< Scale resolution. */ + INT sbr_noise_bands; /*!< Number of noise bands. */ + + /* + header_extra2 configuration + */ + INT sbr_limiter_bands; /*!< Number of limiter bands. */ + INT sbr_limiter_gains; /*!< Gain of limiter. */ + INT sbr_interpol_freq; /*!< Flag: use interpolation in freq. direction. */ + INT sbr_smoothing_length; /*!< Flag: choose length 4 or 0 (=on, off). */ + UCHAR init_amp_res_FF; + FIXP_DBL threshold_AmpRes_FF_m; + SCHAR threshold_AmpRes_FF_e; +} sbrConfiguration, *sbrConfigurationPtr; + +typedef struct SBR_CONFIG_DATA { + UINT sbrSyntaxFlags; /**< SBR syntax flags derived from AOT. */ + INT nChannels; /**< Number of channels. */ + + INT nSfb[2]; /**< Number of SBR scalefactor bands for LO_RES and HI_RES (?) */ + INT num_Master; /**< Number of elements in v_k_master. */ + INT sampleFreq; /**< SBR sampling frequency. */ + INT frameSize; + INT xOverFreq; /**< The SBR start frequency. */ + INT dynXOverFreq; /**< Used crossover frequency when dynamic bandwidth is + enabled. */ + + INT noQmfBands; /**< Number of QMF frequency bands. */ + INT noQmfSlots; /**< Number of QMF slots. */ + + UCHAR *freqBandTable[2]; /**< Frequency table for low and hires, only + MAX_FREQ_COEFFS/2 +1 coeffs actually needed for + lowres. */ + UCHAR + *v_k_master; /**< Master BandTable where freqBandTable is derived from. */ + + SBR_STEREO_MODE stereoMode; + INT noEnvChannels; /**< Number of envelope channels. */ + + INT useWaveCoding; /**< Flag indicates whether to use wave coding at all. */ + INT useParametricCoding; /**< Flag indicates whether to use para coding at + all. */ + INT xposCtrlSwitch; /**< Flag indicates whether to switch xpos ctrl on the + fly. */ + INT switchTransposers; /**< Flag indicates whether to switch xpos on the fly . + */ + UCHAR initAmpResFF; + FIXP_DBL thresholdAmpResFF_m; + SCHAR thresholdAmpResFF_e; +} SBR_CONFIG_DATA, *HANDLE_SBR_CONFIG_DATA; + +typedef struct { + MP4_ELEMENT_ID elType; + INT bitRate; + int instanceTag; + UCHAR fParametricStereo; + UCHAR fDualMono; /**< This flags allows to disable coupling in sbr channel + pair element */ + UCHAR nChannelsInEl; + UCHAR ChannelIndex[2]; +} SBR_ELEMENT_INFO; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct SBR_ENCODER *HANDLE_SBR_ENCODER; + +/** + * \brief Get the max required input buffer size including delay balancing + * space for N audio channels. + * \param noChannels Number of audio channels. + * \return Max required input buffer size in bytes. + */ +INT sbrEncoder_GetInBufferSize(int noChannels); + +INT sbrEncoder_Open(HANDLE_SBR_ENCODER *phSbrEncoder, INT nElements, + INT nChannels, INT supportPS); + +/** + * \brief Get closest working bitrate to specified desired + * bitrate for a single SBR element. + * \param bitRate The desired target bit rate + * \param numChannels The amount of audio channels + * \param coreSampleRate The sample rate of the core coder + * \param aot The current Audio Object Type + * \return Closest working bit rate to bitRate value + */ +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, + UINT coreSampleRate, AUDIO_OBJECT_TYPE aot); + +/** + * \brief Check whether downsampled SBR single rate is possible + * with given audio object type. + * \param aot The Audio object type. + * \return 0 when downsampled SBR is not possible, + * 1 when downsampled SBR is possible. + */ +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot); + +/** + * \brief Initialize SBR Encoder instance. + * \param phSbrEncoder Pointer to a SBR Encoder instance. + * \param elInfo Structure that describes the element/channel + * arrangement. + * \param noElements Amount of elements described in elInfo. + * \param inputBuffer Pointer to the encoder audio buffer + * \param inputBufferBufSize Buffer offset of one channel (frameSize + delay) + * \param bandwidth Returns the core audio encoder bandwidth (output) + * \param bufferOffset Returns the offset for the audio input data in order + * to do delay balancing. + * \param numChannels Input: Encoder input channels. output: core encoder + * channels. + * \param sampleRate Input: Encoder samplerate. output core encoder + * samplerate. + * \param downSampleFactor Input: Relation between SBR and core coder sampling + * rate; + * \param frameLength Input: Encoder frameLength. output core encoder + * frameLength. + * \param aot Input: AOT.. + * \param delay Input: core encoder delay. Output: total delay + * because of SBR. + * \param transformFactor The core encoder transform factor (blockswitching). + * \param headerPeriod Repetition rate of the SBR header: + * - (-1) means intern configuration. + * - (1-10) corresponds to header repetition rate in + * frames. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], int noElements, + INT_PCM *inputBuffer, UINT inputBufferBufSize, + INT *coreBandwidth, INT *inputBufferOffset, + INT *numChannels, const UINT syntaxFlags, INT *sampleRate, + UINT *downSampleFactor, INT *frameLength, + AUDIO_OBJECT_TYPE aot, int *delay, int transformFactor, + const int headerPeriod, ULONG statesInitFlag); + +/** + * \brief Do delay line buffers housekeeping. To be called after + * each encoded audio frame. + * \param hEnvEnc SBR Encoder handle. + * \param timeBuffer Pointer to the encoder audio buffer. + * \param timeBufferBufSIze buffer size for one channel + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hEnvEnc, INT_PCM *timeBuffer, + UINT timeBufferBufSIze); + +/** + * \brief Close SBR encoder instance. + * \param phEbrEncoder Handle of SBR encoder instance to be closed. + * \return void + */ +void sbrEncoder_Close(HANDLE_SBR_ENCODER *phEbrEncoder); + +/** + * \brief Encode SBR data of one complete audio frame. + * \param hEnvEncoder Handle of SBR encoder instance. + * \param samples Time samples, not interleaved. + * \param timeInStride Channel offset of samples buffer. + * \param sbrDataBits Size of SBR payload in bits. + * \param sbrData SBR payload. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hEnvEncoder, INT_PCM *samples, + UINT samplesBufSize, UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE]); + +/** + * \brief Write SBR headers of one SBR element. + * \param sbrEncoder Handle of the SBR encoder instance. + * \param hBs Handle of bit stream handle to write SBR header to. + * \param element_index Index of the SBR element which header should be written. + * \param fSendHeaders Flag indicating that the SBR encoder should send more + * headers in the SBR payload or not. + * \return void + */ +void sbrEncoder_GetHeader(HANDLE_SBR_ENCODER sbrEncoder, + HANDLE_FDK_BITSTREAM hBs, INT element_index, + int fSendHeaders); + +/** + * \brief Request to write SBR header. + * \param hSbrEncoder SBR encoder handle. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Request if last sbr payload contains an SBR header. + * \param hSbrEncoder SBR encoder handle. + * \return 1 contains sbr header, 0 without sbr header. + */ +INT sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief SBR header delay in frames. + * \param hSbrEncoder SBR encoder handle. + * \return Delay in frames, -1 on failure. + */ +INT sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Bitstrem delay in SBR frames. + * \param hSbrEncoder SBR encoder handle. + * \return Delay in frames, -1 on failure. + */ +INT sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Prepare SBR payload for SAP. + * \param hSbrEncoder SBR encoder handle. + * \return 0 on success, and non-zero if failed. + */ +INT sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief SBR encoder bitrate estimation. + * \param hSbrEncoder SBR encoder handle. + * \return Estimated bitrate. + */ +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Delay between input data and downsampled output data. + * \param hSbrEncoder SBR encoder handle. + * \return Delay. + */ +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Delay caused by the SBR decoder. + * \param hSbrEncoder SBR encoder handle. + * \return Delay. + */ +INT sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder); + +/** + * \brief Get decoder library version info. + * \param info Pointer to an allocated LIB_INFO struct, where library info is + * written to. + * \return 0 on sucess. + */ +INT sbrEncoder_GetLibInfo(LIB_INFO *info); + +void sbrPrintRAM(void); + +void sbrPrintROM(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ifndef __SBR_MAIN_H */ diff --git a/fdk-aac/libSBRenc/src/bit_sbr.cpp b/fdk-aac/libSBRenc/src/bit_sbr.cpp new file mode 100644 index 0000000..5a65e98 --- /dev/null +++ b/fdk-aac/libSBRenc/src/bit_sbr.cpp @@ -0,0 +1,1049 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR bit writing routines $Revision: 93300 $ +*/ + +#include "bit_sbr.h" + +#include "code_env.h" +#include "cmondata.h" +#include "sbr.h" + +#include "ps_main.h" + +typedef enum { SBR_ID_SCE = 1, SBR_ID_CPE } SBR_ELEMENT_TYPE; + +static INT encodeSbrData(HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, SBR_ELEMENT_TYPE sbrElem, + INT coupling, UINT sbrSyntaxFlags); + +static INT encodeSbrHeader(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData); + +static INT encodeSbrHeaderData(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT encodeSbrSingleChannelElement( + HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, + HANDLE_PARAMETRIC_STEREO hParametricStereo, const UINT sbrSyntaxFlags); + +static INT encodeSbrChannelPairElement( + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitStream, + const INT coupling, const UINT sbrSyntaxFlags); + +static INT encodeSbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static int encodeLowDelaySbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + const int transmitFreqs, + const UINT sbrSyntaxFlags); + +static INT encodeSbrDtdf(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT writeNoiseLevelData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling); + +static INT writeEnvelopeData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling); + +static INT writeSyntheticCodingData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT encodeExtendedData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream); + +static INT getSbrExtendedDataSize(HANDLE_PARAMETRIC_STEREO hParametricStereo); + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvSingleChannelElement + description: writes pure SBR single channel data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_WriteEnvSingleChannelElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) + +{ + INT payloadBits = 0; + + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if (sbrEnvData != NULL) { + /* write header */ + payloadBits += encodeSbrHeader(sbrHeaderData, sbrBitstreamData, cmonData); + + /* write data */ + payloadBits += encodeSbrData(sbrEnvData, NULL, hParametricStereo, cmonData, + SBR_ID_SCE, 0, sbrSyntaxFlags); + } + return payloadBits; +} + +/***************************************************************************** + + functionname: FDKsbrEnc_WriteEnvChannelPairElement + description: writes pure SBR channel pair data element + returns: number of bits written + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_WriteEnvChannelPairElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) + +{ + INT payloadBits = 0; + cmonData->sbrHdrBits = 0; + cmonData->sbrDataBits = 0; + + /* write pure sbr data */ + if ((sbrEnvDataLeft != NULL) && (sbrEnvDataRight != NULL)) { + /* write header */ + payloadBits += encodeSbrHeader(sbrHeaderData, sbrBitstreamData, cmonData); + + /* write data */ + payloadBits += encodeSbrData(sbrEnvDataLeft, sbrEnvDataRight, + hParametricStereo, cmonData, SBR_ID_CPE, + sbrHeaderData->coupling, sbrSyntaxFlags); + } + return payloadBits; +} + +INT FDKsbrEnc_CountSbrChannelPairElement( + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_COMMON_DATA cmonData, UINT sbrSyntaxFlags) { + INT payloadBits; + INT bitPos = FDKgetValidBits(&cmonData->sbrBitbuf); + + payloadBits = FDKsbrEnc_WriteEnvChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, sbrEnvDataLeft, + sbrEnvDataRight, cmonData, sbrSyntaxFlags); + + FDKpushBack(&cmonData->sbrBitbuf, + (FDKgetValidBits(&cmonData->sbrBitbuf) - bitPos)); + + return payloadBits; +} + +void sbrEncoder_GetHeader(SBR_ENCODER *sbrEncoder, HANDLE_FDK_BITSTREAM hBs, + INT element_index, int fSendHeaders) { + encodeSbrHeaderData(&sbrEncoder->sbrElement[element_index]->sbrHeaderData, + hBs); + + if (fSendHeaders == 0) { + /* Prevent header being embedded into the SBR payload. */ + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.NrSendHeaderData = + -1; + sbrEncoder->sbrElement[element_index]->sbrBitstreamData.HeaderActive = 0; + sbrEncoder->sbrElement[element_index] + ->sbrBitstreamData.CountSendHeaderData = -1; + } +} + +/***************************************************************************** + + functionname: encodeSbrHeader + description: encodes SBR Header information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrHeader(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_COMMON_DATA cmonData) { + INT payloadBits = 0; + + if (sbrBitstreamData->HeaderActive) { + payloadBits += FDKwriteBits(&cmonData->sbrBitbuf, 1, 1); + payloadBits += encodeSbrHeaderData(sbrHeaderData, &cmonData->sbrBitbuf); + } else { + payloadBits += FDKwriteBits(&cmonData->sbrBitbuf, 0, 1); + } + + cmonData->sbrHdrBits = payloadBits; + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrHeaderData + description: writes sbr_header() + bs_protocol_version through bs_header_extra_2 + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrHeaderData(HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_FDK_BITSTREAM hBitStream) + +{ + INT payloadBits = 0; + if (sbrHeaderData != NULL) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_amp_res, + SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_start_frequency, + SI_SBR_START_FREQ_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_stop_frequency, + SI_SBR_STOP_FREQ_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_xover_band, + SI_SBR_XOVER_BAND_BITS); + + payloadBits += FDKwriteBits(hBitStream, 0, SI_SBR_RESERVED_BITS); + + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->header_extra_1, + SI_SBR_HEADER_EXTRA_1_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->header_extra_2, + SI_SBR_HEADER_EXTRA_2_BITS); + + if (sbrHeaderData->header_extra_1) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->freqScale, + SI_SBR_FREQ_SCALE_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->alterScale, + SI_SBR_ALTER_SCALE_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_noise_bands, + SI_SBR_NOISE_BANDS_BITS); + } /* sbrHeaderData->header_extra_1 */ + + if (sbrHeaderData->header_extra_2) { + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_limiter_bands, + SI_SBR_LIMITER_BANDS_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_limiter_gains, + SI_SBR_LIMITER_GAINS_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrHeaderData->sbr_interpol_freq, + SI_SBR_INTERPOL_FREQ_BITS); + payloadBits += + FDKwriteBits(hBitStream, sbrHeaderData->sbr_smoothing_length, + SI_SBR_SMOOTHING_LENGTH_BITS); + + } /* sbrHeaderData->header_extra_2 */ + } /* sbrHeaderData != NULL */ + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrData + description: encodes sbr Data information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrData(HANDLE_SBR_ENV_DATA sbrEnvDataLeft, + HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_COMMON_DATA cmonData, SBR_ELEMENT_TYPE sbrElem, + INT coupling, UINT sbrSyntaxFlags) { + INT payloadBits = 0; + + switch (sbrElem) { + case SBR_ID_SCE: + payloadBits += + encodeSbrSingleChannelElement(sbrEnvDataLeft, &cmonData->sbrBitbuf, + hParametricStereo, sbrSyntaxFlags); + break; + case SBR_ID_CPE: + payloadBits += encodeSbrChannelPairElement( + sbrEnvDataLeft, sbrEnvDataRight, hParametricStereo, + &cmonData->sbrBitbuf, coupling, sbrSyntaxFlags); + break; + default: + /* we never should apply SBR to any other element type */ + FDK_ASSERT(0); + } + + cmonData->sbrDataBits = payloadBits; + + return payloadBits; +} + +#define MODE_FREQ_TANS 1 +#define MODE_NO_FREQ_TRAN 0 +#define LD_TRANSMISSION MODE_FREQ_TANS +static int encodeFreqs(int mode) { return ((mode & MODE_FREQ_TANS) ? 1 : 0); } + +/***************************************************************************** + + functionname: encodeSbrSingleChannelElement + description: encodes sbr SCE information + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeSbrSingleChannelElement( + HANDLE_SBR_ENV_DATA sbrEnvData, HANDLE_FDK_BITSTREAM hBitStream, + HANDLE_PARAMETRIC_STEREO hParametricStereo, const UINT sbrSyntaxFlags) { + INT i, payloadBits = 0; + + payloadBits += FDKwriteBits(hBitStream, 0, + SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + if (sbrEnvData->ldGrid) { + if (sbrEnvData->hSbrBSGrid->frameClass != FIXFIXonly) { + /* encode normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvData, hBitStream); + } else { + /* use FIXFIXonly frame Grid */ + payloadBits += encodeLowDelaySbrGrid( + sbrEnvData, hBitStream, encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else { + if (sbrSyntaxFlags & SBR_SYNTAX_SCALABLE) { + payloadBits += FDKwriteBits(hBitStream, 1, SI_SBR_COUPLING_BITS); + } + payloadBits += encodeSbrGrid(sbrEnvData, hBitStream); + } + + payloadBits += encodeSbrDtdf(sbrEnvData, hBitStream); + + for (i = 0; i < sbrEnvData->noOfnoisebands; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvData, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvData, hBitStream, 0); + + payloadBits += writeSyntheticCodingData(sbrEnvData, hBitStream); + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrChannelPairElement + description: encodes sbr CPE information + returns: + input: + output: + +*****************************************************************************/ +static INT encodeSbrChannelPairElement( + HANDLE_SBR_ENV_DATA sbrEnvDataLeft, HANDLE_SBR_ENV_DATA sbrEnvDataRight, + HANDLE_PARAMETRIC_STEREO hParametricStereo, HANDLE_FDK_BITSTREAM hBitStream, + const INT coupling, const UINT sbrSyntaxFlags) { + INT payloadBits = 0; + INT i = 0; + + payloadBits += FDKwriteBits(hBitStream, 0, + SI_SBR_DATA_EXTRA_BITS); /* no reserved bits */ + + payloadBits += FDKwriteBits(hBitStream, coupling, SI_SBR_COUPLING_BITS); + + if (coupling) { + if (sbrEnvDataLeft->ldGrid) { + if (sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly) { + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataLeft, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + payloadBits += encodeSbrDtdf(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf(sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvDataLeft, hBitStream, 1); + payloadBits += writeNoiseLevelData(sbrEnvDataLeft, hBitStream, 1); + payloadBits += writeEnvelopeData(sbrEnvDataRight, hBitStream, 1); + payloadBits += writeNoiseLevelData(sbrEnvDataRight, hBitStream, 1); + + payloadBits += writeSyntheticCodingData(sbrEnvDataLeft, hBitStream); + payloadBits += writeSyntheticCodingData(sbrEnvDataRight, hBitStream); + + } else { /* no coupling */ + FDK_ASSERT(sbrEnvDataLeft->ldGrid == sbrEnvDataRight->ldGrid); + + if (sbrEnvDataLeft->ldGrid || sbrEnvDataRight->ldGrid) { + /* sbrEnvDataLeft (left channel) */ + if (sbrEnvDataLeft->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataLeft, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + + /* sbrEnvDataRight (right channel) */ + if (sbrEnvDataRight->hSbrBSGrid->frameClass != FIXFIXonly) { + /* no FIXFIXonly Frame so we dont need encodeLowDelaySbrGrid */ + /* normal SbrGrid */ + payloadBits += encodeSbrGrid(sbrEnvDataRight, hBitStream); + + } else { + /* FIXFIXonly frame Grid */ + payloadBits += + encodeLowDelaySbrGrid(sbrEnvDataRight, hBitStream, + encodeFreqs(LD_TRANSMISSION), sbrSyntaxFlags); + } + } else { + payloadBits += encodeSbrGrid(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrGrid(sbrEnvDataRight, hBitStream); + } + payloadBits += encodeSbrDtdf(sbrEnvDataLeft, hBitStream); + payloadBits += encodeSbrDtdf(sbrEnvDataRight, hBitStream); + + for (i = 0; i < sbrEnvDataLeft->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataLeft->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + for (i = 0; i < sbrEnvDataRight->noOfnoisebands; i++) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvDataRight->sbr_invf_mode_vec[i], + SI_SBR_INVF_MODE_BITS); + } + + payloadBits += writeEnvelopeData(sbrEnvDataLeft, hBitStream, 0); + payloadBits += writeEnvelopeData(sbrEnvDataRight, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvDataLeft, hBitStream, 0); + payloadBits += writeNoiseLevelData(sbrEnvDataRight, hBitStream, 0); + + payloadBits += writeSyntheticCodingData(sbrEnvDataLeft, hBitStream); + payloadBits += writeSyntheticCodingData(sbrEnvDataRight, hBitStream); + + } /* coupling */ + + payloadBits += encodeExtendedData(hParametricStereo, hBitStream); + + return payloadBits; +} + +static INT ceil_ln2(INT x) { + INT tmp = -1; + while ((1 << ++tmp) < x) + ; + return (tmp); +} + +/***************************************************************************** + + functionname: encodeSbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; else counts them only + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static INT encodeSbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) { + INT payloadBits = 0; + INT i, temp; + INT bufferFrameStart = sbrEnvData->hSbrBSGrid->bufferFrameStart; + INT numberTimeSlots = sbrEnvData->hSbrBSGrid->numberTimeSlots; + + if (sbrEnvData->ldGrid) + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS_LD); + else + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->frameClass, + SBR_CLA_BITS); + + switch (sbrEnvData->hSbrBSGrid->frameClass) { + case FIXFIXonly: + FDK_ASSERT(0 /* Fatal error in encodeSbrGrid! */); + break; + case FIXFIX: + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_env); + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ENV_BITS); + if ((sbrEnvData->ldGrid) && (sbrEnvData->hSbrBSGrid->bs_num_env == 1)) + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->currentAmpResFF, + SI_SBR_AMP_RES_BITS); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[0], + SBR_RES_BITS); + + break; + + case FIXVAR: + case VARFIX: + if (sbrEnvData->hSbrBSGrid->frameClass == FIXVAR) + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - + (bufferFrameStart + numberTimeSlots); + else + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord - bufferFrameStart; + + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->n, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->n + 2); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->n + 1; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], + SBR_RES_BITS); + } + break; + + case VARVAR: + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_0 - bufferFrameStart; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + temp = sbrEnvData->hSbrBSGrid->bs_abs_bord_1 - + (bufferFrameStart + numberTimeSlots); + payloadBits += FDKwriteBits(hBitStream, temp, SBR_ABS_BITS); + + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_0, SBR_NUM_BITS); + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->bs_num_rel_1, SBR_NUM_BITS); + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_0; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_0[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_rel_1; i++) { + temp = (sbrEnvData->hSbrBSGrid->bs_rel_bord_1[i] - 2) >> 1; + payloadBits += FDKwriteBits(hBitStream, temp, SBR_REL_BITS); + } + + temp = ceil_ln2(sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 2); + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->p, temp); + + temp = sbrEnvData->hSbrBSGrid->bs_num_rel_0 + + sbrEnvData->hSbrBSGrid->bs_num_rel_1 + 1; + + for (i = 0; i < temp; i++) { + payloadBits += FDKwriteBits( + hBitStream, sbrEnvData->hSbrBSGrid->v_fLR[i], SBR_RES_BITS); + } + break; + } + + return payloadBits; +} + +#define SBR_CLA_BITS_LD 1 +/***************************************************************************** + + functionname: encodeLowDelaySbrGrid + description: if hBitStream != NULL writes bits that describes the + time/frequency grouping of a frame; + else counts them only + (this function only write the FIXFIXonly Bitstream data) + returns: number of bits written or counted + input: + output: + +*****************************************************************************/ +static int encodeLowDelaySbrGrid(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, + const int transmitFreqs, + const UINT sbrSyntaxFlags) { + int payloadBits = 0; + int i; + + /* write FIXFIXonly Grid */ + /* write frameClass [1 bit] for FIXFIXonly Grid */ + payloadBits += FDKwriteBits(hBitStream, 1, SBR_CLA_BITS_LD); + + /* absolute Borders are fix: 0,X,X,X,nTimeSlots; so we dont have to transmit + * them */ + /* only transmit the transient position! */ + /* with this info (b1) we can reconstruct the Frame on Decoder side : */ + /* border[0] = 0; border[1] = b1; border[2]=b1+2; border[3] = nrTimeSlots */ + + /* use 3 or 4bits for transient border (border) */ + if (sbrEnvData->hSbrBSGrid->numberTimeSlots == 8) + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 3); + else + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->bs_abs_bord, 4); + + if (transmitFreqs) { + /* write FreqRes grid */ + for (i = 0; i < sbrEnvData->hSbrBSGrid->bs_num_env; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->hSbrBSGrid->v_f[i], + SBR_RES_BITS); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeSbrDtdf + description: writes bits that describes the direction of the envelopes of a +frame returns: number of bits written input: output: + +*****************************************************************************/ +static INT encodeSbrDtdf(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) { + INT i, payloadBits = 0, noOfNoiseEnvelopes; + + noOfNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < sbrEnvData->noOfEnvelopes; ++i) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->domain_vec[i], SBR_DIR_BITS); + } + for (i = 0; i < noOfNoiseEnvelopes; ++i) { + payloadBits += + FDKwriteBits(hBitStream, sbrEnvData->domain_vec_noise[i], SBR_DIR_BITS); + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: writeNoiseLevelData + description: writes bits corresponding to the noise-floor-level + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeNoiseLevelData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling) { + INT j, i, payloadBits = 0; + INT nNoiseEnvelopes = sbrEnvData->noOfEnvelopes > 1 ? 2 : 1; + + for (i = 0; i < nNoiseEnvelopes; i++) { + switch (sbrEnvData->domain_vec_noise[i]) { + case FREQ: + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits_balance); + } else { + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->sbr_noise_levels[i * sbrEnvData->noOfnoisebands], + sbrEnvData->si_sbr_start_noise_bits); + } + + for (j = 1 + i * sbrEnvData->noOfnoisebands; + j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits(hBitStream, + sbrEnvData->hufftableNoiseBalanceFreqC + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceFreqL + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableNoiseLevelFreqC + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelFreqL + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableNoiseFreqC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData + ->hufftableNoiseFreqL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + + case TIME: + for (j = i * sbrEnvData->noOfnoisebands; + j < (sbrEnvData->noOfnoisebands * (1 + i)); j++) { + if (coupling) { + if (sbrEnvData->balance) { + /* coupling && balance */ + payloadBits += FDKwriteBits(hBitStream, + sbrEnvData->hufftableNoiseBalanceTimeC + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11], + sbrEnvData->hufftableNoiseBalanceTimeL + [sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV_BALANCE11]); + } else { + /* coupling && !balance */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableNoiseLevelTimeC + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11], + sbrEnvData->hufftableNoiseLevelTimeL + [sbrEnvData->sbr_noise_levels[j] + CODE_BOOK_SCF_LAV11]); + } + } else { + /* !coupling */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableNoiseLevelTimeC[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11], + sbrEnvData + ->hufftableNoiseLevelTimeL[sbrEnvData->sbr_noise_levels[j] + + CODE_BOOK_SCF_LAV11]); + } + } + break; + } + } + return payloadBits; +} + +/***************************************************************************** + + functionname: writeEnvelopeData + description: writes bits corresponding to the envelope + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeEnvelopeData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream, INT coupling) { + INT payloadBits = 0, j, i, delta; + + for (j = 0; j < sbrEnvData->noOfEnvelopes; + j++) { /* loop over all envelopes */ + if (sbrEnvData->domain_vec[j] == FREQ) { + if (coupling && sbrEnvData->balance) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->ienvelope[j][0], + sbrEnvData->si_sbr_start_env_bits_balance); + } else { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->ienvelope[j][0], + sbrEnvData->si_sbr_start_env_bits); + } + } + + for (i = 1 - sbrEnvData->domain_vec[j]; i < sbrEnvData->noScfBands[j]; + i++) { + delta = sbrEnvData->ienvelope[j][i]; + if (coupling && sbrEnvData->balance) { + FDK_ASSERT(fixp_abs(delta) <= sbrEnvData->codeBookScfLavBalance); + } else { + FDK_ASSERT(fixp_abs(delta) <= sbrEnvData->codeBookScfLav); + } + if (coupling) { + if (sbrEnvData->balance) { + if (sbrEnvData->domain_vec[j]) { + /* coupling && balance && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableBalanceTimeC[delta + + sbrEnvData->codeBookScfLavBalance], + sbrEnvData + ->hufftableBalanceTimeL[delta + + sbrEnvData->codeBookScfLavBalance]); + } else { + /* coupling && balance && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableBalanceFreqC[delta + + sbrEnvData->codeBookScfLavBalance], + sbrEnvData + ->hufftableBalanceFreqL[delta + + sbrEnvData->codeBookScfLavBalance]); + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* coupling && !balance && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableLevelTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData + ->hufftableLevelTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* coupling && !balance && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData + ->hufftableLevelFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData + ->hufftableLevelFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } else { + if (sbrEnvData->domain_vec[j]) { + /* !coupling && TIME */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableTimeC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableTimeL[delta + sbrEnvData->codeBookScfLav]); + } else { + /* !coupling && FREQ */ + payloadBits += FDKwriteBits( + hBitStream, + sbrEnvData->hufftableFreqC[delta + sbrEnvData->codeBookScfLav], + sbrEnvData->hufftableFreqL[delta + sbrEnvData->codeBookScfLav]); + } + } + } + } + return payloadBits; +} + +/***************************************************************************** + + functionname: encodeExtendedData + description: writes bits corresponding to the extended data + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT encodeExtendedData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitStream) { + INT extDataSize; + INT payloadBits = 0; + + extDataSize = getSbrExtendedDataSize(hParametricStereo); + + if (extDataSize != 0) { + INT maxExtSize = (1 << SI_SBR_EXTENSION_SIZE_BITS) - 1; + INT writtenNoBits = 0; /* needed to byte align the extended data */ + + payloadBits += FDKwriteBits(hBitStream, 1, SI_SBR_EXTENDED_DATA_BITS); + FDK_ASSERT(extDataSize <= SBR_EXTENDED_DATA_MAX_CNT); + + if (extDataSize < maxExtSize) { + payloadBits += + FDKwriteBits(hBitStream, extDataSize, SI_SBR_EXTENSION_SIZE_BITS); + } else { + payloadBits += + FDKwriteBits(hBitStream, maxExtSize, SI_SBR_EXTENSION_SIZE_BITS); + payloadBits += FDKwriteBits(hBitStream, extDataSize - maxExtSize, + SI_SBR_EXTENSION_ESC_COUNT_BITS); + } + + /* parametric coding signalled here? */ + if (hParametricStereo) { + writtenNoBits += FDKwriteBits(hBitStream, EXTENSION_ID_PS_CODING, + SI_SBR_EXTENSION_ID_BITS); + writtenNoBits += + FDKsbrEnc_PSEnc_WritePSData(hParametricStereo, hBitStream); + } + + payloadBits += writtenNoBits; + + /* byte alignment */ + writtenNoBits = writtenNoBits % 8; + if (writtenNoBits) + payloadBits += FDKwriteBits(hBitStream, 0, (8 - writtenNoBits)); + } else { + payloadBits += FDKwriteBits(hBitStream, 0, SI_SBR_EXTENDED_DATA_BITS); + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: writeSyntheticCodingData + description: writes bits corresponding to the "synthetic-coding"-extension + returns: number of bits written + input: + output: + +*****************************************************************************/ +static INT writeSyntheticCodingData(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_FDK_BITSTREAM hBitStream) + +{ + INT i; + INT payloadBits = 0; + + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->addHarmonicFlag, 1); + + if (sbrEnvData->addHarmonicFlag) { + for (i = 0; i < sbrEnvData->noHarmonics; i++) { + payloadBits += FDKwriteBits(hBitStream, sbrEnvData->addHarmonic[i], 1); + } + } + + return payloadBits; +} + +/***************************************************************************** + + functionname: getSbrExtendedDataSize + description: counts the number of bits needed for encoding the + extended data (including extension id) + + returns: number of bits needed for the extended data + input: + output: + +*****************************************************************************/ +static INT getSbrExtendedDataSize(HANDLE_PARAMETRIC_STEREO hParametricStereo) { + INT extDataBits = 0; + + /* add your new extended data counting methods here */ + + /* + no extended data + */ + + if (hParametricStereo) { + /* PS extended data */ + extDataBits += SI_SBR_EXTENSION_ID_BITS; + extDataBits += FDKsbrEnc_PSEnc_WritePSData(hParametricStereo, NULL); + } + + return (extDataBits + 7) >> 3; +} diff --git a/fdk-aac/libSBRenc/src/bit_sbr.h b/fdk-aac/libSBRenc/src/bit_sbr.h new file mode 100644 index 0000000..e90f52c --- /dev/null +++ b/fdk-aac/libSBRenc/src/bit_sbr.h @@ -0,0 +1,267 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR bit writing $Revision: 92790 $ +*/ +#ifndef BIT_SBR_H +#define BIT_SBR_H + +#include "sbr_def.h" +#include "cmondata.h" +#include "fram_gen.h" + +struct SBR_ENV_DATA; + +struct SBR_BITSTREAM_DATA { + INT TotalBits; + INT PayloadBits; + INT FillBits; + INT HeaderActive; + INT HeaderActiveDelay; /**< sbr payload and its header is delayed depending on + encoder configuration*/ + INT NrSendHeaderData; /**< input from commandline */ + INT CountSendHeaderData; /**< modulo count. If < 0 then no counting is done + (no SBR headers) */ + INT rightBorderFIX; /**< force VARFIX or FIXFIX frames */ +}; + +typedef struct SBR_BITSTREAM_DATA *HANDLE_SBR_BITSTREAM_DATA; + +struct SBR_HEADER_DATA { + AMP_RES sbr_amp_res; + INT sbr_start_frequency; + INT sbr_stop_frequency; + INT sbr_xover_band; + INT sbr_noise_bands; + INT sbr_data_extra; + INT header_extra_1; + INT header_extra_2; + INT sbr_lc_stereo_mode; + INT sbr_limiter_bands; + INT sbr_limiter_gains; + INT sbr_interpol_freq; + INT sbr_smoothing_length; + INT alterScale; + INT freqScale; + + /* + element of channelpairelement + */ + INT coupling; + INT prev_coupling; + + /* + element of singlechannelelement + */ +}; +typedef struct SBR_HEADER_DATA *HANDLE_SBR_HEADER_DATA; + +struct SBR_ENV_DATA { + INT sbr_xpos_ctrl; + FREQ_RES freq_res_fixfix[2]; + UCHAR fResTransIsLow; + + INVF_MODE sbr_invf_mode; + INVF_MODE sbr_invf_mode_vec[MAX_NUM_NOISE_VALUES]; + + XPOS_MODE sbr_xpos_mode; + + INT ienvelope[MAX_ENVELOPES][MAX_FREQ_COEFFS]; + + INT codeBookScfLavBalance; + INT codeBookScfLav; + const INT *hufftableTimeC; + const INT *hufftableFreqC; + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const INT *hufftableLevelTimeC; + const INT *hufftableBalanceTimeC; + const INT *hufftableLevelFreqC; + const INT *hufftableBalanceFreqC; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + const UCHAR *hufftableNoiseTimeL; + const INT *hufftableNoiseTimeC; + const UCHAR *hufftableNoiseFreqL; + const INT *hufftableNoiseFreqC; + + const UCHAR *hufftableNoiseLevelTimeL; + const INT *hufftableNoiseLevelTimeC; + const UCHAR *hufftableNoiseBalanceTimeL; + const INT *hufftableNoiseBalanceTimeC; + const UCHAR *hufftableNoiseLevelFreqL; + const INT *hufftableNoiseLevelFreqC; + const UCHAR *hufftableNoiseBalanceFreqL; + const INT *hufftableNoiseBalanceFreqC; + + HANDLE_SBR_GRID hSbrBSGrid; + + INT noHarmonics; + INT addHarmonicFlag; + UCHAR addHarmonic[MAX_FREQ_COEFFS]; + + /* calculated helper vars */ + INT si_sbr_start_env_bits_balance; + INT si_sbr_start_env_bits; + INT si_sbr_start_noise_bits_balance; + INT si_sbr_start_noise_bits; + + INT noOfEnvelopes; + INT noScfBands[MAX_ENVELOPES]; + INT domain_vec[MAX_ENVELOPES]; + INT domain_vec_noise[MAX_ENVELOPES]; + SCHAR sbr_noise_levels[MAX_FREQ_COEFFS]; + INT noOfnoisebands; + + INT balance; + AMP_RES init_sbr_amp_res; + AMP_RES currentAmpResFF; + FIXP_DBL + ton_HF[SBR_GLOBAL_TONALITY_VALUES]; /* tonality is scaled by + 2^19/0.524288f (fract part of + RELAXATION) */ + FIXP_DBL global_tonality; + + /* extended data */ + INT extended_data; + INT extension_size; + INT extension_id; + UCHAR extended_data_buffer[SBR_EXTENDED_DATA_MAX_CNT]; + + UCHAR ldGrid; +}; +typedef struct SBR_ENV_DATA *HANDLE_SBR_ENV_DATA; + +INT FDKsbrEnc_WriteEnvSingleChannelElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvData, struct COMMON_DATA *cmonData, + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_WriteEnvChannelPairElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, UINT sbrSyntaxFlags); + +INT FDKsbrEnc_CountSbrChannelPairElement( + struct SBR_HEADER_DATA *sbrHeaderData, + struct T_PARAMETRIC_STEREO *hParametricStereo, + struct SBR_BITSTREAM_DATA *sbrBitstreamData, + struct SBR_ENV_DATA *sbrEnvDataLeft, struct SBR_ENV_DATA *sbrEnvDataRight, + struct COMMON_DATA *cmonData, UINT sbrSyntaxFlags); + +/* debugging and tuning functions */ + +/*#define SBR_ENV_STATISTICS */ + +/*#define SBR_PAYLOAD_MONITOR*/ + +#endif diff --git a/fdk-aac/libSBRenc/src/cmondata.h b/fdk-aac/libSBRenc/src/cmondata.h new file mode 100644 index 0000000..0779b4d --- /dev/null +++ b/fdk-aac/libSBRenc/src/cmondata.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Core Coder's and SBR's shared data structure definition $Revision: + 92790 $ +*/ +#ifndef CMONDATA_H +#define CMONDATA_H + +#include "FDK_bitstream.h" + +struct COMMON_DATA { + INT sbrHdrBits; /**< number of SBR header bits */ + INT sbrDataBits; /**< number of SBR data bits */ + INT sbrFillBits; /**< number of SBR fill bits */ + FDK_BITSTREAM sbrBitbuf; /**< the SBR data bitbuffer */ + FDK_BITSTREAM tmpWriteBitbuf; /**< helper var for writing header*/ + INT xOverFreq; /**< the SBR crossover frequency */ + INT dynBwEnabled; /**< indicates if dynamic bandwidth is enabled */ + INT sbrNumChannels; /**< number of channels (meaning mono or stereo) */ + INT dynXOverFreqEnc; /**< encoder dynamic crossover frequency */ +}; + +typedef struct COMMON_DATA *HANDLE_COMMON_DATA; + +#endif diff --git a/fdk-aac/libSBRenc/src/code_env.cpp b/fdk-aac/libSBRenc/src/code_env.cpp new file mode 100644 index 0000000..fb0f6a4 --- /dev/null +++ b/fdk-aac/libSBRenc/src/code_env.cpp @@ -0,0 +1,602 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "code_env.h" +#include "sbrenc_rom.h" + +/***************************************************************************** + + functionname: FDKsbrEnc_InitSbrHuffmanTables + description: initializes Huffman Tables dependent on chosen amp_res + returns: error handle + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_InitSbrHuffmanTables(HANDLE_SBR_ENV_DATA sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res) { + if ((!henv) || (!hnoise) || (!sbrEnvData)) return (1); /* not init. */ + + sbrEnvData->init_sbr_amp_res = amp_res; + + switch (amp_res) { + case SBR_AMP_RES_3_0: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC11T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL11T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL11F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC11T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL11T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE11; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV11; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_env_bits_balance = + SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0; + break; + + case SBR_AMP_RES_1_5: + /*envelope data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableLevelTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableLevelTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableBalanceTimeC = bookSbrEnvBalanceC10T; + sbrEnvData->hufftableBalanceTimeL = bookSbrEnvBalanceL10T; + + sbrEnvData->hufftableLevelFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableLevelFreqL = v_Huff_envelopeLevelL10F; + sbrEnvData->hufftableBalanceFreqC = bookSbrEnvBalanceC10F; + sbrEnvData->hufftableBalanceFreqL = bookSbrEnvBalanceL10F; + + /*Right/Left - coding */ + sbrEnvData->hufftableTimeC = v_Huff_envelopeLevelC10T; + sbrEnvData->hufftableTimeL = v_Huff_envelopeLevelL10T; + sbrEnvData->hufftableFreqC = v_Huff_envelopeLevelC10F; + sbrEnvData->hufftableFreqL = v_Huff_envelopeLevelL10F; + + sbrEnvData->codeBookScfLavBalance = CODE_BOOK_SCF_LAV_BALANCE10; + sbrEnvData->codeBookScfLav = CODE_BOOK_SCF_LAV10; + + sbrEnvData->si_sbr_start_env_bits = SI_SBR_START_ENV_BITS_AMP_RES_1_5; + sbrEnvData->si_sbr_start_env_bits_balance = + SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5; + break; + + default: + return (1); /* undefined amp_res mode */ + } + + /* these are common to both amp_res values */ + /*Noise data*/ + + /*Level/Pan - coding */ + sbrEnvData->hufftableNoiseLevelTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseLevelTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseBalanceTimeC = bookSbrNoiseBalanceC11T; + sbrEnvData->hufftableNoiseBalanceTimeL = bookSbrNoiseBalanceL11T; + + sbrEnvData->hufftableNoiseLevelFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseLevelFreqL = v_Huff_envelopeLevelL11F; + sbrEnvData->hufftableNoiseBalanceFreqC = bookSbrEnvBalanceC11F; + sbrEnvData->hufftableNoiseBalanceFreqL = bookSbrEnvBalanceL11F; + + /*Right/Left - coding */ + sbrEnvData->hufftableNoiseTimeC = v_Huff_NoiseLevelC11T; + sbrEnvData->hufftableNoiseTimeL = v_Huff_NoiseLevelL11T; + sbrEnvData->hufftableNoiseFreqC = v_Huff_envelopeLevelC11F; + sbrEnvData->hufftableNoiseFreqL = v_Huff_envelopeLevelL11F; + + sbrEnvData->si_sbr_start_noise_bits = SI_SBR_START_NOISE_BITS_AMP_RES_3_0; + sbrEnvData->si_sbr_start_noise_bits_balance = + SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0; + + /* init envelope tables and codebooks */ + henv->codeBookScfLavBalanceTime = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavBalanceFreq = sbrEnvData->codeBookScfLavBalance; + henv->codeBookScfLavLevelTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavLevelFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + + henv->hufftableLevelTimeL = sbrEnvData->hufftableLevelTimeL; + henv->hufftableBalanceTimeL = sbrEnvData->hufftableBalanceTimeL; + henv->hufftableTimeL = sbrEnvData->hufftableTimeL; + henv->hufftableLevelFreqL = sbrEnvData->hufftableLevelFreqL; + henv->hufftableBalanceFreqL = sbrEnvData->hufftableBalanceFreqL; + henv->hufftableFreqL = sbrEnvData->hufftableFreqL; + + henv->codeBookScfLavFreq = sbrEnvData->codeBookScfLav; + henv->codeBookScfLavTime = sbrEnvData->codeBookScfLav; + + henv->start_bits = sbrEnvData->si_sbr_start_env_bits; + henv->start_bits_balance = sbrEnvData->si_sbr_start_env_bits_balance; + + /* init noise tables and codebooks */ + + hnoise->codeBookScfLavBalanceTime = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavBalanceFreq = CODE_BOOK_SCF_LAV_BALANCE11; + hnoise->codeBookScfLavLevelTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavLevelFreq = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavTime = CODE_BOOK_SCF_LAV11; + hnoise->codeBookScfLavFreq = CODE_BOOK_SCF_LAV11; + + hnoise->hufftableLevelTimeL = sbrEnvData->hufftableNoiseLevelTimeL; + hnoise->hufftableBalanceTimeL = sbrEnvData->hufftableNoiseBalanceTimeL; + hnoise->hufftableTimeL = sbrEnvData->hufftableNoiseTimeL; + hnoise->hufftableLevelFreqL = sbrEnvData->hufftableNoiseLevelFreqL; + hnoise->hufftableBalanceFreqL = sbrEnvData->hufftableNoiseBalanceFreqL; + hnoise->hufftableFreqL = sbrEnvData->hufftableNoiseFreqL; + + hnoise->start_bits = sbrEnvData->si_sbr_start_noise_bits; + hnoise->start_bits_balance = sbrEnvData->si_sbr_start_noise_bits_balance; + + /* No delta coding in time from the previous frame due to 1.5dB FIx-FIX rule + */ + henv->upDate = 0; + hnoise->upDate = 0; + return (0); +} + +/******************************************************************************* + Functionname: indexLow2High + ******************************************************************************* + + Description: Nice small patch-functions in order to cope with non-factor-2 + ratios between high-res and low-res + + Arguments: INT offset, INT index, FREQ_RES res + + Return: INT + +*******************************************************************************/ +static INT indexLow2High(INT offset, INT index, FREQ_RES res) { + if (res == FREQ_RES_LOW) { + if (offset >= 0) { + if (index < offset) + return (index); + else + return (2 * index - offset); + } else { + offset = -offset; + if (index < offset) + return (2 * index + index); + else + return (2 * index + offset); + } + } else + return (index); +} + +/******************************************************************************* + Functionname: mapLowResEnergyVal + ******************************************************************************* + + Description: + + Arguments: INT currVal,INT* prevData, INT offset, INT index, FREQ_RES res + + Return: none + +*******************************************************************************/ +static void mapLowResEnergyVal(SCHAR currVal, SCHAR *prevData, INT offset, + INT index, FREQ_RES res) { + if (res == FREQ_RES_LOW) { + if (offset >= 0) { + if (index < offset) + prevData[index] = currVal; + else { + prevData[2 * index - offset] = currVal; + prevData[2 * index + 1 - offset] = currVal; + } + } else { + offset = -offset; + if (index < offset) { + prevData[3 * index] = currVal; + prevData[3 * index + 1] = currVal; + prevData[3 * index + 2] = currVal; + } else { + prevData[2 * index + offset] = currVal; + prevData[2 * index + 1 + offset] = currVal; + } + } + } else + prevData[index] = currVal; +} + +/******************************************************************************* + Functionname: computeBits + ******************************************************************************* + + Description: + + Arguments: INT delta, + INT codeBookScfLavLevel, + INT codeBookScfLavBalance, + const UCHAR * hufftableLevel, + const UCHAR * hufftableBalance, INT coupling, INT channel) + + Return: INT + +*******************************************************************************/ +static INT computeBits(SCHAR *delta, INT codeBookScfLavLevel, + INT codeBookScfLavBalance, const UCHAR *hufftableLevel, + const UCHAR *hufftableBalance, INT coupling, + INT channel) { + INT index; + INT delta_bits = 0; + + if (coupling) { + if (channel == 1) { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavBalance); + else + index = fixMin(*delta, codeBookScfLavBalance); + + if (index != *delta) { + *delta = index; + return (10000); + } + + delta_bits = hufftableBalance[index + codeBookScfLavBalance]; + } else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + } else { + if (*delta < 0) + index = fixMax(*delta, -codeBookScfLavLevel); + else + index = fixMin(*delta, codeBookScfLavLevel); + + if (index != *delta) { + *delta = index; + return (10000); + } + delta_bits = hufftableLevel[index + codeBookScfLavLevel]; + } + + return (delta_bits); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_codeEnvelope + ******************************************************************************* + + Description: + + Arguments: INT *sfb_nrg, + const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE * h_sbrCodeEnvelope, + INT *directionVec, INT scalable, INT nEnvelopes, INT channel, + INT headerActive) + + Return: none + h_sbrCodeEnvelope->sfb_nrg_prev is modified ! + sfb_nrg is modified + h_sbrCodeEnvelope->update is modfied ! + *directionVec is modified + +*******************************************************************************/ +void FDKsbrEnc_codeEnvelope(SCHAR *sfb_nrg, const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE *h_sbrCodeEnvelope, + INT *directionVec, INT coupling, INT nEnvelopes, + INT channel, INT headerActive) { + INT i, no_of_bands, band; + FIXP_DBL tmp1, tmp2, tmp3, dF_edge_1stEnv; + SCHAR *ptr_nrg; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; + + INT offset = h_sbrCodeEnvelope->offset; + INT envDataTableCompFactor; + + INT delta_F_bits = 0, delta_T_bits = 0; + INT use_dT; + + SCHAR delta_F[MAX_FREQ_COEFFS]; + SCHAR delta_T[MAX_FREQ_COEFFS]; + SCHAR last_nrg, curr_nrg; + + tmp1 = FL2FXCONST_DBL(0.5f) >> (DFRACT_BITS - 16 - 1); + tmp2 = h_sbrCodeEnvelope->dF_edge_1stEnv >> (DFRACT_BITS - 16); + tmp3 = (FIXP_DBL)fMult(h_sbrCodeEnvelope->dF_edge_incr, + ((FIXP_DBL)h_sbrCodeEnvelope->dF_edge_incr_fac) << 15); + + dF_edge_1stEnv = tmp1 + tmp2 + tmp3; + + if (coupling) { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavLevelTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavLevelFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavBalanceTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavBalanceFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableLevelTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableBalanceTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableLevelFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableBalanceFreqL; + } else { + codeBookScfLavLevelTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavLevelFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + codeBookScfLavBalanceTime = h_sbrCodeEnvelope->codeBookScfLavTime; + codeBookScfLavBalanceFreq = h_sbrCodeEnvelope->codeBookScfLavFreq; + hufftableLevelTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableBalanceTimeL = h_sbrCodeEnvelope->hufftableTimeL; + hufftableLevelFreqL = h_sbrCodeEnvelope->hufftableFreqL; + hufftableBalanceFreqL = h_sbrCodeEnvelope->hufftableFreqL; + } + + if (coupling == 1 && channel == 1) + envDataTableCompFactor = + 1; /*should be one when the new huffman-tables are ready*/ + else + envDataTableCompFactor = 0; + + if (h_sbrCodeEnvelope->deltaTAcrossFrames == 0) h_sbrCodeEnvelope->upDate = 0; + + /* no delta coding in time in case of a header */ + if (headerActive) h_sbrCodeEnvelope->upDate = 0; + + for (i = 0; i < nEnvelopes; i++) { + if (freq_res[i] == FREQ_RES_HIGH) + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + else + no_of_bands = h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW]; + + ptr_nrg = sfb_nrg; + curr_nrg = *ptr_nrg; + + delta_F[0] = curr_nrg >> envDataTableCompFactor; + + if (coupling && channel == 1) + delta_F_bits = h_sbrCodeEnvelope->start_bits_balance; + else + delta_F_bits = h_sbrCodeEnvelope->start_bits; + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T[0] = (curr_nrg - h_sbrCodeEnvelope->sfb_nrg_prev[0]) >> + envDataTableCompFactor; + + delta_T_bits = computeBits(&delta_T[0], codeBookScfLavLevelTime, + codeBookScfLavBalanceTime, hufftableLevelTimeL, + hufftableBalanceTimeL, coupling, channel); + } + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, 0, + freq_res[i]); + + /* ensure that nrg difference is not higher than codeBookScfLavXXXFreq */ + if (coupling && channel == 1) { + for (band = no_of_bands - 1; band > 0; band--) { + if (ptr_nrg[band] - ptr_nrg[band - 1] > codeBookScfLavBalanceFreq) { + ptr_nrg[band - 1] = ptr_nrg[band] - codeBookScfLavBalanceFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if (ptr_nrg[band - 1] - ptr_nrg[band] > codeBookScfLavBalanceFreq) { + ptr_nrg[band] = ptr_nrg[band - 1] - codeBookScfLavBalanceFreq; + } + } + } else { + for (band = no_of_bands - 1; band > 0; band--) { + if (ptr_nrg[band] - ptr_nrg[band - 1] > codeBookScfLavLevelFreq) { + ptr_nrg[band - 1] = ptr_nrg[band] - codeBookScfLavLevelFreq; + } + } + for (band = 1; band < no_of_bands; band++) { + if (ptr_nrg[band - 1] - ptr_nrg[band] > codeBookScfLavLevelFreq) { + ptr_nrg[band] = ptr_nrg[band - 1] - codeBookScfLavLevelFreq; + } + } + } + + /* Coding loop*/ + for (band = 1; band < no_of_bands; band++) { + last_nrg = (*ptr_nrg); + ptr_nrg++; + curr_nrg = (*ptr_nrg); + + delta_F[band] = (curr_nrg - last_nrg) >> envDataTableCompFactor; + + delta_F_bits += computeBits( + &delta_F[band], codeBookScfLavLevelFreq, codeBookScfLavBalanceFreq, + hufftableLevelFreqL, hufftableBalanceFreqL, coupling, channel); + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T[band] = + curr_nrg - + h_sbrCodeEnvelope + ->sfb_nrg_prev[indexLow2High(offset, band, freq_res[i])]; + delta_T[band] = delta_T[band] >> envDataTableCompFactor; + } + + mapLowResEnergyVal(curr_nrg, h_sbrCodeEnvelope->sfb_nrg_prev, offset, + band, freq_res[i]); + + if (h_sbrCodeEnvelope->upDate != 0) { + delta_T_bits += computeBits( + &delta_T[band], codeBookScfLavLevelTime, codeBookScfLavBalanceTime, + hufftableLevelTimeL, hufftableBalanceTimeL, coupling, channel); + } + } + + /* Replace sfb_nrg with deltacoded samples and set flag */ + if (i == 0) { + INT tmp_bits; + tmp_bits = (((delta_T_bits * dF_edge_1stEnv) >> (DFRACT_BITS - 18)) + + (FIXP_DBL)1) >> + 1; + use_dT = (h_sbrCodeEnvelope->upDate != 0 && (delta_F_bits > tmp_bits)); + } else + use_dT = (delta_T_bits < delta_F_bits && h_sbrCodeEnvelope->upDate != 0); + + if (use_dT) { + directionVec[i] = TIME; + FDKmemcpy(sfb_nrg, delta_T, no_of_bands * sizeof(SCHAR)); + } else { + h_sbrCodeEnvelope->upDate = 0; + directionVec[i] = FREQ; + FDKmemcpy(sfb_nrg, delta_F, no_of_bands * sizeof(SCHAR)); + } + sfb_nrg += no_of_bands; + h_sbrCodeEnvelope->upDate = 1; + } +} + +/******************************************************************************* + Functionname: FDKsbrEnc_InitSbrCodeEnvelope + ******************************************************************************* + + Description: + + Arguments: + + Return: + +*******************************************************************************/ +INT FDKsbrEnc_InitSbrCodeEnvelope(HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr) { + FDKmemclear(h_sbrCodeEnvelope, sizeof(SBR_CODE_ENVELOPE)); + + h_sbrCodeEnvelope->deltaTAcrossFrames = deltaTAcrossFrames; + h_sbrCodeEnvelope->dF_edge_1stEnv = dF_edge_1stEnv; + h_sbrCodeEnvelope->dF_edge_incr = dF_edge_incr; + h_sbrCodeEnvelope->dF_edge_incr_fac = 0; + h_sbrCodeEnvelope->upDate = 0; + h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] = nSfb[FREQ_RES_LOW]; + h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH] = nSfb[FREQ_RES_HIGH]; + h_sbrCodeEnvelope->offset = 2 * h_sbrCodeEnvelope->nSfb[FREQ_RES_LOW] - + h_sbrCodeEnvelope->nSfb[FREQ_RES_HIGH]; + + return (0); +} diff --git a/fdk-aac/libSBRenc/src/code_env.h b/fdk-aac/libSBRenc/src/code_env.h new file mode 100644 index 0000000..673a783 --- /dev/null +++ b/fdk-aac/libSBRenc/src/code_env.h @@ -0,0 +1,161 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief DPCM Envelope coding $Revision: 92790 $ +*/ + +#ifndef CODE_ENV_H +#define CODE_ENV_H + +#include "sbr_def.h" +#include "bit_sbr.h" +#include "fram_gen.h" + +typedef struct { + INT offset; + INT upDate; + INT nSfb[2]; + SCHAR sfb_nrg_prev[MAX_FREQ_COEFFS]; + INT deltaTAcrossFrames; + FIXP_DBL dF_edge_1stEnv; + FIXP_DBL dF_edge_incr; + INT dF_edge_incr_fac; + + INT codeBookScfLavTime; + INT codeBookScfLavFreq; + + INT codeBookScfLavLevelTime; + INT codeBookScfLavLevelFreq; + INT codeBookScfLavBalanceTime; + INT codeBookScfLavBalanceFreq; + + INT start_bits; + INT start_bits_balance; + + const UCHAR *hufftableTimeL; + const UCHAR *hufftableFreqL; + + const UCHAR *hufftableLevelTimeL; + const UCHAR *hufftableBalanceTimeL; + const UCHAR *hufftableLevelFreqL; + const UCHAR *hufftableBalanceFreqL; +} SBR_CODE_ENVELOPE; +typedef SBR_CODE_ENVELOPE *HANDLE_SBR_CODE_ENVELOPE; + +void FDKsbrEnc_codeEnvelope(SCHAR *sfb_nrg, const FREQ_RES *freq_res, + SBR_CODE_ENVELOPE *h_sbrCodeEnvelope, + INT *directionVec, INT coupling, INT nEnvelopes, + INT channel, INT headerActive); + +INT FDKsbrEnc_InitSbrCodeEnvelope(HANDLE_SBR_CODE_ENVELOPE h_sbrCodeEnvelope, + INT *nSfb, INT deltaTAcrossFrames, + FIXP_DBL dF_edge_1stEnv, + FIXP_DBL dF_edge_incr); + +INT FDKsbrEnc_InitSbrHuffmanTables(struct SBR_ENV_DATA *sbrEnvData, + HANDLE_SBR_CODE_ENVELOPE henv, + HANDLE_SBR_CODE_ENVELOPE hnoise, + AMP_RES amp_res); + +#endif diff --git a/fdk-aac/libSBRenc/src/env_bit.cpp b/fdk-aac/libSBRenc/src/env_bit.cpp new file mode 100644 index 0000000..41812ac --- /dev/null +++ b/fdk-aac/libSBRenc/src/env_bit.cpp @@ -0,0 +1,257 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#include "env_bit.h" +#include "cmondata.h" + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +/* ***************************** crcAdvance **********************************/ +/** + * @fn + * @brief updates crc data register + * @return none + * + * This function updates the crc register + * + */ +static void crcAdvance(USHORT crcPoly, USHORT crcMask, USHORT *crc, + ULONG bValue, INT bBits) { + INT i; + USHORT flag; + + for (i = bBits - 1; i >= 0; i--) { + flag = ((*crc) & crcMask) ? (1) : (0); + flag ^= (bValue & (1 << i)) ? (1) : (0); + + (*crc) <<= 1; + if (flag) (*crc) ^= crcPoly; + } +} + +/* ***************************** FDKsbrEnc_InitSbrBitstream + * **********************************/ +/** + * @fn + * @brief Inittialisation of sbr bitstream, write of dummy header and CRC + * @return none + * + * + * + */ + +INT FDKsbrEnc_InitSbrBitstream( + HANDLE_COMMON_DATA hCmonData, + UCHAR *memoryBase, /*!< Pointer to bitstream buffer */ + INT memorySize, /*!< Length of bitstream buffer in bytes */ + HANDLE_FDK_CRCINFO hCrcInfo, UINT sbrSyntaxFlags) /*!< SBR syntax flags */ +{ + INT crcRegion = 0; + + /* reset bit buffer */ + FDKresetBitbuffer(&hCmonData->sbrBitbuf, BS_WRITER); + + FDKinitBitStream(&hCmonData->tmpWriteBitbuf, memoryBase, memorySize, 0, + BS_WRITER); + + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) { /* Init and start CRC region */ + FDKwriteBits(&hCmonData->sbrBitbuf, 0x0, SI_SBR_DRM_CRC_BITS); + FDKcrcInit(hCrcInfo, 0x001d, 0xFFFF, SI_SBR_DRM_CRC_BITS); + crcRegion = FDKcrcStartReg(hCrcInfo, &hCmonData->sbrBitbuf, 0); + } else { + FDKwriteBits(&hCmonData->sbrBitbuf, 0x0, SI_SBR_CRC_BITS); + } + } + + return (crcRegion); +} + +/* ************************** FDKsbrEnc_AssembleSbrBitstream + * *******************************/ +/** + * @fn + * @brief Formats the SBR payload + * @return nothing + * + * Also the CRC will be calculated here. + * + */ + +void FDKsbrEnc_AssembleSbrBitstream(HANDLE_COMMON_DATA hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, INT crcRegion, + UINT sbrSyntaxFlags) { + USHORT crcReg = SBR_CRCINIT; + INT numCrcBits, i; + + /* check if SBR is present */ + if (hCmonData == NULL) return; + + hCmonData->sbrFillBits = 0; /* Fill bits are written only for GA streams */ + + if (sbrSyntaxFlags & SBR_SYNTAX_DRM_CRC) { + /* + * Calculate and write DRM CRC + */ + FDKcrcEndReg(hCrcInfo, &hCmonData->sbrBitbuf, crcRegion); + FDKwriteBits(&hCmonData->tmpWriteBitbuf, FDKcrcGetCRC(hCrcInfo) ^ 0xFF, + SI_SBR_DRM_CRC_BITS); + } else { + if (!(sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)) { + /* Do alignment here, because its defined as part of the + * sbr_extension_data */ + int sbrLoad = hCmonData->sbrHdrBits + hCmonData->sbrDataBits; + + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + sbrLoad += SI_SBR_CRC_BITS; + } + + sbrLoad += 4; /* Do byte Align with 4 bit offset. ISO/IEC 14496-3:2005(E) + page 39. */ + + hCmonData->sbrFillBits = (8 - (sbrLoad % 8)) % 8; + + /* + append fill bits + */ + FDKwriteBits(&hCmonData->sbrBitbuf, 0, hCmonData->sbrFillBits); + + FDK_ASSERT(FDKgetValidBits(&hCmonData->sbrBitbuf) % 8 == 4); + } + + /* + calculate crc + */ + if (sbrSyntaxFlags & SBR_SYNTAX_CRC) { + FDK_BITSTREAM tmpCRCBuf = hCmonData->sbrBitbuf; + FDKresetBitbuffer(&tmpCRCBuf, BS_READER); + + numCrcBits = hCmonData->sbrHdrBits + hCmonData->sbrDataBits + + hCmonData->sbrFillBits; + + for (i = 0; i < numCrcBits; i++) { + INT bit; + bit = FDKreadBits(&tmpCRCBuf, 1); + crcAdvance(SBR_CRC_POLY, SBR_CRC_MASK, &crcReg, bit, 1); + } + crcReg &= (SBR_CRC_RANGE); + + /* + * Write CRC data. + */ + FDKwriteBits(&hCmonData->tmpWriteBitbuf, crcReg, SI_SBR_CRC_BITS); + } + } + + FDKsyncCache(&hCmonData->tmpWriteBitbuf); +} diff --git a/fdk-aac/libSBRenc/src/env_bit.h b/fdk-aac/libSBRenc/src/env_bit.h new file mode 100644 index 0000000..b91802c --- /dev/null +++ b/fdk-aac/libSBRenc/src/env_bit.h @@ -0,0 +1,135 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Remaining SBR Bit Writing Routines +*/ + +#ifndef ENV_BIT_H +#define ENV_BIT_H + +#include "sbr_encoder.h" +#include "FDK_crc.h" + +/* G(x) = x^10 + x^9 + x^5 + x^4 + x + 1 */ +#define SBR_CRC_POLY (0x0233) +#define SBR_CRC_MASK (0x0200) +#define SBR_CRC_RANGE (0x03FF) +#define SBR_CRC_MAXREGS 1 +#define SBR_CRCINIT (0x0) + +#define SI_SBR_CRC_ENABLE_BITS 0 +#define SI_SBR_CRC_BITS 10 +#define SI_SBR_DRM_CRC_BITS 8 + +struct COMMON_DATA; + +INT FDKsbrEnc_InitSbrBitstream(struct COMMON_DATA *hCmonData, UCHAR *memoryBase, + INT memorySize, HANDLE_FDK_CRCINFO hCrcInfo, + UINT sbrSyntaxFlags); + +void FDKsbrEnc_AssembleSbrBitstream(struct COMMON_DATA *hCmonData, + HANDLE_FDK_CRCINFO hCrcInfo, INT crcRegion, + UINT sbrSyntaxFlags); + +#endif /* #ifndef ENV_BIT_H */ diff --git a/fdk-aac/libSBRenc/src/env_est.cpp b/fdk-aac/libSBRenc/src/env_est.cpp new file mode 100644 index 0000000..4af561b --- /dev/null +++ b/fdk-aac/libSBRenc/src/env_est.cpp @@ -0,0 +1,1986 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "env_est.h" +#include "tran_det.h" + +#include "qmf.h" + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "cmondata.h" +#include "sbrenc_ram.h" + +#include "genericStds.h" + +#define QUANT_ERROR_THRES 200 +#define Y_NRG_SCALE 5 /* noCols = 32 -> shift(5) */ +#define MAX_NRG_SLOTS_LD 16 + +static const UCHAR panTable[2][10] = {{0, 2, 4, 6, 8, 12, 16, 20, 24}, + {0, 2, 4, 8, 12, 0, 0, 0, 0}}; +static const UCHAR maxIndex[2] = {9, 5}; + +/****************************************************************************** + Functionname: FDKsbrEnc_GetTonality +******************************************************************************/ +/***************************************************************************/ +/*! + + \brief Calculates complete energy per band from the energy values + of the QMF subsamples. + + \brief quotaMatrix - calculated in FDKsbrEnc_CalculateTonalityQuotas() + \brief noEstPerFrame - number of estimations per frame + \brief startIndex - start index for the quota matrix + \brief Energies - energy matrix + \brief startBand - start band + \brief stopBand - number of QMF bands + \brief numberCols - number of QMF subsamples + + \return mean tonality of the 5 bands with the highest energy + scaled by 2^(RELAXATION_SHIFT+2)*RELAXATION_FRACT + +****************************************************************************/ +static FIXP_DBL FDKsbrEnc_GetTonality(const FIXP_DBL *const *quotaMatrix, + const INT noEstPerFrame, + const INT startIndex, + const FIXP_DBL *const *Energies, + const UCHAR startBand, const INT stopBand, + const INT numberCols) { + UCHAR b, e, k; + INT no_enMaxBand[SBR_MAX_ENERGY_VALUES] = {-1, -1, -1, -1, -1}; + FIXP_DBL energyMax[SBR_MAX_ENERGY_VALUES] = { + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f)}; + FIXP_DBL energyMaxMin = MAXVAL_DBL; /* min. energy in energyMax array */ + UCHAR posEnergyMaxMin = 0; /* min. energy in energyMax array position */ + FIXP_DBL tonalityBand[SBR_MAX_ENERGY_VALUES] = { + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f), + FL2FXCONST_DBL(0.0f), FL2FXCONST_DBL(0.0f)}; + FIXP_DBL globalTonality = FL2FXCONST_DBL(0.0f); + FIXP_DBL energyBand[64]; + INT maxNEnergyValues; /* max. number of max. energy values */ + + /*** Sum up energies for each band ***/ + FDK_ASSERT(numberCols == 15 || numberCols == 16); + /* numberCols is always 15 or 16 for ELD. In case of 16 bands, the + energyBands are initialized with the [15]th column. + The rest of the column energies are added in the next step. */ + if (numberCols == 15) { + for (b = startBand; b < stopBand; b++) { + energyBand[b] = FL2FXCONST_DBL(0.0f); + } + } else { + for (b = startBand; b < stopBand; b++) { + energyBand[b] = Energies[15][b] >> 4; + } + } + + for (k = 0; k < 15; k++) { + for (b = startBand; b < stopBand; b++) { + energyBand[b] += Energies[k][b] >> 4; + } + } + + /*** Determine 5 highest band-energies ***/ + maxNEnergyValues = fMin(SBR_MAX_ENERGY_VALUES, stopBand - startBand); + + /* Get min. value in energyMax array */ + energyMaxMin = energyMax[0] = energyBand[startBand]; + no_enMaxBand[0] = startBand; + posEnergyMaxMin = 0; + for (k = 1; k < maxNEnergyValues; k++) { + energyMax[k] = energyBand[startBand + k]; + no_enMaxBand[k] = startBand + k; + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + + for (b = startBand + maxNEnergyValues; b < stopBand; b++) { + if (energyBand[b] > energyMaxMin) { + energyMax[posEnergyMaxMin] = energyBand[b]; + no_enMaxBand[posEnergyMaxMin] = b; + + /* Again, get min. value in energyMax array */ + energyMaxMin = energyMax[0]; + posEnergyMaxMin = 0; + for (k = 1; k < maxNEnergyValues; k++) { + if (energyMaxMin > energyMax[k]) { + energyMaxMin = energyMax[k]; + posEnergyMaxMin = k; + } + } + } + } + /*** End determine 5 highest band-energies ***/ + + /* Get tonality values for 5 highest energies */ + for (e = 0; e < maxNEnergyValues; e++) { + tonalityBand[e] = FL2FXCONST_DBL(0.0f); + for (k = 0; k < noEstPerFrame; k++) { + tonalityBand[e] += quotaMatrix[startIndex + k][no_enMaxBand[e]] >> 1; + } + globalTonality += + tonalityBand[e] >> 2; /* headroom of 2+1 (max. 5 additions) */ + } + + return globalTonality; +} + +/***************************************************************************/ +/*! + + \brief Calculates energy form real and imaginary part of + the QMF subsamples + + \return none + +****************************************************************************/ +LNK_SECTION_CODE_L1 +static void FDKsbrEnc_getEnergyFromCplxQmfData( + FIXP_DBL **RESTRICT energyValues, /*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT + imagValues, /*!< the imaginary part of the QMF subsamples */ + INT numberBands, /*!< number of QMF bands */ + INT numberCols, /*!< number of QMF subsamples */ + INT *qmfScale, /*!< sclefactor of QMF subsamples */ + INT *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, 32 * 64 / 2) + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k = 0; k < numberCols; k++) { + scale = fixMin(scale, fixMin(getScalefactor(realValues[k], numberBands), + getScalefactor(imagValues[k], numberBands))); + } + + /* Tweak scaling stability for zero signal to non-zero signal transitions */ + if (scale >= DFRACT_BITS - 1) { + scale = (FRACT_BITS - 1 - *qmfScale); + } + /* prevent scaling of QMF values to -1.f */ + scale = fixMax(0, scale - 1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k += 2) { + /* Load band vector addresses of 2 consecutive timeslots */ + FIXP_DBL *RESTRICT r0 = realValues[k]; + FIXP_DBL *RESTRICT i0 = imagValues[k]; + FIXP_DBL *RESTRICT r1 = realValues[k + 1]; + FIXP_DBL *RESTRICT i1 = imagValues[k + 1]; + for (j = 0; j < numberBands; j++) { + FIXP_DBL energy; + FIXP_DBL tr0, tr1, ti0, ti1; + + /* Read QMF values of 2 timeslots */ + tr0 = r0[j]; + tr1 = r1[j]; + ti0 = i0[j]; + ti1 = i1[j]; + + /* Scale QMF Values and Calc Energy average of both timeslots */ + tr0 <<= scale; + ti0 <<= scale; + energy = fPow2AddDiv2(fPow2Div2(tr0), ti0) >> 1; + + tr1 <<= scale; + ti1 <<= scale; + energy += fPow2AddDiv2(fPow2Div2(tr1), ti1) >> 1; + + /* Write timeslot pair energy to scratch */ + *nrgValues++ = energy; + max_val = fixMax(max_val, energy); + + /* Write back scaled QMF values */ + r0[j] = tr0; + r1[j] = tr1; + i0[j] = ti0; + i1[j] = ti1; + } + } + } + /* energyScale: scalefactor energies of current frame */ + *energyScale = + 2 * (*qmfScale) - + 1; /* if qmfScale > 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k> 1; k++) { + scaleValues(energyValues[k], nrgValues, numberBands, scale); + nrgValues += numberBands; + } + *energyScale += scale; + } + + /* Free Scratch buffer */ + C_ALLOC_SCRATCH_END(tmpNrg, FIXP_DBL, 32 * 64 / 2) +} + +LNK_SECTION_CODE_L1 +static void FDKsbrEnc_getEnergyFromCplxQmfDataFull( + FIXP_DBL **RESTRICT energyValues, /*!< the result of the operation */ + FIXP_DBL **RESTRICT realValues, /*!< the real part of the QMF subsamples */ + FIXP_DBL **RESTRICT + imagValues, /*!< the imaginary part of the QMF subsamples */ + int numberBands, /*!< number of QMF bands */ + int numberCols, /*!< number of QMF subsamples */ + int *qmfScale, /*!< scalefactor of QMF subsamples */ + int *energyScale) /*!< scalefactor of energies */ +{ + int j, k; + int scale; + FIXP_DBL max_val = FL2FXCONST_DBL(0.0f); + + /* Get Scratch buffer */ + C_ALLOC_SCRATCH_START(tmpNrg, FIXP_DBL, MAX_NRG_SLOTS_LD * 64) + + FDK_ASSERT(numberCols <= MAX_NRG_SLOTS_LD); + FDK_ASSERT(numberBands <= 64); + + /* Get max possible scaling of QMF data */ + scale = DFRACT_BITS; + for (k = 0; k < numberCols; k++) { + scale = fixMin(scale, fixMin(getScalefactor(realValues[k], numberBands), + getScalefactor(imagValues[k], numberBands))); + } + + /* Tweak scaling stability for zero signal to non-zero signal transitions */ + if (scale >= DFRACT_BITS - 1) { + scale = (FRACT_BITS - 1 - *qmfScale); + } + /* prevent scaling of QFM values to -1.f */ + scale = fixMax(0, scale - 1); + + /* Update QMF scale */ + *qmfScale += scale; + + /* + Calculate energy of each time slot pair, max energy + and shift QMF values as far as possible to the left. + */ + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k++) { + /* Load band vector addresses of 1 timeslot */ + FIXP_DBL *RESTRICT r0 = realValues[k]; + FIXP_DBL *RESTRICT i0 = imagValues[k]; + for (j = 0; j < numberBands; j++) { + FIXP_DBL energy; + FIXP_DBL tr0, ti0; + + /* Read QMF values of 1 timeslot */ + tr0 = r0[j]; + ti0 = i0[j]; + + /* Scale QMF Values and Calc Energy */ + tr0 <<= scale; + ti0 <<= scale; + energy = fPow2AddDiv2(fPow2Div2(tr0), ti0); + *nrgValues++ = energy; + + max_val = fixMax(max_val, energy); + + /* Write back scaled QMF values */ + r0[j] = tr0; + i0[j] = ti0; + } + } + } + /* energyScale: scalefactor energies of current frame */ + *energyScale = + 2 * (*qmfScale) - + 1; /* if qmfScale > 0: nr of right shifts otherwise nr of left shifts */ + + /* Scale timeslot pair energies and write to output buffer */ + scale = CountLeadingBits(max_val); + { + FIXP_DBL *nrgValues = tmpNrg; + for (k = 0; k < numberCols; k++) { + scaleValues(energyValues[k], nrgValues, numberBands, scale); + nrgValues += numberBands; + } + *energyScale += scale; + } + + /* Free Scratch buffer */ + C_ALLOC_SCRATCH_END(tmpNrg, FIXP_DBL, MAX_NRG_SLOTS_LD * 64) +} + +/***************************************************************************/ +/*! + + \brief Quantisation of the panorama value (balance) + + \return the quantized pan value + +****************************************************************************/ +static INT mapPanorama(INT nrgVal, /*! integer value of the energy */ + INT ampRes, /*! amplitude resolution [1.5/3dB] */ + INT *quantError /*! quantization error of energy val*/ +) { + int i; + INT min_val, val; + UCHAR panIndex; + INT sign; + + sign = nrgVal > 0 ? 1 : -1; + + nrgVal *= sign; + + min_val = FDK_INT_MAX; + panIndex = 0; + for (i = 0; i < maxIndex[ampRes]; i++) { + val = fixp_abs((nrgVal - (INT)panTable[ampRes][i])); + + if (val < min_val) { + min_val = val; + panIndex = i; + } + } + + *quantError = min_val; + + return panTable[ampRes][maxIndex[ampRes] - 1] + + sign * panTable[ampRes][panIndex]; +} + +/***************************************************************************/ +/*! + + \brief Quantisation of the noise floor levels + + \return void + +****************************************************************************/ +static void sbrNoiseFloorLevelsQuantisation( + SCHAR *RESTRICT iNoiseLevels, /*! quantized noise levels */ + FIXP_DBL *RESTRICT + NoiseLevels, /*! the noise levels. Exponent = LD_DATA_SHIFT */ + INT coupling /*! the coupling flag */ +) { + INT i; + INT tmp, dummy; + + /* Quantisation, similar to sfb quant... */ + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + /* tmp = NoiseLevels[i] > (PFLOAT)30.0f ? 30: (INT) (NoiseLevels[i] + + * (PFLOAT)0.5); */ + /* 30>>LD_DATA_SHIFT = 0.46875 */ + if ((FIXP_DBL)NoiseLevels[i] > FL2FXCONST_DBL(0.46875f)) { + tmp = 30; + } else { + /* tmp = (INT)((FIXP_DBL)NoiseLevels[i] + (FL2FXCONST_DBL(0.5f)>>(*/ + /* FRACT_BITS+ */ /* 6-1)));*/ + /* tmp = tmp >> (DFRACT_BITS-1-LD_DATA_SHIFT); */ /* conversion to integer + happens here */ + /* rounding is done by shifting one bit less than necessary to the right, + * adding '1' and then shifting the final bit */ + tmp = ((((INT)NoiseLevels[i]) >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT))); /* conversion to integer */ + if (tmp != 0) tmp += 1; + } + + if (coupling) { + tmp = tmp < -30 ? -30 : tmp; + tmp = mapPanorama(tmp, 1, &dummy); + } + iNoiseLevels[i] = tmp; + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of noise floor for coupling + + \return void + +****************************************************************************/ +static void coupleNoiseFloor( + FIXP_DBL *RESTRICT noise_level_left, /*! noise level left (modified)*/ + FIXP_DBL *RESTRICT noise_level_right /*! noise level right (modified)*/ +) { + FIXP_DBL cmpValLeft, cmpValRight; + INT i; + FIXP_DBL temp1, temp2; + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + /* Calculation of the power function using ld64: + z = x^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64; + z = CalcInvLd64(z'); + */ + cmpValLeft = NOISE_FLOOR_OFFSET_64 - noise_level_left[i]; + cmpValRight = NOISE_FLOOR_OFFSET_64 - noise_level_right[i]; + + if (cmpValRight < FL2FXCONST_DBL(0.0f)) { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + } else { + temp1 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_right[i]); + temp1 = temp1 << (DFRACT_BITS - 1 - LD_DATA_SHIFT - + 1); /* INT to fract conversion of result, if input of + CalcInvLdData is positiv */ + } + + if (cmpValLeft < FL2FXCONST_DBL(0.0f)) { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + } else { + temp2 = CalcInvLdData(NOISE_FLOOR_OFFSET_64 - noise_level_left[i]); + temp2 = temp2 << (DFRACT_BITS - 1 - LD_DATA_SHIFT - + 1); /* INT to fract conversion of result, if input of + CalcInvLdData is positiv */ + } + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && + (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = + NOISE_FLOOR_OFFSET_64 - + (CalcLdData( + ((temp1 >> 1) + + (temp2 >> 1)))); /* no scaling needed! both values are dfract */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && + (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> 1) + (temp2 >> 1))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - CalcLdData(temp1); + } + + if ((cmpValLeft >= FL2FXCONST_DBL(0.0f)) && + (cmpValRight < FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> (7 + 1)) + (temp2 >> 1))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = + (CalcLdData(temp2) + FL2FXCONST_DBL(0.109375f)) - CalcLdData(temp1); + } + + if ((cmpValLeft < FL2FXCONST_DBL(0.0f)) && + (cmpValRight >= FL2FXCONST_DBL(0.0f))) { + noise_level_left[i] = NOISE_FLOOR_OFFSET_64 - + (CalcLdData(((temp1 >> 1) + (temp2 >> (7 + 1)))) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + noise_level_right[i] = CalcLdData(temp2) - + (CalcLdData(temp1) + + FL2FXCONST_DBL(0.109375f)); /* scaled with 7/64 */ + } + } +} + +/***************************************************************************/ +/*! + + \brief Calculation of energy starting in lower band (li) up to upper band +(ui) over slots (start_pos) to (stop_pos) + + \return void + +****************************************************************************/ + +static FIXP_DBL getEnvSfbEnergy( + INT li, /*! lower band */ + INT ui, /*! upper band */ + INT start_pos, /*! start slot */ + INT stop_pos, /*! stop slot */ + INT border_pos, /*! slots scaling border */ + FIXP_DBL **YBuffer, /*! sfb energy buffer */ + INT YBufferSzShift, /*! Energy buffer index scale */ + INT scaleNrg0, /*! scaling of lower slots */ + INT scaleNrg1) /*! scaling of upper slots */ +{ + /* use dynamic scaling for outer energy loop; + energies are critical and every bit is important */ + int sc0, sc1, k, l; + + FIXP_DBL nrgSum, nrg1, nrg2, accu1, accu2; + INT dynScale, dynScale1, dynScale2; + if (ui - li == 0) + dynScale = DFRACT_BITS - 1; + else + dynScale = CalcLdInt(ui - li) >> (DFRACT_BITS - 1 - LD_DATA_SHIFT); + + sc0 = fixMin(scaleNrg0, Y_NRG_SCALE); + sc1 = fixMin(scaleNrg1, Y_NRG_SCALE); + /* dynScale{1,2} is set such that the right shift below is positive */ + dynScale1 = fixMin((scaleNrg0 - sc0), dynScale); + dynScale2 = fixMin((scaleNrg1 - sc1), dynScale); + nrgSum = accu1 = accu2 = (FIXP_DBL)0; + + for (k = li; k < ui; k++) { + nrg1 = nrg2 = (FIXP_DBL)0; + for (l = start_pos; l < border_pos; l++) { + nrg1 += YBuffer[l >> YBufferSzShift][k] >> sc0; + } + for (; l < stop_pos; l++) { + nrg2 += YBuffer[l >> YBufferSzShift][k] >> sc1; + } + accu1 += (nrg1 >> dynScale1); + accu2 += (nrg2 >> dynScale2); + } + /* This shift factor is always positive. See comment above. */ + nrgSum += + (accu1 >> fixMin((scaleNrg0 - sc0 - dynScale1), (DFRACT_BITS - 1))) + + (accu2 >> fixMin((scaleNrg1 - sc1 - dynScale2), (DFRACT_BITS - 1))); + + return nrgSum; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL mhLoweringEnergy(FIXP_DBL nrg, INT M) { + /* + Compensating for the fact that we in the decoder map the "average energy to + every QMF band, and use this when we calculate the boost-factor. Since the + mapped energy isn't the average energy but the maximum energy in case of + missing harmonic creation, we will in the boost function calculate that too + much limiting has been applied and hence we will boost the signal although + it isn't called for. Hence we need to compensate for this by lowering the + transmitted energy values for the sines so they will get the correct level + after the boost is applied. + */ + if (M > 2) { + INT tmpScale; + tmpScale = CountLeadingBits(nrg); + nrg <<= tmpScale; + nrg = fMult(nrg, FL2FXCONST_DBL(0.398107267f)); /* The maximum boost + is 1.584893, so the + maximum attenuation + should be + square(1/1.584893) = + 0.398107267 */ + nrg >>= tmpScale; + } else { + if (M > 1) { + nrg >>= 1; + } + } + + return nrg; +} + +/***************************************************************************/ +/*! + + \brief Energy compensation in none missing harmonic mode + + \return void + +****************************************************************************/ +static FIXP_DBL nmhLoweringEnergy(FIXP_DBL nrg, const FIXP_DBL nrgSum, + const INT nrgSum_scale, const INT M) { + if (nrg > FL2FXCONST_DBL(0)) { + int sc = 0; + /* gain = nrgSum / (nrg*(M+1)) */ + FIXP_DBL gain = fMult(fDivNorm(nrgSum, nrg, &sc), GetInvInt(M + 1)); + sc += nrgSum_scale; + + /* reduce nrg if gain smaller 1.f */ + if (!((sc >= 0) && (gain > ((FIXP_DBL)MAXVAL_DBL >> sc)))) { + nrg = fMult(scaleValue(gain, sc), nrg); + } + } + return nrg; +} + +/***************************************************************************/ +/*! + + \brief calculates the envelope values from the energies, depending on + framing and stereo mode + + \return void + +****************************************************************************/ +static void calculateSbrEnvelope( + FIXP_DBL **RESTRICT YBufferLeft, /*! energy buffer left */ + FIXP_DBL **RESTRICT YBufferRight, /*! energy buffer right */ + int *RESTRICT YBufferScaleLeft, /*! scale energy buffer left */ + int *RESTRICT YBufferScaleRight, /*! scale energy buffer right */ + const SBR_FRAME_INFO *frame_info, /*! frame info vector */ + SCHAR *RESTRICT sfb_nrgLeft, /*! sfb energy buffer left */ + SCHAR *RESTRICT sfb_nrgRight, /*! sfb energy buffer right */ + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_ENV_CHANNEL h_sbr, /*! envelope channel handle */ + SBR_STEREO_MODE stereoMode, /*! stereo coding mode */ + INT *maxQuantError, /*! maximum quantization error, for panorama. */ + int YBufferSzShift) /*! Energy buffer index scale */ + +{ + int env, j, m = 0; + INT no_of_bands, start_pos, stop_pos, li, ui; + FREQ_RES freq_res; + + INT ca = 2 - h_sbr->encEnvData.init_sbr_amp_res; + INT oneBitLess = 0; + if (ca == 2) + oneBitLess = + 1; /* LD_DATA_SHIFT => ld64 scaling; one bit less for rounding */ + + INT quantError; + INT nEnvelopes = frame_info->nEnvelopes; + INT short_env = frame_info->shortEnv - 1; + INT timeStep = h_sbr->sbrExtractEnvelope.time_step; + INT commonScale, scaleLeft0, scaleLeft1; + INT scaleRight0 = 0, scaleRight1 = 0; + + commonScale = fixMin(YBufferScaleLeft[0], YBufferScaleLeft[1]); + + if (stereoMode == SBR_COUPLING) { + commonScale = fixMin(commonScale, YBufferScaleRight[0]); + commonScale = fixMin(commonScale, YBufferScaleRight[1]); + } + + commonScale = commonScale - 7; + + scaleLeft0 = YBufferScaleLeft[0] - commonScale; + scaleLeft1 = YBufferScaleLeft[1] - commonScale; + FDK_ASSERT((scaleLeft0 >= 0) && (scaleLeft1 >= 0)); + + if (stereoMode == SBR_COUPLING) { + scaleRight0 = YBufferScaleRight[0] - commonScale; + scaleRight1 = YBufferScaleRight[1] - commonScale; + FDK_ASSERT((scaleRight0 >= 0) && (scaleRight1 >= 0)); + *maxQuantError = 0; + } + + for (env = 0; env < nEnvelopes; env++) { + FIXP_DBL pNrgLeft[32]; + FIXP_DBL pNrgRight[32]; + int envNrg_scale; + FIXP_DBL envNrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL envNrgRight = FL2FXCONST_DBL(0.0f); + int missingHarmonic[32]; + int count[32]; + + start_pos = timeStep * frame_info->borders[env]; + stop_pos = timeStep * frame_info->borders[env + 1]; + freq_res = frame_info->freqRes[env]; + no_of_bands = h_con->nSfb[freq_res]; + envNrg_scale = DFRACT_BITS - fNormz((FIXP_DBL)no_of_bands); + if (env == short_env) { + j = fMax(2, timeStep); /* consider at least 2 QMF slots less for short + envelopes (envelopes just before transients) */ + if ((stop_pos - start_pos - j) > 0) { + stop_pos = stop_pos - j; + } + } + for (j = 0; j < no_of_bands; j++) { + FIXP_DBL nrgLeft = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgRight = FL2FXCONST_DBL(0.0f); + + li = h_con->freqBandTable[freq_res][j]; + ui = h_con->freqBandTable[freq_res][j + 1]; + + if (freq_res == FREQ_RES_HIGH) { + if (j == 0 && ui - li > 1) { + li++; + } + } else { + if (j == 0 && ui - li > 2) { + li++; + } + } + + /* + Find out whether a sine will be missing in the scale-factor + band that we're currently processing. + */ + missingHarmonic[j] = 0; + + if (h_sbr->encEnvData.addHarmonicFlag) { + if (freq_res == FREQ_RES_HIGH) { + if (h_sbr->encEnvData + .addHarmonic[j]) { /*A missing sine in the current band*/ + missingHarmonic[j] = 1; + } + } else { + INT i; + INT startBandHigh = 0; + INT stopBandHigh = 0; + + while (h_con->freqBandTable[FREQ_RES_HIGH][startBandHigh] < + h_con->freqBandTable[FREQ_RES_LOW][j]) + startBandHigh++; + while (h_con->freqBandTable[FREQ_RES_HIGH][stopBandHigh] < + h_con->freqBandTable[FREQ_RES_LOW][j + 1]) + stopBandHigh++; + + for (i = startBandHigh; i < stopBandHigh; i++) { + if (h_sbr->encEnvData.addHarmonic[i]) { + missingHarmonic[j] = 1; + } + } + } + } + + /* + If a sine is missing in a scalefactorband, with more than one qmf + channel use the nrg from the channel with the largest nrg rather than + the mean. Compensate for the boost calculation in the decdoder. + */ + int border_pos = + fixMin(stop_pos, h_sbr->sbrExtractEnvelope.YBufferWriteOffset + << YBufferSzShift); + + if (missingHarmonic[j]) { + int k; + count[j] = stop_pos - start_pos; + nrgLeft = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + FIXP_DBL tmpNrg; + tmpNrg = getEnvSfbEnergy(k, k + 1, start_pos, stop_pos, border_pos, + YBufferLeft, YBufferSzShift, scaleLeft0, + scaleLeft1); + + nrgLeft = fixMax(nrgLeft, tmpNrg); + } + + /* Energy lowering compensation */ + nrgLeft = mhLoweringEnergy(nrgLeft, ui - li); + + if (stereoMode == SBR_COUPLING) { + nrgRight = FL2FXCONST_DBL(0.0f); + + for (k = li; k < ui; k++) { + FIXP_DBL tmpNrg; + tmpNrg = getEnvSfbEnergy(k, k + 1, start_pos, stop_pos, border_pos, + YBufferRight, YBufferSzShift, scaleRight0, + scaleRight1); + + nrgRight = fixMax(nrgRight, tmpNrg); + } + + /* Energy lowering compensation */ + nrgRight = mhLoweringEnergy(nrgRight, ui - li); + } + } /* end missingHarmonic */ + else { + count[j] = (stop_pos - start_pos) * (ui - li); + + nrgLeft = getEnvSfbEnergy(li, ui, start_pos, stop_pos, border_pos, + YBufferLeft, YBufferSzShift, scaleLeft0, + scaleLeft1); + + if (stereoMode == SBR_COUPLING) { + nrgRight = getEnvSfbEnergy(li, ui, start_pos, stop_pos, border_pos, + YBufferRight, YBufferSzShift, scaleRight0, + scaleRight1); + } + } /* !missingHarmonic */ + + /* save energies */ + pNrgLeft[j] = nrgLeft; + pNrgRight[j] = nrgRight; + envNrgLeft += (nrgLeft >> envNrg_scale); + envNrgRight += (nrgRight >> envNrg_scale); + } /* j */ + + for (j = 0; j < no_of_bands; j++) { + FIXP_DBL nrgLeft2 = FL2FXCONST_DBL(0.0f); + FIXP_DBL nrgLeft = pNrgLeft[j]; + FIXP_DBL nrgRight = pNrgRight[j]; + + /* None missing harmonic Energy lowering compensation */ + if (!missingHarmonic[j] && h_sbr->fLevelProtect) { + /* in case of missing energy in base band, + reduce reference energy to prevent overflows in decoder output */ + nrgLeft = + nmhLoweringEnergy(nrgLeft, envNrgLeft, envNrg_scale, no_of_bands); + if (stereoMode == SBR_COUPLING) { + nrgRight = nmhLoweringEnergy(nrgRight, envNrgRight, envNrg_scale, + no_of_bands); + } + } + + if (stereoMode == SBR_COUPLING) { + /* calc operation later with log */ + nrgLeft2 = nrgLeft; + nrgLeft = (nrgRight + nrgLeft) >> 1; + } + + /* nrgLeft = f20_log2(nrgLeft / (PFLOAT)(count * 64))+(PFLOAT)44; */ + /* If nrgLeft == 0 then the Log calculations below do fail. */ + if (nrgLeft > FL2FXCONST_DBL(0.0f)) { + FIXP_DBL tmp0, tmp1, tmp2, tmp3; + INT tmpScale; + + tmpScale = CountLeadingBits(nrgLeft); + nrgLeft = nrgLeft << tmpScale; + + tmp0 = CalcLdData(nrgLeft); /* scaled by 1/64 */ + tmp1 = ((FIXP_DBL)(commonScale + tmpScale)) + << (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1); /* scaled by 1/64 */ + tmp2 = ((FIXP_DBL)(count[j] * 64)) << (DFRACT_BITS - 1 - 14 - 1); + tmp2 = CalcLdData(tmp2); /* scaled by 1/64 */ + tmp3 = FL2FXCONST_DBL(0.6875f - 0.21875f - 0.015625f) >> + 1; /* scaled by 1/64 */ + + nrgLeft = ((tmp0 - tmp2) >> 1) + (tmp3 - tmp1); + } else { + nrgLeft = FL2FXCONST_DBL(-1.0f); + } + + /* ld64 to integer conversion */ + nrgLeft = fixMin(fixMax(nrgLeft, FL2FXCONST_DBL(0.0f)), + (FL2FXCONST_DBL(0.5f) >> oneBitLess)); + nrgLeft = (FIXP_DBL)(LONG)nrgLeft >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1 - oneBitLess - 1); + sfb_nrgLeft[m] = ((INT)nrgLeft + 1) >> 1; /* rounding */ + + if (stereoMode == SBR_COUPLING) { + FIXP_DBL scaleFract; + int sc0, sc1; + + nrgLeft2 = fixMax((FIXP_DBL)0x1, nrgLeft2); + nrgRight = fixMax((FIXP_DBL)0x1, nrgRight); + + sc0 = CountLeadingBits(nrgLeft2); + sc1 = CountLeadingBits(nrgRight); + + scaleFract = + ((FIXP_DBL)(sc0 - sc1)) + << (DFRACT_BITS - 1 - + LD_DATA_SHIFT); /* scale value in ld64 representation */ + nrgRight = CalcLdData(nrgLeft2 << sc0) - CalcLdData(nrgRight << sc1) - + scaleFract; + + /* ld64 to integer conversion */ + nrgRight = (FIXP_DBL)(LONG)(nrgRight) >> + (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1 - oneBitLess); + nrgRight = (nrgRight + (FIXP_DBL)1) >> 1; /* rounding */ + + sfb_nrgRight[m] = mapPanorama( + nrgRight, h_sbr->encEnvData.init_sbr_amp_res, &quantError); + + *maxQuantError = fixMax(quantError, *maxQuantError); + } + + m++; + } /* j */ + + /* Do energy compensation for sines that are present in two + QMF-bands in the original, but will only occur in one band in + the decoder due to the synthetic sine coding.*/ + if (h_con->useParametricCoding) { + m -= no_of_bands; + for (j = 0; j < no_of_bands; j++) { + if (freq_res == FREQ_RES_HIGH && + h_sbr->sbrExtractEnvelope.envelopeCompensation[j]) { + sfb_nrgLeft[m] -= + (ca * + fixp_abs( + (INT)h_sbr->sbrExtractEnvelope.envelopeCompensation[j])); + } + sfb_nrgLeft[m] = fixMax(0, sfb_nrgLeft[m]); + m++; + } + } /* useParametricCoding */ + + } /* env loop */ +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Analysis subband filtering. + -Encoding SA and pan parameters (if enabled). + -Transient detection. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void FDKsbrEnc_extractSbrEnvelope1( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_ENV_CHANNEL hEnvChan, + HANDLE_COMMON_DATA hCmonData, SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData) { + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + + if (sbrExtrEnv->YBufferSzShift == 0) + FDKsbrEnc_getEnergyFromCplxQmfDataFull( + &sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, h_con->noQmfBands, + sbrExtrEnv->no_cols, &hEnvChan->qmfScale, &sbrExtrEnv->YBufferScale[1]); + else + FDKsbrEnc_getEnergyFromCplxQmfData( + &sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset], + sbrExtrEnv->rBuffer + sbrExtrEnv->rBufferReadOffset, + sbrExtrEnv->iBuffer + sbrExtrEnv->rBufferReadOffset, h_con->noQmfBands, + sbrExtrEnv->no_cols, &hEnvChan->qmfScale, &sbrExtrEnv->YBufferScale[1]); + + /* Energie values = + * sbrExtrEnv->YBuffer[sbrExtrEnv->YBufferWriteOffset][x].floatVal * + * (1<<2*7-sbrExtrEnv->YBufferScale[1]) */ + + /* + Precalculation of Tonality Quotas COEFF Transform OK + */ + FDKsbrEnc_CalculateTonalityQuotas( + &hEnvChan->TonCorr, sbrExtrEnv->rBuffer, sbrExtrEnv->iBuffer, + h_con->freqBandTable[HI][h_con->nSfb[HI]], hEnvChan->qmfScale); + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FIXP_DBL tonality = FDKsbrEnc_GetTonality( + hEnvChan->TonCorr.quotaMatrix, + hEnvChan->TonCorr.numberOfEstimatesPerFrame, + hEnvChan->TonCorr.startIndexMatrix, + sbrExtrEnv->YBuffer + sbrExtrEnv->YBufferWriteOffset, + h_con->freqBandTable[HI][0] + 1, h_con->noQmfBands, + sbrExtrEnv->no_cols); + + hEnvChan->encEnvData.ton_HF[1] = hEnvChan->encEnvData.ton_HF[0]; + hEnvChan->encEnvData.ton_HF[0] = tonality; + + /* tonality is scaled by 2^19/0.524288f (fract part of RELAXATION) */ + hEnvChan->encEnvData.global_tonality = + (hEnvChan->encEnvData.ton_HF[0] >> 1) + + (hEnvChan->encEnvData.ton_HF[1] >> 1); + } + + /* + Transient detection COEFF Transform OK + */ + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + FDKsbrEnc_fastTransientDetect(&hEnvChan->sbrFastTransientDetector, + sbrExtrEnv->YBuffer, sbrExtrEnv->YBufferScale, + sbrExtrEnv->YBufferWriteOffset, + eData->transient_info); + + } else { + FDKsbrEnc_transientDetect( + &hEnvChan->sbrTransientDetector, sbrExtrEnv->YBuffer, + sbrExtrEnv->YBufferScale, eData->transient_info, + sbrExtrEnv->YBufferWriteOffset, sbrExtrEnv->YBufferSzShift, + sbrExtrEnv->time_step, hEnvChan->SbrEnvFrame.frameMiddleSlot); + } + + /* + Generate flags for 2 env in a FIXFIX-frame. + Remove this function to get always 1 env per FIXFIX-frame. + */ + + /* + frame Splitter COEFF Transform OK + */ + FDKsbrEnc_frameSplitter( + sbrExtrEnv->YBuffer, sbrExtrEnv->YBufferScale, + &hEnvChan->sbrTransientDetector, h_con->freqBandTable[1], + eData->transient_info, sbrExtrEnv->YBufferWriteOffset, + sbrExtrEnv->YBufferSzShift, h_con->nSfb[1], sbrExtrEnv->time_step, + sbrExtrEnv->no_cols, &hEnvChan->encEnvData.global_tonality); +} + +/***************************************************************************/ +/*! + + \brief calculates the noise floor and the envelope values from the + energies, depending on framing and stereo mode + + FDKsbrEnc_extractSbrEnvelope is the main function for encoding and writing the + envelope and the noise floor. The function includes the following processes: + + -Determine time/frequency division of current granule. + -Sending transient info to bitstream. + -Set amp_res to 1.5 dB if the current frame contains only one envelope. + -Lock dynamic bandwidth frequency change if the next envelope not starts on a + frame boundary. + -MDCT transposer (needed to detect where harmonics will be missing). + -Spectrum Estimation (used for pulse train and missing harmonics detection). + -Pulse train detection. + -Inverse Filtering detection. + -Waveform Coding. + -Missing Harmonics detection. + -Extract envelope of current frame. + -Noise floor estimation. + -Noise floor quantisation and coding. + -Encode envelope of current frame. + -Send the encoded data to the bitstream. + -Write to bitstream. + +****************************************************************************/ + +LNK_SECTION_CODE_L1 +void FDKsbrEnc_extractSbrEnvelope2( + HANDLE_SBR_CONFIG_DATA h_con, /*! handle to config data */ + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, HANDLE_ENV_CHANNEL h_envChan0, + HANDLE_ENV_CHANNEL h_envChan1, HANDLE_COMMON_DATA hCmonData, + SBR_ENV_TEMP_DATA *eData, SBR_FRAME_TEMP_DATA *fData, int clearOutput) { + HANDLE_ENV_CHANNEL h_envChan[MAX_NUM_CHANNELS] = {h_envChan0, h_envChan1}; + int ch, i, j, c, YSzShift = h_envChan[0]->sbrExtractEnvelope.YBufferSzShift; + + SBR_STEREO_MODE stereoMode = h_con->stereoMode; + int nChannels = h_con->nChannels; + FDK_ASSERT(nChannels <= MAX_NUM_CHANNELS); + const int *v_tuning; + static const int v_tuningHEAAC[6] = {0, 2, 4, 0, 0, 0}; + + static const int v_tuningELD[6] = {0, 2, 3, 0, 0, 0}; + + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + v_tuning = v_tuningELD; + else + v_tuning = v_tuningHEAAC; + + /* + Select stereo mode. + */ + if (stereoMode == SBR_COUPLING) { + if (eData[0].transient_info[1] && eData[1].transient_info[1]) { + eData[0].transient_info[0] = + fixMin(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } else { + if (eData[0].transient_info[1] && !eData[1].transient_info[1]) { + eData[1].transient_info[0] = eData[0].transient_info[0]; + } else { + if (!eData[0].transient_info[1] && eData[1].transient_info[1]) + eData[0].transient_info[0] = eData[1].transient_info[0]; + else { + eData[0].transient_info[0] = + fixMax(eData[1].transient_info[0], eData[0].transient_info[0]); + eData[1].transient_info[0] = eData[0].transient_info[0]; + } + } + } + } + + /* + Determine time/frequency division of current granule + */ + eData[0].frame_info = FDKsbrEnc_frameInfoGenerator( + &h_envChan[0]->SbrEnvFrame, eData[0].transient_info, + sbrBitstreamData->rightBorderFIX, + h_envChan[0]->sbrExtractEnvelope.pre_transient_info, + h_envChan[0]->encEnvData.ldGrid, v_tuning); + + h_envChan[0]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + + /* AAC LD patch for transient prediction */ + if (h_envChan[0]->encEnvData.ldGrid && eData[0].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to + * numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[0]->SbrEnvFrame.SbrFrameInfo.shortEnv = + h_envChan[0]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + switch (stereoMode) { + case SBR_LEFT_RIGHT: + case SBR_SWITCH_LRC: + eData[1].frame_info = FDKsbrEnc_frameInfoGenerator( + &h_envChan[1]->SbrEnvFrame, eData[1].transient_info, + sbrBitstreamData->rightBorderFIX, + h_envChan[1]->sbrExtractEnvelope.pre_transient_info, + h_envChan[1]->encEnvData.ldGrid, v_tuning); + + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[1]->SbrEnvFrame.SbrGrid; + + if (h_envChan[1]->encEnvData.ldGrid && eData[1].transient_info[2]) { + /* if next frame will start with transient, set shortEnv to + * numEnvelopes(shortend Envelope = shortEnv-1)*/ + h_envChan[1]->SbrEnvFrame.SbrFrameInfo.shortEnv = + h_envChan[1]->SbrEnvFrame.SbrFrameInfo.nEnvelopes; + } + + /* compare left and right frame_infos */ + if (eData[0].frame_info->nEnvelopes != eData[1].frame_info->nEnvelopes) { + stereoMode = SBR_LEFT_RIGHT; + } else { + for (i = 0; i < eData[0].frame_info->nEnvelopes + 1; i++) { + if (eData[0].frame_info->borders[i] != + eData[1].frame_info->borders[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + for (i = 0; i < eData[0].frame_info->nEnvelopes; i++) { + if (eData[0].frame_info->freqRes[i] != + eData[1].frame_info->freqRes[i]) { + stereoMode = SBR_LEFT_RIGHT; + break; + } + } + if (eData[0].frame_info->shortEnv != eData[1].frame_info->shortEnv) { + stereoMode = SBR_LEFT_RIGHT; + } + } + break; + case SBR_COUPLING: + eData[1].frame_info = eData[0].frame_info; + h_envChan[1]->encEnvData.hSbrBSGrid = &h_envChan[0]->SbrEnvFrame.SbrGrid; + break; + case SBR_MONO: + /* nothing to do */ + break; + default: + FDK_ASSERT(0); + } + + for (ch = 0; ch < nChannels; ch++) { + HANDLE_ENV_CHANNEL hEnvChan = h_envChan[ch]; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &hEnvChan->sbrExtractEnvelope; + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + + /* + Send transient info to bitstream and store for next call + */ + sbrExtrEnv->pre_transient_info[0] = ed->transient_info[0]; /* tran_pos */ + sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1]; /* tran_flag */ + hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes = + ed->frame_info->nEnvelopes; /* number of envelopes of current frame */ + + /* + Check if the current frame is divided into one envelope only. If so, set + the amplitude resolution to 1.5 dB, otherwise may set back to chosen value + */ + if ((hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX) && + (ed->nEnvelopes == 1)) { + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + /* Note: global_tonaliy_float_value == + ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0))); + threshold_float_value == + ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); + */ + /* decision of SBR_AMP_RES */ + if (fIsLessThan(/* global_tonality > threshold ? */ + h_con->thresholdAmpResFF_m, h_con->thresholdAmpResFF_e, + hEnvChan->encEnvData.global_tonality, + RELAXATION_SHIFT + 2)) { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + } else { + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0; + } + } else + hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + + if (hEnvChan->encEnvData.currentAmpResFF != + hEnvChan->encEnvData.init_sbr_amp_res) { + FDKsbrEnc_InitSbrHuffmanTables( + &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, hEnvChan->encEnvData.currentAmpResFF); + } + } else { + if (sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res) { + FDKsbrEnc_InitSbrHuffmanTables( + &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, + &hEnvChan->sbrCodeNoiseFloor, sbrHeaderData->sbr_amp_res); + } + } + + if (!clearOutput) { + /* + Tonality correction parameter extraction (inverse filtering level, noise + floor additional sines). + */ + FDKsbrEnc_TonCorrParamExtr( + &hEnvChan->TonCorr, hEnvChan->encEnvData.sbr_invf_mode_vec, + ed->noiseFloor, &hEnvChan->encEnvData.addHarmonicFlag, + hEnvChan->encEnvData.addHarmonic, sbrExtrEnv->envelopeCompensation, + ed->frame_info, ed->transient_info, h_con->freqBandTable[HI], + h_con->nSfb[HI], hEnvChan->encEnvData.sbr_xpos_mode, + h_con->sbrSyntaxFlags); + } + + /* Low energy in low band fix */ + if (hEnvChan->sbrTransientDetector.prevLowBandEnergy < + hEnvChan->sbrTransientDetector.prevHighBandEnergy && + hEnvChan->sbrTransientDetector.prevHighBandEnergy > FL2FX_DBL(0.03) + /* The fix needs the non-fast transient detector running. + It sets prevLowBandEnergy and prevHighBandEnergy. */ + && !(h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY)) { + hEnvChan->fLevelProtect = 1; + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + hEnvChan->encEnvData.sbr_invf_mode_vec[i] = INVF_HIGH_LEVEL; + } else { + hEnvChan->fLevelProtect = 0; + } + + hEnvChan->encEnvData.sbr_invf_mode = + hEnvChan->encEnvData.sbr_invf_mode_vec[0]; + + hEnvChan->encEnvData.noOfnoisebands = + hEnvChan->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + } /* ch */ + + /* + Save number of scf bands per envelope + */ + for (ch = 0; ch < nChannels; ch++) { + for (i = 0; i < eData[ch].nEnvelopes; i++) { + h_envChan[ch]->encEnvData.noScfBands[i] = + (eData[ch].frame_info->freqRes[i] == FREQ_RES_HIGH + ? h_con->nSfb[FREQ_RES_HIGH] + : h_con->nSfb[FREQ_RES_LOW]); + } + } + + /* + Extract envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + break; + case SBR_LEFT_RIGHT: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info, eData[1].sfb_nrg, NULL, h_con, + h_envChan[1], SBR_MONO, NULL, YSzShift); + break; + case SBR_COUPLING: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, + h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg, + eData[1].sfb_nrg, h_con, h_envChan[0], SBR_COUPLING, + &fData->maxQuantError, YSzShift); + break; + case SBR_SWITCH_LRC: + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, NULL, + eData[0].frame_info, eData[0].sfb_nrg, NULL, h_con, + h_envChan[0], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[1]->sbrExtractEnvelope.YBuffer, NULL, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, NULL, + eData[1].frame_info, eData[1].sfb_nrg, NULL, h_con, + h_envChan[1], SBR_MONO, NULL, YSzShift); + calculateSbrEnvelope(h_envChan[0]->sbrExtractEnvelope.YBuffer, + h_envChan[1]->sbrExtractEnvelope.YBuffer, + h_envChan[0]->sbrExtractEnvelope.YBufferScale, + h_envChan[1]->sbrExtractEnvelope.YBufferScale, + eData[0].frame_info, eData[0].sfb_nrg_coupling, + eData[1].sfb_nrg_coupling, h_con, h_envChan[0], + SBR_COUPLING, &fData->maxQuantError, YSzShift); + break; + } + + /* + Noise floor quantisation and coding. + */ + + switch (stereoMode) { + case SBR_MONO: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + case SBR_LEFT_RIGHT: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + break; + + case SBR_COUPLING: + coupleNoiseFloor(eData[0].noiseFloor, eData[1].noiseFloor); + + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 1); + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + break; + case SBR_SWITCH_LRC: + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level, eData[0].noiseFloor, + 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level, eData[1].noiseFloor, + 0); + coupleNoiseFloor(eData[0].noiseFloor, eData[1].noiseFloor); + sbrNoiseFloorLevelsQuantisation(eData[0].noise_level_coupling, + eData[0].noiseFloor, 0); + sbrNoiseFloorLevelsQuantisation(eData[1].noise_level_coupling, + eData[1].noiseFloor, 1); + break; + } + + /* + Encode envelope of current frame. + */ + switch (stereoMode) { + case SBR_MONO: + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_LEFT_RIGHT: + sbrHeaderData->coupling = 0; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + break; + case SBR_COUPLING: + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + sbrHeaderData->coupling, eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + break; + case SBR_SWITCH_LRC: { + INT payloadbitsLR; + INT payloadbitsCOUPLING; + + SCHAR sfbNrgPrevTemp[MAX_NUM_CHANNELS][MAX_FREQ_COEFFS]; + SCHAR noisePrevTemp[MAX_NUM_CHANNELS][MAX_NUM_NOISE_COEFFS]; + INT upDateNrgTemp[MAX_NUM_CHANNELS]; + INT upDateNoiseTemp[MAX_NUM_CHANNELS]; + INT domainVecTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + INT domainVecNoiseTemp[MAX_NUM_CHANNELS][MAX_ENVELOPES]; + + INT tempFlagRight = 0; + INT tempFlagLeft = 0; + + /* + Store previous values, in order to be able to "undo" what is being + done. + */ + + for (ch = 0; ch < nChannels; ch++) { + FDKmemcpy(sfbNrgPrevTemp[ch], + h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + MAX_FREQ_COEFFS * sizeof(SCHAR)); + + FDKmemcpy(noisePrevTemp[ch], + h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + MAX_NUM_NOISE_COEFFS * sizeof(SCHAR)); + + upDateNrgTemp[ch] = h_envChan[ch]->sbrCodeEnvelope.upDate; + upDateNoiseTemp[ch] = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + if (sbrHeaderData->prev_coupling) { + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + /* + Code ordinary Left/Right stereo + */ + FDKsbrEnc_codeEnvelope(eData[0].sfb_nrg, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, + h_envChan[0]->encEnvData.domain_vec, 0, + eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + FDKsbrEnc_codeEnvelope(eData[1].sfb_nrg, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, + h_envChan[1]->encEnvData.domain_vec, 0, + eData[1].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) { + h_envChan[0]->encEnvData.ienvelope[i][j] = eData[0].sfb_nrg[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = eData[1].sfb_nrg[c]; + c++; + } + } + + FDKsbrEnc_codeEnvelope(eData[0].noise_level, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 0, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = eData[0].noise_level[i]; + + FDKsbrEnc_codeEnvelope(eData[1].noise_level, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 0, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = eData[1].noise_level[i]; + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + + payloadbitsLR = FDKsbrEnc_CountSbrChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + + /* + swap saved stored with current values + */ + for (ch = 0; ch < nChannels; ch++) { + INT itmp; + for (i = 0; i < MAX_FREQ_COEFFS; i++) { + /* + swap sfb energies + */ + itmp = h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev[i] = + sfbNrgPrevTemp[ch][i]; + sfbNrgPrevTemp[ch][i] = itmp; + } + for (i = 0; i < MAX_NUM_NOISE_COEFFS; i++) { + /* + swap noise energies + */ + itmp = h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev[i]; + h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev[i] = + noisePrevTemp[ch][i]; + noisePrevTemp[ch][i] = itmp; + } + /* swap update flags */ + itmp = h_envChan[ch]->sbrCodeEnvelope.upDate; + h_envChan[ch]->sbrCodeEnvelope.upDate = upDateNrgTemp[ch]; + upDateNrgTemp[ch] = itmp; + + itmp = h_envChan[ch]->sbrCodeNoiseFloor.upDate; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = upDateNoiseTemp[ch]; + upDateNoiseTemp[ch] = itmp; + + /* + save domain vecs + */ + FDKmemcpy(domainVecTemp[ch], h_envChan[ch]->encEnvData.domain_vec, + sizeof(INT) * MAX_ENVELOPES); + FDKmemcpy(domainVecNoiseTemp[ch], + h_envChan[ch]->encEnvData.domain_vec_noise, + sizeof(INT) * MAX_ENVELOPES); + + /* + forbid time coding in the first envelope in case of a different + previous stereomode + */ + + if (!sbrHeaderData->prev_coupling) { + h_envChan[ch]->sbrCodeEnvelope.upDate = 0; + h_envChan[ch]->sbrCodeNoiseFloor.upDate = 0; + } + } /* ch */ + + /* + Coupling + */ + + FDKsbrEnc_codeEnvelope( + eData[0].sfb_nrg_coupling, eData[0].frame_info->freqRes, + &h_envChan[0]->sbrCodeEnvelope, h_envChan[0]->encEnvData.domain_vec, + 1, eData[0].frame_info->nEnvelopes, 0, + sbrBitstreamData->HeaderActive); + + FDKsbrEnc_codeEnvelope( + eData[1].sfb_nrg_coupling, eData[1].frame_info->freqRes, + &h_envChan[1]->sbrCodeEnvelope, h_envChan[1]->encEnvData.domain_vec, + 1, eData[1].frame_info->nEnvelopes, 1, + sbrBitstreamData->HeaderActive); + + c = 0; + for (i = 0; i < eData[0].nEnvelopes; i++) { + for (j = 0; j < h_envChan[0]->encEnvData.noScfBands[i]; j++) { + h_envChan[0]->encEnvData.ienvelope[i][j] = + eData[0].sfb_nrg_coupling[c]; + h_envChan[1]->encEnvData.ienvelope[i][j] = + eData[1].sfb_nrg_coupling[c]; + c++; + } + } + + FDKsbrEnc_codeEnvelope(eData[0].noise_level_coupling, fData->res, + &h_envChan[0]->sbrCodeNoiseFloor, + h_envChan[0]->encEnvData.domain_vec_noise, 1, + (eData[0].frame_info->nEnvelopes > 1 ? 2 : 1), 0, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[0]->encEnvData.sbr_noise_levels[i] = + eData[0].noise_level_coupling[i]; + + FDKsbrEnc_codeEnvelope(eData[1].noise_level_coupling, fData->res, + &h_envChan[1]->sbrCodeNoiseFloor, + h_envChan[1]->encEnvData.domain_vec_noise, 1, + (eData[1].frame_info->nEnvelopes > 1 ? 2 : 1), 1, + sbrBitstreamData->HeaderActive); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) + h_envChan[1]->encEnvData.sbr_noise_levels[i] = + eData[1].noise_level_coupling[i]; + + sbrHeaderData->coupling = 1; + + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + + tempFlagLeft = h_envChan[0]->encEnvData.addHarmonicFlag; + tempFlagRight = h_envChan[1]->encEnvData.addHarmonicFlag; + + payloadbitsCOUPLING = FDKsbrEnc_CountSbrChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + + h_envChan[0]->encEnvData.addHarmonicFlag = tempFlagLeft; + h_envChan[1]->encEnvData.addHarmonicFlag = tempFlagRight; + + if (payloadbitsCOUPLING < payloadbitsLR) { + /* + copy coded coupling envelope and noise data to l/r + */ + for (ch = 0; ch < nChannels; ch++) { + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + FDKmemcpy(ed->sfb_nrg, ed->sfb_nrg_coupling, + MAX_NUM_ENVELOPE_VALUES * sizeof(SCHAR)); + FDKmemcpy(ed->noise_level, ed->noise_level_coupling, + MAX_NUM_NOISE_VALUES * sizeof(SCHAR)); + } + + sbrHeaderData->coupling = 1; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 1; + } else { + /* + restore saved l/r items + */ + for (ch = 0; ch < nChannels; ch++) { + FDKmemcpy(h_envChan[ch]->sbrCodeEnvelope.sfb_nrg_prev, + sfbNrgPrevTemp[ch], MAX_FREQ_COEFFS * sizeof(SCHAR)); + + h_envChan[ch]->sbrCodeEnvelope.upDate = upDateNrgTemp[ch]; + + FDKmemcpy(h_envChan[ch]->sbrCodeNoiseFloor.sfb_nrg_prev, + noisePrevTemp[ch], MAX_NUM_NOISE_COEFFS * sizeof(SCHAR)); + + FDKmemcpy(h_envChan[ch]->encEnvData.domain_vec, domainVecTemp[ch], + sizeof(INT) * MAX_ENVELOPES); + FDKmemcpy(h_envChan[ch]->encEnvData.domain_vec_noise, + domainVecNoiseTemp[ch], sizeof(INT) * MAX_ENVELOPES); + + h_envChan[ch]->sbrCodeNoiseFloor.upDate = upDateNoiseTemp[ch]; + } + + sbrHeaderData->coupling = 0; + h_envChan[0]->encEnvData.balance = 0; + h_envChan[1]->encEnvData.balance = 0; + } + } break; + } /* switch */ + + /* tell the envelope encoders how long it has been, since we last sent + a frame starting with a dF-coded envelope */ + if (stereoMode == SBR_MONO) { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME) + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + else + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } else { + if (h_envChan[0]->encEnvData.domain_vec[0] == TIME || + h_envChan[1]->encEnvData.domain_vec[0] == TIME) { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac++; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac++; + } else { + h_envChan[0]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + h_envChan[1]->sbrCodeEnvelope.dF_edge_incr_fac = 0; + } + } + + /* + Send the encoded data to the bitstream + */ + for (ch = 0; ch < nChannels; ch++) { + SBR_ENV_TEMP_DATA *ed = &eData[ch]; + c = 0; + for (i = 0; i < ed->nEnvelopes; i++) { + for (j = 0; j < h_envChan[ch]->encEnvData.noScfBands[i]; j++) { + h_envChan[ch]->encEnvData.ienvelope[i][j] = ed->sfb_nrg[c]; + + c++; + } + } + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) { + h_envChan[ch]->encEnvData.sbr_noise_levels[i] = ed->noise_level[i]; + } + } /* ch */ + + /* + Write bitstream + */ + if (nChannels == 2) { + FDKsbrEnc_WriteEnvChannelPairElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, &h_envChan[1]->encEnvData, hCmonData, + h_con->sbrSyntaxFlags); + } else { + FDKsbrEnc_WriteEnvSingleChannelElement( + sbrHeaderData, hParametricStereo, sbrBitstreamData, + &h_envChan[0]->encEnvData, hCmonData, h_con->sbrSyntaxFlags); + } + + /* + * Update buffers. + */ + for (ch = 0; ch < nChannels; ch++) { + int YBufferLength = h_envChan[ch]->sbrExtractEnvelope.no_cols >> + h_envChan[ch]->sbrExtractEnvelope.YBufferSzShift; + for (i = 0; i < h_envChan[ch]->sbrExtractEnvelope.YBufferWriteOffset; i++) { + FDKmemcpy(h_envChan[ch]->sbrExtractEnvelope.YBuffer[i], + h_envChan[ch]->sbrExtractEnvelope.YBuffer[i + YBufferLength], + sizeof(FIXP_DBL) * 64); + } + h_envChan[ch]->sbrExtractEnvelope.YBufferScale[0] = + h_envChan[ch]->sbrExtractEnvelope.YBufferScale[1]; + } + + sbrHeaderData->prev_coupling = sbrHeaderData->coupling; +} + +/***************************************************************************/ +/*! + + \brief creates an envelope extractor handle + + \return error status + +****************************************************************************/ +INT FDKsbrEnc_CreateExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel, INT chInEl, + UCHAR *dynamic_RAM) { + INT i; + FIXP_DBL *rBuffer, *iBuffer; + INT n; + FIXP_DBL *YBufferDyn; + + FDKmemclear(hSbrCut, sizeof(SBR_EXTRACT_ENVELOPE)); + + if (NULL == (hSbrCut->p_YBuffer = GetRam_Sbr_envYBuffer(channel))) { + goto bail; + } + + for (i = 0; i < (32 >> 1); i++) { + hSbrCut->YBuffer[i] = hSbrCut->p_YBuffer + (i * 64); + } + YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + for (n = 0; i < 32; i++, n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n * 64); + } + + rBuffer = GetRam_Sbr_envRBuffer(0, dynamic_RAM); + iBuffer = GetRam_Sbr_envIBuffer(0, dynamic_RAM); + + for (i = 0; i < 32; i++) { + hSbrCut->rBuffer[i] = rBuffer + (i * 64); + hSbrCut->iBuffer[i] = iBuffer + (i * 64); + } + + return 0; + +bail: + FDKsbrEnc_deleteExtractSbrEnvelope(hSbrCut); + + return -1; +} + +/***************************************************************************/ +/*! + + \brief Initialize an envelope extractor instance. + + \return error status + +****************************************************************************/ +INT FDKsbrEnc_InitExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + int no_cols, int no_rows, int start_index, + int time_slots, int time_step, + int tran_off, ULONG statesInitFlag, + int chInEl, UCHAR *dynamic_RAM, + UINT sbrSyntaxFlags) { + int YBufferLength, rBufferLength; + int i; + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + int off = TRANSIENT_OFFSET_LD; + hSbrCut->YBufferWriteOffset = (no_cols >> 1) + off * time_step; + } else { + hSbrCut->YBufferWriteOffset = tran_off * time_step; + } + hSbrCut->rBufferReadOffset = 0; + + YBufferLength = hSbrCut->YBufferWriteOffset + no_cols; + rBufferLength = no_cols; + + hSbrCut->pre_transient_info[0] = 0; + hSbrCut->pre_transient_info[1] = 0; + + hSbrCut->no_cols = no_cols; + hSbrCut->no_rows = no_rows; + hSbrCut->start_index = start_index; + + hSbrCut->time_slots = time_slots; + hSbrCut->time_step = time_step; + + FDK_ASSERT(no_rows <= 64); + + /* Use half the Energy values if time step is 2 or greater */ + if (time_step >= 2) + hSbrCut->YBufferSzShift = 1; + else + hSbrCut->YBufferSzShift = 0; + + YBufferLength >>= hSbrCut->YBufferSzShift; + hSbrCut->YBufferWriteOffset >>= hSbrCut->YBufferSzShift; + + FDK_ASSERT(YBufferLength <= 32); + + FIXP_DBL *YBufferDyn = GetRam_Sbr_envYBuffer(chInEl, dynamic_RAM); + INT n = 0; + for (i = (32 >> 1); i < 32; i++, n++) { + hSbrCut->YBuffer[i] = YBufferDyn + (n * 64); + } + + if (statesInitFlag) { + for (i = 0; i < YBufferLength; i++) { + FDKmemclear(hSbrCut->YBuffer[i], 64 * sizeof(FIXP_DBL)); + } + } + + for (i = 0; i < rBufferLength; i++) { + FDKmemclear(hSbrCut->rBuffer[i], 64 * sizeof(FIXP_DBL)); + FDKmemclear(hSbrCut->iBuffer[i], 64 * sizeof(FIXP_DBL)); + } + + FDKmemclear(hSbrCut->envelopeCompensation, sizeof(UCHAR) * MAX_FREQ_COEFFS); + + if (statesInitFlag) { + hSbrCut->YBufferScale[0] = hSbrCut->YBufferScale[1] = FRACT_BITS - 1; + } + + return (0); +} + +/***************************************************************************/ +/*! + + \brief deinitializes an envelope extractor handle + + \return void + +****************************************************************************/ + +void FDKsbrEnc_deleteExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut) { + if (hSbrCut) { + FreeRam_Sbr_envYBuffer(&hSbrCut->p_YBuffer); + } +} + +INT FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr) { + return hSbr->no_rows * + ((hSbr->YBufferWriteOffset) * + 2 /* mult 2 because nrg's are grouped half */ + - hSbr->rBufferReadOffset); /* in reference hold half spec and calc + nrg's on overlapped spec */ +} diff --git a/fdk-aac/libSBRenc/src/env_est.h b/fdk-aac/libSBRenc/src/env_est.h new file mode 100644 index 0000000..006f55b --- /dev/null +++ b/fdk-aac/libSBRenc/src/env_est.h @@ -0,0 +1,223 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Envelope estimation structs and prototypes $Revision: 92790 $ +*/ +#ifndef ENV_EST_H +#define ENV_EST_H + +#include "sbr_def.h" +#include "sbr_encoder.h" /* SBR econfig structs */ +#include "ps_main.h" +#include "bit_sbr.h" +#include "fram_gen.h" +#include "tran_det.h" +#include "code_env.h" +#include "ton_corr.h" + +typedef struct { + FIXP_DBL *rBuffer[32]; + FIXP_DBL *iBuffer[32]; + + FIXP_DBL *p_YBuffer; + + FIXP_DBL *YBuffer[32]; + int YBufferScale[2]; + + UCHAR envelopeCompensation[MAX_FREQ_COEFFS]; + UCHAR pre_transient_info[2]; + + int YBufferWriteOffset; + int YBufferSzShift; + int rBufferReadOffset; + + int no_cols; + int no_rows; + int start_index; + + int time_slots; + int time_step; +} SBR_EXTRACT_ENVELOPE; +typedef SBR_EXTRACT_ENVELOPE *HANDLE_SBR_EXTRACT_ENVELOPE; + +struct ENV_CHANNEL { + FAST_TRAN_DETECTOR sbrFastTransientDetector; + SBR_TRANSIENT_DETECTOR sbrTransientDetector; + SBR_CODE_ENVELOPE sbrCodeEnvelope; + SBR_CODE_ENVELOPE sbrCodeNoiseFloor; + SBR_EXTRACT_ENVELOPE sbrExtractEnvelope; + + SBR_ENVELOPE_FRAME SbrEnvFrame; + SBR_TON_CORR_EST TonCorr; + + struct SBR_ENV_DATA encEnvData; + + int qmfScale; + UCHAR fLevelProtect; +}; +typedef struct ENV_CHANNEL *HANDLE_ENV_CHANNEL; + +/************ Function Declarations ***************/ + +INT FDKsbrEnc_CreateExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut, + INT channel, INT chInEl, + UCHAR *dynamic_RAM); + +INT FDKsbrEnc_InitExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbr, + int no_cols, int no_rows, int start_index, + int time_slots, int time_step, + int tran_off, ULONG statesInitFlag, + int chInEl, UCHAR *dynamic_RAM, + UINT sbrSyntaxFlags); + +void FDKsbrEnc_deleteExtractSbrEnvelope(HANDLE_SBR_EXTRACT_ENVELOPE hSbrCut); + +typedef struct { + FREQ_RES res[MAX_NUM_NOISE_VALUES]; + int maxQuantError; + +} SBR_FRAME_TEMP_DATA; + +typedef struct { + const SBR_FRAME_INFO *frame_info; + FIXP_DBL noiseFloor[MAX_NUM_NOISE_VALUES]; + SCHAR sfb_nrg_coupling + [MAX_NUM_ENVELOPE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR sfb_nrg[MAX_NUM_ENVELOPE_VALUES]; + SCHAR noise_level_coupling + [MAX_NUM_NOISE_VALUES]; /* only used if stereomode = SWITCH_L_R_C */ + SCHAR noise_level[MAX_NUM_NOISE_VALUES]; + UCHAR transient_info[3]; + UCHAR nEnvelopes; +} SBR_ENV_TEMP_DATA; + +/* + * Extract features from QMF data. Afterwards, the QMF data is not required + * anymore. + */ +void FDKsbrEnc_extractSbrEnvelope1(HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL h_envChan, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData); + +/* + * Process the previously features extracted by FDKsbrEnc_extractSbrEnvelope1 + * and create/encode SBR envelopes. + */ +void FDKsbrEnc_extractSbrEnvelope2(HANDLE_SBR_CONFIG_DATA h_con, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData, + HANDLE_ENV_CHANNEL sbrEnvChannel0, + HANDLE_ENV_CHANNEL sbrEnvChannel1, + HANDLE_COMMON_DATA cmonData, + SBR_ENV_TEMP_DATA *eData, + SBR_FRAME_TEMP_DATA *fData, int clearOutput); + +INT FDKsbrEnc_GetEnvEstDelay(HANDLE_SBR_EXTRACT_ENVELOPE hSbr); + +#endif diff --git a/fdk-aac/libSBRenc/src/fram_gen.cpp b/fdk-aac/libSBRenc/src/fram_gen.cpp new file mode 100644 index 0000000..7ed6e79 --- /dev/null +++ b/fdk-aac/libSBRenc/src/fram_gen.cpp @@ -0,0 +1,1965 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "fram_gen.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +static const SBR_FRAME_INFO frameInfo1_2048 = {1, {0, 16}, {FREQ_RES_HIGH}, + 0, 1, {0, 16}}; + +static const SBR_FRAME_INFO frameInfo2_2048 = { + 2, {0, 8, 16}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 16}}; + +static const SBR_FRAME_INFO frameInfo4_2048 = { + 4, + {0, 4, 8, 12, 16}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 8, 16}}; + +static const SBR_FRAME_INFO frameInfo1_2304 = {1, {0, 18}, {FREQ_RES_HIGH}, + 0, 1, {0, 18}}; + +static const SBR_FRAME_INFO frameInfo2_2304 = { + 2, {0, 9, 18}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 9, 18}}; + +static const SBR_FRAME_INFO frameInfo4_2304 = { + 4, + {0, 5, 9, 14, 18}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 9, 18}}; + +static const SBR_FRAME_INFO frameInfo1_1920 = {1, {0, 15}, {FREQ_RES_HIGH}, + 0, 1, {0, 15}}; + +static const SBR_FRAME_INFO frameInfo2_1920 = { + 2, {0, 8, 15}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 8, 15}}; + +static const SBR_FRAME_INFO frameInfo4_1920 = { + 4, + {0, 4, 8, 12, 15}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 8, 15}}; + +static const SBR_FRAME_INFO frameInfo1_1152 = {1, {0, 9}, {FREQ_RES_HIGH}, + 0, 1, {0, 9}}; + +static const SBR_FRAME_INFO frameInfo2_1152 = { + 2, {0, 5, 9}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 5, 9}}; + +static const SBR_FRAME_INFO frameInfo4_1152 = { + 4, + {0, 2, 5, 7, 9}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 5, 9}}; + +/* AACLD frame info */ +static const SBR_FRAME_INFO frameInfo1_512LD = {1, {0, 8}, {FREQ_RES_HIGH}, + 0, 1, {0, 8}}; + +static const SBR_FRAME_INFO frameInfo2_512LD = { + 2, {0, 4, 8}, {FREQ_RES_HIGH, FREQ_RES_HIGH}, 0, 2, {0, 4, 8}}; + +static const SBR_FRAME_INFO frameInfo4_512LD = { + 4, + {0, 2, 4, 6, 8}, + {FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}, + 0, + 2, + {0, 4, 8}}; + +static int calcFillLengthMax( + int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ +); + +static void fillFrameTran( + const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ +); + +static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq, + INT *length_v_freq, INT bmin, INT rest); + +static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT bmax, INT bufferFrameStart, INT numberTimeSlots, + INT fmax); + +static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord, + INT *length_v_bord, INT bmin, INT *v_freq, + INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, INT dmin, + INT dmax, INT numberTimeSlots); + +static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, + INT tranFlag, INT *spreadFlag); + +static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT *parts, INT d); + +static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord, + INT *length_v_bord, INT tran, INT bufferFrameStart, + INT numberTimeSlots); + +static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT i_cmon, + INT i_tran, INT parts, INT numberTimeSlots); + +static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, + INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, + INT spreadFlag, INT nL); + +static void ctrlSignal2FrameInfo(HANDLE_SBR_GRID hSbrGrid, + HANDLE_SBR_FRAME_INFO hFrameInfo, + FREQ_RES *freq_res_fixfix); + +/* table for 8 time slot index */ +static const int envelopeTable_8[8][5] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* borders from left to right side; -1 = not in use */ + /*[|T-|------]*/ {2, 0, 0, 1, -1}, + /*[|-T-|-----]*/ {2, 0, 0, 2, -1}, + /*[--|T-|----]*/ {3, 1, 1, 2, 4}, + /*[---|T-|---]*/ {3, 1, 1, 3, 5}, + /*[----|T-|--]*/ {3, 1, 1, 4, 6}, + /*[-----|T--|]*/ {2, 1, 1, 5, -1}, + /*[------|T-|]*/ {2, 1, 1, 6, -1}, + /*[-------|T|]*/ {2, 1, 1, 7, -1}, +}; + +/* table for 16 time slot index */ +static const int envelopeTable_16[16][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------|]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------|]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|----------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|---------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|--------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|-------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|------]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|-----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|----]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|---]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T---|--]*/ {3, 1, 1, 10, 14, -1}, + /*[|-----------|T----|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T---|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T--|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T-|]*/ {2, 1, 1, 14, -1, -1}, + /*[|---------------|T|]*/ {2, 1, 1, 15, -1, -1}, +}; + +/* table for 15 time slot index */ +static const int envelopeTable_15[15][6] = { + /* transientIndex nEnv, tranIdx, shortEnv, border1, border2, ... */ + /* length from left to right side; -1 = not in use */ + /*[|T---|------------]*/ {2, 0, 0, 4, -1, -1}, + /*[|-T---|-----------]*/ {2, 0, 0, 5, -1, -1}, + /*[|--|T---|---------]*/ {3, 1, 1, 2, 6, -1}, + /*[|---|T---|--------]*/ {3, 1, 1, 3, 7, -1}, + /*[|----|T---|-------]*/ {3, 1, 1, 4, 8, -1}, + /*[|-----|T---|------]*/ {3, 1, 1, 5, 9, -1}, + /*[|------|T---|-----]*/ {3, 1, 1, 6, 10, -1}, + /*[|-------|T---|----]*/ {3, 1, 1, 7, 11, -1}, + /*[|--------|T---|---]*/ {3, 1, 1, 8, 12, -1}, + /*[|---------|T---|--]*/ {3, 1, 1, 9, 13, -1}, + /*[|----------|T----|]*/ {2, 1, 1, 10, -1, -1}, + /*[|-----------|T---|]*/ {2, 1, 1, 11, -1, -1}, + /*[|------------|T--|]*/ {2, 1, 1, 12, -1, -1}, + /*[|-------------|T-|]*/ {2, 1, 1, 13, -1, -1}, + /*[|--------------|T|]*/ {2, 1, 1, 14, -1, -1}, +}; + +static const int minFrameTranDistance = 4; + +static const FREQ_RES freqRes_table_8[] = { + FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, FREQ_RES_LOW, + FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH, FREQ_RES_HIGH}; + +static const FREQ_RES freqRes_table_16[16] = { + /* size of envelope */ + /* 0-4 */ FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + FREQ_RES_LOW, + /* 5-9 */ FREQ_RES_LOW, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + /* 10-16 */ FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH, + FREQ_RES_HIGH}; + +static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, + int numberTimeSlots, UCHAR fResTransIsLow); + +/*! + Functionname: FDKsbrEnc_frameInfoGenerator + + Description: produces the FRAME_INFO struct for the current frame + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + v_pre_transient_info - pointer to transient info vector + v_transient_info - pointer to previous transient info +vector v_tuning - pointer to tuning vector + + Return: frame_info - pointer to SBR_FRAME_INFO struct + +*******************************************************************************/ +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, const INT rightBorderFIX, + UCHAR *v_transient_info_pre, int ldGrid, + const int *v_tuning) { + INT numEnv, tranPosInternal = 0, bmin = 0, bmax = 0, parts, d, i_cmon = 0, + i_tran = 0, nL; + INT fmax = 0; + + INT *v_bord = hSbrEnvFrame->v_bord; + INT *v_freq = hSbrEnvFrame->v_freq; + INT *v_bordFollow = hSbrEnvFrame->v_bordFollow; + INT *v_freqFollow = hSbrEnvFrame->v_freqFollow; + + INT *length_v_bordFollow = &hSbrEnvFrame->length_v_bordFollow; + INT *length_v_freqFollow = &hSbrEnvFrame->length_v_freqFollow; + INT *length_v_bord = &hSbrEnvFrame->length_v_bord; + INT *length_v_freq = &hSbrEnvFrame->length_v_freq; + INT *spreadFlag = &hSbrEnvFrame->spreadFlag; + INT *i_tranFollow = &hSbrEnvFrame->i_tranFollow; + INT *i_fillFollow = &hSbrEnvFrame->i_fillFollow; + FRAME_CLASS *frameClassOld = &hSbrEnvFrame->frameClassOld; + FRAME_CLASS frameClass = FIXFIX; + + INT allowSpread = hSbrEnvFrame->allowSpread; + INT numEnvStatic = hSbrEnvFrame->numEnvStatic; + INT staticFraming = hSbrEnvFrame->staticFraming; + INT dmin = hSbrEnvFrame->dmin; + INT dmax = hSbrEnvFrame->dmax; + + INT bufferFrameStart = hSbrEnvFrame->SbrGrid.bufferFrameStart; + INT numberTimeSlots = hSbrEnvFrame->SbrGrid.numberTimeSlots; + INT frameMiddleSlot = hSbrEnvFrame->frameMiddleSlot; + + INT tranPos = v_transient_info[0]; + INT tranFlag = v_transient_info[1]; + + const int *v_tuningSegm = v_tuning; + const int *v_tuningFreq = v_tuning + 3; + + hSbrEnvFrame->v_tuningSegm = v_tuningSegm; + + if (ldGrid) { + /* in case there was a transient at the very end of the previous frame, + * start with a transient envelope */ + if (!tranFlag && v_transient_info_pre[1] && + (numberTimeSlots - v_transient_info_pre[0] < minFrameTranDistance)) { + tranFlag = 1; + tranPos = 0; + } + } + + /* + * Synopsis: + * + * The frame generator creates the time-/frequency-grid for one SBR frame. + * Input signals are provided by the transient detector and the frame + * splitter (transientDetectNew() & FrameSplitter() in tran_det.c). The + * framing is controlled by adjusting tuning parameters stored in + * FRAME_GEN_TUNING. The parameter values are dependent on frame lengths + * and bitrates, and may in the future be signal dependent. + * + * The envelope borders are stored for frame generator internal use in + * aBorders. The contents of aBorders represent positions along the time + * axis given in the figures in fram_gen.h (the "frame-generator" rows). + * The unit is "time slot". The figures in fram_gen.h also define the + * detection ranges for the transient detector. For every border in + * aBorders, there is a corresponding entry in aFreqRes, which defines the + * frequency resolution of the envelope following (delimited by) the + * border. + * + * When no transients are present, FIXFIX class frames are used. The + * frame splitter decides whether to use one or two envelopes in the + * FIXFIX frame. "Sparse transients" (separated by a few frames without + * transients) are handeled by [FIXVAR, VARFIX] pairs or (depending on + * tuning and transient position relative the nominal frame boundaries) + * by [FIXVAR, VARVAR, VARFIX] triples. "Tight transients" (in + * consecutive frames) are handeled by [..., VARVAR, VARVAR, ...] + * sequences. + * + * The generator assumes that transients are "sparse", and designs + * borders for [FIXVAR, VARFIX] pairs right away, where the first frame + * corresponds to the present frame. At the next call of the generator + * it is known whether the transient actually is "sparse" or not. If + * 'yes', the already calculated VARFIX borders are used. If 'no', new + * borders, meeting the requirements of the "tight" transient, are + * calculated. + * + * The generator produces two outputs: A "clear-text bitstream" stored in + * SBR_GRID, and a straight-forward representation of the grid stored in + * SBR_FRAME_INFO. The former is subsequently converted to the actual + * bitstream sbr_grid() (encodeSbrGrid() in bit_sbr.c). The latter is + * used by other encoder functions, such as the envelope estimator + * (calculateSbrEnvelope() in env_est.c) and the noise floor and missing + * harmonics detector (TonCorrParamExtr() in nf_est.c). + */ + + if (staticFraming) { + /*-------------------------------------------------------------------------- + Ignore transient detector + ---------------------------------------------------------------------------*/ + + frameClass = FIXFIX; + numEnv = numEnvStatic; /* {1,2,4,8} */ + *frameClassOld = FIXFIX; /* for change to dyn */ + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + } else { + /*-------------------------------------------------------------------------- + Calculate frame class to use + ---------------------------------------------------------------------------*/ + if (rightBorderFIX) { + tranFlag = 0; + *spreadFlag = 0; + } + calcFrameClass(&frameClass, frameClassOld, tranFlag, spreadFlag); + + /* patch for new frame class FIXFIXonly for AAC LD */ + if (tranFlag && ldGrid) { + frameClass = FIXFIXonly; + *frameClassOld = FIXFIX; + } + + /* + * every transient is processed below by inserting + * + * - one border at the onset of the transient + * - one or more "decay borders" (after the onset of the transient) + * - optionally one "attack border" (before the onset of the transient) + * + * those borders are referred to as "mandatory borders" and are + * defined by the 'segmentLength' array in FRAME_GEN_TUNING + * + * the frequency resolutions of the corresponding envelopes are + * defined by the 'segmentRes' array in FRAME_GEN_TUNING + */ + + /*-------------------------------------------------------------------------- + Design frame (or follow-up old design) + ---------------------------------------------------------------------------*/ + if (tranFlag) { + /* Always for FixVar, often but not always for VarVar */ + + /*-------------------------------------------------------------------------- + Design part of T/F-grid around the new transient + ---------------------------------------------------------------------------*/ + + tranPosInternal = + frameMiddleSlot + tranPos + bufferFrameStart; /* FH 00-06-26 */ + /* + add mandatory borders around transient + */ + + fillFrameTran(v_tuningSegm, v_tuningFreq, tranPosInternal, v_bord, + length_v_bord, v_freq, length_v_freq, &bmin, &bmax); + + /* make sure we stay within the maximum SBR frame overlap */ + fmax = calcFillLengthMax(tranPos, numberTimeSlots); + } + + switch (frameClass) { + case FIXFIXonly: + FDK_ASSERT(ldGrid); + tranPosInternal = tranPos; + generateFixFixOnly(&(hSbrEnvFrame->SbrFrameInfo), + &(hSbrEnvFrame->SbrGrid), tranPosInternal, + numberTimeSlots, hSbrEnvFrame->fResTransIsLow); + + return &(hSbrEnvFrame->SbrFrameInfo); + + case FIXVAR: + + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + ---------------------------------------------------------------------------*/ + + /*-------------------------------------------------------------------------- + Fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + bmin - bufferFrameStart); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Fill region after new transient: + ---------------------------------------------------------------------------*/ + fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, + fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /* no fill, short last envelope */ + specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq, + length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord, tranPosInternal, + bufferFrameStart, numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow, + length_v_freqFollow, i_tranFollow, i_fillFollow, v_bord, + length_v_bord, v_freq, i_cmon, i_tran, parts, + numberTimeSlots); /* FH 00-06-26 */ + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord, + *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran, + *spreadFlag, DC); + break; + case VARFIX: + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow, + *length_v_bordFollow, v_freqFollow, *length_v_freqFollow, + DC, *i_tranFollow, *spreadFlag, DC); + break; + case VARVAR: + if (*spreadFlag) { /* spread across three frames */ + /*-------------------------------------------------------------------------- + Follow-up old transient - calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bordFollow, + *length_v_bordFollow, v_freqFollow, + *length_v_freqFollow, DC, *i_tranFollow, *spreadFlag, + DC); + + *spreadFlag = 0; + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + v_bordFollow[0] = hSbrEnvFrame->SbrGrid.bs_abs_bord_1 - + numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[0] = 1; + *length_v_bordFollow = 1; + *length_v_freqFollow = 1; + + *i_tranFollow = -DC; + *i_fillFollow = -DC; + } else { + /*-------------------------------------------------------------------------- + Design remaining parts of T/F-grid (assuming next frame is VarFix) + adapt or fill region before new transient: + ---------------------------------------------------------------------------*/ + fillFrameInter(&nL, v_tuningSegm, v_bord, length_v_bord, bmin, v_freq, + length_v_freq, v_bordFollow, length_v_bordFollow, + v_freqFollow, length_v_freqFollow, *i_fillFollow, dmin, + dmax, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Fill after transient: + ---------------------------------------------------------------------------*/ + fillFramePost(&parts, &d, dmax, v_bord, length_v_bord, v_freq, + length_v_freq, bmax, bufferFrameStart, numberTimeSlots, + fmax); + + /*-------------------------------------------------------------------------- + Take care of special case: + ---------------------------------------------------------------------------*/ + if (parts == 1 && d < dmin) /*% no fill, short last envelope */ + specialCase(spreadFlag, allowSpread, v_bord, length_v_bord, v_freq, + length_v_freq, &parts, d); + + /*-------------------------------------------------------------------------- + Calculate common border (split-point) + ---------------------------------------------------------------------------*/ + calcCmonBorder(&i_cmon, &i_tran, v_bord, length_v_bord, + tranPosInternal, bufferFrameStart, numberTimeSlots); + + /*-------------------------------------------------------------------------- + Extract data for proper follow-up in next frame + ---------------------------------------------------------------------------*/ + keepForFollowUp(v_bordFollow, length_v_bordFollow, v_freqFollow, + length_v_freqFollow, i_tranFollow, i_fillFollow, + v_bord, length_v_bord, v_freq, i_cmon, i_tran, parts, + numberTimeSlots); + + /*-------------------------------------------------------------------------- + Calculate control signal + ---------------------------------------------------------------------------*/ + calcCtrlSignal(&hSbrEnvFrame->SbrGrid, frameClass, v_bord, + *length_v_bord, v_freq, *length_v_freq, i_cmon, i_tran, + 0, nL); + } + break; + case FIXFIX: + if (tranPos == 0) + numEnv = 1; + else + numEnv = 2; + + hSbrEnvFrame->SbrGrid.bs_num_env = numEnv; + hSbrEnvFrame->SbrGrid.frameClass = frameClass; + + break; + default: + FDK_ASSERT(0); + } + } + + /*------------------------------------------------------------------------- + Convert control signal to frame info struct + ---------------------------------------------------------------------------*/ + ctrlSignal2FrameInfo(&hSbrEnvFrame->SbrGrid, &hSbrEnvFrame->SbrFrameInfo, + hSbrEnvFrame->freq_res_fixfix); + + return &hSbrEnvFrame->SbrFrameInfo; +} + +/***************************************************************************/ +/*! + \brief Gnerates frame info for FIXFIXonly frame class used for low delay + version + + \return nothing + ****************************************************************************/ +static void generateFixFixOnly(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, + HANDLE_SBR_GRID hSbrGrid, int tranPosInternal, + int numberTimeSlots, UCHAR fResTransIsLow) { + int nEnv, i, k = 0, tranIdx; + const int *pTable = NULL; + const FREQ_RES *freqResTable = NULL; + + switch (numberTimeSlots) { + case 8: { + pTable = envelopeTable_8[tranPosInternal]; + } + freqResTable = freqRes_table_8; + break; + case 15: + pTable = envelopeTable_15[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + case 16: + pTable = envelopeTable_16[tranPosInternal]; + freqResTable = freqRes_table_16; + break; + } + + /* look number of envolpes in table */ + nEnv = pTable[0]; + /* look up envolpe distribution in table */ + for (i = 1; i < nEnv; i++) hSbrFrameInfo->borders[i] = pTable[i + 2]; + + /* open and close frame border */ + hSbrFrameInfo->borders[0] = 0; + hSbrFrameInfo->borders[nEnv] = numberTimeSlots; + + /* adjust segment-frequency-resolution according to the segment-length */ + for (i = 0; i < nEnv; i++) { + k = hSbrFrameInfo->borders[i + 1] - hSbrFrameInfo->borders[i]; + if (!fResTransIsLow) + hSbrFrameInfo->freqRes[i] = freqResTable[k]; + else + hSbrFrameInfo->freqRes[i] = FREQ_RES_LOW; + + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i]; + } + + hSbrFrameInfo->nEnvelopes = nEnv; + hSbrFrameInfo->shortEnv = pTable[2]; + /* transient idx */ + tranIdx = pTable[1]; + + /* add noise floors */ + hSbrFrameInfo->bordersNoise[0] = 0; + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[tranIdx ? tranIdx : 1]; + hSbrFrameInfo->bordersNoise[2] = numberTimeSlots; + hSbrFrameInfo->nNoiseEnvelopes = 2; + + hSbrGrid->frameClass = FIXFIXonly; + hSbrGrid->bs_abs_bord = tranPosInternal; + hSbrGrid->bs_num_env = nEnv; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_initFrameInfoGenerator + ******************************************************************************* + + Description: + + Arguments: hSbrEnvFrame - pointer to sbr envelope handle + allowSpread - commandline parameter + numEnvStatic - commandline parameter + staticFraming - commandline parameter + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_initFrameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, INT numEnvStatic, + INT staticFraming, INT timeSlots, + const FREQ_RES *freq_res_fixfix, + UCHAR fResTransIsLow, + INT ldGrid) { /* FH 00-06-26 */ + + FDKmemclear(hSbrEnvFrame, sizeof(SBR_ENVELOPE_FRAME)); + + /* Initialisation */ + hSbrEnvFrame->frameClassOld = FIXFIX; + hSbrEnvFrame->spreadFlag = 0; + + hSbrEnvFrame->allowSpread = allowSpread; + hSbrEnvFrame->numEnvStatic = numEnvStatic; + hSbrEnvFrame->staticFraming = staticFraming; + hSbrEnvFrame->freq_res_fixfix[0] = freq_res_fixfix[0]; + hSbrEnvFrame->freq_res_fixfix[1] = freq_res_fixfix[1]; + hSbrEnvFrame->fResTransIsLow = fResTransIsLow; + + hSbrEnvFrame->length_v_bord = 0; + hSbrEnvFrame->length_v_bordFollow = 0; + + hSbrEnvFrame->length_v_freq = 0; + hSbrEnvFrame->length_v_freqFollow = 0; + + hSbrEnvFrame->i_tranFollow = 0; + hSbrEnvFrame->i_fillFollow = 0; + + hSbrEnvFrame->SbrGrid.numberTimeSlots = timeSlots; + + if (ldGrid) { + /*case CODEC_AACLD:*/ + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 16; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_512LD; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + } else + switch (timeSlots) { + case NUMBER_TIME_SLOTS_1920: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1920; + break; + case NUMBER_TIME_SLOTS_2048: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 12; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1152: + hSbrEnvFrame->dmin = 2; + hSbrEnvFrame->dmax = 8; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_1152; + break; + case NUMBER_TIME_SLOTS_2304: + hSbrEnvFrame->dmin = 4; + hSbrEnvFrame->dmax = 15; + hSbrEnvFrame->SbrGrid.bufferFrameStart = 0; + hSbrEnvFrame->frameMiddleSlot = FRAME_MIDDLE_SLOT_2304; + break; + default: + FDK_ASSERT(0); + } +} + +/******************************************************************************* + Functionname: fillFrameTran + ******************************************************************************* + + Description: Add mandatory borders, as described by the tuning vector + and the current transient position + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + bmin - int pointer to bmin (call by reference) + bmax - int pointer to bmax (call by reference) + not modified: + tran - position of transient + v_tuningSegm - int pointer to v_tuningSegm vector + v_tuningFreq - int pointer to v_tuningFreq vector + + Return: none + +*******************************************************************************/ +static void fillFrameTran( + const int *v_tuningSegm, /*!< tuning: desired segment lengths */ + const int *v_tuningFreq, /*!< tuning: desired frequency resolutions */ + int tran, /*!< input : position of transient */ + int *v_bord, /*!< memNew: borders */ + int *length_v_bord, /*!< memNew: # borders */ + int *v_freq, /*!< memNew: frequency resolutions */ + int *length_v_freq, /*!< memNew: # frequency resolutions */ + int *bmin, /*!< hlpNew: first mandatory border */ + int *bmax /*!< hlpNew: last mandatory border */ +) { + int bord, i; + + *length_v_bord = 0; + *length_v_freq = 0; + + /* add attack env leading border (optional) */ + if (v_tuningSegm[0]) { + /* v_bord = [(Ba)] start of attack env */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, (tran - v_tuningSegm[0])); + + /* v_freq = [(Fa)] res of attack env */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[0]); + } + + /* add attack env trailing border/first decay env leading border */ + bord = tran; + FDKsbrEnc_AddRight(v_bord, length_v_bord, tran); /* v_bord = [(Ba),Bd1] */ + + /* add first decay env trailing border/2:nd decay env leading border */ + if (v_tuningSegm[1]) { + bord += v_tuningSegm[1]; + + /* v_bord = [(Ba),Bd1,Bd2] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[1]); + } + + /* add 2:nd decay env trailing border (optional) */ + if (v_tuningSegm[2] != 0) { + bord += v_tuningSegm[2]; + + /* v_bord = [(Ba),Bd1, Bd2,(Bd3)] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [(Fa),Fd1,(Fd2)] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, v_tuningFreq[2]); + } + + /* v_freq = [(Fa),Fd1,(Fd2),1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + + /* calc min and max values of mandatory borders */ + *bmin = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] < *bmin) *bmin = v_bord[i]; + + *bmax = v_bord[0]; + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] > *bmax) *bmax = v_bord[i]; +} + +/******************************************************************************* + Functionname: fillFramePre + ******************************************************************************* + + Description: Add borders before mandatory borders, if needed + + Arguments: + modified: + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + dmax - int value + bmin - int value + rest - int value + + Return: none + +*******************************************************************************/ +static void fillFramePre(INT dmax, INT *v_bord, INT *length_v_bord, INT *v_freq, + INT *length_v_freq, INT bmin, INT rest) { + /* + input state: + v_bord = [(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [(Fa),Fd1,(Fd2),1 ] + */ + + INT parts, d, j, S, s = 0, segm, bord; + + /* + start with one envelope + */ + + parts = 1; + d = rest; + + /* + calc # of additional envelopes and corresponding lengths + */ + + while (d > dmax) { + parts++; + + segm = rest / parts; + S = (segm - 2) >> 1; + s = fixMin(8, 2 * S + 2); + d = rest - (parts - 1) * s; + } + + /* + add borders before mandatory borders + */ + + bord = bmin; + + for (j = 0; j <= parts - 2; j++) { + bord = bord - s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] */ + FDKsbrEnc_AddLeft(v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 ] */ + FDKsbrEnc_AddLeft(v_freq, length_v_freq, 1); + } +} + +/***************************************************************************/ +/*! + \brief Overlap control + + Calculate max length of trailing fill segments, such that we always get a + border within the frame overlap region + + \return void + +****************************************************************************/ +static int calcFillLengthMax( + int tranPos, /*!< input : transient position (ref: tran det) */ + int numberTimeSlots /*!< input : number of timeslots */ +) { + int fmax; + + /* + calculate transient position within envelope buffer + */ + switch (numberTimeSlots) { + case NUMBER_TIME_SLOTS_2048: + if (tranPos < 4) + fmax = 6; + else if (tranPos == 4 || tranPos == 5) + fmax = 4; + else + fmax = 8; + break; + + case NUMBER_TIME_SLOTS_1920: + if (tranPos < 4) + fmax = 5; + else if (tranPos == 4 || tranPos == 5) + fmax = 3; + else + fmax = 7; + break; + + default: + fmax = 8; + break; + } + + return fmax; +} + +/******************************************************************************* + Functionname: fillFramePost + ******************************************************************************* + + Description: -Add borders after mandatory borders, if needed + Make a preliminary design of next frame, + assuming no transient is present there + + Arguments: + modified: + parts - int pointer to parts (call by reference) + d - int pointer to d (call by reference) + v_bord - int pointer to v_bord vector + length_v_bord - length of v_bord vector + v_freq - int pointer to v_freq vector + length_v_freq - length of v_freq vector + not modified: + bmax - int value + dmax - int value + + Return: none + +*******************************************************************************/ +static void fillFramePost(INT *parts, INT *d, INT dmax, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT bmax, INT bufferFrameStart, INT numberTimeSlots, + INT fmax) { + INT j, rest, segm, S, s = 0, bord; + + /* + input state: + v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3)] + v_freq = [...,(1 ),(Fa),Fd1,(Fd2),1 ] + */ + + rest = bufferFrameStart + 2 * numberTimeSlots - bmax; + *d = rest; + + if (*d > 0) { + *parts = 1; /* start with one envelope */ + + /* calc # of additional envelopes and corresponding lengths */ + + while (*d > dmax) { + *parts = *parts + 1; + + segm = rest / (*parts); + S = (segm - 2) >> 1; + s = fixMin(fmax, 2 * S + 2); + *d = rest - (*parts - 1) * s; + } + + /* add borders after mandatory borders */ + + bord = bmax; + for (j = 0; j <= *parts - 2; j++) { + bord += s; + + /* v_bord = [...,(Bf),(Ba),Bd1, Bd2 ,(Bd3),(Bf)] */ + FDKsbrEnc_AddRight(v_bord, length_v_bord, bord); + + /* v_freq = [...,(1 ),(Fa),Fd1,(Fd2), 1 , 1! ,1] */ + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + } + } else { + *parts = 1; + + /* remove last element from v_bord and v_freq */ + + *length_v_bord = *length_v_bord - 1; + *length_v_freq = *length_v_freq - 1; + } +} + +/******************************************************************************* + Functionname: fillFrameInter + ******************************************************************************* + + Description: + + Arguments: nL - + v_tuningSegm - + v_bord - + length_v_bord - + bmin - + v_freq - + length_v_freq - + v_bordFollow - + length_v_bordFollow - + v_freqFollow - + length_v_freqFollow - + i_fillFollow - + dmin - + dmax - + + Return: none + +*******************************************************************************/ +static void fillFrameInter(INT *nL, const int *v_tuningSegm, INT *v_bord, + INT *length_v_bord, INT bmin, INT *v_freq, + INT *length_v_freq, INT *v_bordFollow, + INT *length_v_bordFollow, INT *v_freqFollow, + INT *length_v_freqFollow, INT i_fillFollow, INT dmin, + INT dmax, INT numberTimeSlots) { + INT middle, b_new, numBordFollow, bordMaxFollow, i; + + if (numberTimeSlots != NUMBER_TIME_SLOTS_1152) { + /* % remove fill borders: */ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /* remove even more borders if needed */ + middle = bmin - bordMaxFollow; + while (middle < 0) { + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + *nL = numBordFollow - 1; + + b_new = *length_v_bord; + + if (middle <= dmax) { + if (middle >= dmin) { /* concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + + else { + if (v_tuningSegm[0] != 0) { /* remove one new border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } else { + if (*length_v_bordFollow > + 1) { /* remove one old border and concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } else { /* remove new "transient" border and concatenate */ + + for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } + } + } else { /* middle > dmax */ + + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + + } else { /* numberTimeSlots==NUMBER_TIME_SLOTS_1152 */ + + INT l, m; + + /*------------------------------------------------------------------------ + remove fill borders + ------------------------------------------------------------------------*/ + if (i_fillFollow >= 1) { + *length_v_bordFollow = i_fillFollow; + *length_v_freqFollow = i_fillFollow; + } + + numBordFollow = *length_v_bordFollow; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + + /*------------------------------------------------------------------------ + remove more borders if necessary to eliminate overlap + ------------------------------------------------------------------------*/ + + /* check for overlap */ + middle = bmin - bordMaxFollow; + + /* intervals: + i) middle < 0 : overlap, must remove borders + ii) 0 <= middle < dmin : no overlap but too tight, must remove + borders iii) dmin <= middle <= dmax : ok, just concatenate iv) dmax + <= middle : too wide, must add borders + */ + + /* first remove old non-fill-borders... */ + while (middle < 0) { + /* ...but don't remove all of them */ + if (numBordFollow == 1) break; + + numBordFollow--; + bordMaxFollow = v_bordFollow[numBordFollow - 1]; + middle = bmin - bordMaxFollow; + } + + /* if this isn't enough, remove new non-fill borders */ + if (middle < 0) { + for (l = 0, m = 0; l < *length_v_bord; l++) { + if (v_bord[l] > bordMaxFollow) { + v_bord[m] = v_bord[l]; + v_freq[m] = v_freq[l]; + m++; + } + } + + *length_v_bord = l; + *length_v_freq = l; + + bmin = v_bord[0]; + } + + /*------------------------------------------------------------------------ + update modified follow-up data + ------------------------------------------------------------------------*/ + + *length_v_bordFollow = numBordFollow; + *length_v_freqFollow = numBordFollow; + + /* left relative borders correspond to follow-up */ + *nL = numBordFollow - 1; + + /*------------------------------------------------------------------------ + take care of intervals ii through iv + ------------------------------------------------------------------------*/ + + /* now middle should be >= 0 */ + middle = bmin - bordMaxFollow; + + if (middle <= dmin) /* (ii) */ + { + b_new = *length_v_bord; + + if (v_tuningSegm[0] != 0) { + /* remove new "luxury" border and concatenate */ + *length_v_bord = b_new - 1; + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + + *length_v_freq = b_new - 1; + FDKsbrEnc_AddVecLeft(v_freq + 1, length_v_freq, v_freqFollow, + *length_v_freqFollow); + + } else if (*length_v_bordFollow > 1) { + /* remove old border and concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow - 1); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_bordFollow - 1); + + *nL = *nL - 1; + } else { + /* remove new border and concatenate */ + for (i = 0; i < *length_v_bord - 1; i++) v_bord[i] = v_bord[i + 1]; + + for (i = 0; i < *length_v_freq - 1; i++) v_freq[i] = v_freq[i + 1]; + + *length_v_bord = b_new - 1; + *length_v_freq = b_new - 1; + + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } else if ((middle >= dmin) && (middle <= dmax)) /* (iii) */ + { + /* concatenate */ + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + + } else /* (iv) */ + { + fillFramePre(dmax, v_bord, length_v_bord, v_freq, length_v_freq, bmin, + middle); + FDKsbrEnc_AddVecLeft(v_bord, length_v_bord, v_bordFollow, + *length_v_bordFollow); + FDKsbrEnc_AddVecLeft(v_freq, length_v_freq, v_freqFollow, + *length_v_freqFollow); + } + } +} + +/******************************************************************************* + Functionname: calcFrameClass + ******************************************************************************* + + Description: + + Arguments: INT* frameClass, INT* frameClassOld, INT tranFlag, INT* spreadFlag) + + Return: none + +*******************************************************************************/ +static void calcFrameClass(FRAME_CLASS *frameClass, FRAME_CLASS *frameClassOld, + INT tranFlag, INT *spreadFlag) { + switch (*frameClassOld) { + case FIXFIXonly: + case FIXFIX: + if (tranFlag) + *frameClass = FIXVAR; + else + *frameClass = FIXFIX; + break; + case FIXVAR: + if (tranFlag) { + *frameClass = VARVAR; + *spreadFlag = 0; + } else { + if (*spreadFlag) + *frameClass = VARVAR; + else + *frameClass = VARFIX; + } + break; + case VARFIX: + if (tranFlag) + *frameClass = FIXVAR; + else + *frameClass = FIXFIX; + break; + case VARVAR: + if (tranFlag) { + *frameClass = VARVAR; + *spreadFlag = 0; + } else { + if (*spreadFlag) + *frameClass = VARVAR; + else + *frameClass = VARFIX; + } + break; + }; + + *frameClassOld = *frameClass; +} + +/******************************************************************************* + Functionname: specialCase + ******************************************************************************* + + Description: + + Arguments: spreadFlag + allowSpread + v_bord + length_v_bord + v_freq + length_v_freq + parts + d + + Return: none + +*******************************************************************************/ +static void specialCase(INT *spreadFlag, INT allowSpread, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT *length_v_freq, + INT *parts, INT d) { + INT L; + + L = *length_v_bord; + + if (allowSpread) { /* add one "step 8" */ + *spreadFlag = 1; + FDKsbrEnc_AddRight(v_bord, length_v_bord, v_bord[L - 1] + 8); + FDKsbrEnc_AddRight(v_freq, length_v_freq, 1); + (*parts)++; + } else { + if (d == 1) { /* stretch one slot */ + *length_v_bord = L - 1; + *length_v_freq = L - 1; + } else { + if ((v_bord[L - 1] - v_bord[L - 2]) > 2) { /* compress one quant step */ + v_bord[L - 1] = v_bord[L - 1] - 2; + v_freq[*length_v_freq - 1] = 0; /* use low res for short segment */ + } + } + } +} + +/******************************************************************************* + Functionname: calcCmonBorder + ******************************************************************************* + + Description: + + Arguments: i_cmon + i_tran + v_bord + length_v_bord + tran + + Return: none + +*******************************************************************************/ +static void calcCmonBorder(INT *i_cmon, INT *i_tran, INT *v_bord, + INT *length_v_bord, INT tran, INT bufferFrameStart, + INT numberTimeSlots) { /* FH 00-06-26 */ + INT i; + + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= bufferFrameStart + numberTimeSlots) { /* FH 00-06-26 */ + *i_cmon = i; + break; + } + + /* keep track of transient: */ + for (i = 0; i < *length_v_bord; i++) + if (v_bord[i] >= tran) { + *i_tran = i; + break; + } else + *i_tran = EMPTY; +} + +/******************************************************************************* + Functionname: keepForFollowUp + ******************************************************************************* + + Description: + + Arguments: v_bordFollow + length_v_bordFollow + v_freqFollow + length_v_freqFollow + i_tranFollow + i_fillFollow + v_bord + length_v_bord + v_freq + i_cmon + i_tran + parts) + + Return: none + +*******************************************************************************/ +static void keepForFollowUp(INT *v_bordFollow, INT *length_v_bordFollow, + INT *v_freqFollow, INT *length_v_freqFollow, + INT *i_tranFollow, INT *i_fillFollow, INT *v_bord, + INT *length_v_bord, INT *v_freq, INT i_cmon, + INT i_tran, INT parts, + INT numberTimeSlots) { /* FH 00-06-26 */ + INT L, i, j; + + L = *length_v_bord; + + (*length_v_bordFollow) = 0; + (*length_v_freqFollow) = 0; + + for (j = 0, i = i_cmon; i < L; i++, j++) { + v_bordFollow[j] = v_bord[i] - numberTimeSlots; /* FH 00-06-26 */ + v_freqFollow[j] = v_freq[i]; + (*length_v_bordFollow)++; + (*length_v_freqFollow)++; + } + if (i_tran != EMPTY) + *i_tranFollow = i_tran - i_cmon; + else + *i_tranFollow = EMPTY; + *i_fillFollow = L - (parts - 1) - i_cmon; +} + +/******************************************************************************* + Functionname: calcCtrlSignal + ******************************************************************************* + + Description: + + Arguments: hSbrGrid + frameClass + v_bord + length_v_bord + v_freq + length_v_freq + i_cmon + i_tran + spreadFlag + nL + + Return: none + +*******************************************************************************/ +static void calcCtrlSignal(HANDLE_SBR_GRID hSbrGrid, FRAME_CLASS frameClass, + INT *v_bord, INT length_v_bord, INT *v_freq, + INT length_v_freq, INT i_cmon, INT i_tran, + INT spreadFlag, INT nL) { + INT i, r, a, n, p, b, aL, aR, ntot, nmax, nR; + + INT *v_f = hSbrGrid->v_f; + INT *v_fLR = hSbrGrid->v_fLR; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_rL = hSbrGrid->bs_rel_bord_0; + INT *v_rR = hSbrGrid->bs_rel_bord_1; + + INT length_v_r = 0; + INT length_v_rR = 0; + INT length_v_rL = 0; + + switch (frameClass) { + case FIXVAR: + /* absolute border: */ + + a = v_bord[i_cmon]; + + /* relative borders: */ + length_v_r = 0; + i = i_cmon; + + while (i >= 1) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_r, &length_v_r, r); + i--; + } + + /* number of relative borders: */ + n = length_v_r; + + /* freq res: */ + for (i = 0; i < i_cmon; i++) v_f[i] = v_freq[i_cmon - 1 - i]; + v_f[i_cmon] = 1; + + /* pointer: */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0); + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARFIX: + /* absolute border: */ + a = v_bord[0]; + + /* relative borders: */ + length_v_r = 0; + + for (i = 1; i < length_v_bord; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_r, &length_v_r, r); + } + + /* number of relative borders: */ + n = length_v_r; + + /* freq res: */ + FDKmemcpy(v_f, v_freq, length_v_freq * sizeof(INT)); + + /* pointer: */ + p = (i_tran >= 0 && i_tran != EMPTY) ? (i_tran + 1) : (0); + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord = a; + hSbrGrid->n = n; + hSbrGrid->p = p; + + break; + case VARVAR: + if (spreadFlag) { + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + /* number of relative borders: */ + ntot = b - 2; + + nmax = 2; /* n: {0,1,2} */ + if (ntot > nmax) { + nL = nmax; + nR = ntot - nmax; + } else { + nL = ntot; + nR = 0; + } + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_tran > 0 && i_tran != EMPTY) ? (b - i_tran) : (0); + + /* freq res: */ + + for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i]; + } else { + length_v_bord = i_cmon + 1; + + /* absolute borders: */ + b = length_v_bord; + + aL = v_bord[0]; + aR = v_bord[b - 1]; + + /* number of relative borders: */ + ntot = b - 2; + nR = ntot - nL; + + /* relative borders: */ + length_v_rL = 0; + for (i = 1; i <= nL; i++) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rL, &length_v_rL, r); + } + + length_v_rR = 0; + i = b - 1; + while (i >= b - nR) { + r = v_bord[i] - v_bord[i - 1]; + FDKsbrEnc_AddRight(v_rR, &length_v_rR, r); + i--; + } + + /* pointer (only one due to constraint in frame info): */ + p = (i_cmon >= i_tran && i_tran != EMPTY) ? (i_cmon - i_tran + 1) : (0); + + /* freq res: */ + for (i = 0; i < b - 1; i++) v_fLR[i] = v_freq[i]; + } + + hSbrGrid->frameClass = frameClass; + hSbrGrid->bs_abs_bord_0 = aL; + hSbrGrid->bs_abs_bord_1 = aR; + hSbrGrid->bs_num_rel_0 = nL; + hSbrGrid->bs_num_rel_1 = nR; + hSbrGrid->p = p; + + break; + + default: + /* do nothing */ + break; + } +} + +/******************************************************************************* + Functionname: createDefFrameInfo + ******************************************************************************* + + Description: Copies the default (static) frameInfo structs to the frameInfo + passed by reference; only used for FIXFIX frames + + Arguments: hFrameInfo - HANLDE_SBR_FRAME_INFO + nEnv - INT + nTimeSlots - INT + + Return: none; hSbrFrameInfo contains a copy of the default frameInfo + + Written: Andreas Schneider + Revised: +*******************************************************************************/ +static void createDefFrameInfo(HANDLE_SBR_FRAME_INFO hSbrFrameInfo, INT nEnv, + INT nTimeSlots) { + switch (nEnv) { + case 1: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo1_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 2: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo2_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + case 4: + switch (nTimeSlots) { + case NUMBER_TIME_SLOTS_1920: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_1920, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2048: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_2048, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_1152: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_1152, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_2304: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_2304, sizeof(SBR_FRAME_INFO)); + break; + case NUMBER_TIME_SLOTS_512LD: + FDKmemcpy(hSbrFrameInfo, &frameInfo4_512LD, sizeof(SBR_FRAME_INFO)); + break; + default: + FDK_ASSERT(0); + } + break; + default: + FDK_ASSERT(0); + } +} + +/******************************************************************************* + Functionname: ctrlSignal2FrameInfo + ******************************************************************************* + + Description: Convert "clear-text" sbr_grid() to "frame info" used by the + envelope and noise floor estimators. + This is basically (except for "low level" calculations) the + bitstream decoder defined in the MPEG-4 standard, sub clause + 4.6.18.3.3, Time / Frequency Grid. See inline comments for + explanation of the shorten and noise border algorithms. + + Arguments: hSbrGrid - source + hSbrFrameInfo - destination + freq_res_fixfix - frequency resolution for FIXFIX frames + + Return: void; hSbrFrameInfo contains the updated FRAME_INFO struct + +*******************************************************************************/ +static void ctrlSignal2FrameInfo( + HANDLE_SBR_GRID hSbrGrid, /* input : the grid handle */ + HANDLE_SBR_FRAME_INFO hSbrFrameInfo, /* output: the frame info handle */ + FREQ_RES + *freq_res_fixfix /* in/out: frequency resolution for FIXFIX frames */ +) { + INT frameSplit = 0; + INT nEnv = 0, border = 0, i, k, p /*?*/; + INT *v_r = hSbrGrid->bs_rel_bord; + INT *v_f = hSbrGrid->v_f; + + FRAME_CLASS frameClass = hSbrGrid->frameClass; + INT bufferFrameStart = hSbrGrid->bufferFrameStart; + INT numberTimeSlots = hSbrGrid->numberTimeSlots; + + switch (frameClass) { + case FIXFIX: + createDefFrameInfo(hSbrFrameInfo, hSbrGrid->bs_num_env, numberTimeSlots); + + frameSplit = (hSbrFrameInfo->nEnvelopes > 1); + for (i = 0; i < hSbrFrameInfo->nEnvelopes; i++) { + hSbrGrid->v_f[i] = hSbrFrameInfo->freqRes[i] = + freq_res_fixfix[frameSplit]; + } + break; + + case FIXVAR: + case VARFIX: + nEnv = hSbrGrid->n + 1; /* read n [SBR_NUM_BITS bits] */ /*? snd*/ + FDK_ASSERT(nEnv <= MAX_ENVELOPES_FIXVAR_VARFIX); + + hSbrFrameInfo->nEnvelopes = nEnv; + + border = hSbrGrid->bs_abs_bord; /* read the absolute border */ + + if (nEnv == 1) + hSbrFrameInfo->nNoiseEnvelopes = 1; + else + hSbrFrameInfo->nNoiseEnvelopes = 2; + + break; + + default: + /* do nothing */ + break; + } + + switch (frameClass) { + case FIXVAR: + hSbrFrameInfo->borders[0] = + bufferFrameStart; /* start-position of 1st envelope */ + + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < nEnv - 1; k++, i--) { + border -= v_r[k]; + hSbrFrameInfo->borders[i] = border; + } + + /* make either envelope nr. nEnv + 1 - p short; or don't shorten if p == 0 + */ + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0, i = nEnv - 1; k < nEnv; k++, i--) { + hSbrFrameInfo->freqRes[i] = (FREQ_RES)v_f[k]; + } + + /* if either there is no short envelope or the last envelope is short... + */ + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + + break; + + case VARFIX: + /* in this case 'border' indicates the start of the 1st envelope */ + hSbrFrameInfo->borders[0] = border; + + for (k = 0; k < nEnv - 1; k++) { + border += v_r[k]; + hSbrFrameInfo->borders[k + 1] = border; + } + + hSbrFrameInfo->borders[nEnv] = bufferFrameStart + numberTimeSlots; + + p = hSbrGrid->p; + if (p == 0 || p == 1) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = p - 1; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)v_f[k]; + } + + switch (p) { + case 0: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[1]; + break; + case 1: + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + break; + default: + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + break; + } + break; + + case VARVAR: + nEnv = hSbrGrid->bs_num_rel_0 + hSbrGrid->bs_num_rel_1 + 1; + FDK_ASSERT(nEnv <= MAX_ENVELOPES_VARVAR); /* just to be sure */ + hSbrFrameInfo->nEnvelopes = nEnv; + + hSbrFrameInfo->borders[0] = border = hSbrGrid->bs_abs_bord_0; + + for (k = 0, i = 1; k < hSbrGrid->bs_num_rel_0; k++, i++) { + border += hSbrGrid->bs_rel_bord_0[k]; + hSbrFrameInfo->borders[i] = border; + } + + border = hSbrGrid->bs_abs_bord_1; + hSbrFrameInfo->borders[nEnv] = border; + + for (k = 0, i = nEnv - 1; k < hSbrGrid->bs_num_rel_1; k++, i--) { + border -= hSbrGrid->bs_rel_bord_1[k]; + hSbrFrameInfo->borders[i] = border; + } + + p = hSbrGrid->p; + if (p == 0) { + hSbrFrameInfo->shortEnv = 0; + } else { + hSbrFrameInfo->shortEnv = nEnv + 1 - p; + } + + for (k = 0; k < nEnv; k++) { + hSbrFrameInfo->freqRes[k] = (FREQ_RES)hSbrGrid->v_fLR[k]; + } + + if (nEnv == 1) { + hSbrFrameInfo->nNoiseEnvelopes = 1; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + hSbrFrameInfo->bordersNoise[1] = hSbrGrid->bs_abs_bord_1; + } else { + hSbrFrameInfo->nNoiseEnvelopes = 2; + hSbrFrameInfo->bordersNoise[0] = hSbrGrid->bs_abs_bord_0; + + if (p == 0 || p == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv - 1]; + } else { + hSbrFrameInfo->bordersNoise[1] = + hSbrFrameInfo->borders[hSbrFrameInfo->shortEnv]; + } + hSbrFrameInfo->bordersNoise[2] = hSbrGrid->bs_abs_bord_1; + } + break; + + default: + /* do nothing */ + break; + } + + if (frameClass == VARFIX || frameClass == FIXVAR) { + hSbrFrameInfo->bordersNoise[0] = hSbrFrameInfo->borders[0]; + if (nEnv == 1) { + hSbrFrameInfo->bordersNoise[1] = hSbrFrameInfo->borders[nEnv]; + } else { + hSbrFrameInfo->bordersNoise[2] = hSbrFrameInfo->borders[nEnv]; + } + } +} diff --git a/fdk-aac/libSBRenc/src/fram_gen.h b/fdk-aac/libSBRenc/src/fram_gen.h new file mode 100644 index 0000000..0c5edc3 --- /dev/null +++ b/fdk-aac/libSBRenc/src/fram_gen.h @@ -0,0 +1,343 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Framing generator prototypes and structs $Revision: 92790 $ +*/ +#ifndef FRAM_GEN_H +#define FRAM_GEN_H + +#include "sbr_def.h" /* for MAX_ENVELOPES and MAX_NOISE_ENVELOPES in struct FRAME_INFO and CODEC_TYPE */ +#include "sbr_encoder.h" /* for FREQ_RES */ + +#define MAX_ENVELOPES_VARVAR \ + MAX_ENVELOPES /*!< worst case number of envelopes in a VARVAR frame */ +#define MAX_ENVELOPES_FIXVAR_VARFIX \ + 4 /*!< worst case number of envelopes in VARFIX and FIXVAR frames */ +#define MAX_NUM_REL \ + 3 /*!< maximum number of relative borders in any VAR frame */ + +/* SBR frame class definitions */ +typedef enum { + FIXFIX = + 0, /*!< bs_frame_class: leading and trailing frame borders are fixed */ + FIXVAR, /*!< bs_frame_class: leading frame border is fixed, trailing frame + border is variable */ + VARFIX, /*!< bs_frame_class: leading frame border is variable, trailing frame + border is fixed */ + VARVAR /*!< bs_frame_class: leading and trailing frame borders are variable */ + , + FIXFIXonly /*!< bs_frame_class: leading border fixed (0), trailing border + fixed (nrTimeSlots) and encased borders are dynamically derived + from the tranPos */ +} FRAME_CLASS; + +/* helper constants */ +#define DC 4711 /*!< helper constant: don't care */ +#define EMPTY (-99) /*!< helper constant: empty */ + +/* system constants: AAC+SBR, DRM Frame-Length */ +#define FRAME_MIDDLE_SLOT_1920 4 +#define NUMBER_TIME_SLOTS_1920 15 + +#define LD_PRETRAN_OFF 3 +#define FRAME_MIDDLE_SLOT_512LD 4 +#define NUMBER_TIME_SLOTS_512LD 8 +#define TRANSIENT_OFFSET_LD 0 + +/* +system constants: AAC+SBR or aacPRO (hybrid format), Standard Frame-Length, +Multi-Rate +--------------------------------------------------------------------------- +Number of slots (numberTimeSlots): 16 (NUMBER_TIME_SLOTS_2048) +Detector-offset (frameMiddleSlot): 4 +Overlap : 3 +Buffer-offset : 8 (BUFFER_FRAME_START_2048 = 0) + + + |<------------tranPos---------->| + |c|d|e|f|0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 9 a b c d e f 0 1 2 3 +................................................................................ + +|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-|-|-|-|-|-|-|-| + +frame-generator:0 16 24 32 +analysis-buffer:8 24 32 40 +*/ +#define FRAME_MIDDLE_SLOT_2048 4 +#define NUMBER_TIME_SLOTS_2048 16 + +/* +system constants: mp3PRO, Multi-Rate & Single-Rate +-------------------------------------------------- +Number of slots (numberTimeSlots): 9 (NUMBER_TIME_SLOTS_1152) +Detector-offset (frameMiddleSlot): 4 (FRAME_MIDDLE_SLOT_1152) +Overlap : 3 +Buffer-offset : 4.5 (BUFFER_FRAME_START_1152 = 0) + + + |<----tranPos---->| + |5|6|7|8|0|1|2|3|4|5|6|7|8| + FixFix | | + FixVar | :<- ->: + VarFix :<- ->: | + VarVar :<- ->: :<- ->: + 0 1 2 3 4 5 6 7 8 0 1 2 3 + ............................................. + + -|-|-|-|-B-|-|-|-|-|-|-|-|-B-|-|-|-|-|-|-|-|-| + +frame-generator: 0 9 13 18 +analysis-buffer: 4.5 13.5 22.5 +*/ +#define FRAME_MIDDLE_SLOT_1152 4 +#define NUMBER_TIME_SLOTS_1152 9 + +/* system constants: Layer2+SBR */ +#define FRAME_MIDDLE_SLOT_2304 8 +#define NUMBER_TIME_SLOTS_2304 18 + +/*! + \struct SBR_GRID + \brief sbr_grid() signals to be converted to bitstream elements + + The variables hold the signals (e.g. lengths and numbers) in "clear text" +*/ + +typedef struct { + /* system constants */ + INT bufferFrameStart; /*!< frame generator vs analysis buffer time alignment + (currently set to 0, offset added elsewhere) */ + INT numberTimeSlots; /*!< number of SBR timeslots per frame */ + + /* will be adjusted for every frame */ + FRAME_CLASS frameClass; /*!< SBR frame class */ + INT bs_num_env; /*!< bs_num_env, number of envelopes for FIXFIX */ + INT bs_abs_bord; /*!< bs_abs_bord, absolute border for VARFIX and FIXVAR */ + INT n; /*!< number of relative borders for VARFIX and FIXVAR */ + INT p; /*!< pointer-to-transient-border */ + INT bs_rel_bord[MAX_NUM_REL]; /*!< bs_rel_bord, relative borders for all VAR + */ + INT v_f[MAX_ENVELOPES_FIXVAR_VARFIX]; /*!< envelope frequency resolutions for + FIXVAR and VARFIX */ + + INT bs_abs_bord_0; /*!< bs_abs_bord_0, leading absolute border for VARVAR */ + INT bs_abs_bord_1; /*!< bs_abs_bord_1, trailing absolute border for VARVAR */ + INT bs_num_rel_0; /*!< bs_num_rel_0, number of relative borders associated + with leading absolute border for VARVAR */ + INT bs_num_rel_1; /*!< bs_num_rel_1, number of relative borders associated + with trailing absolute border for VARVAR */ + INT bs_rel_bord_0[MAX_NUM_REL]; /*!< bs_rel_bord_0, relative borders + associated with leading absolute border + for VARVAR */ + INT bs_rel_bord_1[MAX_NUM_REL]; /*!< bs_rel_bord_1, relative borders + associated with trailing absolute border + for VARVAR */ + INT v_fLR[MAX_ENVELOPES_VARVAR]; /*!< envelope frequency resolutions for + VARVAR */ + +} SBR_GRID; +typedef SBR_GRID *HANDLE_SBR_GRID; + +/*! + \struct SBR_FRAME_INFO + \brief time/frequency grid description for one frame +*/ +typedef struct { + INT nEnvelopes; /*!< number of envelopes */ + INT borders[MAX_ENVELOPES + 1]; /*!< envelope borders in SBR timeslots */ + FREQ_RES freqRes[MAX_ENVELOPES]; /*!< frequency resolution of each envelope */ + INT shortEnv; /*!< number of an envelope to be shortened (starting at 1) or 0 + for no shortened envelope */ + INT nNoiseEnvelopes; /*!< number of noise floors */ + INT bordersNoise[MAX_NOISE_ENVELOPES + + 1]; /*!< noise floor borders in SBR timeslots */ +} SBR_FRAME_INFO; +/* WARNING: When rearranging the elements of this struct keep in mind that the + * static initializations in the corresponding C-file have to be rearranged as + * well! snd 2002/01/23 + */ +typedef SBR_FRAME_INFO *HANDLE_SBR_FRAME_INFO; + +/*! + \struct SBR_ENVELOPE_FRAME + \brief frame generator main struct + + Contains tuning parameters, time/frequency grid description, sbr_grid() + bitstream elements, and generator internal signals +*/ +typedef struct { + /* system constants */ + INT frameMiddleSlot; /*!< transient detector offset in SBR timeslots */ + + /* basic tuning parameters */ + INT staticFraming; /*!< 1: run static framing in time, i.e. exclusive use of + bs_frame_class = FIXFIX */ + INT numEnvStatic; /*!< number of envelopes per frame for static framing */ + FREQ_RES + freq_res_fixfix[2]; /*!< envelope frequency resolution to use for + bs_frame_class = FIXFIX; single env and split */ + UCHAR + fResTransIsLow; /*!< frequency resolution for transient frames - always + low (0) or according to table (1) */ + + /* expert tuning parameters */ + const int *v_tuningSegm; /*!< segment lengths to use around transient */ + const int *v_tuningFreq; /*!< frequency resolutions to use around transient */ + INT dmin; /*!< minimum length of dependent segments */ + INT dmax; /*!< maximum length of dependent segments */ + INT allowSpread; /*!< 1: allow isolated transient to influence grid of 3 + consecutive frames */ + + /* internally used signals */ + FRAME_CLASS frameClassOld; /*!< frame class used for previous frame */ + INT spreadFlag; /*!< 1: use VARVAR instead of VARFIX to follow up old + transient */ + + INT v_bord[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< borders for current frame and + preliminary borders for next + frame (fixed borders excluded) */ + INT length_v_bord; /*!< helper variable: length of v_bord */ + INT v_freq[2 * MAX_ENVELOPES_VARVAR + 1]; /*!< frequency resolutions for + current frame and preliminary + resolutions for next frame */ + INT length_v_freq; /*!< helper variable: length of v_freq */ + + INT v_bordFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary borders for current + frame (calculated during previous + frame) */ + INT length_v_bordFollow; /*!< helper variable: length of v_bordFollow */ + INT i_tranFollow; /*!< points to transient border in v_bordFollow (may be + negative, see keepForFollowUp()) */ + INT i_fillFollow; /*!< points to first fill border in v_bordFollow */ + INT v_freqFollow[MAX_ENVELOPES_VARVAR]; /*!< preliminary frequency resolutions + for current frame (calculated + during previous frame) */ + INT length_v_freqFollow; /*!< helper variable: length of v_freqFollow */ + + /* externally needed signals */ + SBR_GRID + SbrGrid; /*!< sbr_grid() signals to be converted to bitstream elements */ + SBR_FRAME_INFO + SbrFrameInfo; /*!< time/frequency grid description for one frame */ +} SBR_ENVELOPE_FRAME; +typedef SBR_ENVELOPE_FRAME *HANDLE_SBR_ENVELOPE_FRAME; + +void FDKsbrEnc_initFrameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + INT allowSpread, INT numEnvStatic, + INT staticFraming, INT timeSlots, + const FREQ_RES *freq_res_fixfix, + UCHAR fResTransIsLow, INT ldGrid); + +HANDLE_SBR_FRAME_INFO +FDKsbrEnc_frameInfoGenerator(HANDLE_SBR_ENVELOPE_FRAME hSbrEnvFrame, + UCHAR *v_transient_info, const INT rightBorderFIX, + UCHAR *v_transient_info_pre, int ldGrid, + const int *v_tuning); + +#endif diff --git a/fdk-aac/libSBRenc/src/invf_est.cpp b/fdk-aac/libSBRenc/src/invf_est.cpp new file mode 100644 index 0000000..53b47ac --- /dev/null +++ b/fdk-aac/libSBRenc/src/invf_est.cpp @@ -0,0 +1,610 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "invf_est.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define MAX_NUM_REGIONS 10 +#define SCALE_FAC_QUO 512.0f +#define SCALE_FAC_NRG 256.0f + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +static const FIXP_DBL quantStepsSbr[4] = { + 0x00400000, 0x02800000, 0x03800000, + 0x04c00000}; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL quantStepsOrig[4] = { + 0x00000000, 0x00c00000, 0x01c00000, + 0x02800000}; /* table scaled with SCALE_FAC_QUO */ +static const FIXP_DBL nrgBorders[4] = { + 0x0c800000, 0x0f000000, 0x11800000, + 0x14000000}; /* table scaled with SCALE_FAC_NRG */ + +static const DETECTOR_PARAMETERS detectorParamsAAC = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { + /* Region space. */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + { + /* Region space transient. */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, + 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +static const FIXP_DBL hysteresis = + 0x00400000; /* Delta value for hysteresis. scaled with SCALE_FAC_QUO */ + +/* + * AAC+SBR PARAMETERS for Speech + *********************************/ +static const DETECTOR_PARAMETERS detectorParamsAACSpeech = { + quantStepsSbr, + quantStepsOrig, + nrgBorders, + 4, /* Number of borders SBR. */ + 4, /* Number of borders orig. */ + 4, /* Number of borders Nrg. */ + { + /* Region space. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + { + /* Region space transient. */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_LOW_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* regionSbr */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF}, /* | */ + {INVF_HIGH_LEVEL, INVF_HIGH_LEVEL, INVF_MID_LEVEL, INVF_OFF, + INVF_OFF} /* | */ + }, /*------------------------ regionOrig ---------------------------------*/ + {-4, -3, -2, -1, + 0} /* Reduction factor of the inverse filtering for low energies.*/ +}; + +/* + * Smoothing filters. + ************************/ +typedef const FIXP_DBL FIR_FILTER[5]; + +static const FIR_FILTER fir_0 = {0x7fffffff, 0x00000000, 0x00000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_1 = {0x2aaaaa80, 0x555554ff, 0x00000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_2 = {0x10000000, 0x30000000, 0x40000000, 0x00000000, + 0x00000000}; +static const FIR_FILTER fir_3 = {0x077f80e8, 0x199999a0, 0x2bb3b240, 0x33333340, + 0x00000000}; +static const FIR_FILTER fir_4 = {0x04130598, 0x0ebdb000, 0x1becfa60, 0x2697a4c0, + 0x2aaaaa80}; + +static const FIR_FILTER *const fir_table[5] = {&fir_0, &fir_1, &fir_2, &fir_3, + &fir_4}; + +/**************************************************************************/ +/*! + \brief Calculates the values used for the detector. + + + \return none + +*/ +/**************************************************************************/ +static void calculateDetectorValues( + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the tonality values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + FIXP_DBL *nrgVector, /*!< Energy vector. */ + DETECTOR_VALUES *detectorValues, /*!< pointer to DETECTOR_VALUES struct. */ + INT startChannel, /*!< Start channel. */ + INT stopChannel, /*!< Stop channel. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT numberOfStrongest /*!< The number of sorted tonal components to be + considered. */ +) { + INT i, temp, j; + + const FIXP_DBL *filter = *fir_table[INVF_SMOOTHING_LENGTH]; + FIXP_DBL origQuotaMeanStrongest, sbrQuotaMeanStrongest; + FIXP_DBL origQuota, sbrQuota; + FIXP_DBL invIndex, invChannel, invTemp; + FIXP_DBL quotaVecOrig[64], quotaVecSbr[64]; + + FDKmemclear(quotaVecOrig, 64 * sizeof(FIXP_DBL)); + FDKmemclear(quotaVecSbr, 64 * sizeof(FIXP_DBL)); + + invIndex = GetInvInt(stopIndex - startIndex); + invChannel = GetInvInt(stopChannel - startChannel); + + /* + Calculate the mean value, over the current time segment, for the original, + the HFR and the difference, over all channels in the current frequency range. + NOTE: the averaging is done on the values quota/(1 - quota + RELAXATION). + */ + + /* The original, the sbr signal and the total energy */ + detectorValues->avgNrg = FL2FXCONST_DBL(0.0f); + for (j = startIndex; j < stopIndex; j++) { + for (i = startChannel; i < stopChannel; i++) { + quotaVecOrig[i] += fMult(quotaMatrixOrig[j][i], invIndex); + + if (indexVector[i] != -1) + quotaVecSbr[i] += fMult(quotaMatrixOrig[j][indexVector[i]], invIndex); + } + detectorValues->avgNrg += fMult(nrgVector[j], invIndex); + } + + /* + Calculate the mean value, over the current frequency range, for the original, + the HFR and the difference. Also calculate the same mean values for the three + vectors, but only includeing the x strongest copmponents. + */ + + origQuota = FL2FXCONST_DBL(0.0f); + sbrQuota = FL2FXCONST_DBL(0.0f); + for (i = startChannel; i < stopChannel; i++) { + origQuota += fMultDiv2(quotaVecOrig[i], invChannel); + sbrQuota += fMultDiv2(quotaVecSbr[i], invChannel); + } + + /* + Calculate the mean value for the x strongest components + */ + FDKsbrEnc_Shellsort_fract(quotaVecOrig + startChannel, + stopChannel - startChannel); + FDKsbrEnc_Shellsort_fract(quotaVecSbr + startChannel, + stopChannel - startChannel); + + origQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); + sbrQuotaMeanStrongest = FL2FXCONST_DBL(0.0f); + + temp = min(stopChannel - startChannel, numberOfStrongest); + invTemp = GetInvInt(temp); + + for (i = 0; i < temp; i++) { + origQuotaMeanStrongest += + fMultDiv2(quotaVecOrig[i + stopChannel - temp], invTemp); + sbrQuotaMeanStrongest += + fMultDiv2(quotaVecSbr[i + stopChannel - temp], invTemp); + } + + /* + The value for the strongest component + */ + detectorValues->origQuotaMax = quotaVecOrig[stopChannel - 1]; + detectorValues->sbrQuotaMax = quotaVecSbr[stopChannel - 1]; + + /* + Buffer values + */ + FDKmemmove(detectorValues->origQuotaMean, detectorValues->origQuotaMean + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMean, detectorValues->sbrQuotaMean + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->origQuotaMeanStrongest, + detectorValues->origQuotaMeanStrongest + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + FDKmemmove(detectorValues->sbrQuotaMeanStrongest, + detectorValues->sbrQuotaMeanStrongest + 1, + INVF_SMOOTHING_LENGTH * sizeof(FIXP_DBL)); + + detectorValues->origQuotaMean[INVF_SMOOTHING_LENGTH] = origQuota << 1; + detectorValues->sbrQuotaMean[INVF_SMOOTHING_LENGTH] = sbrQuota << 1; + detectorValues->origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = + origQuotaMeanStrongest << 1; + detectorValues->sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH] = + sbrQuotaMeanStrongest << 1; + + /* + Filter values + */ + detectorValues->origQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanFilt = FL2FXCONST_DBL(0.0f); + detectorValues->origQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + detectorValues->sbrQuotaMeanStrongestFilt = FL2FXCONST_DBL(0.0f); + + for (i = 0; i < INVF_SMOOTHING_LENGTH + 1; i++) { + detectorValues->origQuotaMeanFilt += + fMult(detectorValues->origQuotaMean[i], filter[i]); + detectorValues->sbrQuotaMeanFilt += + fMult(detectorValues->sbrQuotaMean[i], filter[i]); + detectorValues->origQuotaMeanStrongestFilt += + fMult(detectorValues->origQuotaMeanStrongest[i], filter[i]); + detectorValues->sbrQuotaMeanStrongestFilt += + fMult(detectorValues->sbrQuotaMeanStrongest[i], filter[i]); + } +} + +/**************************************************************************/ +/*! + \brief Returns the region in which the input value belongs. + + + + \return region. + +*/ +/**************************************************************************/ +static INT findRegion( + FIXP_DBL currVal, /*!< The current value. */ + const FIXP_DBL *borders, /*!< The border of the regions. */ + const INT numBorders /*!< The number of borders. */ +) { + INT i; + + if (currVal < borders[0]) { + return 0; + } + + for (i = 1; i < numBorders; i++) { + if (currVal >= borders[i - 1] && currVal < borders[i]) { + return i; + } + } + + if (currVal >= borders[numBorders - 1]) { + return numBorders; + } + + return 0; /* We never get here, it's just to avoid compiler warnings.*/ +} + +/**************************************************************************/ +/*! + \brief Makes a clever decision based on the quota vector. + + + \return decision on which invf mode to use + +*/ +/**************************************************************************/ +static INVF_MODE decisionAlgorithm( + const DETECTOR_PARAMETERS + *detectorParams, /*!< Struct with the detector parameters. */ + DETECTOR_VALUES *detectorValues, /*!< Struct with the detector values. */ + INT transientFlag, /*!< Flag indicating if there is a transient present.*/ + INT *prevRegionSbr, /*!< The previous region in which the Sbr value was. */ + INT *prevRegionOrig /*!< The previous region in which the Orig value was. */ +) { + INT invFiltLevel, regionSbr, regionOrig, regionNrg; + + /* + Current thresholds. + */ + const INT numRegionsSbr = detectorParams->numRegionsSbr; + const INT numRegionsOrig = detectorParams->numRegionsOrig; + const INT numRegionsNrg = detectorParams->numRegionsNrg; + + FIXP_DBL quantStepsSbrTmp[MAX_NUM_REGIONS]; + FIXP_DBL quantStepsOrigTmp[MAX_NUM_REGIONS]; + + /* + Current detector values. + */ + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL nrg; + + /* 0.375 = 3.0 / 8.0; 0.31143075889 = log2(RELAXATION)/64.0; 0.625 = + * log(16)/64.0; 0.6875 = 44/64.0 */ + origQuotaMeanFilt = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(max(detectorValues->origQuotaMeanFilt, + (FIXP_DBL)1)) + + FL2FXCONST_DBL(0.31143075889f)))) + << 0; /* scaled by 1/2^9 */ + sbrQuotaMeanFilt = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(max(detectorValues->sbrQuotaMeanFilt, + (FIXP_DBL)1)) + + FL2FXCONST_DBL(0.31143075889f)))) + << 0; /* scaled by 1/2^9 */ + /* If energy is zero then we will get different results for different word + * lengths. */ + nrg = + (fMultDiv2(FL2FXCONST_DBL(2.f * 0.375f), + (FIXP_DBL)(CalcLdData(detectorValues->avgNrg + (FIXP_DBL)1) + + FL2FXCONST_DBL(0.0625f) + FL2FXCONST_DBL(0.6875f)))) + << 0; /* scaled by 1/2^8; 2^44 -> qmf energy scale */ + + FDKmemcpy(quantStepsSbrTmp, detectorParams->quantStepsSbr, + numRegionsSbr * sizeof(FIXP_DBL)); + FDKmemcpy(quantStepsOrigTmp, detectorParams->quantStepsOrig, + numRegionsOrig * sizeof(FIXP_DBL)); + + if (*prevRegionSbr < numRegionsSbr) + quantStepsSbrTmp[*prevRegionSbr] = + detectorParams->quantStepsSbr[*prevRegionSbr] + hysteresis; + if (*prevRegionSbr > 0) + quantStepsSbrTmp[*prevRegionSbr - 1] = + detectorParams->quantStepsSbr[*prevRegionSbr - 1] - hysteresis; + + if (*prevRegionOrig < numRegionsOrig) + quantStepsOrigTmp[*prevRegionOrig] = + detectorParams->quantStepsOrig[*prevRegionOrig] + hysteresis; + if (*prevRegionOrig > 0) + quantStepsOrigTmp[*prevRegionOrig - 1] = + detectorParams->quantStepsOrig[*prevRegionOrig - 1] - hysteresis; + + regionSbr = findRegion(sbrQuotaMeanFilt, quantStepsSbrTmp, numRegionsSbr); + regionOrig = findRegion(origQuotaMeanFilt, quantStepsOrigTmp, numRegionsOrig); + regionNrg = findRegion(nrg, detectorParams->nrgBorders, numRegionsNrg); + + *prevRegionSbr = regionSbr; + *prevRegionOrig = regionOrig; + + /* Use different settings if a transient is present*/ + invFiltLevel = + (transientFlag == 1) + ? detectorParams->regionSpaceTransient[regionSbr][regionOrig] + : detectorParams->regionSpace[regionSbr][regionOrig]; + + /* Compensate for low energy.*/ + invFiltLevel = + max(invFiltLevel + detectorParams->EnergyCompFactor[regionNrg], 0); + + return (INVF_MODE)(invFiltLevel); +} + +/**************************************************************************/ +/*! + \brief Estiamtion of the inverse filtering level required + in the decoder. + + A second order LPC is calculated for every filterbank channel, using + the covariance method. THe ratio between the energy of the predicted + signal and the energy of the non-predictable signal is calcualted. + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_qmfInverseFilteringDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + FIXP_DBL **quotaMatrix, /*!< The matrix holding the tonality values of the + original. */ + FIXP_DBL *nrgVector, /*!< The energy vector. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT transientFlag, /*!< Flag indicating if a transient is present or not.*/ + INVF_MODE *infVec /*!< Vector holding the inverse filtering levels. */ +) { + INT band; + + /* + * Do the inverse filtering level estimation. + *****************************************************/ + for (band = 0; band < hInvFilt->noDetectorBands; band++) { + INT startChannel = hInvFilt->freqBandTableInvFilt[band]; + INT stopChannel = hInvFilt->freqBandTableInvFilt[band + 1]; + + calculateDetectorValues(quotaMatrix, indexVector, nrgVector, + &hInvFilt->detectorValues[band], startChannel, + stopChannel, startIndex, stopIndex, + hInvFilt->numberOfStrongest); + + infVec[band] = decisionAlgorithm( + hInvFilt->detectorParams, &hInvFilt->detectorValues[band], + transientFlag, &hInvFilt->prevRegionSbr[band], + &hInvFilt->prevRegionOrig[band]); + } +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the inverse filtering level estimator. + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_initInvFiltDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Pointer to a handle to the SBR_INV_FILT_EST struct. */ + INT *freqBandTableDetector, /*!< Frequency band table for the inverse + filtering. */ + INT numDetectorBands, /*!< Number of inverse filtering bands. */ + UINT + useSpeechConfig /*!< Flag: adapt tuning parameters according to speech*/ +) { + INT i; + + FDKmemclear(hInvFilt, sizeof(SBR_INV_FILT_EST)); + + hInvFilt->detectorParams = + (useSpeechConfig) ? &detectorParamsAACSpeech : &detectorParamsAAC; + + hInvFilt->noDetectorBandsMax = numDetectorBands; + + /* + Memory initialisation + */ + for (i = 0; i < hInvFilt->noDetectorBandsMax; i++) { + FDKmemclear(&hInvFilt->detectorValues[i], sizeof(DETECTOR_VALUES)); + hInvFilt->prevInvfMode[i] = INVF_OFF; + hInvFilt->prevRegionOrig[i] = 0; + hInvFilt->prevRegionSbr[i] = 0; + } + + /* + Reset the inverse fltering detector. + */ + FDKsbrEnc_resetInvFiltDetector(hInvFilt, freqBandTableDetector, + hInvFilt->noDetectorBandsMax); + + return (0); +} + +/**************************************************************************/ +/*! + \brief resets sbr inverse filtering structure. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_resetInvFiltDetector( + HANDLE_SBR_INV_FILT_EST + hInvFilt, /*!< Handle to the SBR_INV_FILT_EST struct. */ + INT *freqBandTableDetector, /*!< Frequency band table for the inverse + filtering. */ + INT numDetectorBands) /*!< Number of inverse filtering bands. */ +{ + hInvFilt->numberOfStrongest = 1; + FDKmemcpy(hInvFilt->freqBandTableInvFilt, freqBandTableDetector, + (numDetectorBands + 1) * sizeof(INT)); + hInvFilt->noDetectorBands = numDetectorBands; + + return (0); +} diff --git a/fdk-aac/libSBRenc/src/invf_est.h b/fdk-aac/libSBRenc/src/invf_est.h new file mode 100644 index 0000000..3ab6726 --- /dev/null +++ b/fdk-aac/libSBRenc/src/invf_est.h @@ -0,0 +1,181 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Inverse Filtering detection prototypes $Revision: 92790 $ +*/ +#ifndef INVF_EST_H +#define INVF_EST_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define INVF_SMOOTHING_LENGTH 2 + +typedef struct { + const FIXP_DBL *quantStepsSbr; + const FIXP_DBL *quantStepsOrig; + const FIXP_DBL *nrgBorders; + INT numRegionsSbr; + INT numRegionsOrig; + INT numRegionsNrg; + INVF_MODE regionSpace[5][5]; + INVF_MODE regionSpaceTransient[5][5]; + INT EnergyCompFactor[5]; + +} DETECTOR_PARAMETERS; + +typedef struct { + FIXP_DBL origQuotaMean[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL sbrQuotaMean[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL origQuotaMeanStrongest[INVF_SMOOTHING_LENGTH + 1]; + FIXP_DBL sbrQuotaMeanStrongest[INVF_SMOOTHING_LENGTH + 1]; + + FIXP_DBL origQuotaMeanFilt; + FIXP_DBL sbrQuotaMeanFilt; + FIXP_DBL origQuotaMeanStrongestFilt; + FIXP_DBL sbrQuotaMeanStrongestFilt; + + FIXP_DBL origQuotaMax; + FIXP_DBL sbrQuotaMax; + + FIXP_DBL avgNrg; +} DETECTOR_VALUES; + +typedef struct { + INT numberOfStrongest; + + INT prevRegionSbr[MAX_NUM_NOISE_VALUES]; + INT prevRegionOrig[MAX_NUM_NOISE_VALUES]; + + INT freqBandTableInvFilt[MAX_NUM_NOISE_VALUES]; + INT noDetectorBands; + INT noDetectorBandsMax; + + const DETECTOR_PARAMETERS *detectorParams; + + INVF_MODE prevInvfMode[MAX_NUM_NOISE_VALUES]; + DETECTOR_VALUES detectorValues[MAX_NUM_NOISE_VALUES]; + + FIXP_DBL nrgAvg; + FIXP_DBL wmQmf[MAX_NUM_NOISE_VALUES]; +} SBR_INV_FILT_EST; + +typedef SBR_INV_FILT_EST *HANDLE_SBR_INV_FILT_EST; + +void FDKsbrEnc_qmfInverseFilteringDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + FIXP_DBL **quotaMatrix, + FIXP_DBL *nrgVector, + SCHAR *indexVector, INT startIndex, + INT stopIndex, INT transientFlag, + INVF_MODE *infVec); + +INT FDKsbrEnc_initInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + INT *freqBandTableDetector, + INT numDetectorBands, UINT useSpeechConfig); + +INT FDKsbrEnc_resetInvFiltDetector(HANDLE_SBR_INV_FILT_EST hInvFilt, + INT *freqBandTableDetector, + INT numDetectorBands); + +#endif /* _QMF_INV_FILT_H */ diff --git a/fdk-aac/libSBRenc/src/mh_det.cpp b/fdk-aac/libSBRenc/src/mh_det.cpp new file mode 100644 index 0000000..2f3b386 --- /dev/null +++ b/fdk-aac/libSBRenc/src/mh_det.cpp @@ -0,0 +1,1396 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "mh_det.h" + +#include "sbrenc_ram.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define SFM_SHIFT 2 /* Attention: SFM_SCALE depends on SFM_SHIFT */ +#define SFM_SCALE (MAXVAL_DBL >> SFM_SHIFT) /* 1.0 >> SFM_SHIFT */ + +/*!< Detector Parameters for AAC core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAac = { + 9, /*!< deltaTime */ + { + FL2FXCONST_DBL(20.0f * RELAXATION_FLOAT), /*!< thresHoldDiff */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldDiffGuide */ + FL2FXCONST_DBL(15.0f * RELAXATION_FLOAT), /*!< thresHoldTone */ + FL2FXCONST_DBL((1.0f / 15.0f) * + RELAXATION_FLOAT), /*!< invThresHoldTone */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldToneGuide */ + FL2FXCONST_DBL(0.3f) >> SFM_SHIFT, /*!< sfmThresSbr */ + FL2FXCONST_DBL(0.1f) >> SFM_SHIFT, /*!< sfmThresOrig */ + FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ + FL2FXCONST_DBL(0.5f), /*!< decayGuideDiff */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ + FL2FXCONST_DBL( + -0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< + derivThresAboveLD64 + */ + }, + 50 /*!< maxComp */ +}; + +/*!< Detector Parameters for AAC LD core codec. */ +static const DETECTOR_PARAMETERS_MH paramsAacLd = { + 16, /*!< Delta time. */ + { + FL2FXCONST_DBL(25.0f * RELAXATION_FLOAT), /*!< thresHoldDiff */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< tresHoldDiffGuide */ + FL2FXCONST_DBL(15.0f * RELAXATION_FLOAT), /*!< thresHoldTone */ + FL2FXCONST_DBL((1.0f / 15.0f) * + RELAXATION_FLOAT), /*!< invThresHoldTone */ + FL2FXCONST_DBL(1.26f * RELAXATION_FLOAT), /*!< thresHoldToneGuide */ + FL2FXCONST_DBL(0.3f) >> SFM_SHIFT, /*!< sfmThresSbr */ + FL2FXCONST_DBL(0.1f) >> SFM_SHIFT, /*!< sfmThresOrig */ + FL2FXCONST_DBL(0.3f), /*!< decayGuideOrig */ + FL2FXCONST_DBL(0.2f), /*!< decayGuideDiff */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresMaxLD64 */ + FL2FXCONST_DBL(-0.000112993269), + /* LD64(FL2FXCONST_DBL(0.995f)) */ /*!< derivThresBelowLD64 */ + FL2FXCONST_DBL( + -0.005030126483f) /* LD64(FL2FXCONST_DBL(0.8f)) */ /*!< + derivThresAboveLD64 + */ + }, + 50 /*!< maxComp */ +}; + +/**************************************************************************/ +/*! + \brief Calculates the difference in tonality between original and SBR + for a given time and frequency region. + + The values for pDiffMapped2Scfb are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ +static void diff(FIXP_DBL *RESTRICT pTonalityOrig, FIXP_DBL *pDiffMapped2Scfb, + const UCHAR *RESTRICT pFreqBandTable, INT nScfb, + SCHAR *indexVector) { + UCHAR i, ll, lu, k; + FIXP_DBL maxValOrig, maxValSbr, tmp; + INT scale; + + for (i = 0; i < nScfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + maxValOrig = FL2FXCONST_DBL(0.0f); + maxValSbr = FL2FXCONST_DBL(0.0f); + + for (k = ll; k < lu; k++) { + maxValOrig = fixMax(maxValOrig, pTonalityOrig[k]); + maxValSbr = fixMax(maxValSbr, pTonalityOrig[indexVector[k]]); + } + + if ((maxValSbr >= RELAXATION)) { + tmp = fDivNorm(maxValOrig, maxValSbr, &scale); + pDiffMapped2Scfb[i] = + scaleValue(fMult(tmp, RELAXATION_FRACT), + fixMax(-(DFRACT_BITS - 1), (scale - RELAXATION_SHIFT))); + } else { + pDiffMapped2Scfb[i] = maxValOrig; + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates a flatness measure of the tonality measures. + + Calculation of the power function and using scalefactor for basis: + Using log2: + z = (2^k * x)^y; + z' = CalcLd(z) = y*CalcLd(x) + y*k; + z = CalcInvLd(z'); + + Using ld64: + z = (2^k * x)^y; + z' = CalcLd64(z) = y*CalcLd64(x)/64 + y*k/64; + z = CalcInvLd64(z'); + + The values pSfmOrigVec and pSfmSbrVec are scaled by the factor 1/4.0 + + \return none. + +*/ +/**************************************************************************/ +static void calculateFlatnessMeasure(FIXP_DBL *pQuotaBuffer, SCHAR *indexVector, + FIXP_DBL *pSfmOrigVec, + FIXP_DBL *pSfmSbrVec, + const UCHAR *pFreqBandTable, INT nSfb) { + INT i, j; + FIXP_DBL invBands, tmp1, tmp2; + INT shiftFac0, shiftFacSum0; + INT shiftFac1, shiftFacSum1; + FIXP_DBL accu; + + for (i = 0; i < nSfb; i++) { + INT ll = pFreqBandTable[i]; + INT lu = pFreqBandTable[i + 1]; + pSfmOrigVec[i] = (FIXP_DBL)(MAXVAL_DBL >> 2); + pSfmSbrVec[i] = (FIXP_DBL)(MAXVAL_DBL >> 2); + + if (lu - ll > 1) { + FIXP_DBL amOrig, amTransp, gmOrig, gmTransp, sfmOrig, sfmTransp; + invBands = GetInvInt(lu - ll); + shiftFacSum0 = 0; + shiftFacSum1 = 0; + amOrig = amTransp = FL2FXCONST_DBL(0.0f); + gmOrig = gmTransp = (FIXP_DBL)MAXVAL_DBL; + + for (j = ll; j < lu; j++) { + sfmOrig = pQuotaBuffer[j]; + sfmTransp = pQuotaBuffer[indexVector[j]]; + + amOrig += fMult(sfmOrig, invBands); + amTransp += fMult(sfmTransp, invBands); + + shiftFac0 = CountLeadingBits(sfmOrig); + shiftFac1 = CountLeadingBits(sfmTransp); + + gmOrig = fMult(gmOrig, sfmOrig << shiftFac0); + gmTransp = fMult(gmTransp, sfmTransp << shiftFac1); + + shiftFacSum0 += shiftFac0; + shiftFacSum1 += shiftFac1; + } + + if (gmOrig > FL2FXCONST_DBL(0.0f)) { + tmp1 = CalcLdData(gmOrig); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum0 << (DFRACT_BITS - 1 - 8); + tmp2 = fMultDiv2(invBands, accu) << (2 + 1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmOrig = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } else { + gmOrig = FL2FXCONST_DBL(0.0f); + } + + if (gmTransp > FL2FXCONST_DBL(0.0f)) { + tmp1 = CalcLdData(gmTransp); /* CalcLd64(x)/64 */ + tmp1 = fMult(invBands, tmp1); /* y*CalcLd64(x)/64 */ + + /* y*k/64 */ + accu = (FIXP_DBL)-shiftFacSum1 << (DFRACT_BITS - 1 - 8); + tmp2 = fMultDiv2(invBands, accu) << (2 + 1); + + tmp2 = tmp1 + tmp2; /* y*CalcLd64(x)/64 + y*k/64 */ + gmTransp = CalcInvLdData(tmp2); /* CalcInvLd64(z'); */ + } else { + gmTransp = FL2FXCONST_DBL(0.0f); + } + if (amOrig != FL2FXCONST_DBL(0.0f)) + pSfmOrigVec[i] = + FDKsbrEnc_LSI_divide_scale_fract(gmOrig, amOrig, SFM_SCALE); + + if (amTransp != FL2FXCONST_DBL(0.0f)) + pSfmSbrVec[i] = + FDKsbrEnc_LSI_divide_scale_fract(gmTransp, amTransp, SFM_SCALE); + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates the input to the missing harmonics detection. + + + \return none. + +*/ +/**************************************************************************/ +static void calculateDetectorInput( + FIXP_DBL **RESTRICT pQuotaBuffer, /*!< Pointer to tonality matrix. */ + SCHAR *RESTRICT indexVector, FIXP_DBL **RESTRICT tonalityDiff, + FIXP_DBL **RESTRICT pSfmOrig, FIXP_DBL **RESTRICT pSfmSbr, + const UCHAR *freqBandTable, INT nSfb, INT noEstPerFrame, INT move) { + INT est; + + /* + New estimate. + */ + for (est = 0; est < noEstPerFrame; est++) { + diff(pQuotaBuffer[est + move], tonalityDiff[est + move], freqBandTable, + nSfb, indexVector); + + calculateFlatnessMeasure(pQuotaBuffer[est + move], indexVector, + pSfmOrig[est + move], pSfmSbr[est + move], + freqBandTable, nSfb); + } +} + +/**************************************************************************/ +/*! + \brief Checks that the detection is not due to a LP filter + + This function determines if a newly detected missing harmonics is not + in fact just a low-pass filtere input signal. If so, the detection is + removed. + + \return none. + +*/ +/**************************************************************************/ +static void removeLowPassDetection(UCHAR *RESTRICT pAddHarmSfb, + UCHAR **RESTRICT pDetectionVectors, + INT start, INT stop, INT nSfb, + const UCHAR *RESTRICT pFreqBandTable, + FIXP_DBL *RESTRICT pNrgVector, + THRES_HOLDS mhThresh) + +{ + INT i, est; + INT maxDerivPos = pFreqBandTable[nSfb]; + INT numBands = pFreqBandTable[nSfb]; + FIXP_DBL nrgLow, nrgHigh; + FIXP_DBL nrgLD64, nrgLowLD64, nrgHighLD64, nrgDiffLD64; + FIXP_DBL valLD64, maxValLD64, maxValAboveLD64; + INT bLPsignal = 0; + + maxValLD64 = FL2FXCONST_DBL(-1.0f); + for (i = numBands - 1 - 2; i > pFreqBandTable[0]; i--) { + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if (nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh) { + nrgLowLD64 = CalcLdData(nrgLow >> 1); + nrgDiffLD64 = CalcLdData((nrgLow >> 1) - (nrgHigh >> 1)); + valLD64 = nrgDiffLD64 - nrgLowLD64; + if (valLD64 > maxValLD64) { + maxDerivPos = i; + maxValLD64 = valLD64; + } + if (maxValLD64 > mhThresh.derivThresMaxLD64) { + break; + } + } + } + + /* Find the largest "gradient" above. (should be relatively flat, hence we + expect a low value if the signal is LP.*/ + maxValAboveLD64 = FL2FXCONST_DBL(-1.0f); + for (i = numBands - 1 - 2; i > maxDerivPos + 2; i--) { + nrgLow = pNrgVector[i]; + nrgHigh = pNrgVector[i + 2]; + + if (nrgLow != FL2FXCONST_DBL(0.0f) && nrgLow > nrgHigh) { + nrgLowLD64 = CalcLdData(nrgLow >> 1); + nrgDiffLD64 = CalcLdData((nrgLow >> 1) - (nrgHigh >> 1)); + valLD64 = nrgDiffLD64 - nrgLowLD64; + if (valLD64 > maxValAboveLD64) { + maxValAboveLD64 = valLD64; + } + } else { + if (nrgHigh != FL2FXCONST_DBL(0.0f) && nrgHigh > nrgLow) { + nrgHighLD64 = CalcLdData(nrgHigh >> 1); + nrgDiffLD64 = CalcLdData((nrgHigh >> 1) - (nrgLow >> 1)); + valLD64 = nrgDiffLD64 - nrgHighLD64; + if (valLD64 > maxValAboveLD64) { + maxValAboveLD64 = valLD64; + } + } + } + } + + if (maxValLD64 > mhThresh.derivThresMaxLD64 && + maxValAboveLD64 < mhThresh.derivThresAboveLD64) { + bLPsignal = 1; + + for (i = maxDerivPos - 1; i > maxDerivPos - 5 && i >= 0; i--) { + if (pNrgVector[i] != FL2FXCONST_DBL(0.0f) && + pNrgVector[i] > pNrgVector[maxDerivPos + 2]) { + nrgDiffLD64 = CalcLdData((pNrgVector[i] >> 1) - + (pNrgVector[maxDerivPos + 2] >> 1)); + nrgLD64 = CalcLdData(pNrgVector[i] >> 1); + valLD64 = nrgDiffLD64 - nrgLD64; + if (valLD64 < mhThresh.derivThresBelowLD64) { + bLPsignal = 0; + break; + } + } else { + bLPsignal = 0; + break; + } + } + } + + if (bLPsignal) { + for (i = 0; i < nSfb; i++) { + if (maxDerivPos >= pFreqBandTable[i] && + maxDerivPos < pFreqBandTable[i + 1]) + break; + } + + if (pAddHarmSfb[i]) { + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + pDetectionVectors[est][i] = 0; + } + } + } +} + +/**************************************************************************/ +/*! + \brief Checks if it is allowed to detect a missing tone, that wasn't + detected previously. + + + \return newDetectionAllowed flag. + +*/ +/**************************************************************************/ +static INT isDetectionOfNewToneAllowed( + const SBR_FRAME_INFO *pFrameInfo, INT *pDetectionStartPos, + INT noEstPerFrame, INT prevTransientFrame, INT prevTransientPos, + INT prevTransientFlag, INT transientPosOffset, INT transientFlag, + INT transientPos, INT deltaTime, + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector) { + INT transientFrame, newDetectionAllowed; + + /* Determine if this is a frame where a transient starts... + * If the transient flag was set the previous frame but not the + * transient frame flag, the transient frame flag is set in the current frame. + *****************************************************************************/ + transientFrame = 0; + if (transientFlag) { + if (transientPos + transientPosOffset < + pFrameInfo->borders[pFrameInfo->nEnvelopes]) { + transientFrame = 1; + if (noEstPerFrame > 1) { + if (transientPos + transientPosOffset > + h_sbrMissingHarmonicsDetector->timeSlots >> 1) { + *pDetectionStartPos = noEstPerFrame; + } else { + *pDetectionStartPos = noEstPerFrame >> 1; + } + + } else { + *pDetectionStartPos = noEstPerFrame; + } + } + } else { + if (prevTransientFlag && !prevTransientFrame) { + transientFrame = 1; + *pDetectionStartPos = 0; + } + } + + /* + * Determine if detection of new missing harmonics are allowed. + * If the frame contains a transient it's ok. If the previous + * frame contained a transient it needs to be sufficiently close + * to the start of the current frame. + ****************************************************************/ + newDetectionAllowed = 0; + if (transientFrame) { + newDetectionAllowed = 1; + } else { + if (prevTransientFrame && + fixp_abs(pFrameInfo->borders[0] - + (prevTransientPos + transientPosOffset - + h_sbrMissingHarmonicsDetector->timeSlots)) < deltaTime) { + newDetectionAllowed = 1; + *pDetectionStartPos = 0; + } + } + + h_sbrMissingHarmonicsDetector->previousTransientFlag = transientFlag; + h_sbrMissingHarmonicsDetector->previousTransientFrame = transientFrame; + h_sbrMissingHarmonicsDetector->previousTransientPos = transientPos; + + return (newDetectionAllowed); +} + +/**************************************************************************/ +/*! + \brief Cleans up the detection after a transient. + + + \return none. + +*/ +/**************************************************************************/ +static void transientCleanUp(FIXP_DBL **quotaBuffer, INT nSfb, + UCHAR **detectionVectors, UCHAR *pAddHarmSfb, + UCHAR *pPrevAddHarmSfb, INT **signBuffer, + const UCHAR *pFreqBandTable, INT start, INT stop, + INT newDetectionAllowed, FIXP_DBL *pNrgVector, + THRES_HOLDS mhThresh) { + INT i, j, est; + + for (est = start; est < stop; est++) { + for (i = 0; i < nSfb; i++) { + pAddHarmSfb[i] = pAddHarmSfb[i] || detectionVectors[est][i]; + } + } + + if (newDetectionAllowed == 1) { + /* + * Check for duplication of sines located + * on the border of two scf-bands. + *************************************************/ + for (i = 0; i < nSfb - 1; i++) { + /* detection in adjacent channels.*/ + if (pAddHarmSfb[i] && pAddHarmSfb[i + 1]) { + FIXP_DBL maxVal1, maxVal2; + INT maxPos1, maxPos2, maxPosTime1, maxPosTime2; + + INT li = pFreqBandTable[i]; + INT ui = pFreqBandTable[i + 1]; + + /* Find maximum tonality in the the two scf bands.*/ + maxPosTime1 = start; + maxPos1 = li; + maxVal1 = quotaBuffer[start][li]; + for (est = start; est < stop; est++) { + for (j = li; j < ui; j++) { + if (quotaBuffer[est][j] > maxVal1) { + maxVal1 = quotaBuffer[est][j]; + maxPos1 = j; + maxPosTime1 = est; + } + } + } + + li = pFreqBandTable[i + 1]; + ui = pFreqBandTable[i + 2]; + + /* Find maximum tonality in the the two scf bands.*/ + maxPosTime2 = start; + maxPos2 = li; + maxVal2 = quotaBuffer[start][li]; + for (est = start; est < stop; est++) { + for (j = li; j < ui; j++) { + if (quotaBuffer[est][j] > maxVal2) { + maxVal2 = quotaBuffer[est][j]; + maxPos2 = j; + maxPosTime2 = est; + } + } + } + + /* If the maximum values are in adjacent QMF-channels, we need to remove + the lowest of the two.*/ + if (maxPos2 - maxPos1 < 2) { + if (pPrevAddHarmSfb[i] == 1 && pPrevAddHarmSfb[i + 1] == 0) { + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i + 1] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i + 1] = 0; + } + } else { + if (pPrevAddHarmSfb[i] == 0 && pPrevAddHarmSfb[i + 1] == 1) { + /* Keep the upper, remove the lower.*/ + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i] = 0; + } + } else { + /* If the maximum values are in adjacent QMF-channels, and if the + signs indicate that it is the same sine, we need to remove the + lowest of the two.*/ + if (maxVal1 > maxVal2) { + if (signBuffer[maxPosTime1][maxPos2] < 0 && + signBuffer[maxPosTime1][maxPos1] > 0) { + /* Keep the lower, remove the upper.*/ + pAddHarmSfb[i + 1] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i + 1] = 0; + } + } + } else { + if (signBuffer[maxPosTime2][maxPos2] < 0 && + signBuffer[maxPosTime2][maxPos1] > 0) { + /* Keep the upper, remove the lower.*/ + pAddHarmSfb[i] = 0; + for (est = start; est < stop; est++) { + detectionVectors[est][i] = 0; + } + } + } + } + } + } + } + } + + /* Make sure that the detection is not the cut-off of a low pass filter. */ + removeLowPassDetection(pAddHarmSfb, detectionVectors, start, stop, nSfb, + pFreqBandTable, pNrgVector, mhThresh); + } else { + /* + * If a missing harmonic wasn't missing the previous frame + * the transient-flag needs to be set in order to be allowed to detect it. + *************************************************************************/ + for (i = 0; i < nSfb; i++) { + if (pAddHarmSfb[i] - pPrevAddHarmSfb[i] > 0) pAddHarmSfb[i] = 0; + } + } +} + +/*****************************************************************************/ +/*! + \brief Detection for one tonality estimate. + + This is the actual missing harmonics detection, using information from the + previous detection. + + If a missing harmonic was detected (in a previous frame) due to too high + tonality differences, but there was not enough tonality difference in the + current frame, the detection algorithm still continues to trace the strongest + tone in the scalefactor band (assuming that this is the tone that is going to + be replaced in the decoder). This is done to avoid abrupt endings of sines + fading out (e.g. in the glockenspiel). + + The function also tries to estimate where one sine is going to be replaced + with multiple sines (due to the patching). This is done by comparing the + tonality flatness measure of the original and the SBR signal. + + The function also tries to estimate (for the scalefactor bands only + containing one qmf subband) when a strong tone in the original will be + replaced by a strong tone in the adjacent QMF subband. + + \return none. + +*/ +/**************************************************************************/ +static void detection(FIXP_DBL *quotaBuffer, FIXP_DBL *pDiffVecScfb, INT nSfb, + UCHAR *pHarmVec, const UCHAR *pFreqBandTable, + FIXP_DBL *sfmOrig, FIXP_DBL *sfmSbr, + GUIDE_VECTORS guideVectors, GUIDE_VECTORS newGuideVectors, + THRES_HOLDS mhThresh) { + INT i, j, ll, lu; + FIXP_DBL thresTemp, thresOrig; + + /* + * Do detection on the difference vector, i.e. the difference between + * the original and the transposed. + *********************************************************************/ + for (i = 0; i < nSfb; i++) { + thresTemp = (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) + ? fMax(fMult(mhThresh.decayGuideDiff, + guideVectors.guideVectorDiff[i]), + mhThresh.thresHoldDiffGuide) + : mhThresh.thresHoldDiff; + + thresTemp = fMin(thresTemp, mhThresh.thresHoldDiff); + + if (pDiffVecScfb[i] > thresTemp) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorDiff[i] = pDiffVecScfb[i]; + } else { + /* If the guide wasn't zero, but the current level is to low, + start tracking the decay on the tone in the original rather + than the difference.*/ + if (guideVectors.guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors.guideVectorOrig[i] = mhThresh.thresHoldToneGuide; + } + } + } + + /* + * Trace tones in the original signal that at one point + * have been detected because they will be replaced by + * multiple tones in the sbr signal. + ****************************************************/ + + for (i = 0; i < nSfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + thresOrig = + fixMax(fMult(guideVectors.guideVectorOrig[i], mhThresh.decayGuideOrig), + mhThresh.thresHoldToneGuide); + thresOrig = fixMin(thresOrig, mhThresh.thresHoldTone); + + if (guideVectors.guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)) { + for (j = ll; j < lu; j++) { + if (quotaBuffer[j] > thresOrig) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } + } + + /* + * Check for multiple sines in the transposed signal, + * where there is only one in the original. + ****************************************************/ + thresOrig = mhThresh.thresHoldTone; + + for (i = 0; i < nSfb; i++) { + ll = pFreqBandTable[i]; + lu = pFreqBandTable[i + 1]; + + if (pHarmVec[i] == 0) { + if (lu - ll > 1) { + for (j = ll; j < lu; j++) { + if (quotaBuffer[j] > thresOrig && + (sfmSbr[i] > mhThresh.sfmThresSbr && + sfmOrig[i] < mhThresh.sfmThresOrig)) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[j]; + } + } + } else { + if (i < nSfb - 1) { + ll = pFreqBandTable[i]; + + if (i > 0) { + if (quotaBuffer[ll] > mhThresh.thresHoldTone && + (pDiffVecScfb[i + 1] < mhThresh.invThresHoldTone || + pDiffVecScfb[i - 1] < mhThresh.invThresHoldTone)) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } else { + if (quotaBuffer[ll] > mhThresh.thresHoldTone && + pDiffVecScfb[i + 1] < mhThresh.invThresHoldTone) { + pHarmVec[i] = 1; + newGuideVectors.guideVectorOrig[i] = quotaBuffer[ll]; + } + } + } + } + } + } +} + +/**************************************************************************/ +/*! + \brief Do detection for every tonality estimate, using forward prediction. + + + \return none. + +*/ +/**************************************************************************/ +static void detectionWithPrediction( + FIXP_DBL **quotaBuffer, FIXP_DBL **pDiffVecScfb, INT **signBuffer, INT nSfb, + const UCHAR *pFreqBandTable, FIXP_DBL **sfmOrig, FIXP_DBL **sfmSbr, + UCHAR **detectionVectors, UCHAR *pPrevAddHarmSfb, + GUIDE_VECTORS *guideVectors, INT noEstPerFrame, INT detectionStart, + INT totNoEst, INT newDetectionAllowed, INT *pAddHarmFlag, + UCHAR *pAddHarmSfb, FIXP_DBL *pNrgVector, + const DETECTOR_PARAMETERS_MH *mhParams) { + INT est = 0, i; + INT start; + + FDKmemclear(pAddHarmSfb, nSfb * sizeof(UCHAR)); + + if (newDetectionAllowed) { + /* Since we don't want to use the transient region for detection (since the + tonality values tend to be a bit unreliable for this region) the + guide-values are copied to the current starting point. */ + if (totNoEst > 1) { + start = detectionStart + 1; + + if (start != 0) { + FDKmemcpy(guideVectors[start].guideVectorDiff, + guideVectors[0].guideVectorDiff, nSfb * sizeof(FIXP_DBL)); + FDKmemcpy(guideVectors[start].guideVectorOrig, + guideVectors[0].guideVectorOrig, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[start - 1].guideVectorDetected, + nSfb * sizeof(UCHAR)); + } + } else { + start = 0; + } + } else { + start = 0; + } + + for (est = start; est < totNoEst; est++) { + /* + * Do detection on the current frame using + * guide-info from the previous. + *******************************************/ + if (est > 0) { + FDKmemcpy(guideVectors[est].guideVectorDetected, + detectionVectors[est - 1], nSfb * sizeof(UCHAR)); + } + + FDKmemclear(detectionVectors[est], nSfb * sizeof(UCHAR)); + + if (est < totNoEst - 1) { + FDKmemclear(guideVectors[est + 1].guideVectorDiff, + nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est + 1].guideVectorOrig, + nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est + 1].guideVectorDetected, + nSfb * sizeof(UCHAR)); + + detection(quotaBuffer[est], pDiffVecScfb[est], nSfb, + detectionVectors[est], pFreqBandTable, sfmOrig[est], + sfmSbr[est], guideVectors[est], guideVectors[est + 1], + mhParams->thresHolds); + } else { + FDKmemclear(guideVectors[est].guideVectorDiff, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorOrig, nSfb * sizeof(FIXP_DBL)); + FDKmemclear(guideVectors[est].guideVectorDetected, nSfb * sizeof(UCHAR)); + + detection(quotaBuffer[est], pDiffVecScfb[est], nSfb, + detectionVectors[est], pFreqBandTable, sfmOrig[est], + sfmSbr[est], guideVectors[est], guideVectors[est], + mhParams->thresHolds); + } + } + + /* Clean up the detection.*/ + transientCleanUp(quotaBuffer, nSfb, detectionVectors, pAddHarmSfb, + pPrevAddHarmSfb, signBuffer, pFreqBandTable, start, totNoEst, + newDetectionAllowed, pNrgVector, mhParams->thresHolds); + + /* Set flag... */ + *pAddHarmFlag = 0; + for (i = 0; i < nSfb; i++) { + if (pAddHarmSfb[i]) { + *pAddHarmFlag = 1; + break; + } + } + + FDKmemcpy(pPrevAddHarmSfb, pAddHarmSfb, nSfb * sizeof(UCHAR)); + FDKmemcpy(guideVectors[0].guideVectorDetected, pAddHarmSfb, + nSfb * sizeof(INT)); + + for (i = 0; i < nSfb; i++) { + guideVectors[0].guideVectorDiff[i] = FL2FXCONST_DBL(0.0f); + guideVectors[0].guideVectorOrig[i] = FL2FXCONST_DBL(0.0f); + + if (pAddHarmSfb[i] == 1) { + /* If we had a detection use the guide-value in the next frame from the + last estimate were the detection was done.*/ + for (est = start; est < totNoEst; est++) { + if (guideVectors[est].guideVectorDiff[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors[0].guideVectorDiff[i] = + guideVectors[est].guideVectorDiff[i]; + } + if (guideVectors[est].guideVectorOrig[i] != FL2FXCONST_DBL(0.0f)) { + guideVectors[0].guideVectorOrig[i] = + guideVectors[est].guideVectorOrig[i]; + } + } + } + } +} + +/**************************************************************************/ +/*! + \brief Calculates a compensation vector for the energy data. + + This function calculates a compensation vector for the energy data (i.e. + envelope data) that is calculated elsewhere. This is since, one sine on + the border of two scalefactor bands, will be replace by one sine in the + middle of either scalefactor band. However, since the sine that is replaced + will influence the energy estimate in both scalefactor bands (in the envelops + calculation function) a compensation value is required in order to avoid + noise substitution in the decoder next to the synthetic sine. + + \return none. + +*/ +/**************************************************************************/ +static void calculateCompVector(UCHAR *pAddHarmSfb, FIXP_DBL **pTonalityMatrix, + INT **pSignMatrix, UCHAR *pEnvComp, INT nSfb, + const UCHAR *freqBandTable, INT totNoEst, + INT maxComp, UCHAR *pPrevEnvComp, + INT newDetectionAllowed) { + INT scfBand, est, l, ll, lu, maxPosF, maxPosT; + FIXP_DBL maxVal; + INT compValue; + FIXP_DBL tmp; + + FDKmemclear(pEnvComp, nSfb * sizeof(UCHAR)); + + for (scfBand = 0; scfBand < nSfb; scfBand++) { + if (pAddHarmSfb[scfBand]) { /* A missing sine was detected */ + ll = freqBandTable[scfBand]; + lu = freqBandTable[scfBand + 1]; + + maxPosF = 0; /* First find the maximum*/ + maxPosT = 0; + maxVal = FL2FXCONST_DBL(0.0f); + + for (est = 0; est < totNoEst; est++) { + for (l = ll; l < lu; l++) { + if (pTonalityMatrix[est][l] > maxVal) { + maxVal = pTonalityMatrix[est][l]; + maxPosF = l; + maxPosT = est; + } + } + } + + /* + * If the maximum tonality is at the lower border of the + * scalefactor band, we check the sign of the adjacent channels + * to see if this sine is shared by the lower channel. If so, the + * energy of the single sine will be present in two scalefactor bands + * in the SBR data, which will cause problems in the decoder, when we + * add a sine to just one of the channels. + *********************************************************************/ + if (maxPosF == ll && scfBand) { + if (!pAddHarmSfb[scfBand - 1]) { /* No detection below*/ + if (pSignMatrix[maxPosT][maxPosF - 1] > 0 && + pSignMatrix[maxPosT][maxPosF] < 0) { + /* The comp value is calulated as the tonallity value, i.e we want + to reduce the envelope data for this channel with as much as the + tonality that is spread from the channel above. (ld64(RELAXATION) + = 0.31143075889) */ + tmp = fixp_abs( + (FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF - 1]) + + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1)) + + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + /* limit the comp-value*/ + if (compValue > maxComp) compValue = maxComp; + + pEnvComp[scfBand - 1] = compValue; + } + } + } + + /* + * Same as above, but for the upper end of the scalefactor-band. + ***************************************************************/ + if (maxPosF == lu - 1 && scfBand + 1 < nSfb) { /* Upper border*/ + if (!pAddHarmSfb[scfBand + 1]) { + if (pSignMatrix[maxPosT][maxPosF] > 0 && + pSignMatrix[maxPosT][maxPosF + 1] < 0) { + tmp = fixp_abs( + (FIXP_DBL)CalcLdData(pTonalityMatrix[maxPosT][maxPosF + 1]) + + RELAXATION_LD64); + tmp = (tmp >> (DFRACT_BITS - 1 - LD_DATA_SHIFT - 1)) + + (FIXP_DBL)1; /* shift one bit less for rounding */ + compValue = ((INT)(LONG)tmp) >> 1; + + if (compValue > maxComp) compValue = maxComp; + + pEnvComp[scfBand + 1] = compValue; + } + } + } + } + } + + if (newDetectionAllowed == 0) { + for (scfBand = 0; scfBand < nSfb; scfBand++) { + if (pEnvComp[scfBand] != 0 && pPrevEnvComp[scfBand] == 0) + pEnvComp[scfBand] = 0; + } + } + + /* remember the value for the next frame.*/ + FDKmemcpy(pPrevEnvComp, pEnvComp, nSfb * sizeof(UCHAR)); +} + +/**************************************************************************/ +/*! + \brief Detects where strong tonal components will be missing after + HFR in the decoder. + + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMHDet, FIXP_DBL **pQuotaBuffer, + INT **pSignBuffer, SCHAR *indexVector, const SBR_FRAME_INFO *pFrameInfo, + const UCHAR *pTranInfo, INT *pAddHarmonicsFlag, + UCHAR *pAddHarmonicsScaleFactorBands, const UCHAR *freqBandTable, INT nSfb, + UCHAR *envelopeCompensation, FIXP_DBL *pNrgVector) { + INT transientFlag = pTranInfo[1]; + INT transientPos = pTranInfo[0]; + INT newDetectionAllowed; + INT transientDetStart = 0; + + UCHAR **detectionVectors = h_sbrMHDet->detectionVectors; + INT move = h_sbrMHDet->move; + INT noEstPerFrame = h_sbrMHDet->noEstPerFrame; + INT totNoEst = h_sbrMHDet->totNoEst; + INT prevTransientFlag = h_sbrMHDet->previousTransientFlag; + INT prevTransientFrame = h_sbrMHDet->previousTransientFrame; + INT transientPosOffset = h_sbrMHDet->transientPosOffset; + INT prevTransientPos = h_sbrMHDet->previousTransientPos; + GUIDE_VECTORS *guideVectors = h_sbrMHDet->guideVectors; + INT deltaTime = h_sbrMHDet->mhParams->deltaTime; + INT maxComp = h_sbrMHDet->mhParams->maxComp; + + int est; + + /* + Buffer values. + */ + FDK_ASSERT(move <= (MAX_NO_OF_ESTIMATES >> 1)); + FDK_ASSERT(noEstPerFrame <= (MAX_NO_OF_ESTIMATES >> 1)); + + FIXP_DBL *sfmSbr[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *sfmOrig[MAX_NO_OF_ESTIMATES]; + FIXP_DBL *tonalityDiff[MAX_NO_OF_ESTIMATES]; + + for (est = 0; est < MAX_NO_OF_ESTIMATES / 2; est++) { + sfmSbr[est] = h_sbrMHDet->sfmSbr[est]; + sfmOrig[est] = h_sbrMHDet->sfmOrig[est]; + tonalityDiff[est] = h_sbrMHDet->tonalityDiff[est]; + } + + C_ALLOC_SCRATCH_START(_scratch, FIXP_DBL, + 3 * MAX_NO_OF_ESTIMATES / 2 * MAX_FREQ_COEFFS) + FIXP_DBL *scratch = _scratch; + for (; est < MAX_NO_OF_ESTIMATES; est++) { + sfmSbr[est] = scratch; + scratch += MAX_FREQ_COEFFS; + sfmOrig[est] = scratch; + scratch += MAX_FREQ_COEFFS; + tonalityDiff[est] = scratch; + scratch += MAX_FREQ_COEFFS; + } + + /* Determine if we're allowed to detect "missing harmonics" that wasn't + detected before. In order to be allowed to do new detection, there must be + a transient in the current frame, or a transient in the previous frame + sufficiently close to the current frame. */ + newDetectionAllowed = isDetectionOfNewToneAllowed( + pFrameInfo, &transientDetStart, noEstPerFrame, prevTransientFrame, + prevTransientPos, prevTransientFlag, transientPosOffset, transientFlag, + transientPos, deltaTime, h_sbrMHDet); + + /* Calulate the variables that will be used subsequently for the actual + * detection */ + calculateDetectorInput(pQuotaBuffer, indexVector, tonalityDiff, sfmOrig, + sfmSbr, freqBandTable, nSfb, noEstPerFrame, move); + + /* Do the actual detection using information from previous detections */ + detectionWithPrediction(pQuotaBuffer, tonalityDiff, pSignBuffer, nSfb, + freqBandTable, sfmOrig, sfmSbr, detectionVectors, + h_sbrMHDet->guideScfb, guideVectors, noEstPerFrame, + transientDetStart, totNoEst, newDetectionAllowed, + pAddHarmonicsFlag, pAddHarmonicsScaleFactorBands, + pNrgVector, h_sbrMHDet->mhParams); + + /* Calculate the comp vector, so that the energy can be + compensated for a sine between two QMF-bands. */ + calculateCompVector(pAddHarmonicsScaleFactorBands, pQuotaBuffer, pSignBuffer, + envelopeCompensation, nSfb, freqBandTable, totNoEst, + maxComp, h_sbrMHDet->prevEnvelopeCompensation, + newDetectionAllowed); + + for (est = 0; est < move; est++) { + FDKmemcpy(tonalityDiff[est], tonalityDiff[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemcpy(sfmOrig[est], sfmOrig[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemcpy(sfmSbr[est], sfmSbr[est + noEstPerFrame], + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + } + C_ALLOC_SCRATCH_END(_scratch, FIXP_DBL, + 3 * MAX_NO_OF_ESTIMATES / 2 * MAX_FREQ_COEFFS) +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT chan) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + INT i; + + UCHAR *detectionVectors = GetRam_Sbr_detectionVectors(chan); + UCHAR *guideVectorDetected = GetRam_Sbr_guideVectorDetected(chan); + FIXP_DBL *guideVectorDiff = GetRam_Sbr_guideVectorDiff(chan); + FIXP_DBL *guideVectorOrig = GetRam_Sbr_guideVectorOrig(chan); + + FDKmemclear(hs, sizeof(SBR_MISSING_HARMONICS_DETECTOR)); + + hs->prevEnvelopeCompensation = GetRam_Sbr_prevEnvelopeCompensation(chan); + hs->guideScfb = GetRam_Sbr_guideScfb(chan); + + if ((NULL == detectionVectors) || (NULL == guideVectorDetected) || + (NULL == guideVectorDiff) || (NULL == guideVectorOrig) || + (NULL == hs->prevEnvelopeCompensation) || (NULL == hs->guideScfb)) { + goto bail; + } + + for (i = 0; i < MAX_NO_OF_ESTIMATES; i++) { + hs->guideVectors[i].guideVectorDiff = + guideVectorDiff + (i * MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorOrig = + guideVectorOrig + (i * MAX_FREQ_COEFFS); + hs->detectionVectors[i] = detectionVectors + (i * MAX_FREQ_COEFFS); + hs->guideVectors[i].guideVectorDetected = + guideVectorDetected + (i * MAX_FREQ_COEFFS); + } + + return 0; + +bail: + hs->guideVectors[0].guideVectorDiff = guideVectorDiff; + hs->guideVectors[0].guideVectorOrig = guideVectorOrig; + hs->detectionVectors[0] = detectionVectors; + hs->guideVectors[0].guideVectorDetected = guideVectorDetected; + + FDKsbrEnc_DeleteSbrMissingHarmonicsDetector(hs); + return -1; +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the missing harmonics detector. + + + \return errorCode, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT sampleFreq, + INT frameSize, INT nSfb, INT qmfNoChannels, INT totNoEst, INT move, + INT noEstPerFrame, UINT sbrSyntaxFlags) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + int i; + + FDK_ASSERT(totNoEst <= MAX_NO_OF_ESTIMATES); + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + switch (frameSize) { + case 1024: + case 512: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 16; + break; + case 960: + case 480: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + hs->timeSlots = 15; + break; + default: + return -1; + } + } else { + switch (frameSize) { + case 2048: + case 1024: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + hs->timeSlots = NUMBER_TIME_SLOTS_2048; + break; + case 1920: + case 960: + hs->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + hs->timeSlots = NUMBER_TIME_SLOTS_1920; + break; + default: + return -1; + } + } + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + hs->mhParams = ¶msAacLd; + } else + hs->mhParams = ¶msAac; + + hs->qmfNoChannels = qmfNoChannels; + hs->sampleFreq = sampleFreq; + hs->nSfb = nSfb; + + hs->totNoEst = totNoEst; + hs->move = move; + hs->noEstPerFrame = noEstPerFrame; + + for (i = 0; i < totNoEst; i++) { + FDKmemclear(hs->guideVectors[i].guideVectorDiff, + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideVectors[i].guideVectorOrig, + sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->detectionVectors[i], sizeof(UCHAR) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideVectors[i].guideVectorDetected, + sizeof(UCHAR) * MAX_FREQ_COEFFS); + } + + // for(i=0; itonalityDiff[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->sfmOrig[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + FDKmemclear(hs->sfmSbr[i], sizeof(FIXP_DBL) * MAX_FREQ_COEFFS); + } + + FDKmemclear(hs->prevEnvelopeCompensation, sizeof(UCHAR) * MAX_FREQ_COEFFS); + FDKmemclear(hs->guideScfb, sizeof(UCHAR) * MAX_FREQ_COEFFS); + + hs->previousTransientFlag = 0; + hs->previousTransientFrame = 0; + hs->previousTransientPos = 0; + + return (0); +} + +/**************************************************************************/ +/*! + \brief Deletes an instance of the missing harmonics detector. + + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet) { + if (hSbrMHDet) { + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hs = hSbrMHDet; + + FreeRam_Sbr_detectionVectors(&hs->detectionVectors[0]); + FreeRam_Sbr_guideVectorDetected(&hs->guideVectors[0].guideVectorDetected); + FreeRam_Sbr_guideVectorDiff(&hs->guideVectors[0].guideVectorDiff); + FreeRam_Sbr_guideVectorOrig(&hs->guideVectors[0].guideVectorOrig); + FreeRam_Sbr_prevEnvelopeCompensation(&hs->prevEnvelopeCompensation); + FreeRam_Sbr_guideScfb(&hs->guideScfb); + } +} + +/**************************************************************************/ +/*! + \brief Resets an instance of the missing harmonics detector. + + + \return error code, noError if OK. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb) { + int i; + FIXP_DBL tempGuide[MAX_FREQ_COEFFS]; + UCHAR tempGuideInt[MAX_FREQ_COEFFS]; + INT nSfbPrev; + + nSfbPrev = hSbrMissingHarmonicsDetector->nSfb; + hSbrMissingHarmonicsDetector->nSfb = nSfb; + + FDKmemcpy(tempGuideInt, hSbrMissingHarmonicsDetector->guideScfb, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideScfb[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideScfb[i + (nSfb - nSfbPrev)] = + tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideScfb[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuide, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff, + nSfbPrev * sizeof(FIXP_DBL)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = + FL2FXCONST_DBL(0.0f); + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorDiff[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDiff[i] = + tempGuide[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuide, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig, + nSfbPrev * sizeof(FIXP_DBL)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = + FL2FXCONST_DBL(0.0f); + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorOrig[i + (nSfb - nSfbPrev)] = tempGuide[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorOrig[i] = + tempGuide[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuideInt, + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0] + .guideVectorDetected[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->guideVectors[0].guideVectorDetected[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + FDKmemcpy(tempGuideInt, + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation, + nSfbPrev * sizeof(UCHAR)); + + if (nSfb > nSfbPrev) { + for (i = 0; i < (nSfb - nSfbPrev); i++) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = 0; + } + + for (i = 0; i < nSfbPrev; i++) { + hSbrMissingHarmonicsDetector + ->prevEnvelopeCompensation[i + (nSfb - nSfbPrev)] = tempGuideInt[i]; + } + } else { + for (i = 0; i < nSfb; i++) { + hSbrMissingHarmonicsDetector->prevEnvelopeCompensation[i] = + tempGuideInt[i + (nSfbPrev - nSfb)]; + } + } + + return 0; +} diff --git a/fdk-aac/libSBRenc/src/mh_det.h b/fdk-aac/libSBRenc/src/mh_det.h new file mode 100644 index 0000000..89d81b5 --- /dev/null +++ b/fdk-aac/libSBRenc/src/mh_det.h @@ -0,0 +1,204 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief missing harmonics detection header file $Revision: 92790 $ +*/ + +#ifndef MH_DET_H +#define MH_DET_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +typedef struct { + FIXP_DBL thresHoldDiff; /*!< threshold for tonality difference */ + FIXP_DBL thresHoldDiffGuide; /*!< threshold for tonality difference for the + guide */ + FIXP_DBL thresHoldTone; /*!< threshold for tonality for a sine */ + FIXP_DBL invThresHoldTone; + FIXP_DBL thresHoldToneGuide; /*!< threshold for tonality for a sine for the + guide */ + FIXP_DBL sfmThresSbr; /*!< tonality flatness measure threshold for the SBR + signal.*/ + FIXP_DBL sfmThresOrig; /*!< tonality flatness measure threshold for the + original signal.*/ + FIXP_DBL decayGuideOrig; /*!< decay value of the tonality value of the guide + for the tone. */ + FIXP_DBL decayGuideDiff; /*!< decay value of the tonality value of the guide + for the tonality difference. */ + FIXP_DBL derivThresMaxLD64; /*!< threshold for detecting LP character in a + signal. */ + FIXP_DBL derivThresBelowLD64; /*!< threshold for detecting LP character in a + signal. */ + FIXP_DBL derivThresAboveLD64; /*!< threshold for detecting LP character in a + signal. */ +} THRES_HOLDS; + +typedef struct { + INT deltaTime; /*!< maximum allowed transient distance (from frame border in + number of qmf subband sample) for a frame to be considered a + transient frame.*/ + THRES_HOLDS thresHolds; /*!< the thresholds used for detection. */ + INT maxComp; /*!< maximum alllowed compensation factor for the envelope data. + */ +} DETECTOR_PARAMETERS_MH; + +typedef struct { + FIXP_DBL *guideVectorDiff; + FIXP_DBL *guideVectorOrig; + UCHAR *guideVectorDetected; +} GUIDE_VECTORS; + +typedef struct { + INT qmfNoChannels; + INT nSfb; + INT sampleFreq; + INT previousTransientFlag; + INT previousTransientFrame; + INT previousTransientPos; + + INT noVecPerFrame; + INT transientPosOffset; + + INT move; + INT totNoEst; + INT noEstPerFrame; + INT timeSlots; + + UCHAR *guideScfb; + UCHAR *prevEnvelopeCompensation; + UCHAR *detectionVectors[MAX_NO_OF_ESTIMATES]; + FIXP_DBL tonalityDiff[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmOrig[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + FIXP_DBL sfmSbr[MAX_NO_OF_ESTIMATES / 2][MAX_FREQ_COEFFS]; + const DETECTOR_PARAMETERS_MH *mhParams; + GUIDE_VECTORS guideVectors[MAX_NO_OF_ESTIMATES]; +} SBR_MISSING_HARMONICS_DETECTOR; + +typedef SBR_MISSING_HARMONICS_DETECTOR *HANDLE_SBR_MISSING_HARMONICS_DETECTOR; + +void FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + FIXP_DBL **pQuotaBuffer, INT **pSignBuffer, SCHAR *indexVector, + const SBR_FRAME_INFO *pFrameInfo, const UCHAR *pTranInfo, + INT *pAddHarmonicsFlag, UCHAR *pAddHarmonicsScaleFactorBands, + const UCHAR *freqBandTable, INT nSfb, UCHAR *envelopeCompensation, + FIXP_DBL *pNrgVector); + +INT FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMHDet, INT chan); + +INT FDKsbrEnc_InitSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector, + INT sampleFreq, INT frameSize, INT nSfb, INT qmfNoChannels, INT totNoEst, + INT move, INT noEstPerFrame, UINT sbrSyntaxFlags); + +void FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR h_sbrMissingHarmonicsDetector); + +INT FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + HANDLE_SBR_MISSING_HARMONICS_DETECTOR hSbrMissingHarmonicsDetector, + INT nSfb); + +#endif diff --git a/fdk-aac/libSBRenc/src/nf_est.cpp b/fdk-aac/libSBRenc/src/nf_est.cpp new file mode 100644 index 0000000..290ec35 --- /dev/null +++ b/fdk-aac/libSBRenc/src/nf_est.cpp @@ -0,0 +1,612 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "nf_est.h" + +#include "sbr_misc.h" + +#include "genericStds.h" + +/* smoothFilter[4] = {0.05857864376269f, 0.2f, 0.34142135623731f, 0.4f}; */ +static const FIXP_DBL smoothFilter[4] = {0x077f813d, 0x19999995, 0x2bb3b1f5, + 0x33333335}; + +/* static const INT smoothFilterLength = 4; */ + +static const FIXP_DBL QuantOffset = (INT)0xfc000000; /* ld64(0.25) */ + +#ifndef min +#define min(a, b) (a < b ? a : b) +#endif + +#ifndef max +#define max(a, b) (a > b ? a : b) +#endif + +#define NOISE_FLOOR_OFFSET_SCALING (4) + +/**************************************************************************/ +/*! + \brief The function applies smoothing to the noise levels. + + + + \return none + +*/ +/**************************************************************************/ +static void smoothingOfNoiseLevels( + FIXP_DBL *NoiseLevels, /*!< pointer to noise-floor levels.*/ + INT nEnvelopes, /*!< Number of noise floor envelopes.*/ + INT noNoiseBands, /*!< Number of noise bands for every noise floor envelope. + */ + FIXP_DBL prevNoiseLevels[NF_SMOOTHING_LENGTH] + [MAX_NUM_NOISE_VALUES], /*!< Previous noise floor + envelopes. */ + const FIXP_DBL * + pSmoothFilter, /*!< filter used for smoothing the noise floor levels. */ + INT transientFlag) /*!< flag indicating if a transient is present*/ + +{ + INT i, band, env; + FIXP_DBL accu; + + for (env = 0; env < nEnvelopes; env++) { + if (transientFlag) { + for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { + FDKmemcpy(prevNoiseLevels[i], NoiseLevels + env * noNoiseBands, + noNoiseBands * sizeof(FIXP_DBL)); + } + } else { + for (i = 1; i < NF_SMOOTHING_LENGTH; i++) { + FDKmemcpy(prevNoiseLevels[i - 1], prevNoiseLevels[i], + noNoiseBands * sizeof(FIXP_DBL)); + } + FDKmemcpy(prevNoiseLevels[NF_SMOOTHING_LENGTH - 1], + NoiseLevels + env * noNoiseBands, + noNoiseBands * sizeof(FIXP_DBL)); + } + + for (band = 0; band < noNoiseBands; band++) { + accu = FL2FXCONST_DBL(0.0f); + for (i = 0; i < NF_SMOOTHING_LENGTH; i++) { + accu += fMultDiv2(pSmoothFilter[i], prevNoiseLevels[i][band]); + } + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + NoiseLevels[band + env * noNoiseBands] = accu << 1; + } + } +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + + The noiseLevel samples are scaled by the factor 0.25 + + \return none + +*/ +/**************************************************************************/ +static void qmfBasedNoiseFloorDetection( + FIXP_DBL *noiseLevel, /*!< Pointer to vector to + store the noise levels + in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota + values of the original. */ + SCHAR *indexVector, /*!< Index vector to obtain the + patched data. */ + INT startIndex, /*!< Start index. */ + INT stopIndex, /*!< Stop index. */ + INT startChannel, /*!< Start channel of the current + noise floor band.*/ + INT stopChannel, /*!< Stop channel of the current + noise floor band. */ + FIXP_DBL ana_max_level, /*!< Maximum level of the + adaptive noise.*/ + FIXP_DBL noiseFloorOffset, /*!< Noise floor offset. */ + INT missingHarmonicFlag, /*!< Flag indicating if a + strong tonal component + is missing.*/ + FIXP_DBL weightFac, /*!< Weightening factor for the + difference between orig and sbr. + */ + INVF_MODE diffThres, /*!< Threshold value to control the + inverse filtering decision.*/ + INVF_MODE inverseFilteringLevel) /*!< Inverse filtering + level of the current + band.*/ +{ + INT scale, l, k; + FIXP_DBL meanOrig = FL2FXCONST_DBL(0.0f), meanSbr = FL2FXCONST_DBL(0.0f), + diff; + FIXP_DBL invIndex = GetInvInt(stopIndex - startIndex); + FIXP_DBL invChannel = GetInvInt(stopChannel - startChannel); + FIXP_DBL accu; + + /* + Calculate the mean value, over the current time segment, for the original, the + HFR and the difference, over all channels in the current frequency range. + */ + + if (missingHarmonicFlag == 1) { + for (l = startChannel; l < stopChannel; l++) { + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig = fixMax(meanOrig, (accu << 1)); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr = fixMax(meanSbr, (accu << 1)); + } + } else { + for (l = startChannel; l < stopChannel; l++) { + /* tonalityOrig */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][l], invIndex); + } + meanOrig += fMult((accu << 1), invChannel); + + /* tonalitySbr */ + accu = FL2FXCONST_DBL(0.0f); + for (k = startIndex; k < stopIndex; k++) { + accu += fMultDiv2(quotaMatrixOrig[k][indexVector[l]], invIndex); + } + meanSbr += fMult((accu << 1), invChannel); + } + } + + /* Small fix to avoid noise during silent passages.*/ + if (meanOrig <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT) && + meanSbr <= FL2FXCONST_DBL(0.000976562f * RELAXATION_FLOAT)) { + meanOrig = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); + meanSbr = FL2FXCONST_DBL(101.5936673f * RELAXATION_FLOAT); + } + + meanOrig = fixMax(meanOrig, RELAXATION); + meanSbr = fixMax(meanSbr, RELAXATION); + + if (missingHarmonicFlag == 1 || inverseFilteringLevel == INVF_MID_LEVEL || + inverseFilteringLevel == INVF_LOW_LEVEL || + inverseFilteringLevel == INVF_OFF || inverseFilteringLevel <= diffThres) { + diff = RELAXATION; + } else { + accu = fDivNorm(meanSbr, meanOrig, &scale); + + diff = fixMax(RELAXATION, fMult(RELAXATION_FRACT, fMult(weightFac, accu)) >> + (RELAXATION_SHIFT - scale)); + } + + /* + * noise Level is now a positive value, i.e. + * the more harmonic the signal is the higher noise level, + * this makes no sense so we change the sign. + *********************************************************/ + accu = fDivNorm(diff, meanOrig, &scale); + scale -= 2; + + if ((scale > 0) && (accu > ((FIXP_DBL)MAXVAL_DBL) >> scale)) { + *noiseLevel = (FIXP_DBL)MAXVAL_DBL; + } else { + *noiseLevel = scaleValue(accu, scale); + } + + /* + * Add a noise floor offset to compensate for bias in the detector + *****************************************************************/ + if (!missingHarmonicFlag) { + *noiseLevel = fixMin(fMult(*noiseLevel, noiseFloorOffset), + (FIXP_DBL)MAXVAL_DBL >> NOISE_FLOOR_OFFSET_SCALING) + << NOISE_FLOOR_OFFSET_SCALING; + } + + /* + * check to see that we don't exceed the maximum allowed level + **************************************************************/ + *noiseLevel = + fixMin(*noiseLevel, + ana_max_level); /* ana_max_level is scaled with factor 0.25 */ +} + +/**************************************************************************/ +/*! + \brief Does the noise floor level estiamtion. + The function calls the Noisefloor estimation function + for the time segments decided based upon the transient + information. The block is always divided into one or two segments. + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_sbrNoiseFloorEstimateQmf( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const SBR_FRAME_INFO + *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL + *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component + will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per + frame. */ + int transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE *pInvFiltLevels, /*!< Pointer to the vector holding the inverse + filtering levels. */ + UINT sbrSyntaxFlags) + +{ + INT nNoiseEnvelopes, startPos[2], stopPos[2], env, band; + + INT noNoiseBands = h_sbrNoiseFloorEstimate->noNoiseBands; + INT *freqBandTable = h_sbrNoiseFloorEstimate->freqBandTableQmf; + + nNoiseEnvelopes = frame_info->nNoiseEnvelopes; + + startPos[0] = startIndex; + + if (nNoiseEnvelopes == 1) { + stopPos[0] = startIndex + min(numberOfEstimatesPerFrame, 2); + } else { + stopPos[0] = startIndex + 1; + startPos[1] = startIndex + 1; + stopPos[1] = startIndex + min(numberOfEstimatesPerFrame, 2); + } + + /* + * Estimate the noise floor. + **************************************/ + for (env = 0; env < nNoiseEnvelopes; env++) { + for (band = 0; band < noNoiseBands; band++) { + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + qmfBasedNoiseFloorDetection( + &noiseLevels[band + env * noNoiseBands], quotaMatrixOrig, indexVector, + startPos[env], stopPos[env], freqBandTable[band], + freqBandTable[band + 1], h_sbrNoiseFloorEstimate->ana_max_level, + h_sbrNoiseFloorEstimate->noiseFloorOffset[band], missingHarmonicsFlag, + h_sbrNoiseFloorEstimate->weightFac, + h_sbrNoiseFloorEstimate->diffThres, pInvFiltLevels[band]); + } + } + + /* + * Smoothing of the values. + **************************/ + smoothingOfNoiseLevels(noiseLevels, nNoiseEnvelopes, + h_sbrNoiseFloorEstimate->noNoiseBands, + h_sbrNoiseFloorEstimate->prevNoiseLevels, + h_sbrNoiseFloorEstimate->smoothFilter, transientFrame); + + /* quantisation*/ + for (env = 0; env < nNoiseEnvelopes; env++) { + for (band = 0; band < noNoiseBands; band++) { + FDK_ASSERT((band + env * noNoiseBands) < MAX_NUM_NOISE_VALUES); + noiseLevels[band + env * noNoiseBands] = + (FIXP_DBL)NOISE_FLOOR_OFFSET_64 - + (FIXP_DBL)CalcLdData(noiseLevels[band + env * noNoiseBands] + + (FIXP_DBL)1) + + QuantOffset; + } + } +} + +/**************************************************************************/ +/*! + \brief + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +static INT downSampleLoRes(INT *v_result, /*!< */ + INT num_result, /*!< */ + const UCHAR *freqBandTableRef, /*!< */ + INT num_Ref) /*!< */ +{ + INT step; + INT i, j; + INT org_length, result_length; + INT v_index[MAX_FREQ_COEFFS / 2]; + + /* init */ + org_length = num_Ref; + result_length = num_result; + + v_index[0] = 0; /* Always use left border */ + i = 0; + while (org_length > 0) /* Create downsample vector */ + { + i++; + step = org_length / result_length; /* floor; */ + org_length = org_length - step; + result_length--; + v_index[i] = v_index[i - 1] + step; + } + + if (i != num_result) /* Should never happen */ + return (1); /* error downsampling */ + + for (j = 0; j <= i; + j++) /* Use downsample vector to index LoResolution vector. */ + { + v_result[j] = freqBandTableRef[v_index[j]]; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the noise floor level estimation module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequency band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech + */ +) { + INT i, qexp, qtmp; + FIXP_DBL tmp, exp; + + FDKmemclear(h_sbrNoiseFloorEstimate, sizeof(SBR_NOISE_FLOOR_ESTIMATE)); + + h_sbrNoiseFloorEstimate->smoothFilter = smoothFilter; + if (useSpeechConfig) { + h_sbrNoiseFloorEstimate->weightFac = (FIXP_DBL)MAXVAL_DBL; + h_sbrNoiseFloorEstimate->diffThres = INVF_LOW_LEVEL; + } else { + h_sbrNoiseFloorEstimate->weightFac = FL2FXCONST_DBL(0.25f); + h_sbrNoiseFloorEstimate->diffThres = INVF_MID_LEVEL; + } + + h_sbrNoiseFloorEstimate->timeSlots = timeSlots; + h_sbrNoiseFloorEstimate->noiseBands = noiseBands; + + /* h_sbrNoiseFloorEstimate->ana_max_level is scaled by 0.25 */ + switch (ana_max_level) { + case 6: + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + case 3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.5); + break; + case -3: + h_sbrNoiseFloorEstimate->ana_max_level = FL2FXCONST_DBL(0.125); + break; + default: + /* Should not enter here */ + h_sbrNoiseFloorEstimate->ana_max_level = (FIXP_DBL)MAXVAL_DBL; + break; + } + + /* + calculate number of noise bands and allocate + */ + if (FDKsbrEnc_resetSbrNoiseFloorEstimate(h_sbrNoiseFloorEstimate, + freqBandTable, nSfb)) + return (1); + + if (noiseFloorOffset == 0) { + tmp = ((FIXP_DBL)MAXVAL_DBL) >> NOISE_FLOOR_OFFSET_SCALING; + } else { + /* noiseFloorOffset has to be smaller than 12, because + the result of the calculation below must be smaller than 1: + (2^(noiseFloorOffset/3))*2^4<1 */ + FDK_ASSERT(noiseFloorOffset < 12); + + /* Assumes the noise floor offset in tuning table are in q31 */ + /* Change the qformat here when non-zero values would be filled */ + exp = fDivNorm((FIXP_DBL)noiseFloorOffset, 3, &qexp); + tmp = fPow(2, DFRACT_BITS - 1, exp, qexp, &qtmp); + tmp = scaleValue(tmp, qtmp - NOISE_FLOOR_OFFSET_SCALING); + } + + for (i = 0; i < h_sbrNoiseFloorEstimate->noNoiseBands; i++) { + h_sbrNoiseFloorEstimate->noiseFloorOffset[i] = tmp; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Resets the current instance of the noise floor estiamtion + module. + + + \return errorCode, noError if successful + +*/ +/**************************************************************************/ +INT FDKsbrEnc_resetSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const UCHAR *freqBandTable, /*!< Frequency band table. */ + INT nSfb /*!< Number of bands in the frequency band table. */ +) { + INT k2, kx; + + /* + * Calculate number of noise bands + ***********************************/ + k2 = freqBandTable[nSfb]; + kx = freqBandTable[0]; + if (h_sbrNoiseFloorEstimate->noiseBands == 0) { + h_sbrNoiseFloorEstimate->noNoiseBands = 1; + } else { + /* + * Calculate number of noise bands 1,2 or 3 bands/octave + ********************************************************/ + FIXP_DBL tmp, ratio, lg2; + INT ratio_e, qlg2, nNoiseBands; + + ratio = fDivNorm(k2, kx, &ratio_e); + lg2 = fLog2(ratio, ratio_e, &qlg2); + tmp = fMult((FIXP_DBL)(h_sbrNoiseFloorEstimate->noiseBands << 24), lg2); + tmp = scaleValue(tmp, qlg2 - 23); + + nNoiseBands = (INT)((tmp + (FIXP_DBL)1) >> 1); + + if (nNoiseBands > MAX_NUM_NOISE_COEFFS) { + nNoiseBands = MAX_NUM_NOISE_COEFFS; + } + + if (nNoiseBands == 0) { + nNoiseBands = 1; + } + + h_sbrNoiseFloorEstimate->noNoiseBands = nNoiseBands; + } + + return (downSampleLoRes(h_sbrNoiseFloorEstimate->freqBandTableQmf, + h_sbrNoiseFloorEstimate->noNoiseBands, freqBandTable, + nSfb)); +} + +/**************************************************************************/ +/*! + \brief Deletes the current instancce of the noise floor level + estimation module. + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_deleteSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate) /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ +{ + if (h_sbrNoiseFloorEstimate) { + /* + nothing to do + */ + } +} diff --git a/fdk-aac/libSBRenc/src/nf_est.h b/fdk-aac/libSBRenc/src/nf_est.h new file mode 100644 index 0000000..c2f16e9 --- /dev/null +++ b/fdk-aac/libSBRenc/src/nf_est.h @@ -0,0 +1,185 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Noise floor estimation structs and prototypes $Revision: 92790 $ +*/ + +#ifndef NF_EST_H +#define NF_EST_H + +#include "sbr_encoder.h" +#include "fram_gen.h" + +#define NF_SMOOTHING_LENGTH 4 /*!< Smoothing length of the noise floors. */ + +typedef struct { + FIXP_DBL + prevNoiseLevels[NF_SMOOTHING_LENGTH] + [MAX_NUM_NOISE_VALUES]; /*!< The previous noise levels. */ + FIXP_DBL noiseFloorOffset + [MAX_NUM_NOISE_VALUES]; /*!< Noise floor offset, scaled with + NOISE_FLOOR_OFFSET_SCALING */ + const FIXP_DBL *smoothFilter; /*!< Smoothing filter to use. */ + FIXP_DBL ana_max_level; /*!< Max level allowed. */ + FIXP_DBL weightFac; /*!< Weightening factor for the difference between orig + and sbr. */ + INT freqBandTableQmf[MAX_NUM_NOISE_VALUES + + 1]; /*!< Frequncy band table for the noise floor bands.*/ + INT noNoiseBands; /*!< Number of noisebands. */ + INT noiseBands; /*!< NoiseBands switch 4 bit.*/ + INT timeSlots; /*!< Number of timeslots in a frame. */ + INVF_MODE diffThres; /*!< Threshold value to control the inverse filtering + decision */ +} SBR_NOISE_FLOOR_ESTIMATE; + +typedef SBR_NOISE_FLOOR_ESTIMATE *HANDLE_SBR_NOISE_FLOOR_ESTIMATE; + +void FDKsbrEnc_sbrNoiseFloorEstimateQmf( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const SBR_FRAME_INFO + *frame_info, /*!< Time frequency grid of the current frame. */ + FIXP_DBL + *noiseLevels, /*!< Pointer to vector to store the noise levels in.*/ + FIXP_DBL **quotaMatrixOrig, /*!< Matrix holding the quota values of the + original. */ + SCHAR *indexVector, /*!< Index vector to obtain the patched data. */ + INT missingHarmonicsFlag, /*!< Flag indicating if a strong tonal component + will be missing. */ + INT startIndex, /*!< Start index. */ + UINT numberOfEstimatesPerFrame, /*!< The number of tonality estimates per + frame. */ + INT transientFrame, /*!< A flag indicating if a transient is present. */ + INVF_MODE *pInvFiltLevels, /*!< Pointer to the vector holding the inverse + filtering levels. */ + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_InitSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb, /*!< Number of frequency bands. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + INT timeSlots, /*!< Number of time slots in a frame. */ + UINT useSpeechConfig /*!< Flag: adapt tuning parameters according to speech + */ +); + +INT FDKsbrEnc_resetSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate, /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + const UCHAR *freqBandTable, /*!< Frequany band table. */ + INT nSfb); /*!< Number of bands in the frequency band table. */ + +void FDKsbrEnc_deleteSbrNoiseFloorEstimate( + HANDLE_SBR_NOISE_FLOOR_ESTIMATE + h_sbrNoiseFloorEstimate); /*!< Handle to SBR_NOISE_FLOOR_ESTIMATE struct + */ + +#endif diff --git a/fdk-aac/libSBRenc/src/ps_bitenc.cpp b/fdk-aac/libSBRenc/src/ps_bitenc.cpp new file mode 100644 index 0000000..e30af2a --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_bitenc.cpp @@ -0,0 +1,624 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo bitstream encoder + +*******************************************************************************/ + +#include "ps_bitenc.h" + +#include "ps_main.h" + +static inline UCHAR FDKsbrEnc_WriteBits_ps(HANDLE_FDK_BITSTREAM hBitStream, + UINT value, + const UINT numberOfBits) { + /* hBitStream == NULL happens here intentionally */ + if (hBitStream != NULL) { + FDKwriteBits(hBitStream, value, numberOfBits); + } + return numberOfBits; +} + +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 +#define EXTENSION_ID_PS_CODING 2 +#define PS_EXT_ID_V0 0 + +static const INT iidDeltaCoarse_Offset = 14; +static const INT iidDeltaCoarse_MaxVal = 28; +static const INT iidDeltaFine_Offset = 30; +static const INT iidDeltaFine_MaxVal = 60; + +/* PS Stereo Huffmantable: iidDeltaFreqCoarse */ +static const UINT iidDeltaFreqCoarse_Length[] = { + 17, 17, 17, 17, 16, 15, 13, 10, 9, 7, 6, 5, 4, 3, 1, + 3, 4, 5, 6, 6, 8, 11, 13, 14, 14, 15, 17, 18, 18}; +static const UINT iidDeltaFreqCoarse_Code[] = { + 0x0001fffb, 0x0001fffc, 0x0001fffd, 0x0001fffa, 0x0000fffc, 0x00007ffc, + 0x00001ffd, 0x000003fe, 0x000001fe, 0x0000007e, 0x0000003c, 0x0000001d, + 0x0000000d, 0x00000005, 0000000000, 0x00000004, 0x0000000c, 0x0000001c, + 0x0000003d, 0x0000003e, 0x000000fe, 0x000007fe, 0x00001ffc, 0x00003ffc, + 0x00003ffd, 0x00007ffd, 0x0001fffe, 0x0003fffe, 0x0003ffff}; + +/* PS Stereo Huffmantable: iidDeltaFreqFine */ +static const UINT iidDeltaFreqFine_Length[] = { + 18, 18, 18, 18, 18, 18, 18, 18, 18, 17, 18, 17, 17, 16, 16, 15, + 14, 14, 13, 12, 12, 11, 10, 10, 8, 7, 6, 5, 4, 3, 1, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 11, 12, 13, 14, 14, 15, 16, 16, + 17, 17, 18, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18}; +static const UINT iidDeltaFreqFine_Code[] = { + 0x0001feb4, 0x0001feb5, 0x0001fd76, 0x0001fd77, 0x0001fd74, 0x0001fd75, + 0x0001fe8a, 0x0001fe8b, 0x0001fe88, 0x0000fe80, 0x0001feb6, 0x0000fe82, + 0x0000feb8, 0x00007f42, 0x00007fae, 0x00003faf, 0x00001fd1, 0x00001fe9, + 0x00000fe9, 0x000007ea, 0x000007fb, 0x000003fb, 0x000001fb, 0x000001ff, + 0x0000007c, 0x0000003c, 0x0000001c, 0x0000000c, 0000000000, 0x00000001, + 0x00000001, 0x00000002, 0x00000001, 0x0000000d, 0x0000001d, 0x0000003d, + 0x0000007d, 0x000000fc, 0x000001fc, 0x000003fc, 0x000003f4, 0x000007eb, + 0x00000fea, 0x00001fea, 0x00001fd6, 0x00003fd0, 0x00007faf, 0x00007f43, + 0x0000feb9, 0x0000fe83, 0x0001feb7, 0x0000fe81, 0x0001fe89, 0x0001fe8e, + 0x0001fe8f, 0x0001fe8c, 0x0001fe8d, 0x0001feb2, 0x0001feb3, 0x0001feb0, + 0x0001feb1}; + +/* PS Stereo Huffmantable: iidDeltaTimeCoarse */ +static const UINT iidDeltaTimeCoarse_Length[] = { + 19, 19, 19, 20, 20, 20, 17, 15, 12, 10, 8, 6, 4, 2, 1, + 3, 5, 7, 9, 11, 13, 14, 17, 19, 20, 20, 20, 20, 20}; +static const UINT iidDeltaTimeCoarse_Code[] = { + 0x0007fff9, 0x0007fffa, 0x0007fffb, 0x000ffff8, 0x000ffff9, 0x000ffffa, + 0x0001fffd, 0x00007ffe, 0x00000ffe, 0x000003fe, 0x000000fe, 0x0000003e, + 0x0000000e, 0x00000002, 0000000000, 0x00000006, 0x0000001e, 0x0000007e, + 0x000001fe, 0x000007fe, 0x00001ffe, 0x00003ffe, 0x0001fffc, 0x0007fff8, + 0x000ffffb, 0x000ffffc, 0x000ffffd, 0x000ffffe, 0x000fffff}; + +/* PS Stereo Huffmantable: iidDeltaTimeFine */ +static const UINT iidDeltaTimeFine_Length[] = { + 16, 16, 16, 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, + 14, 13, 13, 13, 12, 12, 11, 10, 9, 9, 7, 6, 5, 3, 1, 2, + 5, 6, 7, 8, 9, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, + 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; +static const UINT iidDeltaTimeFine_Code[] = { + 0x00004ed4, 0x00004ed5, 0x00004ece, 0x00004ecf, 0x00004ecc, 0x00004ed6, + 0x00004ed8, 0x00004f46, 0x00004f60, 0x00002718, 0x00002719, 0x00002764, + 0x00002765, 0x0000276d, 0x000027b1, 0x000013b7, 0x000013d6, 0x000009c7, + 0x000009e9, 0x000009ed, 0x000004ee, 0x000004f7, 0x00000278, 0x00000139, + 0x0000009a, 0x0000009f, 0x00000020, 0x00000011, 0x0000000a, 0x00000003, + 0x00000001, 0000000000, 0x0000000b, 0x00000012, 0x00000021, 0x0000004c, + 0x0000009b, 0x0000013a, 0x00000279, 0x00000270, 0x000004ef, 0x000004e2, + 0x000009ea, 0x000009d8, 0x000013d7, 0x000013d0, 0x000027b2, 0x000027a2, + 0x0000271a, 0x0000271b, 0x00004f66, 0x00004f67, 0x00004f61, 0x00004f47, + 0x00004ed9, 0x00004ed7, 0x00004ecd, 0x00004ed2, 0x00004ed3, 0x00004ed0, + 0x00004ed1}; + +static const INT iccDelta_Offset = 7; +static const INT iccDelta_MaxVal = 14; +/* PS Stereo Huffmantable: iccDeltaFreq */ +static const UINT iccDeltaFreq_Length[] = {14, 14, 12, 10, 7, 5, 3, 1, + 2, 4, 6, 8, 9, 11, 13}; +static const UINT iccDeltaFreq_Code[] = { + 0x00003fff, 0x00003ffe, 0x00000ffe, 0x000003fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000001fe, 0x000007fe, 0x00001ffe}; + +/* PS Stereo Huffmantable: iccDeltaTime */ +static const UINT iccDeltaTime_Length[] = {14, 13, 11, 9, 7, 5, 3, 1, + 2, 4, 6, 8, 10, 12, 14}; +static const UINT iccDeltaTime_Code[] = { + 0x00003ffe, 0x00001ffe, 0x000007fe, 0x000001fe, 0x0000007e, + 0x0000001e, 0x00000006, 0000000000, 0x00000002, 0x0000000e, + 0x0000003e, 0x000000fe, 0x000003fe, 0x00000ffe, 0x00003fff}; + +static const INT ipdDelta_Offset = 0; +static const INT ipdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: ipdDeltaFreq */ +static const UINT ipdDeltaFreq_Length[] = {1, 3, 4, 4, 4, 4, 4, 4}; +static const UINT ipdDeltaFreq_Code[] = {0x00000001, 0000000000, 0x00000006, + 0x00000004, 0x00000002, 0x00000003, + 0x00000005, 0x00000007}; + +/* PS Stereo Huffmantable: ipdDeltaTime */ +static const UINT ipdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT ipdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000002, + 0x00000003, 0x00000002, 0000000000, + 0x00000003, 0x00000003}; + +static const INT opdDelta_Offset = 0; +static const INT opdDelta_MaxVal = 7; +/* PS Stereo Huffmantable: opdDeltaFreq */ +static const UINT opdDeltaFreq_Length[] = {1, 3, 4, 4, 5, 5, 4, 3}; +static const UINT opdDeltaFreq_Code[] = { + 0x00000001, 0x00000001, 0x00000006, 0x00000004, + 0x0000000f, 0x0000000e, 0x00000005, 0000000000, +}; + +/* PS Stereo Huffmantable: opdDeltaTime */ +static const UINT opdDeltaTime_Length[] = {1, 3, 4, 5, 5, 4, 4, 3}; +static const UINT opdDeltaTime_Code[] = {0x00000001, 0x00000002, 0x00000001, + 0x00000007, 0x00000006, 0000000000, + 0x00000002, 0x00000003}; + +static INT getNoBands(const INT mode) { + INT noBands = 0; + + switch (mode) { + case 0: + case 3: /* coarse */ + noBands = PS_BANDS_COARSE; + break; + case 1: + case 4: /* mid */ + noBands = PS_BANDS_MID; + break; + case 2: + case 5: /* fine not supported */ + default: /* coarse as default */ + noBands = PS_BANDS_COARSE; + } + + return noBands; +} + +static INT getIIDRes(INT iidMode) { + if (iidMode < 3) + return PS_IID_RES_COARSE; + else + return PS_IID_RES_FINE; +} + +static INT encodeDeltaFreq(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT nBands, const UINT *codeTable, + const UINT *lengthTable, const INT tableOffset, + const INT maxVal, INT *error) { + INT bitCnt = 0; + INT lastVal = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - lastVal) + tableOffset; + lastVal = val[band]; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +static INT encodeDeltaTime(HANDLE_FDK_BITSTREAM hBitBuf, const INT *val, + const INT *valLast, const INT nBands, + const UINT *codeTable, const UINT *lengthTable, + const INT tableOffset, const INT maxVal, + INT *error) { + INT bitCnt = 0; + INT band; + + for (band = 0; band < nBands; band++) { + INT delta = (val[band] - valLast[band]) + tableOffset; + if ((delta > maxVal) || (delta < 0)) { + *error = 1; + delta = delta > 0 ? maxVal : 0; + } + bitCnt += + FDKsbrEnc_WriteBits_ps(hBitBuf, codeTable[delta], lengthTable[delta]); + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iidVal, + const INT *iidValLast, const INT nBands, + const PS_IID_RESOLUTION res, const PS_DELTA mode, + INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaFreqCoarse_Code; + lengthTable = iidDeltaFreqCoarse_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, + lengthTable, iidDeltaCoarse_Offset, + iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaFreqFine_Code; + lengthTable = iidDeltaFreqFine_Length; + bitCnt += + encodeDeltaFreq(hBitBuf, iidVal, nBands, codeTable, lengthTable, + iidDeltaFine_Offset, iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + case PS_DELTA_TIME: + switch (res) { + case PS_IID_RES_COARSE: + codeTable = iidDeltaTimeCoarse_Code; + lengthTable = iidDeltaTimeCoarse_Length; + bitCnt += encodeDeltaTime( + hBitBuf, iidVal, iidValLast, nBands, codeTable, lengthTable, + iidDeltaCoarse_Offset, iidDeltaCoarse_MaxVal, error); + break; + case PS_IID_RES_FINE: + codeTable = iidDeltaTimeFine_Code; + lengthTable = iidDeltaTimeFine_Length; + bitCnt += encodeDeltaTime(hBitBuf, iidVal, iidValLast, nBands, + codeTable, lengthTable, iidDeltaFine_Offset, + iidDeltaFine_MaxVal, error); + break; + default: + *error = 1; + } + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iccVal, + const INT *iccValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = iccDeltaFreq_Code; + lengthTable = iccDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, iccVal, nBands, codeTable, lengthTable, + iccDelta_Offset, iccDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = iccDeltaTime_Code; + lengthTable = iccDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, iccVal, iccValLast, nBands, codeTable, + lengthTable, iccDelta_Offset, iccDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *ipdVal, + const INT *ipdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = ipdDeltaFreq_Code; + lengthTable = ipdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, ipdVal, nBands, codeTable, lengthTable, + ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = ipdDeltaTime_Code; + lengthTable = ipdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, ipdVal, ipdValLast, nBands, codeTable, + lengthTable, ipdDelta_Offset, ipdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *opdVal, + const INT *opdValLast, const INT nBands, + const PS_DELTA mode, INT *error) { + const UINT *codeTable; + const UINT *lengthTable; + INT bitCnt = 0; + + switch (mode) { + case PS_DELTA_FREQ: + codeTable = opdDeltaFreq_Code; + lengthTable = opdDeltaFreq_Length; + bitCnt += encodeDeltaFreq(hBitBuf, opdVal, nBands, codeTable, lengthTable, + opdDelta_Offset, opdDelta_MaxVal, error); + break; + + case PS_DELTA_TIME: + codeTable = opdDeltaTime_Code; + lengthTable = opdDeltaTime_Length; + + bitCnt += + encodeDeltaTime(hBitBuf, opdVal, opdValLast, nBands, codeTable, + lengthTable, opdDelta_Offset, opdDelta_MaxVal, error); + break; + + default: + *error = 1; + } + + return bitCnt; +} + +static INT encodeIpdOpd(HANDLE_PS_OUT psOut, HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + INT error = 0; + INT env; + + FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIpdOpd, 1); + + if (psOut->enableIpdOpd == 1) { + INT *ipdLast = psOut->ipdLast; + INT *opdLast = psOut->opdLast; + + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIPD[env], 1); + bitCnt += FDKsbrEnc_EncodeIpd(hBitBuf, psOut->ipd[env], ipdLast, + getNoBands(psOut->iidMode), + psOut->deltaIPD[env], &error); + + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaOPD[env], 1); + bitCnt += FDKsbrEnc_EncodeOpd(hBitBuf, psOut->opd[env], opdLast, + getNoBands(psOut->iidMode), + psOut->deltaOPD[env], &error); + } + /* reserved bit */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, 1); + } + + return bitCnt; +} + +static INT getEnvIdx(const INT nEnvelopes, const INT frameClass) { + INT envIdx = 0; + + switch (nEnvelopes) { + case 0: + envIdx = 0; + break; + + case 1: + if (frameClass == 0) + envIdx = 1; + else + envIdx = 0; + break; + + case 2: + if (frameClass == 0) + envIdx = 2; + else + envIdx = 1; + break; + + case 3: + envIdx = 2; + break; + + case 4: + envIdx = 3; + break; + + default: + /* unsupported number of envelopes */ + envIdx = 0; + } + + return envIdx; +} + +static INT encodePSExtension(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT bitCnt = 0; + + if (psOut->enableIpdOpd == 1) { + INT ipdOpdBits = 0; + INT extSize = (2 + encodeIpdOpd(psOut, NULL) + 7) >> 3; + + if (extSize < 15) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, extSize, 4); + } else { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, 15, 4); + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, (extSize - 15), 8); + } + + /* write ipd opd data */ + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, PS_EXT_ID_V0, 2); + ipdOpdBits += encodeIpdOpd(psOut, hBitBuf); + + /* byte align the ipd opd data */ + if (ipdOpdBits % 8) + ipdOpdBits += FDKsbrEnc_WriteBits_ps(hBitBuf, 0, (8 - (ipdOpdBits % 8))); + + bitCnt += ipdOpdBits; + } + + return (bitCnt); +} + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf) { + INT psExtEnable = 0; + INT bitCnt = 0; + INT error = 0; + INT env; + + if (psOut != NULL) { + /* PS HEADER */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enablePSHeader, 1); + + if (psOut->enablePSHeader) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableIID, 1); + if (psOut->enableIID) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iidMode, 3); + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->enableICC, 1); + if (psOut->enableICC) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->iccMode, 3); + } + if (psOut->enableIpdOpd) { + psExtEnable = 1; + } + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psExtEnable, 1); + } + + /* Frame class, number of envelopes */ + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameClass, 1); + bitCnt += FDKsbrEnc_WriteBits_ps( + hBitBuf, getEnvIdx(psOut->nEnvelopes, psOut->frameClass), 2); + + if (psOut->frameClass == 1) { + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->frameBorder[env], 5); + } + } + + if (psOut->enableIID == 1) { + INT *iidLast = psOut->iidLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaIID[env], 1); + bitCnt += FDKsbrEnc_EncodeIid( + hBitBuf, psOut->iid[env], iidLast, getNoBands(psOut->iidMode), + (PS_IID_RESOLUTION)getIIDRes(psOut->iidMode), psOut->deltaIID[env], + &error); + + iidLast = psOut->iid[env]; + } + } + + if (psOut->enableICC == 1) { + INT *iccLast = psOut->iccLast; + for (env = 0; env < psOut->nEnvelopes; env++) { + bitCnt += FDKsbrEnc_WriteBits_ps(hBitBuf, psOut->deltaICC[env], 1); + bitCnt += FDKsbrEnc_EncodeIcc(hBitBuf, psOut->icc[env], iccLast, + getNoBands(psOut->iccMode), + psOut->deltaICC[env], &error); + + iccLast = psOut->icc[env]; + } + } + + if (psExtEnable != 0) { + bitCnt += encodePSExtension(psOut, hBitBuf); + } + + } /* if(psOut != NULL) */ + + return bitCnt; +} diff --git a/fdk-aac/libSBRenc/src/ps_bitenc.h b/fdk-aac/libSBRenc/src/ps_bitenc.h new file mode 100644 index 0000000..1d383e3 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_bitenc.h @@ -0,0 +1,173 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo bitstream encoder + +*******************************************************************************/ + +#include "ps_main.h" +#include "ps_const.h" +#include "FDK_bitstream.h" + +#ifndef PS_BITENC_H +#define PS_BITENC_H + +typedef struct T_PS_OUT { + INT enablePSHeader; + INT enableIID; + INT iidMode; + INT enableICC; + INT iccMode; + INT enableIpdOpd; + + INT frameClass; + INT nEnvelopes; + /* ENV data */ + INT frameBorder[PS_MAX_ENVELOPES]; + + /* iid data */ + PS_DELTA deltaIID[PS_MAX_ENVELOPES]; + INT iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidLast[PS_MAX_BANDS]; + + /* icc data */ + PS_DELTA deltaICC[PS_MAX_ENVELOPES]; + INT icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccLast[PS_MAX_BANDS]; + + /* ipd data */ + PS_DELTA deltaIPD[PS_MAX_ENVELOPES]; + INT ipd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT ipdLast[PS_MAX_BANDS]; + + /* opd data */ + PS_DELTA deltaOPD[PS_MAX_ENVELOPES]; + INT opd[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT opdLast[PS_MAX_BANDS]; + +} PS_OUT, *HANDLE_PS_OUT; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +INT FDKsbrEnc_EncodeIid(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iidVal, + const INT *iidValLast, const INT nBands, + const PS_IID_RESOLUTION res, const PS_DELTA mode, + INT *error); + +INT FDKsbrEnc_EncodeIcc(HANDLE_FDK_BITSTREAM hBitBuf, const INT *iccVal, + const INT *iccValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_EncodeIpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *ipdVal, + const INT *ipdValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_EncodeOpd(HANDLE_FDK_BITSTREAM hBitBuf, const INT *opdVal, + const INT *opdValLast, const INT nBands, + const PS_DELTA mode, INT *error); + +INT FDKsbrEnc_WritePSBitstream(const HANDLE_PS_OUT psOut, + HANDLE_FDK_BITSTREAM hBitBuf); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* defined(PSENC_ENABLE) */ diff --git a/fdk-aac/libSBRenc/src/ps_const.h b/fdk-aac/libSBRenc/src/ps_const.h new file mode 100644 index 0000000..b9a33f9 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_const.h @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): N. Rettelbach + + Description: Parametric Stereo constants + +*******************************************************************************/ + +#ifndef PS_CONST_H +#define PS_CONST_H + +#define MAX_PS_CHANNELS (2) +#define HYBRID_MAX_QMF_BANDS (3) +#define HYBRID_FILTER_LENGTH (13) +#define HYBRID_FILTER_DELAY ((HYBRID_FILTER_LENGTH - 1) / 2) + +#define HYBRID_FRAMESIZE (32) +#define HYBRID_READ_OFFSET (10) + +#define MAX_HYBRID_BANDS ((64 - HYBRID_MAX_QMF_BANDS + 10)) + +typedef enum { + PS_RES_COARSE = 0, + PS_RES_MID = 1, + PS_RES_FINE = 2 +} PS_RESOLUTION; + +typedef enum { + PS_BANDS_COARSE = 10, + PS_BANDS_MID = 20, + PS_MAX_BANDS = PS_BANDS_MID +} PS_BANDS; + +typedef enum { PS_IID_RES_COARSE = 0, PS_IID_RES_FINE } PS_IID_RESOLUTION; + +typedef enum { PS_ICC_ROT_A = 0, PS_ICC_ROT_B } PS_ICC_ROTATION_MODE; + +typedef enum { PS_DELTA_FREQ, PS_DELTA_TIME } PS_DELTA; + +typedef enum { + PS_MAX_ENVELOPES = 4 + +} PS_CONSTS; + +typedef enum { + PSENC_OK = 0x0000, /*!< No error happened. All fine. */ + PSENC_INVALID_HANDLE = + 0x0020, /*!< Handle passed to function call was invalid. */ + PSENC_MEMORY_ERROR = 0x0021, /*!< Memory allocation failed. */ + PSENC_INIT_ERROR = 0x0040, /*!< General initialization error. */ + PSENC_ENCODE_ERROR = 0x0060 /*!< The encoding process was interrupted by an + unexpected error. */ + +} FDK_PSENC_ERROR; + +#endif diff --git a/fdk-aac/libSBRenc/src/ps_encode.cpp b/fdk-aac/libSBRenc/src/ps_encode.cpp new file mode 100644 index 0000000..88d3131 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_encode.cpp @@ -0,0 +1,1031 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Neuendorf, N. Rettelbach, M. Multrus + + Description: PS parameter extraction, encoding + +*******************************************************************************/ + +/*! + \file + \brief PS parameter extraction, encoding functions $Revision: 96441 $ +*/ + +#include "ps_main.h" +#include "ps_encode.h" +#include "qmf.h" +#include "sbr_misc.h" +#include "sbrenc_ram.h" + +#include "genericStds.h" + +inline void FDKsbrEnc_addFIXP_DBL(const FIXP_DBL *X, const FIXP_DBL *Y, + FIXP_DBL *Z, INT n) { + for (INT i = 0; i < n; i++) Z[i] = (X[i] >> 1) + (Y[i] >> 1); +} + +#define LOG10_2_10 3.01029995664f /* 10.0f*log10(2.f) */ + +static const INT + iidGroupBordersLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES + 1] = { + 0, 1, 2, 3, 4, 5, /* 6 subqmf subbands - 0th qmf subband */ + 6, 7, /* 2 subqmf subbands - 1st qmf subband */ + 8, 9, /* 2 subqmf subbands - 2nd qmf subband */ + 10, 11, 12, 13, 14, 15, 16, 18, 21, 25, 30, 42, 71}; + +static const UCHAR + iidGroupWidthLdLoRes[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 3, 4, 5}; + +static const INT subband2parameter20[QMF_GROUPS_LO_RES + SUBQMF_GROUPS_LO_RES] = + {1, 0, 0, 1, 2, 3, /* 6 subqmf subbands - 0th qmf subband */ + 4, 5, /* 2 subqmf subbands - 1st qmf subband */ + 6, 7, /* 2 subqmf subbands - 2nd qmf subband */ + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +typedef enum { + MAX_TIME_DIFF_FRAMES = 20, + MAX_PS_NOHEADER_CNT = 10, + MAX_NOENV_CNT = 10, + DO_NOT_USE_THIS_MODE = 0x7FFFFF +} __PS_CONSTANTS; + +static const FIXP_DBL iidQuant_fx[15] = { + (FIXP_DBL)0xce000000, (FIXP_DBL)0xdc000000, (FIXP_DBL)0xe4000000, + (FIXP_DBL)0xec000000, (FIXP_DBL)0xf2000000, (FIXP_DBL)0xf8000000, + (FIXP_DBL)0xfc000000, (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, + (FIXP_DBL)0x08000000, (FIXP_DBL)0x0e000000, (FIXP_DBL)0x14000000, + (FIXP_DBL)0x1c000000, (FIXP_DBL)0x24000000, (FIXP_DBL)0x32000000}; + +static const FIXP_DBL iidQuantFine_fx[31] = { + (FIXP_DBL)0x9c000001, (FIXP_DBL)0xa6000001, (FIXP_DBL)0xb0000001, + (FIXP_DBL)0xba000001, (FIXP_DBL)0xc4000000, (FIXP_DBL)0xce000000, + (FIXP_DBL)0xd4000000, (FIXP_DBL)0xda000000, (FIXP_DBL)0xe0000000, + (FIXP_DBL)0xe6000000, (FIXP_DBL)0xec000000, (FIXP_DBL)0xf0000000, + (FIXP_DBL)0xf4000000, (FIXP_DBL)0xf8000000, (FIXP_DBL)0xfc000000, + (FIXP_DBL)0x00000000, (FIXP_DBL)0x04000000, (FIXP_DBL)0x08000000, + (FIXP_DBL)0x0c000000, (FIXP_DBL)0x10000000, (FIXP_DBL)0x14000000, + (FIXP_DBL)0x1a000000, (FIXP_DBL)0x20000000, (FIXP_DBL)0x26000000, + (FIXP_DBL)0x2c000000, (FIXP_DBL)0x32000000, (FIXP_DBL)0x3c000000, + (FIXP_DBL)0x45ffffff, (FIXP_DBL)0x4fffffff, (FIXP_DBL)0x59ffffff, + (FIXP_DBL)0x63ffffff}; + +static const FIXP_DBL iccQuant[8] = { + (FIXP_DBL)0x7fffffff, (FIXP_DBL)0x77ef9d7f, (FIXP_DBL)0x6babc97f, + (FIXP_DBL)0x4ceaf27f, (FIXP_DBL)0x2f0ed3c0, (FIXP_DBL)0x00000000, + (FIXP_DBL)0xb49ba601, (FIXP_DBL)0x80000000}; + +static FDK_PSENC_ERROR InitPSData(HANDLE_PS_DATA hPsData) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hPsData == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int i, env; + FDKmemclear(hPsData, sizeof(PS_DATA)); + + for (i = 0; i < PS_MAX_BANDS; i++) { + hPsData->iidIdxLast[i] = 0; + hPsData->iccIdxLast[i] = 0; + } + + hPsData->iidEnable = hPsData->iidEnableLast = 0; + hPsData->iccEnable = hPsData->iccEnableLast = 0; + hPsData->iidQuantMode = hPsData->iidQuantModeLast = PS_IID_RES_COARSE; + hPsData->iccQuantMode = hPsData->iccQuantModeLast = PS_ICC_ROT_A; + + for (env = 0; env < PS_MAX_ENVELOPES; env++) { + hPsData->iccDiffMode[env] = PS_DELTA_FREQ; + hPsData->iccDiffMode[env] = PS_DELTA_FREQ; + + for (i = 0; i < PS_MAX_BANDS; i++) { + hPsData->iidIdx[env][i] = 0; + hPsData->iccIdx[env][i] = 0; + } + } + + hPsData->nEnvelopesLast = 0; + + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + return error; +} + +static FIXP_DBL quantizeCoef(const FIXP_DBL *RESTRICT input, const INT nBands, + const FIXP_DBL *RESTRICT quantTable, + const INT idxOffset, const INT nQuantSteps, + INT *RESTRICT quantOut) { + INT idx, band; + FIXP_DBL quantErr = FL2FXCONST_DBL(0.f); + + for (band = 0; band < nBands; band++) { + for (idx = 0; idx < nQuantSteps - 1; idx++) { + if (fixp_abs((input[band] >> 1) - (quantTable[idx + 1] >> 1)) > + fixp_abs((input[band] >> 1) - (quantTable[idx] >> 1))) { + break; + } + } + quantErr += (fixp_abs(input[band] - quantTable[idx]) >> + PS_QUANT_SCALE); /* don't scale before subtraction; diff + smaller (64-25)/64 */ + quantOut[band] = idx - idxOffset; + } + + return quantErr; +} + +static INT getICCMode(const INT nBands, const INT rotType) { + INT mode = 0; + + switch (nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + } + if (rotType == PS_ICC_ROT_B) { + mode += 3; + } + + return mode; +} + +static INT getIIDMode(const INT nBands, const INT iidRes) { + INT mode = 0; + + switch (nBands) { + case PS_BANDS_COARSE: + mode = PS_RES_COARSE; + break; + case PS_BANDS_MID: + mode = PS_RES_MID; + break; + default: + mode = 0; + break; + } + + if (iidRes == PS_IID_RES_FINE) { + mode += 3; + } + + return mode; +} + +static INT envelopeReducible(FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT psBands, INT nEnvelopes) { +#define THRESH_SCALE 7 + + INT reducible = 1; /* true */ + INT e = 0, b = 0; + FIXP_DBL dIid = FL2FXCONST_DBL(0.f); + FIXP_DBL dIcc = FL2FXCONST_DBL(0.f); + + FIXP_DBL iidErrThreshold, iccErrThreshold; + FIXP_DBL iidMeanError, iccMeanError; + + /* square values to prevent sqrt, + multiply bands to prevent division; bands shifted DFRACT_BITS instead + (DFRACT_BITS-1) because fMultDiv2 used*/ + iidErrThreshold = + fMultDiv2(FL2FXCONST_DBL(6.5f * 6.5f / (IID_SCALE_FT * IID_SCALE_FT)), + (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); + iccErrThreshold = + fMultDiv2(FL2FXCONST_DBL(0.75f * 0.75f), + (FIXP_DBL)(psBands << ((DFRACT_BITS)-THRESH_SCALE))); + + if (nEnvelopes <= 1) { + reducible = 0; + } else { + /* mean error criterion */ + for (e = 0; (e < nEnvelopes / 2) && (reducible != 0); e++) { + iidMeanError = iccMeanError = FL2FXCONST_DBL(0.f); + for (b = 0; b < psBands; b++) { + dIid = (iid[2 * e][b] >> 1) - + (iid[2 * e + 1][b] >> 1); /* scale 1 bit; squared -> 2 bit */ + dIcc = (icc[2 * e][b] >> 1) - (icc[2 * e + 1][b] >> 1); + iidMeanError += fPow2Div2(dIid) >> (5 - 1); /* + (bands=20) scale = 5 */ + iccMeanError += fPow2Div2(dIcc) >> (5 - 1); + } /* --> scaling = 7 bit = THRESH_SCALE !! */ + + /* instead sqrt values are squared! + instead of division, multiply threshold with psBands + scaling necessary!! */ + + /* quit as soon as threshold is reached */ + if ((iidMeanError > (iidErrThreshold)) || + (iccMeanError > (iccErrThreshold))) { + reducible = 0; + } + } + } /* nEnvelopes != 1 */ + + return reducible; +} + +static void processIidData(PS_DATA *psData, + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + const INT psBands, const INT nEnvelopes, + const FIXP_DBL quantErrorThreshold) { + INT iidIdxFine[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxCoarse[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + + FIXP_DBL errIID = FL2FXCONST_DBL(0.f); + FIXP_DBL errIIDFine = FL2FXCONST_DBL(0.f); + INT bitsIidFreq = 0; + INT bitsIidTime = 0; + INT bitsFineTot = 0; + INT bitsCoarseTot = 0; + INT error = 0; + INT env, band; + INT diffMode[PS_MAX_ENVELOPES], diffModeFine[PS_MAX_ENVELOPES]; + INT loudnDiff = 0; + INT iidTransmit = 0; + + /* Quantize IID coefficients */ + for (env = 0; env < nEnvelopes; env++) { + errIID += + quantizeCoef(iid[env], psBands, iidQuant_fx, 7, 15, iidIdxCoarse[env]); + errIIDFine += quantizeCoef(iid[env], psBands, iidQuantFine_fx, 15, 31, + iidIdxFine[env]); + } + + /* normalize error to number of envelopes, ps bands + errIID /= psBands*nEnvelopes; + errIIDFine /= psBands*nEnvelopes; */ + + /* Check if IID coefficients should be used in this frame */ + psData->iidEnable = 0; + for (env = 0; env < nEnvelopes; env++) { + for (band = 0; band < psBands; band++) { + loudnDiff += fixp_abs(iidIdxCoarse[env][band]); + iidTransmit++; + } + } + + if (loudnDiff > + fMultI(FL2FXCONST_DBL(0.7f), iidTransmit)) { /* 0.7f empiric value */ + psData->iidEnable = 1; + } + + /* if iid not active -> RESET data */ + if (psData->iidEnable == 0) { + psData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iidIdx[env], sizeof(INT) * psBands); + } + return; + } + + /* count COARSE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], NULL, psBands, + PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); + + if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || + (psData->iidQuantModeLast == PS_IID_RES_FINE)) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } else { + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[0], psData->iidIdxLast, psBands, + PS_IID_RES_COARSE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffMode[0] = PS_DELTA_FREQ; + bitsCoarseTot = bitsIidFreq; + } else { + diffMode[0] = PS_DELTA_TIME; + bitsCoarseTot = bitsIidTime; + } + + /* count COARSE quantization bits for following envelopes*/ + for (env = 1; env < nEnvelopes; env++) { + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], NULL, psBands, + PS_IID_RES_COARSE, PS_DELTA_FREQ, &error); + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxCoarse[env], iidIdxCoarse[env - 1], + psBands, PS_IID_RES_COARSE, PS_DELTA_TIME, &error); + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffMode[env] = PS_DELTA_FREQ; + bitsCoarseTot += bitsIidFreq; + } else { + diffMode[env] = PS_DELTA_TIME; + bitsCoarseTot += bitsIidTime; + } + } + + /* count FINE quantization bits for first envelope*/ + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], NULL, psBands, + PS_IID_RES_FINE, PS_DELTA_FREQ, &error); + + if ((psData->iidTimeCnt >= MAX_TIME_DIFF_FRAMES) || + (psData->iidQuantModeLast == PS_IID_RES_COARSE)) { + bitsIidTime = DO_NOT_USE_THIS_MODE; + } else { + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxFine[0], psData->iidIdxLast, psBands, + PS_IID_RES_FINE, PS_DELTA_TIME, &error); + } + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffModeFine[0] = PS_DELTA_FREQ; + bitsFineTot = bitsIidFreq; + } else { + diffModeFine[0] = PS_DELTA_TIME; + bitsFineTot = bitsIidTime; + } + + /* count FINE quantization bits for following envelopes*/ + for (env = 1; env < nEnvelopes; env++) { + bitsIidFreq = FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], NULL, psBands, + PS_IID_RES_FINE, PS_DELTA_FREQ, &error); + bitsIidTime = + FDKsbrEnc_EncodeIid(NULL, iidIdxFine[env], iidIdxFine[env - 1], psBands, + PS_IID_RES_FINE, PS_DELTA_TIME, &error); + + /* decision DELTA_FREQ vs DELTA_TIME */ + if (bitsIidTime > bitsIidFreq) { + diffModeFine[env] = PS_DELTA_FREQ; + bitsFineTot += bitsIidFreq; + } else { + diffModeFine[env] = PS_DELTA_TIME; + bitsFineTot += bitsIidTime; + } + } + + if (bitsFineTot == bitsCoarseTot) { + /* if same number of bits is needed, use the quantization with lower error + */ + if (errIIDFine < errIID) { + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } else { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } else { + /* const FIXP_DBL minThreshold = + * FL2FXCONST_DBL(0.2f/(IID_SCALE_FT*PS_QUANT_SCALE_FT)*(psBands*nEnvelopes)); + */ + const FIXP_DBL minThreshold = + (FIXP_DBL)((LONG)0x00019999 * (psBands * nEnvelopes)); + + /* decision RES_FINE vs RES_COARSE */ + /* test if errIIDFine*quantErrorThreshold < errIID */ + /* shiftVal 2 comes from scaling of quantErrorThreshold */ + if (fixMax(((errIIDFine >> 1) + (minThreshold >> 1)) >> 1, + fMult(quantErrorThreshold, errIIDFine)) < (errIID >> 2)) { + bitsCoarseTot = DO_NOT_USE_THIS_MODE; + } else if (fixMax(((errIID >> 1) + (minThreshold >> 1)) >> 1, + fMult(quantErrorThreshold, errIID)) < (errIIDFine >> 2)) { + bitsFineTot = DO_NOT_USE_THIS_MODE; + } + } + + /* decision RES_FINE vs RES_COARSE */ + if (bitsFineTot < bitsCoarseTot) { + psData->iidQuantMode = PS_IID_RES_FINE; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = diffModeFine[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxFine[env], psBands * sizeof(INT)); + } + } else { + psData->iidQuantMode = PS_IID_RES_COARSE; + for (env = 0; env < nEnvelopes; env++) { + psData->iidDiffMode[env] = diffMode[env]; + FDKmemcpy(psData->iidIdx[env], iidIdxCoarse[env], psBands * sizeof(INT)); + } + } + + /* Count DELTA_TIME encoding streaks */ + for (env = 0; env < nEnvelopes; env++) { + if (psData->iidDiffMode[env] == PS_DELTA_TIME) + psData->iidTimeCnt++; + else + psData->iidTimeCnt = 0; + } +} + +static INT similarIid(PS_DATA *psData, const INT psBands, + const INT nEnvelopes) { + const INT diffThr = (psData->iidQuantMode == PS_IID_RES_COARSE) ? 2 : 3; + const INT sumDiffThr = diffThr * psBands / 4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { + similar = 1; + for (env = 0; env < nEnvelopes; env++) { + sumDiff = 0; + b = 0; + do { + diff = fixp_abs(psData->iidIdx[env][b] - psData->iidIdxLast[b]); + sumDiff += diff; + if ((diff > diffThr) /* more than x quantization steps in any band */ + || (sumDiff > sumDiffThr)) { /* more than x quantisations steps + overall difference */ + similar = 0; + } + b++; + } while ((b < psBands) && (similar > 0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + +static INT similarIcc(PS_DATA *psData, const INT psBands, + const INT nEnvelopes) { + const INT diffThr = 2; + const INT sumDiffThr = diffThr * psBands / 4; + INT similar = 0; + INT diff = 0; + INT sumDiff = 0; + INT env = 0; + INT b = 0; + if ((nEnvelopes == psData->nEnvelopesLast) && (nEnvelopes == 1)) { + similar = 1; + for (env = 0; env < nEnvelopes; env++) { + sumDiff = 0; + b = 0; + do { + diff = fixp_abs(psData->iccIdx[env][b] - psData->iccIdxLast[b]); + sumDiff += diff; + if ((diff > diffThr) /* more than x quantisation step in any band */ + || (sumDiff > sumDiffThr)) { /* more than x quantisations steps + overall difference */ + similar = 0; + } + b++; + } while ((b < psBands) && (similar > 0)); + } + } /* nEnvelopes==1 */ + + return similar; +} + +static void processIccData( + PS_DATA *psData, + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], /* const input values: + unable to declare as + const, since it does + not poINT to const + memory */ + const INT psBands, const INT nEnvelopes) { + FIXP_DBL errICC = FL2FXCONST_DBL(0.f); + INT env, band; + INT bitsIccFreq, bitsIccTime; + INT error = 0; + INT inCoherence = 0, iccTransmit = 0; + INT *iccIdxLast; + + iccIdxLast = psData->iccIdxLast; + + /* Quantize ICC coefficients */ + for (env = 0; env < nEnvelopes; env++) { + errICC += + quantizeCoef(icc[env], psBands, iccQuant, 0, 8, psData->iccIdx[env]); + } + + /* Check if ICC coefficients should be used */ + psData->iccEnable = 0; + for (env = 0; env < nEnvelopes; env++) { + for (band = 0; band < psBands; band++) { + inCoherence += psData->iccIdx[env][band]; + iccTransmit++; + } + } + if (inCoherence > + fMultI(FL2FXCONST_DBL(0.5f), iccTransmit)) { /* 0.5f empiric value */ + psData->iccEnable = 1; + } + + if (psData->iccEnable == 0) { + psData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + for (env = 0; env < nEnvelopes; env++) { + psData->iccDiffMode[env] = PS_DELTA_FREQ; + FDKmemclear(psData->iccIdx[env], sizeof(INT) * psBands); + } + return; + } + + for (env = 0; env < nEnvelopes; env++) { + bitsIccFreq = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], NULL, psBands, + PS_DELTA_FREQ, &error); + + if (psData->iccTimeCnt < MAX_TIME_DIFF_FRAMES) { + bitsIccTime = FDKsbrEnc_EncodeIcc(NULL, psData->iccIdx[env], iccIdxLast, + psBands, PS_DELTA_TIME, &error); + } else { + bitsIccTime = DO_NOT_USE_THIS_MODE; + } + + if (bitsIccFreq > bitsIccTime) { + psData->iccDiffMode[env] = PS_DELTA_TIME; + psData->iccTimeCnt++; + } else { + psData->iccDiffMode[env] = PS_DELTA_FREQ; + psData->iccTimeCnt = 0; + } + iccIdxLast = psData->iccIdx[env]; + } +} + +static void calculateIID(FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, INT psBands) { + INT i = 0; + INT env = 0; + for (env = 0; env < nEnvelopes; env++) { + for (i = 0; i < psBands; i++) { + /* iid[env][i] = 10.0f*(float)log10(pwrL[env][i]/pwrR[env][i]); + */ + FIXP_DBL IID = fMultDiv2(FL2FXCONST_DBL(LOG10_2_10 / IID_SCALE_FT), + (ldPwrL[env][i] - ldPwrR[env][i])); + + IID = fixMin(IID, (FIXP_DBL)(MAXVAL_DBL >> (LD_DATA_SHIFT + 1))); + IID = fixMax(IID, (FIXP_DBL)(MINVAL_DBL >> (LD_DATA_SHIFT + 1))); + iid[env][i] = IID << (LD_DATA_SHIFT + 1); + } + } +} + +static void calculateICC(FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS], + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS], + INT nEnvelopes, INT psBands) { + INT i = 0; + INT env = 0; + INT border = psBands; + + switch (psBands) { + case PS_BANDS_COARSE: + border = 5; + break; + case PS_BANDS_MID: + border = 11; + break; + default: + break; + } + + for (env = 0; env < nEnvelopes; env++) { + for (i = 0; i < border; i++) { + /* icc[env][i] = min( pwrCr[env][i] / (float) sqrt(pwrL[env][i] * + * pwrR[env][i]) , 1.f); + */ + int scale; + FIXP_DBL invNrg = invSqrtNorm2( + fMax(fMult(pwrL[env][i], pwrR[env][i]), (FIXP_DBL)1), &scale); + icc[env][i] = + SATURATE_LEFT_SHIFT(fMult(pwrCr[env][i], invNrg), scale, DFRACT_BITS); + } + + for (; i < psBands; i++) { + int denom_e; + FIXP_DBL denom_m = fMultNorm(pwrL[env][i], pwrR[env][i], &denom_e); + + if (denom_m == (FIXP_DBL)0) { + icc[env][i] = (FIXP_DBL)MAXVAL_DBL; + } else { + int num_e, result_e; + FIXP_DBL num_m, result_m; + + num_e = CountLeadingBits( + fixMax(fixp_abs(pwrCr[env][i]), fixp_abs(pwrCi[env][i]))); + num_m = fPow2Div2((pwrCr[env][i] << num_e)) + + fPow2Div2((pwrCi[env][i] << num_e)); + + result_m = fDivNorm(num_m, denom_m, &result_e); + result_e += (-2 * num_e + 1) - denom_e; + icc[env][i] = scaleValueSaturate(sqrtFixp(result_m >> (result_e & 1)), + (result_e + (result_e & 1)) >> 1); + } + } + } +} + +void FDKsbrEnc_initPsBandNrgScale(HANDLE_PS_ENCODE hPsEncode) { + INT group, bin; + INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + FDKmemclear(hPsEncode->psBandNrgScale, PS_MAX_BANDS * sizeof(SCHAR)); + + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin = bin >> 1; + } + + hPsEncode->psBandNrgScale[bin] = + (hPsEncode->psBandNrgScale[bin] == 0) + ? (hPsEncode->iidGroupWidthLd[group] + 5) + : (fixMax(hPsEncode->iidGroupWidthLd[group], + hPsEncode->psBandNrgScale[bin]) + + 1); + } +} + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (phPsEncode == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + HANDLE_PS_ENCODE hPsEncode = NULL; + if (NULL == (hPsEncode = GetRam_PsEncode())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hPsEncode, sizeof(PS_ENCODE)); + *phPsEncode = hPsEncode; /* return allocated handle */ + } +bail: + return error; +} + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL == hPsEncode) { + error = PSENC_INVALID_HANDLE; + } else { + if (PSENC_OK != (InitPSData(&hPsEncode->psData))) { + goto bail; + } + + switch (psEncMode) { + case PS_BANDS_COARSE: + case PS_BANDS_MID: + hPsEncode->nQmfIidGroups = QMF_GROUPS_LO_RES; + hPsEncode->nSubQmfIidGroups = SUBQMF_GROUPS_LO_RES; + FDKmemcpy(hPsEncode->iidGroupBorders, iidGroupBordersLoRes, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups + 1) * + sizeof(INT)); + FDKmemcpy(hPsEncode->subband2parameterIndex, subband2parameter20, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * + sizeof(INT)); + FDKmemcpy(hPsEncode->iidGroupWidthLd, iidGroupWidthLdLoRes, + (hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups) * + sizeof(UCHAR)); + break; + default: + error = PSENC_INIT_ERROR; + goto bail; + } + + hPsEncode->psEncMode = psEncMode; + hPsEncode->iidQuantErrorThreshold = iidQuantErrorThreshold; + FDKsbrEnc_initPsBandNrgScale(hPsEncode); + } +bail: + return error; +} + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL != phPsEncode) { + FreeRam_PsEncode(phPsEncode); + } + + return error; +} + +typedef struct { + FIXP_DBL pwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrL[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL ldPwrR[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCr[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL pwrCi[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + +} PS_PWR_DATA; + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, HANDLE_PS_OUT hPsOut, UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, const INT sendHeader) { + FDK_PSENC_ERROR error = PSENC_OK; + + HANDLE_PS_DATA hPsData = &hPsEncode->psData; + FIXP_DBL iid[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + FIXP_DBL icc[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + int envBorder[PS_MAX_ENVELOPES + 1]; + + int group, bin, col, subband, band; + int i = 0; + + int env = 0; + int psBands = (int)hPsEncode->psEncMode; + int nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + int nEnvelopes = fixMin(maxEnvelopes, (UINT)PS_MAX_ENVELOPES); + + C_ALLOC_SCRATCH_START(pwrData, PS_PWR_DATA, 1) + + for (env = 0; env < nEnvelopes + 1; env++) { + envBorder[env] = fMultI(GetInvInt(nEnvelopes), frameSize * env); + } + + for (env = 0; env < nEnvelopes; env++) { + /* clear energy array */ + for (band = 0; band < psBands; band++) { + pwrData->pwrL[env][band] = pwrData->pwrR[env][band] = + pwrData->pwrCr[env][band] = pwrData->pwrCi[env][band] = FIXP_DBL(1); + } + + /**** calculate energies and correlation ****/ + + /* start with hybrid data */ + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* determine group border */ + int bScale = hPsEncode->psBandNrgScale[bin]; + + FIXP_DBL pwrL_env_bin = pwrData->pwrL[env][bin]; + FIXP_DBL pwrR_env_bin = pwrData->pwrR[env][bin]; + FIXP_DBL pwrCr_env_bin = pwrData->pwrCr[env][bin]; + FIXP_DBL pwrCi_env_bin = pwrData->pwrCi[env][bin]; + + int scale = (int)dynBandScale[bin]; + for (col = envBorder[env]; col < envBorder[env + 1]; col++) { + for (subband = hPsEncode->iidGroupBorders[group]; + subband < hPsEncode->iidGroupBorders[group + 1]; subband++) { + FIXP_DBL l_real = (hybridData[col][0][0][subband]) << scale; + FIXP_DBL l_imag = (hybridData[col][0][1][subband]) << scale; + FIXP_DBL r_real = (hybridData[col][1][0][subband]) << scale; + FIXP_DBL r_imag = (hybridData[col][1][1][subband]) << scale; + + pwrL_env_bin += (fPow2Div2(l_real) + fPow2Div2(l_imag)) >> bScale; + pwrR_env_bin += (fPow2Div2(r_real) + fPow2Div2(r_imag)) >> bScale; + pwrCr_env_bin += + (fMultDiv2(l_real, r_real) + fMultDiv2(l_imag, r_imag)) >> bScale; + pwrCi_env_bin += + (fMultDiv2(r_real, l_imag) - fMultDiv2(l_real, r_imag)) >> bScale; + } + } + /* assure, nrg's of left and right channel are not negative; necessary on + * 16 bit multiply units */ + pwrData->pwrL[env][bin] = fixMax((FIXP_DBL)0, pwrL_env_bin); + pwrData->pwrR[env][bin] = fixMax((FIXP_DBL)0, pwrR_env_bin); + + pwrData->pwrCr[env][bin] = pwrCr_env_bin; + pwrData->pwrCi[env][bin] = pwrCi_env_bin; + + } /* nIidGroups */ + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[env], pwrData->ldPwrL[env], psBands); + LdDataVector(pwrData->pwrR[env], pwrData->ldPwrR[env], psBands); + + } /* nEnvelopes */ + + /* calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, + icc, nEnvelopes, psBands); + + /*** Envelope Reduction ***/ + while (envelopeReducible(iid, icc, psBands, nEnvelopes)) { + int e = 0; + /* sum energies of two neighboring envelopes */ + nEnvelopes >>= 1; + for (e = 0; e < nEnvelopes; e++) { + FDKsbrEnc_addFIXP_DBL(pwrData->pwrL[2 * e], pwrData->pwrL[2 * e + 1], + pwrData->pwrL[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrR[2 * e], pwrData->pwrR[2 * e + 1], + pwrData->pwrR[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCr[2 * e], pwrData->pwrCr[2 * e + 1], + pwrData->pwrCr[e], psBands); + FDKsbrEnc_addFIXP_DBL(pwrData->pwrCi[2 * e], pwrData->pwrCi[2 * e + 1], + pwrData->pwrCi[e], psBands); + + /* calc logarithmic energy */ + LdDataVector(pwrData->pwrL[e], pwrData->ldPwrL[e], psBands); + LdDataVector(pwrData->pwrR[e], pwrData->ldPwrR[e], psBands); + + /* reduce number of envelopes and adjust borders */ + envBorder[e] = envBorder[2 * e]; + } + envBorder[nEnvelopes] = envBorder[2 * nEnvelopes]; + + /* re-calculate iid and icc */ + calculateIID(pwrData->ldPwrL, pwrData->ldPwrR, iid, nEnvelopes, psBands); + calculateICC(pwrData->pwrL, pwrData->pwrR, pwrData->pwrCr, pwrData->pwrCi, + icc, nEnvelopes, psBands); + } + + /* */ + if (sendHeader) { + hPsData->headerCnt = MAX_PS_NOHEADER_CNT; + hPsData->iidTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->iccTimeCnt = MAX_TIME_DIFF_FRAMES; + hPsData->noEnvCnt = MAX_NOENV_CNT; + } + + /*** Parameter processing, quantisation etc ***/ + processIidData(hPsData, iid, psBands, nEnvelopes, + hPsEncode->iidQuantErrorThreshold); + processIccData(hPsData, icc, psBands, nEnvelopes); + + /*** Initialize output struct ***/ + + /* PS Header on/off ? */ + if ((hPsData->headerCnt < MAX_PS_NOHEADER_CNT) && + ((hPsData->iidQuantMode == hPsData->iidQuantModeLast) && + (hPsData->iccQuantMode == hPsData->iccQuantModeLast)) && + ((hPsData->iidEnable == hPsData->iidEnableLast) && + (hPsData->iccEnable == hPsData->iccEnableLast))) { + hPsOut->enablePSHeader = 0; + } else { + hPsOut->enablePSHeader = 1; + hPsData->headerCnt = 0; + } + + /* nEnvelopes = 0 ? */ + if ((hPsData->noEnvCnt < MAX_NOENV_CNT) && + (similarIid(hPsData, psBands, nEnvelopes)) && + (similarIcc(hPsData, psBands, nEnvelopes))) { + hPsOut->nEnvelopes = nEnvelopes = 0; + hPsData->noEnvCnt++; + } else { + hPsData->noEnvCnt = 0; + } + + if (nEnvelopes > 0) { + hPsOut->enableIID = hPsData->iidEnable; + hPsOut->iidMode = getIIDMode(psBands, hPsData->iidQuantMode); + + hPsOut->enableICC = hPsData->iccEnable; + hPsOut->iccMode = getICCMode(psBands, hPsData->iccQuantMode); + + hPsOut->enableIpdOpd = 0; + hPsOut->frameClass = 0; + hPsOut->nEnvelopes = nEnvelopes; + + for (env = 0; env < nEnvelopes; env++) { + hPsOut->frameBorder[env] = envBorder[env + 1]; + hPsOut->deltaIID[env] = (PS_DELTA)hPsData->iidDiffMode[env]; + hPsOut->deltaICC[env] = (PS_DELTA)hPsData->iccDiffMode[env]; + for (band = 0; band < psBands; band++) { + hPsOut->iid[env][band] = hPsData->iidIdx[env][band]; + hPsOut->icc[env][band] = hPsData->iccIdx[env][band]; + } + } + + /* IPD OPD not supported right now */ + FDKmemclear(hPsOut->ipd, + PS_MAX_ENVELOPES * PS_MAX_BANDS * sizeof(PS_DELTA)); + for (env = 0; env < PS_MAX_ENVELOPES; env++) { + hPsOut->deltaIPD[env] = PS_DELTA_FREQ; + hPsOut->deltaOPD[env] = PS_DELTA_FREQ; + } + + FDKmemclear(hPsOut->ipdLast, PS_MAX_BANDS * sizeof(INT)); + FDKmemclear(hPsOut->opdLast, PS_MAX_BANDS * sizeof(INT)); + + for (band = 0; band < PS_MAX_BANDS; band++) { + hPsOut->iidLast[band] = hPsData->iidIdxLast[band]; + hPsOut->iccLast[band] = hPsData->iccIdxLast[band]; + } + + /* save iids and iccs for differential time coding in the next frame */ + hPsData->nEnvelopesLast = nEnvelopes; + hPsData->iidEnableLast = hPsData->iidEnable; + hPsData->iccEnableLast = hPsData->iccEnable; + hPsData->iidQuantModeLast = hPsData->iidQuantMode; + hPsData->iccQuantModeLast = hPsData->iccQuantMode; + for (i = 0; i < psBands; i++) { + hPsData->iidIdxLast[i] = hPsData->iidIdx[nEnvelopes - 1][i]; + hPsData->iccIdxLast[i] = hPsData->iccIdx[nEnvelopes - 1][i]; + } + } /* Envelope > 0 */ + + C_ALLOC_SCRATCH_END(pwrData, PS_PWR_DATA, 1) + + return error; +} diff --git a/fdk-aac/libSBRenc/src/ps_encode.h b/fdk-aac/libSBRenc/src/ps_encode.h new file mode 100644 index 0000000..4237a00 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_encode.h @@ -0,0 +1,185 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Neuendorf, N. Rettelbach, M. Multrus + + Description: PS Parameter extraction, encoding + +*******************************************************************************/ + +/*! + \file + \brief PS parameter extraction, encoding functions $Revision: 92790 $ +*/ + +#ifndef PS_ENCODE_H +#define PS_ENCODE_H + +#include "ps_const.h" +#include "ps_bitenc.h" + +#define IID_SCALE_FT (64.f) /* maxVal in Quant tab is +/- 50 */ +#define IID_SCALE 6 /* maxVal in Quant tab is +/- 50 */ +#define IID_MAXVAL (1 << IID_SCALE) + +#define PS_QUANT_SCALE_FT \ + (64.f) /* error smaller (64-25)/64 * 20 bands * 4 env -> QuantScale 64 */ +#define PS_QUANT_SCALE \ + 6 /* error smaller (64-25)/64 * 20 bands * 4 env -> QuantScale 6 bit */ + +#define QMF_GROUPS_LO_RES 12 +#define SUBQMF_GROUPS_LO_RES 10 +#define QMF_GROUPS_HI_RES 18 +#define SUBQMF_GROUPS_HI_RES 30 + +typedef struct T_PS_DATA { + INT iidEnable; + INT iidEnableLast; + INT iidQuantMode; + INT iidQuantModeLast; + INT iidDiffMode[PS_MAX_ENVELOPES]; + INT iidIdx[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iidIdxLast[PS_MAX_BANDS]; + + INT iccEnable; + INT iccEnableLast; + INT iccQuantMode; + INT iccQuantModeLast; + INT iccDiffMode[PS_MAX_ENVELOPES]; + INT iccIdx[PS_MAX_ENVELOPES][PS_MAX_BANDS]; + INT iccIdxLast[PS_MAX_BANDS]; + + INT nEnvelopesLast; + + INT headerCnt; + INT iidTimeCnt; + INT iccTimeCnt; + INT noEnvCnt; + +} PS_DATA, *HANDLE_PS_DATA; + +typedef struct T_PS_ENCODE { + PS_DATA psData; + + PS_BANDS psEncMode; + INT nQmfIidGroups; + INT nSubQmfIidGroups; + INT iidGroupBorders[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES + 1]; + INT subband2parameterIndex[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + UCHAR iidGroupWidthLd[QMF_GROUPS_HI_RES + SUBQMF_GROUPS_HI_RES]; + FIXP_DBL iidQuantErrorThreshold; + + UCHAR psBandNrgScale[PS_MAX_BANDS]; + +} PS_ENCODE; + +typedef struct T_PS_ENCODE *HANDLE_PS_ENCODE; + +FDK_PSENC_ERROR FDKsbrEnc_CreatePSEncode(HANDLE_PS_ENCODE *phPsEncode); + +FDK_PSENC_ERROR FDKsbrEnc_InitPSEncode(HANDLE_PS_ENCODE hPsEncode, + const PS_BANDS psEncMode, + const FIXP_DBL iidQuantErrorThreshold); + +FDK_PSENC_ERROR FDKsbrEnc_DestroyPSEncode(HANDLE_PS_ENCODE *phPsEncode); + +FDK_PSENC_ERROR FDKsbrEnc_PSEncode( + HANDLE_PS_ENCODE hPsEncode, HANDLE_PS_OUT hPsOut, UCHAR *dynBandScale, + UINT maxEnvelopes, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT frameSize, const INT sendHeader); + +#endif diff --git a/fdk-aac/libSBRenc/src/ps_main.cpp b/fdk-aac/libSBRenc/src/ps_main.cpp new file mode 100644 index 0000000..4d7a7a5 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_main.cpp @@ -0,0 +1,606 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): M. Multrus + + Description: PS Wrapper, Downmix + +*******************************************************************************/ + +#include "ps_main.h" + +/* Includes ******************************************************************/ +#include "ps_bitenc.h" +#include "sbrenc_ram.h" + +/*--------------- function declarations --------------------*/ +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale); + +/*------------- function definitions ----------------*/ +FDK_PSENC_ERROR PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo) { + FDK_PSENC_ERROR error = PSENC_OK; + HANDLE_PARAMETRIC_STEREO hParametricStereo = NULL; + + if (phParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int i; + + if (NULL == (hParametricStereo = GetRam_ParamStereo())) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + FDKmemclear(hParametricStereo, sizeof(PARAMETRIC_STEREO)); + + if (PSENC_OK != + (error = FDKsbrEnc_CreatePSEncode(&hParametricStereo->hPsEncode))) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + + for (i = 0; i < MAX_PS_CHANNELS; i++) { + if (FDKhybridAnalysisOpen( + &hParametricStereo->fdkHybAnaFilter[i], + hParametricStereo->__staticHybAnaStatesLF[i], + sizeof(hParametricStereo->__staticHybAnaStatesLF[i]), + hParametricStereo->__staticHybAnaStatesHF[i], + sizeof(hParametricStereo->__staticHybAnaStatesHF[i])) != 0) { + error = PSENC_MEMORY_ERROR; + goto bail; + } + } + } + +bail: + if (phParametricStereo != NULL) { + *phParametricStereo = hParametricStereo; /* return allocated handle */ + } + + if (error != PSENC_OK) { + PSEnc_Destroy(phParametricStereo); + } + return error; +} + +FDK_PSENC_ERROR PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, INT noQmfBands, UCHAR *dynamic_RAM) { + FDK_PSENC_ERROR error = PSENC_OK; + + if ((NULL == hParametricStereo) || (NULL == hPsEncConfig)) { + error = PSENC_INVALID_HANDLE; + } else { + int ch, i; + + hParametricStereo->initPS = 1; + hParametricStereo->noQmfSlots = noQmfSlots; + hParametricStereo->noQmfBands = noQmfBands; + + /* clear delay lines */ + FDKmemclear(hParametricStereo->qmfDelayLines, + sizeof(hParametricStereo->qmfDelayLines)); + + hParametricStereo->qmfDelayScale = FRACT_BITS - 1; + + /* create configuration for hybrid filter bank */ + for (ch = 0; ch < MAX_PS_CHANNELS; ch++) { + FDKhybridAnalysisInit(&hParametricStereo->fdkHybAnaFilter[ch], + THREE_TO_TEN, 64, 64, 1); + } /* ch */ + + FDKhybridSynthesisInit(&hParametricStereo->fdkHybSynFilter, THREE_TO_TEN, + 64, 64); + + /* determine average delay */ + hParametricStereo->psDelay = + (HYBRID_FILTER_DELAY * hParametricStereo->noQmfBands); + + if ((hPsEncConfig->maxEnvelopes < PSENC_NENV_1) || + (hPsEncConfig->maxEnvelopes > PSENC_NENV_MAX)) { + hPsEncConfig->maxEnvelopes = PSENC_NENV_DEFAULT; + } + hParametricStereo->maxEnvelopes = hPsEncConfig->maxEnvelopes; + + if (PSENC_OK != + (error = FDKsbrEnc_InitPSEncode( + hParametricStereo->hPsEncode, (PS_BANDS)hPsEncConfig->nStereoBands, + hPsEncConfig->iidQuantErrorThreshold))) { + goto bail; + } + + for (ch = 0; ch < MAX_PS_CHANNELS; ch++) { + FIXP_DBL *pDynReal = GetRam_Sbr_envRBuffer(ch, dynamic_RAM); + FIXP_DBL *pDynImag = GetRam_Sbr_envIBuffer(ch, dynamic_RAM); + + for (i = 0; i < HYBRID_FRAMESIZE; i++) { + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][0] = + &pDynReal[i * MAX_HYBRID_BANDS]; + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][ch][1] = + &pDynImag[i * MAX_HYBRID_BANDS]; + ; + } + + for (i = 0; i < HYBRID_READ_OFFSET; i++) { + hParametricStereo->pHybridData[i][ch][0] = + hParametricStereo->__staticHybridData[i][ch][0]; + hParametricStereo->pHybridData[i][ch][1] = + hParametricStereo->__staticHybridData[i][ch][1]; + } + } /* ch */ + + /* clear static hybrid buffer */ + FDKmemclear(hParametricStereo->__staticHybridData, + sizeof(hParametricStereo->__staticHybridData)); + + /* clear bs buffer */ + FDKmemclear(hParametricStereo->psOut, sizeof(hParametricStereo->psOut)); + + hParametricStereo->psOut[0].enablePSHeader = + 1; /* write ps header in first frame */ + + /* clear scaling buffer */ + FDKmemclear(hParametricStereo->dynBandScale, sizeof(UCHAR) * PS_MAX_BANDS); + FDKmemclear(hParametricStereo->maxBandValue, + sizeof(FIXP_DBL) * PS_MAX_BANDS); + + } /* valid handle */ +bail: + return error; +} + +FDK_PSENC_ERROR PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (NULL != phParametricStereo) { + HANDLE_PARAMETRIC_STEREO hParametricStereo = *phParametricStereo; + if (hParametricStereo != NULL) { + FDKsbrEnc_DestroyPSEncode(&hParametricStereo->hPsEncode); + FreeRam_ParamStereo(phParametricStereo); + } + } + + return error; +} + +static FDK_PSENC_ERROR ExtractPSParameters( + HANDLE_PARAMETRIC_STEREO hParametricStereo, const int sendHeader, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + /* call ps encode function */ + if (hParametricStereo->initPS) { + hParametricStereo->psOut[1] = hParametricStereo->psOut[0]; + } + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + + if (PSENC_OK != + (error = FDKsbrEnc_PSEncode( + hParametricStereo->hPsEncode, &hParametricStereo->psOut[1], + hParametricStereo->dynBandScale, hParametricStereo->maxEnvelopes, + hybridData, hParametricStereo->noQmfSlots, sendHeader))) { + goto bail; + } + + if (hParametricStereo->initPS) { + hParametricStereo->psOut[0] = hParametricStereo->psOut[1]; + hParametricStereo->initPS = 0; + } + } +bail: + return error; +} + +static FDK_PSENC_ERROR DownmixPSQmfData( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, FIXP_DBL **RESTRICT mixRealQmfData, + FIXP_DBL **RESTRICT mixImagQmfData, INT_PCM *downsampledOutSignal, + const UINT downsampledOutSignalBufSize, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + const INT noQmfSlots, const INT psQmfScale[MAX_PS_CHANNELS], + SCHAR *qmfScale) { + FDK_PSENC_ERROR error = PSENC_OK; + + if (hParametricStereo == NULL) { + error = PSENC_INVALID_HANDLE; + } else { + int n, k; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 2 * 64) + + /* define scalings */ + int dynQmfScale = fixMax( + 0, hParametricStereo->dmxScale - + 1); /* scale one bit more for addition of left and right */ + int downmixScale = psQmfScale[0] - dynQmfScale; + const FIXP_DBL maxStereoScaleFactor = MAXVAL_DBL; /* 2.f/2.f */ + + for (n = 0; n < noQmfSlots; n++) { + FIXP_DBL tmpHybrid[2][MAX_HYBRID_BANDS]; + + for (k = 0; k < 71; k++) { + int dynScale, sc; /* scaling */ + FIXP_DBL tmpLeftReal, tmpRightReal, tmpLeftImag, tmpRightImag; + FIXP_DBL tmpScaleFactor, stereoScaleFactor; + + tmpLeftReal = hybridData[n][0][0][k]; + tmpLeftImag = hybridData[n][0][1][k]; + tmpRightReal = hybridData[n][1][0][k]; + tmpRightImag = hybridData[n][1][1][k]; + + sc = fixMax( + 0, CntLeadingZeros(fixMax( + fixMax(fixp_abs(tmpLeftReal), fixp_abs(tmpLeftImag)), + fixMax(fixp_abs(tmpRightReal), fixp_abs(tmpRightImag)))) - + 2); + + tmpLeftReal <<= sc; + tmpLeftImag <<= sc; + tmpRightReal <<= sc; + tmpRightImag <<= sc; + dynScale = fixMin(sc - dynQmfScale, DFRACT_BITS - 1); + + /* calc stereo scale factor to avoid loss of energy in bands */ + /* stereo scale factor = min(2.0f, sqrt( (abs(l(k, n)^2 + abs(r(k, n)^2 + * )))/(0.5f*abs(l(k, n) + r(k, n))) )) */ + stereoScaleFactor = fPow2Div2(tmpLeftReal) + fPow2Div2(tmpLeftImag) + + fPow2Div2(tmpRightReal) + fPow2Div2(tmpRightImag); + + /* might be that tmpScaleFactor becomes negative, so fabs(.) */ + tmpScaleFactor = + fixp_abs(stereoScaleFactor + fMult(tmpLeftReal, tmpRightReal) + + fMult(tmpLeftImag, tmpRightImag)); + + /* min(2.0f, sqrt(stereoScaleFactor/(0.5f*tmpScaleFactor))) */ + if ((stereoScaleFactor >> 1) < + fMult(maxStereoScaleFactor, tmpScaleFactor)) { + int sc_num = CountLeadingBits(stereoScaleFactor); + int sc_denum = CountLeadingBits(tmpScaleFactor); + sc = -(sc_num - sc_denum); + + tmpScaleFactor = schur_div((stereoScaleFactor << (sc_num)) >> 1, + tmpScaleFactor << sc_denum, 16); + + /* prevent odd scaling for next sqrt calculation */ + if (sc & 0x1) { + sc++; + tmpScaleFactor >>= 1; + } + stereoScaleFactor = sqrtFixp(tmpScaleFactor); + stereoScaleFactor <<= (sc >> 1); + } else { + stereoScaleFactor = maxStereoScaleFactor; + } + + /* write data to hybrid output */ + tmpHybrid[0][k] = fMultDiv2(stereoScaleFactor, + (FIXP_DBL)(tmpLeftReal + tmpRightReal)) >> + dynScale; + tmpHybrid[1][k] = fMultDiv2(stereoScaleFactor, + (FIXP_DBL)(tmpLeftImag + tmpRightImag)) >> + dynScale; + + } /* hybrid bands - k */ + + FDKhybridSynthesisApply(&hParametricStereo->fdkHybSynFilter, tmpHybrid[0], + tmpHybrid[1], mixRealQmfData[n], + mixImagQmfData[n]); + + qmfSynthesisFilteringSlot( + sbrSynthQmf, mixRealQmfData[n], mixImagQmfData[n], downmixScale - 7, + downmixScale - 7, + downsampledOutSignal + (n * sbrSynthQmf->no_channels), 1, + pWorkBuffer); + + } /* slots */ + + *qmfScale = -downmixScale + 7; + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 2 * 64) + + { + const INT noQmfSlots2 = hParametricStereo->noQmfSlots >> 1; + const int noQmfBands = hParametricStereo->noQmfBands; + + INT scale, i, j, slotOffset; + + FIXP_DBL tmp[2][64]; + + for (i = 0; i < noQmfSlots2; i++) { + FDKmemcpy(tmp[0], hParametricStereo->qmfDelayLines[0][i], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(tmp[1], hParametricStereo->qmfDelayLines[1][i], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(hParametricStereo->qmfDelayLines[0][i], + mixRealQmfData[i + noQmfSlots2], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(hParametricStereo->qmfDelayLines[1][i], + mixImagQmfData[i + noQmfSlots2], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(mixRealQmfData[i + noQmfSlots2], mixRealQmfData[i], + noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(mixImagQmfData[i + noQmfSlots2], mixImagQmfData[i], + noQmfBands * sizeof(FIXP_DBL)); + + FDKmemcpy(mixRealQmfData[i], tmp[0], noQmfBands * sizeof(FIXP_DBL)); + FDKmemcpy(mixImagQmfData[i], tmp[1], noQmfBands * sizeof(FIXP_DBL)); + } + + if (hParametricStereo->qmfDelayScale > *qmfScale) { + scale = hParametricStereo->qmfDelayScale - *qmfScale; + slotOffset = 0; + } else { + scale = *qmfScale - hParametricStereo->qmfDelayScale; + slotOffset = noQmfSlots2; + } + + for (i = 0; i < noQmfSlots2; i++) { + for (j = 0; j < noQmfBands; j++) { + mixRealQmfData[i + slotOffset][j] >>= scale; + mixImagQmfData[i + slotOffset][j] >>= scale; + } + } + + scale = *qmfScale; + *qmfScale = fMin(*qmfScale, hParametricStereo->qmfDelayScale); + hParametricStereo->qmfDelayScale = scale; + } + + } /* valid handle */ + + return error; +} + +INT FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream) { + return ( + (hParametricStereo != NULL) + ? FDKsbrEnc_WritePSBitstream(&hParametricStereo->psOut[0], hBitstream) + : 0); +} + +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, INT_PCM *samples[2], + UINT samplesBufSize, QMF_FILTER_BANK **hQmfAnalysis, + FIXP_DBL **RESTRICT downmixedRealQmfData, + FIXP_DBL **RESTRICT downmixedImagQmfData, INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, SCHAR *qmfScale, const int sendHeader) { + FDK_PSENC_ERROR error = PSENC_OK; + INT psQmfScale[MAX_PS_CHANNELS] = {0}; + int psCh, i; + C_AALLOC_SCRATCH_START(pWorkBuffer, FIXP_DBL, 4 * 64) + + for (psCh = 0; psCh < MAX_PS_CHANNELS; psCh++) { + for (i = 0; i < hQmfAnalysis[psCh]->no_col; i++) { + qmfAnalysisFilteringSlot( + hQmfAnalysis[psCh], &pWorkBuffer[2 * 64], /* qmfReal[64] */ + &pWorkBuffer[3 * 64], /* qmfImag[64] */ + samples[psCh] + i * hQmfAnalysis[psCh]->no_channels, 1, + &pWorkBuffer[0 * 64] /* qmf workbuffer 2*64 */ + ); + + FDKhybridAnalysisApply( + &hParametricStereo->fdkHybAnaFilter[psCh], + &pWorkBuffer[2 * 64], /* qmfReal[64] */ + &pWorkBuffer[3 * 64], /* qmfImag[64] */ + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][0], + hParametricStereo->pHybridData[i + HYBRID_READ_OFFSET][psCh][1]); + + } /* no_col loop i */ + + psQmfScale[psCh] = hQmfAnalysis[psCh]->outScalefactor; + + } /* for psCh */ + + C_AALLOC_SCRATCH_END(pWorkBuffer, FIXP_DBL, 4 * 64) + + /* find best scaling in new QMF and Hybrid data */ + psFindBestScaling( + hParametricStereo, &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->dynBandScale, hParametricStereo->maxBandValue, + &hParametricStereo->dmxScale); + + /* extract the ps parameters */ + if (PSENC_OK != + (error = ExtractPSParameters(hParametricStereo, sendHeader, + &hParametricStereo->pHybridData[0]))) { + goto bail; + } + + /* save hybrid date for next frame */ + for (i = 0; i < HYBRID_READ_OFFSET; i++) { + FDKmemcpy( + hParametricStereo->pHybridData[i][0][0], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][0], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, real */ + FDKmemcpy( + hParametricStereo->pHybridData[i][0][1], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][0][1], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* left, imag */ + FDKmemcpy( + hParametricStereo->pHybridData[i][1][0], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][0], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, real */ + FDKmemcpy( + hParametricStereo->pHybridData[i][1][1], + hParametricStereo->pHybridData[hParametricStereo->noQmfSlots + i][1][1], + MAX_HYBRID_BANDS * sizeof(FIXP_DBL)); /* right, imag */ + } + + /* downmix and hybrid synthesis */ + if (PSENC_OK != + (error = DownmixPSQmfData( + hParametricStereo, sbrSynthQmf, downmixedRealQmfData, + downmixedImagQmfData, downsampledOutSignal, samplesBufSize, + &hParametricStereo->pHybridData[HYBRID_READ_OFFSET], + hParametricStereo->noQmfSlots, psQmfScale, qmfScale))) { + goto bail; + } + +bail: + + return error; +} + +static void psFindBestScaling( + HANDLE_PARAMETRIC_STEREO hParametricStereo, + FIXP_DBL *hybridData[HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2], + UCHAR *dynBandScale, FIXP_DBL *maxBandValue, SCHAR *dmxScale) { + HANDLE_PS_ENCODE hPsEncode = hParametricStereo->hPsEncode; + + INT group, bin, col, band; + const INT frameSize = hParametricStereo->noQmfSlots; + const INT psBands = (INT)hPsEncode->psEncMode; + const INT nIidGroups = hPsEncode->nQmfIidGroups + hPsEncode->nSubQmfIidGroups; + + /* group wise scaling */ + FIXP_DBL maxVal[2][PS_MAX_BANDS]; + FIXP_DBL maxValue = FL2FXCONST_DBL(0.f); + + FDKmemclear(maxVal, sizeof(maxVal)); + + /* start with hybrid data */ + for (group = 0; group < nIidGroups; group++) { + /* Translate group to bin */ + bin = hPsEncode->subband2parameterIndex[group]; + + /* Translate from 20 bins to 10 bins */ + if (hPsEncode->psEncMode == PS_BANDS_COARSE) { + bin >>= 1; + } + + /* QMF downmix scaling */ + for (col = 0; col < frameSize; col++) { + int i, section = (col < frameSize - HYBRID_READ_OFFSET) ? 0 : 1; + FIXP_DBL tmp = maxVal[section][bin]; + for (i = hPsEncode->iidGroupBorders[group]; + i < hPsEncode->iidGroupBorders[group + 1]; i++) { + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][0][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][0][1][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][0][i])); + tmp = fixMax(tmp, (FIXP_DBL)fixp_abs(hybridData[col][1][1][i])); + } + maxVal[section][bin] = tmp; + } + } /* nIidGroups */ + + /* convert maxSpec to maxScaling, find scaling space */ + for (band = 0; band < psBands; band++) { +#ifndef MULT_16x16 + dynBandScale[band] = + CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band])); +#else + dynBandScale[band] = fixMax( + 0, CountLeadingBits(fixMax(maxVal[0][band], maxBandValue[band])) - + FRACT_BITS); +#endif + maxValue = fixMax(maxValue, fixMax(maxVal[0][band], maxVal[1][band])); + maxBandValue[band] = fixMax(maxVal[0][band], maxVal[1][band]); + } + + /* calculate maximal scaling for QMF downmix */ +#ifndef MULT_16x16 + *dmxScale = fixMin(DFRACT_BITS, CountLeadingBits(maxValue)); +#else + *dmxScale = fixMax(0, fixMin(FRACT_BITS, CountLeadingBits((maxValue)))); +#endif +} diff --git a/fdk-aac/libSBRenc/src/ps_main.h b/fdk-aac/libSBRenc/src/ps_main.h new file mode 100644 index 0000000..88b2993 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ps_main.h @@ -0,0 +1,270 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Markus Multrus + + Description: PS Wrapper, Downmix header file + +*******************************************************************************/ + +#ifndef PS_MAIN_H +#define PS_MAIN_H + +/* Includes ******************************************************************/ + +#include "sbr_def.h" +#include "qmf.h" +#include "ps_encode.h" +#include "FDK_bitstream.h" +#include "FDK_hybrid.h" + +/* Data Types ****************************************************************/ +typedef enum { + PSENC_STEREO_BANDS_INVALID = 0, + PSENC_STEREO_BANDS_10 = 10, + PSENC_STEREO_BANDS_20 = 20 + +} PSENC_STEREO_BANDS_CONFIG; + +typedef enum { + PSENC_NENV_1 = 1, + PSENC_NENV_2 = 2, + PSENC_NENV_4 = 4, + PSENC_NENV_DEFAULT = PSENC_NENV_2, + PSENC_NENV_MAX = PSENC_NENV_4 + +} PSENC_NENV_CONFIG; + +typedef struct { + UINT bitrateFrom; /* inclusive */ + UINT bitrateTo; /* exclusive */ + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG nEnvelopes; + LONG iidQuantErrorThreshold; /* quantization threshold to switch between + coarse and fine iid quantization */ + +} psTuningTable_t; + +/* Function / Class Declarations *********************************************/ + +typedef struct T_PARAMETRIC_STEREO { + HANDLE_PS_ENCODE hPsEncode; + PS_OUT psOut[2]; + + FIXP_DBL __staticHybridData[HYBRID_READ_OFFSET][MAX_PS_CHANNELS][2] + [MAX_HYBRID_BANDS]; + FIXP_DBL + *pHybridData[HYBRID_READ_OFFSET + HYBRID_FRAMESIZE][MAX_PS_CHANNELS][2]; + + FIXP_DBL qmfDelayLines[2][32 >> 1][64]; + int qmfDelayScale; + + INT psDelay; + UINT maxEnvelopes; + UCHAR dynBandScale[PS_MAX_BANDS]; + FIXP_DBL maxBandValue[PS_MAX_BANDS]; + SCHAR dmxScale; + INT initPS; + INT noQmfSlots; + INT noQmfBands; + + FIXP_DBL __staticHybAnaStatesLF[MAX_PS_CHANNELS][2 * HYBRID_FILTER_LENGTH * + HYBRID_MAX_QMF_BANDS]; + FIXP_DBL __staticHybAnaStatesHF[MAX_PS_CHANNELS][2 * HYBRID_FILTER_DELAY * + (64 - HYBRID_MAX_QMF_BANDS)]; + FDK_ANA_HYB_FILTER fdkHybAnaFilter[MAX_PS_CHANNELS]; + FDK_SYN_HYB_FILTER fdkHybSynFilter; + +} PARAMETRIC_STEREO; + +typedef struct T_PSENC_CONFIG { + INT frameSize; + INT qmfFilterMode; + INT sbrPsDelay; + PSENC_STEREO_BANDS_CONFIG nStereoBands; + PSENC_NENV_CONFIG maxEnvelopes; + FIXP_DBL iidQuantErrorThreshold; + +} PSENC_CONFIG, *HANDLE_PSENC_CONFIG; + +typedef struct T_PARAMETRIC_STEREO *HANDLE_PARAMETRIC_STEREO; + +/** + * \brief Create a parametric stereo encoder instance. + * + * \param phParametricStereo A pointer to a parametric stereo handle to be + * allocated. Initialized on return. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_MEMORY_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Create(HANDLE_PARAMETRIC_STEREO *phParametricStereo); + +/** + * \brief Initialize a parametric stereo encoder instance. + * + * \param hParametricStereo Meta Data handle. + * \param hPsEncConfig Filled parametric stereo configuration + * structure. + * \param noQmfSlots Number of slots within one audio frame. + * \param noQmfBands Number of QMF bands. + * \param dynamic_RAM Pointer to preallocated workbuffer. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_INIT_ERROR, on failure. + */ +FDK_PSENC_ERROR PSEnc_Init(HANDLE_PARAMETRIC_STEREO hParametricStereo, + const HANDLE_PSENC_CONFIG hPsEncConfig, + INT noQmfSlots, INT noQmfBands, UCHAR *dynamic_RAM); + +/** + * \brief Destroy parametric stereo encoder instance. + * + * Deallocate instance and free whole memory. + * + * \param phParametricStereo Pointer to the parametric stereo handle to be + * deallocated. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, on failure. + */ +FDK_PSENC_ERROR PSEnc_Destroy(HANDLE_PARAMETRIC_STEREO *phParametricStereo); + +/** + * \brief Apply parametric stereo processing. + * + * \param hParametricStereo Meta Data handle. + * \param samples Pointer to 2 channel audio input signal. + * \param timeInStride, Stride factor of input buffer. + * \param hQmfAnalysis, Pointer to QMF analysis filterbanks. + * \param downmixedRealQmfData Pointer to real QMF buffer to be written to. + * \param downmixedImagQmfData Pointer to imag QMF buffer to be written to. + * \param downsampledOutSignal Pointer to buffer where to write downmixed + * timesignal. + * \param sbrSynthQmf Pointer to QMF synthesis filterbank. + * \param qmfScale Return scaling factor of the qmf data. + * \param sendHeader Signal whether to write header data. + * + * \return + * - PSENC_OK, on succes. + * - PSENC_INVALID_HANDLE, PSENC_ENCODE_ERROR, on failure. + */ +FDK_PSENC_ERROR FDKsbrEnc_PSEnc_ParametricStereoProcessing( + HANDLE_PARAMETRIC_STEREO hParametricStereo, INT_PCM *samples[2], + UINT timeInStride, QMF_FILTER_BANK **hQmfAnalysis, + FIXP_DBL **RESTRICT downmixedRealQmfData, + FIXP_DBL **RESTRICT downmixedImagQmfData, INT_PCM *downsampledOutSignal, + HANDLE_QMF_FILTER_BANK sbrSynthQmf, SCHAR *qmfScale, const int sendHeader); + +/** + * \brief Write parametric stereo bitstream. + * + * Write ps_data() element to bitstream and return number of written bits. + * Returns number of written bits only, if hBitstream == NULL. + * + * \param hParametricStereo Meta Data handle. + * \param hBitstream Bitstream buffer handle. + * + * \return + * - number of written bits. + */ +INT FDKsbrEnc_PSEnc_WritePSData(HANDLE_PARAMETRIC_STEREO hParametricStereo, + HANDLE_FDK_BITSTREAM hBitstream); + +#endif /* PS_MAIN_H */ diff --git a/fdk-aac/libSBRenc/src/resampler.cpp b/fdk-aac/libSBRenc/src/resampler.cpp new file mode 100644 index 0000000..b1781a7 --- /dev/null +++ b/fdk-aac/libSBRenc/src/resampler.cpp @@ -0,0 +1,444 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief FDK resampler tool box:$Revision: 91655 $ + \author M. Werner +*/ + +#include "resampler.h" + +#include "genericStds.h" + +/**************************************************************************/ +/* BIQUAD Filter Specifications */ +/**************************************************************************/ + +#define B1 0 +#define B2 1 +#define A1 2 +#define A2 3 + +#define BQC(x) FL2FXCONST_SGL(x / 2) + +struct FILTER_PARAM { + const FIXP_SGL *coeffa; /*! SOS matrix One row/section. Scaled using BQC(). + Order of coefficients: B1,B2,A1,A2. B0=A0=1.0 */ + FIXP_DBL g; /*! overall gain */ + int Wc; /*! normalized passband bandwidth at input samplerate * 1000 */ + int noCoeffs; /*! number of filter coeffs */ + int delay; /*! delay in samples at input samplerate */ +}; + +#define BIQUAD_COEFSTEP 4 + +/** + *\brief Low Pass + Wc = 0,5, order 30, Stop Band -96dB. Wc criteria is "almost 0dB passband", not + the usual -3db gain point. [b,a]=cheby2(30,96,0.505) [sos,g]=tf2sos(b,a) + bandwidth 0.48 + */ +static const FIXP_SGL sos48[] = { + BQC(1.98941075681938), BQC(0.999999996890811), + BQC(0.863264527201963), BQC(0.189553799960663), + BQC(1.90733804822445), BQC(1.00000001736189), + BQC(0.836321575841691), BQC(0.203505809266564), + BQC(1.75616665495325), BQC(0.999999946079721), + BQC(0.784699225121588), BQC(0.230471265506986), + BQC(1.55727745512726), BQC(1.00000011737815), + BQC(0.712515423588351), BQC(0.268752723900498), + BQC(1.33407591943643), BQC(0.999999795953228), + BQC(0.625059117330989), BQC(0.316194685288965), + BQC(1.10689898412458), BQC(1.00000035057114), + BQC(0.52803514366398), BQC(0.370517843224669), + BQC(0.89060371078454), BQC(0.999999343962822), + BQC(0.426920462165257), BQC(0.429608200207746), + BQC(0.694438261209433), BQC(1.0000008629792), + BQC(0.326530699561716), BQC(0.491714450654174), + BQC(0.523237800935322), BQC(1.00000101349782), + BQC(0.230829556274851), BQC(0.555559034843281), + BQC(0.378631165929563), BQC(0.99998986482665), + BQC(0.142906422036095), BQC(0.620338874442411), + BQC(0.260786911308437), BQC(1.00003261460178), + BQC(0.0651008576256505), BQC(0.685759923926262), + BQC(0.168409429188098), BQC(0.999933049695828), + BQC(-0.000790067789975562), BQC(0.751905896602325), + BQC(0.100724533818628), BQC(1.00009472669872), + BQC(-0.0533772830257041), BQC(0.81930744384525), + BQC(0.0561434357867363), BQC(0.999911636304276), + BQC(-0.0913550299236405), BQC(0.88883625875915), + BQC(0.0341680678662057), BQC(1.00003667508676), + BQC(-0.113405185536697), BQC(0.961756638268446)}; + +static const FIXP_DBL g48 = + FL2FXCONST_DBL(0.002712866530047) - (FIXP_DBL)0x8000; + +static const struct FILTER_PARAM param_set48 = { + sos48, g48, 480, 15, 4 /* LF 2 */ +}; + +/** + *\brief Low Pass + Wc = 0,5, order 24, Stop Band -96dB. Wc criteria is "almost 0dB passband", not + the usual -3db gain point. [b,a]=cheby2(24,96,0.5) [sos,g]=tf2sos(b,a) + bandwidth 0.45 + */ +static const FIXP_SGL sos45[] = { + BQC(1.982962601444), BQC(1.00000000007504), BQC(0.646113303737836), + BQC(0.10851149979981), BQC(1.85334094281111), BQC(0.999999999677192), + BQC(0.612073220102006), BQC(0.130022141698044), BQC(1.62541051415425), + BQC(1.00000000080398), BQC(0.547879702855959), BQC(0.171165825133192), + BQC(1.34554656923247), BQC(0.9999999980169), BQC(0.460373914508491), + BQC(0.228677463376354), BQC(1.05656568503116), BQC(1.00000000569363), + BQC(0.357891894038287), BQC(0.298676843912185), BQC(0.787967587877312), + BQC(0.999999984415017), BQC(0.248826893211877), BQC(0.377441803512978), + BQC(0.555480971120497), BQC(1.00000003583307), BQC(0.140614263345315), + BQC(0.461979302213679), BQC(0.364986207070964), BQC(0.999999932084303), + BQC(0.0392669446074516), BQC(0.55033451180825), BQC(0.216827267631558), + BQC(1.00000010534682), BQC(-0.0506232228865103), BQC(0.641691581560946), + BQC(0.108951672277119), BQC(0.999999871167516), BQC(-0.125584840183225), + BQC(0.736367748771803), BQC(0.0387988607229035), BQC(1.00000011205574), + BQC(-0.182814849097974), BQC(0.835802108714964), BQC(0.0042866175809225), + BQC(0.999999954830813), BQC(-0.21965740617151), BQC(0.942623047782363)}; + +static const FIXP_DBL g45 = + FL2FXCONST_DBL(0.00242743980909524) - (FIXP_DBL)0x8000; + +static const struct FILTER_PARAM param_set45 = { + sos45, g45, 450, 12, 4 /* LF 2 */ +}; + +/* + Created by Octave 2.1.73, Mon Oct 13 17:31:32 2008 CEST + Wc = 0,5, order 16, Stop Band -96dB damping. + [b,a]=cheby2(16,96,0.5) + [sos,g]=tf2sos(b,a) + bandwidth = 0.41 + */ + +static const FIXP_SGL sos41[] = { + BQC(1.96193625292), BQC(0.999999999999964), BQC(0.169266178786789), + BQC(0.0128823300475907), BQC(1.68913437662092), BQC(1.00000000000053), + BQC(0.124751503206552), BQC(0.0537472273950989), BQC(1.27274692366017), + BQC(0.999999999995674), BQC(0.0433108625178357), BQC(0.131015753236317), + BQC(0.85214175088395), BQC(1.00000000001813), BQC(-0.0625658152550408), + BQC(0.237763778993806), BQC(0.503841579939009), BQC(0.999999999953223), + BQC(-0.179176128722865), BQC(0.367475236424474), BQC(0.249990711986162), + BQC(1.00000000007952), BQC(-0.294425165824676), BQC(0.516594857170212), + BQC(0.087971668680286), BQC(0.999999999915528), BQC(-0.398956566777928), + BQC(0.686417767801123), BQC(0.00965373325350294), BQC(1.00000000003744), + BQC(-0.48579173764817), BQC(0.884931534239068)}; + +static const FIXP_DBL g41 = FL2FXCONST_DBL(0.00155956951169248); + +static const struct FILTER_PARAM param_set41 = { + sos41, g41, 410, 8, 5 /* LF 3 */ +}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 17:55:33 2008 CEST + Wc = 0,5, order 12, Stop Band -96dB damping. + [b,a]=cheby2(12,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos35[] = { + BQC(1.93299325235762), BQC(0.999999999999985), BQC(-0.140733187246596), + BQC(0.0124139497836062), BQC(1.4890416764109), BQC(1.00000000000011), + BQC(-0.198215402588504), BQC(0.0746730616584138), BQC(0.918450161309795), + BQC(0.999999999999619), BQC(-0.30133912791941), BQC(0.192276468839529), + BQC(0.454877024246818), BQC(1.00000000000086), BQC(-0.432337328809815), + BQC(0.356852933642815), BQC(0.158017147118507), BQC(0.999999999998876), + BQC(-0.574817494249777), BQC(0.566380436970833), BQC(0.0171834649478749), + BQC(1.00000000000055), BQC(-0.718581178041165), BQC(0.83367484487889)}; + +static const FIXP_DBL g35 = FL2FXCONST_DBL(0.00162580994125131); + +static const struct FILTER_PARAM param_set35 = {sos35, g35, 350, 6, 4}; + +/* + # Created by Octave 2.1.73, Mon Oct 13 18:15:38 2008 CEST + Wc = 0,5, order 8, Stop Band -96dB damping. + [b,a]=cheby2(8,96,0.5); + [sos,g]=tf2sos(b,a) +*/ +static const FIXP_SGL sos25[] = { + BQC(1.85334094301225), BQC(1.0), + BQC(-0.702127214212663), BQC(0.132452403998767), + BQC(1.056565682167), BQC(0.999999999999997), + BQC(-0.789503667880785), BQC(0.236328693569128), + BQC(0.364986307455489), BQC(0.999999999999996), + BQC(-0.955191189843375), BQC(0.442966457936379), + BQC(0.0387985751642125), BQC(1.0), + BQC(-1.19817786088084), BQC(0.770493895456328)}; + +static const FIXP_DBL g25 = FL2FXCONST_DBL(0.000945182835294559); + +static const struct FILTER_PARAM param_set25 = {sos25, g25, 250, 4, 5}; + +/* Must be sorted in descending order */ +static const struct FILTER_PARAM *const filter_paramSet[] = { + ¶m_set48, ¶m_set45, ¶m_set41, ¶m_set35, ¶m_set25}; + +/**************************************************************************/ +/* Resampler Functions */ +/**************************************************************************/ + +/*! + \brief Reset downsampler instance and clear delay lines + + \return success of operation +*/ + +INT FDKaacEnc_InitDownsampler( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + int Wc, /*!< normalized cutoff freq * 1000* */ + int ratio) /*!< downsampler ratio */ + +{ + UINT i; + const struct FILTER_PARAM *currentSet = NULL; + + FDKmemclear(DownSampler->downFilter.states, + sizeof(DownSampler->downFilter.states)); + DownSampler->downFilter.ptr = 0; + + /* + find applicable parameter set + */ + currentSet = filter_paramSet[0]; + for (i = 1; i < sizeof(filter_paramSet) / sizeof(struct FILTER_PARAM *); + i++) { + if (filter_paramSet[i]->Wc <= Wc) { + break; + } + currentSet = filter_paramSet[i]; + } + + DownSampler->downFilter.coeffa = currentSet->coeffa; + + DownSampler->downFilter.gain = currentSet->g; + FDK_ASSERT(currentSet->noCoeffs <= MAXNR_SECTIONS * 2); + + DownSampler->downFilter.noCoeffs = currentSet->noCoeffs; + DownSampler->delay = currentSet->delay; + DownSampler->downFilter.Wc = currentSet->Wc; + + DownSampler->ratio = ratio; + DownSampler->pending = ratio - 1; + return (1); +} + +/*! + \brief faster simple folding operation + Filter: + H(z) = A(z)/B(z) + with + A(z) = a[0]*z^0 + a[1]*z^1 + a[2]*z^2 ... a[n]*z^n + + \return filtered value +*/ + +static inline INT_PCM AdvanceFilter( + LP_FILTER *downFilter, /*!< pointer to iir filter instance */ + INT_PCM *pInput, /*!< input of filter */ + int downRatio) { + INT_PCM output; + int i, n; + +#define BIQUAD_SCALE 12 + + FIXP_DBL y = FL2FXCONST_DBL(0.0f); + FIXP_DBL input; + + for (n = 0; n < downRatio; n++) { + FIXP_BQS(*states)[2] = downFilter->states; + const FIXP_SGL *coeff = downFilter->coeffa; + int s1, s2; + + s1 = downFilter->ptr; + s2 = s1 ^ 1; + +#if (SAMPLE_BITS == 16) + input = ((FIXP_DBL)pInput[n]) << (DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE); +#elif (SAMPLE_BITS == 32) + input = pInput[n] >> BIQUAD_SCALE; +#else +#error NOT IMPLEMENTED +#endif + + FIXP_BQS state1, state2, state1b, state2b; + + state1 = states[0][s1]; + state2 = states[0][s2]; + + /* Loop over sections */ + for (i = 0; i < downFilter->noCoeffs; i++) { + FIXP_DBL state0; + + /* Load merged states (from next section) */ + state1b = states[i + 1][s1]; + state2b = states[i + 1][s2]; + + state0 = input + fMult(state1, coeff[B1]) + fMult(state2, coeff[B2]); + y = state0 - fMult(state1b, coeff[A1]) - fMult(state2b, coeff[A2]); + + /* Store new feed forward merge state */ + states[i + 1][s2] = y << 1; + /* Store new feed backward state */ + states[i][s2] = input << 1; + + /* Feedback output to next section. */ + input = y; + + /* Transfer merged states */ + state1 = state1b; + state2 = state2b; + + /* Step to next coef set */ + coeff += BIQUAD_COEFSTEP; + } + downFilter->ptr ^= 1; + } + /* Apply global gain */ + y = fMult(y, downFilter->gain); + + /* Apply final gain/scaling to output */ +#if (SAMPLE_BITS == 16) + output = (INT_PCM)SATURATE_RIGHT_SHIFT( + y + (FIXP_DBL)(1 << (DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE - 1)), + DFRACT_BITS - SAMPLE_BITS - BIQUAD_SCALE, SAMPLE_BITS); + // output = (INT_PCM) SATURATE_RIGHT_SHIFT(y, + // DFRACT_BITS-SAMPLE_BITS-BIQUAD_SCALE, SAMPLE_BITS); +#else + output = SATURATE_LEFT_SHIFT(y, BIQUAD_SCALE, SAMPLE_BITS); +#endif + + return output; +} + +/*! + \brief FDKaacEnc_Downsample numInSamples of type INT_PCM + Returns number of output samples in numOutSamples + + \return success of operation +*/ + +INT FDKaacEnc_Downsample( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples /*!< pointer tp number of output samples */ +) { + INT i; + *numOutSamples = 0; + + for (i = 0; i < numInSamples; i += DownSampler->ratio) { + *outSamples = AdvanceFilter(&(DownSampler->downFilter), &inSamples[i], + DownSampler->ratio); + outSamples++; + } + *numOutSamples = numInSamples / DownSampler->ratio; + + return 0; +} diff --git a/fdk-aac/libSBRenc/src/resampler.h b/fdk-aac/libSBRenc/src/resampler.h new file mode 100644 index 0000000..7aa1cae --- /dev/null +++ b/fdk-aac/libSBRenc/src/resampler.h @@ -0,0 +1,159 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#ifndef RESAMPLER_H +#define RESAMPLER_H +/*! + \file + \brief Fixed Point Resampler Tool Box $Revision: 92790 $ +*/ + +#include "common_fix.h" + +/**************************************************************************/ +/* BIQUAD Filter Structure */ +/**************************************************************************/ + +#define MAXNR_SECTIONS (15) + +typedef FIXP_DBL FIXP_BQS; + +typedef struct { + FIXP_BQS states[MAXNR_SECTIONS + 1][2]; /*! state buffer */ + const FIXP_SGL *coeffa; /*! pointer to filter coeffs */ + FIXP_DBL gain; /*! overall gain factor */ + int Wc; /*! normalized cutoff freq * 1000 */ + int noCoeffs; /*! number of filter coeffs sets */ + int ptr; /*! index to rinbuffers */ +} LP_FILTER; + +/**************************************************************************/ +/* Downsampler Structure */ +/**************************************************************************/ + +typedef struct { + LP_FILTER downFilter; /*! filter instance */ + int ratio; /*! downsampling ration */ + int delay; /*! downsampling delay (source fs) */ + int pending; /*! number of pending output samples */ +} DOWNSAMPLER; + +/** + * \brief Initialized a given downsampler structure. + */ +INT FDKaacEnc_InitDownsampler( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT Wc, /*!< normalized cutoff freq * 1000 */ + INT ratio); /*!< downsampler ratio */ + +/** + * \brief Downsample a set of audio samples. numInSamples must be at least equal + * to the downsampler ratio. + */ +INT FDKaacEnc_Downsample( + DOWNSAMPLER *DownSampler, /*!< pointer to downsampler instance */ + INT_PCM *inSamples, /*!< pointer to input samples */ + INT numInSamples, /*!< number of input samples */ + INT_PCM *outSamples, /*!< pointer to output samples */ + INT *numOutSamples); /*!< pointer tp number of output samples */ + +#endif /* RESAMPLER_H */ diff --git a/fdk-aac/libSBRenc/src/sbr.h b/fdk-aac/libSBRenc/src/sbr.h new file mode 100644 index 0000000..341dcab --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbr.h @@ -0,0 +1,194 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Main SBR structs definitions $Revision: 92790 $ +*/ + +#ifndef SBR_H +#define SBR_H + +#include "fram_gen.h" +#include "bit_sbr.h" +#include "tran_det.h" +#include "code_env.h" +#include "env_est.h" +#include "cmondata.h" + +#include "qmf.h" +#include "resampler.h" + +#include "ton_corr.h" + +/* SBR bitstream delay */ +#define MAX_DELAY_FRAMES 2 + +/* sbr encoder downsampling type */ +typedef enum { SBRENC_DS_NONE, SBRENC_DS_TIME, SBRENC_DS_QMF } SBRENC_DS_TYPE; + +typedef struct SBR_CHANNEL { + struct ENV_CHANNEL hEnvChannel; + // INT_PCM *pDSOutBuffer; /**< Pointer to + // downsampled audio output of SBR encoder */ + DOWNSAMPLER downSampler; + +} SBR_CHANNEL; +typedef SBR_CHANNEL* HANDLE_SBR_CHANNEL; + +typedef struct SBR_ELEMENT { + HANDLE_SBR_CHANNEL sbrChannel[2]; + QMF_FILTER_BANK* hQmfAnalysis[2]; + SBR_CONFIG_DATA sbrConfigData; + SBR_HEADER_DATA sbrHeaderData; + SBR_BITSTREAM_DATA sbrBitstreamData; + COMMON_DATA CmonData; + INT dynXOverFreqDelay[5]; /**< to delay a frame (I don't like it that much + that way - hrc) */ + SBR_ELEMENT_INFO elInfo; + + UCHAR payloadDelayLine[1 + MAX_DELAY_FRAMES][MAX_PAYLOAD_SIZE]; + UINT payloadDelayLineSize[1 + MAX_DELAY_FRAMES]; /* Sizes in bits */ + +} SBR_ELEMENT, *HANDLE_SBR_ELEMENT; + +typedef struct SBR_ENCODER { + HANDLE_SBR_ELEMENT sbrElement[(8)]; + HANDLE_SBR_CHANNEL pSbrChannel[(8)]; + QMF_FILTER_BANK QmfAnalysis[(8)]; + DOWNSAMPLER lfeDownSampler; + int lfeChIdx; /* -1 default for no lfe, else assign channel index. */ + int noElements; /* Number of elements. */ + int nChannels; /* Total channel count across all elements. */ + int frameSize; /* SBR framelength. */ + int bufferOffset; /* Offset for SBR parameter extraction in time domain input + buffer. */ + int downsampledOffset; /* Offset of downsampled/mixed output for core encoder. + */ + int downmixSize; /* Size in samples of downsampled/mixed output for core + encoder. */ + INT downSampleFactor; /* Sampling rate relation between the SBR and the core + encoder. */ + SBRENC_DS_TYPE + downsamplingMethod; /* Method of downsmapling, time-domain, QMF or none. + */ + int nBitstrDelay; /* Amount of SBR frames to be delayed in bitstream domain. + */ + int sbrDecDelay; /* SBR decoder delay in samples */ + INT estimateBitrate; /* Estimate bitrate of SBR encoder. */ + INT inputDataDelay; /* Delay caused by downsampler, in/out buffer at + sbrEncoder_EncodeFrame. */ + + UCHAR* dynamicRam; + UCHAR* pSBRdynamic_RAM; + + HANDLE_PARAMETRIC_STEREO hParametricStereo; + QMF_FILTER_BANK qmfSynthesisPS; + + /* parameters describing allocation volume of present instance */ + INT maxElements; + INT maxChannels; + INT supportPS; + +} SBR_ENCODER; + +#endif /* SBR_H */ diff --git a/fdk-aac/libSBRenc/src/sbr_def.h b/fdk-aac/libSBRenc/src/sbr_def.h new file mode 100644 index 0000000..53eba71 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbr_def.h @@ -0,0 +1,276 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief SBR main definitions $Revision: 92790 $ +*/ +#ifndef SBR_DEF_H +#define SBR_DEF_H + +#include "common_fix.h" + +#define noError 0 +#define HANDLE_ERROR_INFO INT +#define ERROR(a, b) 1 + +/* #define SBR_ENV_STATISTICS_BITRATE */ +#undef SBR_ENV_STATISTICS_BITRATE + +/* #define SBR_ENV_STATISTICS */ +#undef SBR_ENV_STATISTICS + +/* #define SBR_PAYLOAD_MONITOR */ +#undef SBR_PAYLOAD_MONITOR + +#define SWAP(a, b) tempr = a, a = b, b = tempr +#define TRUE 1 +#define FALSE 0 + +/* Constants */ +#define EPS 1e-12 +#define LOG2 0.69314718056f /* natural logarithm of 2 */ +#define ILOG2 1.442695041f /* 1/LOG2 */ +#define RELAXATION_FLOAT (1e-6f) +#define RELAXATION (FL2FXCONST_DBL(RELAXATION_FLOAT)) +#define RELAXATION_FRACT \ + (FL2FXCONST_DBL(0.524288f)) /* 0.524288f is fractional part of RELAXATION */ +#define RELAXATION_SHIFT (19) +#define RELAXATION_LD64 \ + (FL2FXCONST_DBL(0.31143075889f)) /* (ld64(RELAXATION) \ + */ + +/************ Definitions ***************/ +#define SBR_COMP_MODE_DELTA 0 +#define SBR_COMP_MODE_CTS 1 +#define SBR_MAX_ENERGY_VALUES 5 +#define SBR_GLOBAL_TONALITY_VALUES 2 + +#define MAX_NUM_CHANNELS 2 + +#define MAX_NOISE_ENVELOPES 2 +#define MAX_NUM_NOISE_COEFFS 5 +#define MAX_NUM_NOISE_VALUES (MAX_NUM_NOISE_COEFFS * MAX_NOISE_ENVELOPES) + +#define MAX_NUM_ENVELOPE_VALUES (MAX_ENVELOPES * MAX_FREQ_COEFFS) +#define MAX_ENVELOPES 5 +#define MAX_FREQ_COEFFS 48 + +#define MAX_FREQ_COEFFS_FS44100 35 +#define MAX_FREQ_COEFFS_FS48000 32 + +#define NO_OF_ESTIMATES_LC 4 +#define NO_OF_ESTIMATES_LD 3 +#define MAX_NO_OF_ESTIMATES 4 + +#define NOISE_FLOOR_OFFSET 6 +#define NOISE_FLOOR_OFFSET_64 (FL2FXCONST_DBL(0.09375f)) + +#define LOW_RES 0 +#define HIGH_RES 1 + +#define LO 0 +#define HI 1 + +#define LENGTH_SBR_FRAME_INFO 35 /* 19 */ + +#define SBR_NSFB_LOW_RES 9 /* 8 */ +#define SBR_NSFB_HIGH_RES 18 /* 16 */ + +#define SBR_XPOS_CTRL_DEFAULT 2 + +#define SBR_FREQ_SCALE_DEFAULT 2 +#define SBR_ALTER_SCALE_DEFAULT 1 +#define SBR_NOISE_BANDS_DEFAULT 2 + +#define SBR_LIMITER_BANDS_DEFAULT 2 +#define SBR_LIMITER_GAINS_DEFAULT 2 +#define SBR_LIMITER_GAINS_INFINITE 3 +#define SBR_INTERPOL_FREQ_DEFAULT 1 +#define SBR_SMOOTHING_LENGTH_DEFAULT 0 + +/* sbr_header */ +#define SI_SBR_AMP_RES_BITS 1 +#define SI_SBR_COUPLING_BITS 1 +#define SI_SBR_START_FREQ_BITS 4 +#define SI_SBR_STOP_FREQ_BITS 4 +#define SI_SBR_XOVER_BAND_BITS 3 +#define SI_SBR_RESERVED_BITS 2 +#define SI_SBR_DATA_EXTRA_BITS 1 +#define SI_SBR_HEADER_EXTRA_1_BITS 1 +#define SI_SBR_HEADER_EXTRA_2_BITS 1 + +/* sbr_header extra 1 */ +#define SI_SBR_FREQ_SCALE_BITS 2 +#define SI_SBR_ALTER_SCALE_BITS 1 +#define SI_SBR_NOISE_BANDS_BITS 2 + +/* sbr_header extra 2 */ +#define SI_SBR_LIMITER_BANDS_BITS 2 +#define SI_SBR_LIMITER_GAINS_BITS 2 +#define SI_SBR_INTERPOL_FREQ_BITS 1 +#define SI_SBR_SMOOTHING_LENGTH_BITS 1 + +/* sbr_grid */ +#define SBR_CLA_BITS 2 /*!< size of bs_frame_class */ +#define SBR_CLA_BITS_LD 1 /*!< size of bs_frame_class */ +#define SBR_ENV_BITS 2 /*!< size of bs_num_env_raw */ +#define SBR_ABS_BITS 2 /*!< size of bs_abs_bord_raw for HE-AAC */ +#define SBR_NUM_BITS 2 /*!< size of bs_num_rel */ +#define SBR_REL_BITS 2 /*!< size of bs_rel_bord_raw */ +#define SBR_RES_BITS 1 /*!< size of bs_freq_res_flag */ +#define SBR_DIR_BITS 1 /*!< size of bs_df_flag */ + +/* sbr_data */ +#define SI_SBR_INVF_MODE_BITS 2 + +#define SI_SBR_START_ENV_BITS_AMP_RES_3_0 6 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_AMP_RES_3_0 5 +#define SI_SBR_START_NOISE_BITS_BALANCE_AMP_RES_3_0 5 + +#define SI_SBR_START_ENV_BITS_AMP_RES_1_5 7 +#define SI_SBR_START_ENV_BITS_BALANCE_AMP_RES_1_5 6 + +#define SI_SBR_EXTENDED_DATA_BITS 1 +#define SI_SBR_EXTENSION_SIZE_BITS 4 +#define SI_SBR_EXTENSION_ESC_COUNT_BITS 8 +#define SI_SBR_EXTENSION_ID_BITS 2 + +#define SBR_EXTENDED_DATA_MAX_CNT (15 + 255) + +#define EXTENSION_ID_PS_CODING 2 + +/* Envelope coding constants */ +#define FREQ 0 +#define TIME 1 + +/* qmf data scaling */ +#define QMF_SCALE_OFFSET 7 + +/* huffman tables */ +#define CODE_BOOK_SCF_LAV00 60 +#define CODE_BOOK_SCF_LAV01 31 +#define CODE_BOOK_SCF_LAV10 60 +#define CODE_BOOK_SCF_LAV11 31 +#define CODE_BOOK_SCF_LAV_BALANCE11 12 +#define CODE_BOOK_SCF_LAV_BALANCE10 24 + +typedef enum { SBR_AMP_RES_1_5 = 0, SBR_AMP_RES_3_0 } AMP_RES; + +typedef enum { + XPOS_MDCT, + XPOS_MDCT_CROSS, + XPOS_LC, + XPOS_RESERVED, + XPOS_SWITCHED /* not a real choice but used here to control behaviour */ +} XPOS_MODE; + +typedef enum { + INVF_OFF = 0, + INVF_LOW_LEVEL, + INVF_MID_LEVEL, + INVF_HIGH_LEVEL, + INVF_SWITCHED /* not a real choice but used here to control behaviour */ +} INVF_MODE; + +#endif diff --git a/fdk-aac/libSBRenc/src/sbr_encoder.cpp b/fdk-aac/libSBRenc/src/sbr_encoder.cpp new file mode 100644 index 0000000..26257a1 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbr_encoder.cpp @@ -0,0 +1,2577 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Andreas Ehret, Tobias Chalupka + + Description: SBR encoder top level processing. + +*******************************************************************************/ + +#include "sbr_encoder.h" + +#include "sbrenc_ram.h" +#include "sbrenc_rom.h" +#include "sbrenc_freq_sca.h" +#include "env_bit.h" +#include "cmondata.h" +#include "sbr_misc.h" +#include "sbr.h" +#include "qmf.h" + +#include "ps_main.h" + +#define SBRENCODER_LIB_VL0 4 +#define SBRENCODER_LIB_VL1 0 +#define SBRENCODER_LIB_VL2 0 + +/***************************************************************************/ +/* + * SBR Delay balancing definitions. + */ + +/* + input buffer (1ch) + + |------------ 1537 -------------|-----|---------- 2048 -------------| + (core2sbr delay ) ds (read, core and ds area) +*/ + +#define SFB(dwnsmp) \ + (32 << (dwnsmp - \ + 1)) /* SBR Frequency bands: 64 for dual-rate, 32 for single-rate */ +#define STS(fl) \ + (((fl) == 1024) ? 32 \ + : 30) /* SBR Time Slots: 32 for core frame length 1024, 30 \ + for core frame length 960 */ + +#define DELAY_QMF_ANA(dwnsmp) \ + ((320 << ((dwnsmp)-1)) - (32 << ((dwnsmp)-1))) /* Full bandwidth */ +#define DELAY_HYB_ANA (10 * 64) /* + 0.5 */ /* */ +#define DELAY_HYB_SYN (6 * 64 - 32) /* */ +#define DELAY_QMF_POSTPROC(dwnsmp) \ + (32 * (dwnsmp)) /* QMF postprocessing delay */ +#define DELAY_DEC_QMF(dwnsmp) (6 * SFB(dwnsmp)) /* Decoder QMF overlap */ +#define DELAY_QMF_SYN(dwnsmp) \ + (1 << (dwnsmp - \ + 1)) /* QMF_NO_POLY/2=2.5, rounded down to 2, half for single-rate */ +#define DELAY_QMF_DS (32) /* QMF synthesis for downsampled time signal */ + +/* Delay in QMF paths */ +#define DELAY_SBR(fl, dwnsmp) \ + (DELAY_QMF_ANA(dwnsmp) + (SFB(dwnsmp) * STS(fl) - 1) + DELAY_QMF_SYN(dwnsmp)) +#define DELAY_PS(fl, dwnsmp) \ + (DELAY_QMF_ANA(dwnsmp) + DELAY_HYB_ANA + DELAY_DEC_QMF(dwnsmp) + \ + (SFB(dwnsmp) * STS(fl) - 1) + DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp)) +#define DELAY_ELDSBR(fl, dwnsmp) \ + ((((fl) / 2) * (dwnsmp)) - 1 + DELAY_QMF_POSTPROC(dwnsmp)) +#define DELAY_ELDv2SBR(fl, dwnsmp) \ + ((((fl) / 2) * (dwnsmp)) - 1 + 80 * (dwnsmp)) /* 80 is the delay caused \ + by the sum of the CLD \ + analysis and the MPSLD \ + synthesis filterbank */ + +/* Delay in core path (core and downsampler not taken into account) */ +#define DELAY_COREPATH_SBR(fl, dwnsmp) \ + ((DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + DELAY_QMF_SYN(dwnsmp))) +#define DELAY_COREPATH_ELDSBR(fl, dwnsmp) ((DELAY_QMF_POSTPROC(dwnsmp))) +#define DELAY_COREPATH_ELDv2SBR(fl, dwnsmp) (128 * (dwnsmp)) /* 4 slots */ +#define DELAY_COREPATH_PS(fl, dwnsmp) \ + ((DELAY_QMF_ANA(dwnsmp) + DELAY_QMF_DS + \ + /*(DELAY_AAC(fl)*2) + */ DELAY_QMF_ANA(dwnsmp) + DELAY_DEC_QMF(dwnsmp) + \ + DELAY_HYB_SYN + DELAY_QMF_SYN(dwnsmp))) /* 2048 - 463*2 */ + +/* Delay differences between SBR- and downsampled path for SBR and SBR+PS */ +#define DELAY_AAC2SBR(fl, dwnsmp) \ + ((DELAY_COREPATH_SBR(fl, dwnsmp)) - DELAY_SBR((fl), (dwnsmp))) +#define DELAY_ELD2SBR(fl, dwnsmp) \ + ((DELAY_COREPATH_ELDSBR(fl, dwnsmp)) - DELAY_ELDSBR(fl, dwnsmp)) +#define DELAY_AAC2PS(fl, dwnsmp) \ + ((DELAY_COREPATH_PS(fl, dwnsmp)) - DELAY_PS(fl, dwnsmp)) /* 2048 - 463*2 */ + +/* Assumption: The sample delay resulting of of DELAY_AAC2PS is always smaller + * than the sample delay implied by DELAY_AAC2SBR */ +#define MAX_DS_FILTER_DELAY \ + (5) /* the additional max downsampler filter delay (source fs) */ +#define MAX_SAMPLE_DELAY \ + (DELAY_AAC2SBR(1024, 2) + MAX_DS_FILTER_DELAY) /* maximum delay: frame \ + length of 1024 and \ + dual-rate sbr */ + +/***************************************************************************/ + +/*************** Delay parameters for sbrEncoder_Init_delay() **************/ +typedef struct { + int dsDelay; /* the delay of the (time-domain) downsampler itself */ + int delay; /* overall delay / samples */ + int sbrDecDelay; /* SBR decoder's delay */ + int corePathOffset; /* core path offset / samples; added by + sbrEncoder_Init_delay() */ + int sbrPathOffset; /* SBR path offset / samples; added by + sbrEncoder_Init_delay() */ + int bitstrDelay; /* bitstream delay / frames; added by sbrEncoder_Init_delay() + */ + int delayInput2Core; /* delay of the input to the core / samples */ +} DELAY_PARAM; +/***************************************************************************/ + +#define INVALID_TABLE_IDX -1 + +/***************************************************************************/ +/*! + + \brief Selects the SBR tuning settings to use dependent on number of + channels, bitrate, sample rate and core coder + + \return Index to the appropriate table + +****************************************************************************/ +#define DISTANCE_CEIL_VALUE 5000000 +static INT getSbrTuningTableIndex( + UINT bitrate, /*! the total bitrate in bits/sec */ + UINT numChannels, /*! the number of channels for the core coder */ + UINT sampleRate, /*! the sampling rate of the core coder */ + AUDIO_OBJECT_TYPE core, UINT *pBitRateClosest) { + int i, bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1, + found = 0; + UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE; + +#define isForThisCore(i) \ + ((sbrTuningTable[i].coreCoder == CODEC_AACLD && core == AOT_ER_AAC_ELD) || \ + (sbrTuningTable[i].coreCoder == CODEC_AAC && core != AOT_ER_AAC_ELD)) + + for (i = 0; i < sbrTuningTableSize; i++) { + if (isForThisCore(i)) /* tuning table is for this core codec */ + { + if (numChannels == sbrTuningTable[i].numChannels && + sampleRate == sbrTuningTable[i].sampleRate) { + found = 1; + if ((bitrate >= sbrTuningTable[i].bitrateFrom) && + (bitrate < sbrTuningTable[i].bitrateTo)) { + return i; + } else { + if (sbrTuningTable[i].bitrateFrom > bitrate) { + if (sbrTuningTable[i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = sbrTuningTable[i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if (sbrTuningTable[i].bitrateTo <= bitrate) { + if (sbrTuningTable[i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = sbrTuningTable[i].bitrateTo - 1; + bitRateClosestUpperIndex = i; + } + } + } + } + } + } + + if (bitRateClosestUpperIndex >= 0) { + return bitRateClosestUpperIndex; + } + + if (pBitRateClosest != NULL) { + /* If there was at least one matching tuning entry pick the least distance + * bit rate */ + if (found) { + int distanceUpper = DISTANCE_CEIL_VALUE, + distanceLower = DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = + sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = + bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo; + } + if (distanceUpper < distanceLower) { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } else { + *pBitRateClosest = 0; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief Selects the PS tuning settings to use dependent on bitrate + and core coder + + \return Index to the appropriate table + +****************************************************************************/ +static INT getPsTuningTableIndex(UINT bitrate, UINT *pBitRateClosest) { + INT i, paramSets = sizeof(psTuningTable) / sizeof(psTuningTable[0]); + int bitRateClosestLowerIndex = -1, bitRateClosestUpperIndex = -1; + UINT bitRateClosestUpper = 0, bitRateClosestLower = DISTANCE_CEIL_VALUE; + + for (i = 0; i < paramSets; i++) { + if ((bitrate >= psTuningTable[i].bitrateFrom) && + (bitrate < psTuningTable[i].bitrateTo)) { + return i; + } else { + if (psTuningTable[i].bitrateFrom > bitrate) { + if (psTuningTable[i].bitrateFrom < bitRateClosestLower) { + bitRateClosestLower = psTuningTable[i].bitrateFrom; + bitRateClosestLowerIndex = i; + } + } + if (psTuningTable[i].bitrateTo <= bitrate) { + if (psTuningTable[i].bitrateTo > bitRateClosestUpper) { + bitRateClosestUpper = psTuningTable[i].bitrateTo - 1; + bitRateClosestUpperIndex = i; + } + } + } + } + + if (bitRateClosestUpperIndex >= 0) { + return bitRateClosestUpperIndex; + } + + if (pBitRateClosest != NULL) { + int distanceUpper = DISTANCE_CEIL_VALUE, + distanceLower = DISTANCE_CEIL_VALUE; + if (bitRateClosestLowerIndex >= 0) { + distanceLower = + sbrTuningTable[bitRateClosestLowerIndex].bitrateFrom - bitrate; + } + if (bitRateClosestUpperIndex >= 0) { + distanceUpper = + bitrate - sbrTuningTable[bitRateClosestUpperIndex].bitrateTo; + } + if (distanceUpper < distanceLower) { + *pBitRateClosest = bitRateClosestUpper; + } else { + *pBitRateClosest = bitRateClosestLower; + } + } + + return INVALID_TABLE_IDX; +} + +/***************************************************************************/ +/*! + + \brief In case of downsampled SBR we may need to lower the stop freq + of a tuning setting to fit into the lower half of the + spectrum ( which is sampleRate/4 ) + + \return the adapted stop frequency index (-1 -> error) + + \ingroup SbrEncCfg + +****************************************************************************/ +static INT FDKsbrEnc_GetDownsampledStopFreq(const INT sampleRateCore, + const INT startFreq, INT stopFreq, + const INT downSampleFactor) { + INT maxStopFreqRaw = sampleRateCore / 2; + INT startBand, stopBand; + HANDLE_ERROR_INFO err; + + while (stopFreq > 0 && FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > + maxStopFreqRaw) { + stopFreq--; + } + + if (FDKsbrEnc_getSbrStopFreqRAW(stopFreq, sampleRateCore) > maxStopFreqRaw) + return -1; + + err = FDKsbrEnc_FindStartAndStopBand( + sampleRateCore << (downSampleFactor - 1), sampleRateCore, + 32 << (downSampleFactor - 1), startFreq, stopFreq, &startBand, &stopBand); + if (err) return -1; + + return stopFreq; +} + +/***************************************************************************/ +/*! + + \brief tells us, if for the given coreCoder, bitrate, number of channels + and input sampling rate an SBR setting is available. If yes, it + tells us also the core sampling rate we would need to run with + + \return a flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT FDKsbrEnc_IsSbrSettingAvail( + UINT bitrate, /*! the total bitrate in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 means constant bitrate */ + UINT numOutputChannels, /*! the number of channels for the core coder */ + UINT sampleRateInput, /*! the input sample rate [in Hz] */ + UINT sampleRateCore, /*! the core's sampling rate */ + AUDIO_OBJECT_TYPE core) { + INT idx = INVALID_TABLE_IDX; + + if (sampleRateInput < 16000) return 0; + + if (bitrate == 0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitrate = 24000; + else if (vbrMode < 40) + bitrate = 28000; + else if (vbrMode < 60) + bitrate = 32000; + else if (vbrMode < 75) + bitrate = 40000; + else + bitrate = 48000; + bitrate *= numOutputChannels; + } + + idx = getSbrTuningTableIndex(bitrate, numOutputChannels, sampleRateCore, core, + NULL); + + return (idx == INVALID_TABLE_IDX ? 0 : 1); +} + +/***************************************************************************/ +/*! + + \brief Adjusts the SBR settings according to the chosen core coder + settings which are accessible via config->codecSettings + + \return A flag indicating success: yes (1) or no (0) + +****************************************************************************/ +static UINT FDKsbrEnc_AdjustSbrSettings( + const sbrConfigurationPtr config, /*! output, modified */ + UINT bitRate, /*! the total bitrate in bits/sec */ + UINT numChannels, /*! the core coder number of channels */ + UINT sampleRateCore, /*! the core coder sampling rate in Hz */ + UINT sampleRateSbr, /*! the sbr coder sampling rate in Hz */ + UINT transFac, /*! the short block to long block ratio */ + UINT standardBitrate, /*! the standard bitrate per channel in bits/sec */ + UINT vbrMode, /*! the vbr paramter, 0 poor quality .. 100 high quality*/ + UINT useSpeechConfig, /*!< adapt tuning parameters for speech ? */ + UINT lcsMode, /*! the low complexity stereo mode */ + UINT bParametricStereo, /*!< use parametric stereo */ + AUDIO_OBJECT_TYPE core) /* Core audio codec object type */ +{ + INT idx = INVALID_TABLE_IDX; + /* set the core codec settings */ + config->codecSettings.bitRate = bitRate; + config->codecSettings.nChannels = numChannels; + config->codecSettings.sampleFreq = sampleRateCore; + config->codecSettings.transFac = transFac; + config->codecSettings.standardBitrate = standardBitrate; + + if (bitRate < 28000) { + config->threshold_AmpRes_FF_m = (FIXP_DBL)MAXVAL_DBL; + config->threshold_AmpRes_FF_e = 7; + } else if (bitRate >= 28000 && bitRate <= 48000) { + /* The float threshold is 75 + 0.524288f is fractional part of RELAXATION, the quotaMatrix and therefore + tonality are scaled by this 2/3 is because the original implementation + divides the tonality values by 3, here it's divided by 2 128 compensates + the necessary shiftfactor of 7 */ + config->threshold_AmpRes_FF_m = + FL2FXCONST_DBL(75.0f * 0.524288f / (2.0f / 3.0f) / 128.0f); + config->threshold_AmpRes_FF_e = 7; + } else if (bitRate > 48000) { + config->threshold_AmpRes_FF_m = FL2FXCONST_DBL(0); + config->threshold_AmpRes_FF_e = 0; + } + + if (bitRate == 0) { + /* map vbr quality to bitrate */ + if (vbrMode < 30) + bitRate = 24000; + else if (vbrMode < 40) + bitRate = 28000; + else if (vbrMode < 60) + bitRate = 32000; + else if (vbrMode < 75) + bitRate = 40000; + else + bitRate = 48000; + bitRate *= numChannels; + /* fix to enable mono vbrMode<40 @ 44.1 of 48kHz */ + if (numChannels == 1) { + if (sampleRateSbr == 44100 || sampleRateSbr == 48000) { + if (vbrMode < 40) bitRate = 32000; + } + } + } + + idx = + getSbrTuningTableIndex(bitRate, numChannels, sampleRateCore, core, NULL); + + if (idx != INVALID_TABLE_IDX) { + config->startFreq = sbrTuningTable[idx].startFreq; + config->stopFreq = sbrTuningTable[idx].stopFreq; + if (useSpeechConfig) { + config->startFreq = sbrTuningTable[idx].startFreqSpeech; + config->stopFreq = sbrTuningTable[idx].stopFreqSpeech; + } + + /* Adapt stop frequency in case of downsampled SBR - only 32 bands then */ + if (1 == config->downSampleFactor) { + INT dsStopFreq = FDKsbrEnc_GetDownsampledStopFreq( + sampleRateCore, config->startFreq, config->stopFreq, + config->downSampleFactor); + if (dsStopFreq < 0) { + return 0; + } + + config->stopFreq = dsStopFreq; + } + + config->sbr_noise_bands = sbrTuningTable[idx].numNoiseBands; + if (core == AOT_ER_AAC_ELD) config->init_amp_res_FF = SBR_AMP_RES_1_5; + config->noiseFloorOffset = sbrTuningTable[idx].noiseFloorOffset; + + config->ana_max_level = sbrTuningTable[idx].noiseMaxLevel; + config->stereoMode = sbrTuningTable[idx].stereoMode; + config->freqScale = sbrTuningTable[idx].freqScale; + + if (numChannels == 1) { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= (useSpeechConfig ? 24000U : 20000U)) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 36000) + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + if (bitRate < 26000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->fResTransIsLow = + 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + } else { + /* stereo case */ + switch (core) { + case AOT_AAC_LC: + if (bitRate <= 28000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + break; + case AOT_ER_AAC_ELD: + if (bitRate < 72000) { + config->freq_res_fixfix[1] = FREQ_RES_LOW; /* set low frequency + resolution for split + frames */ + } + if (bitRate < 52000) { + config->freq_res_fixfix[0] = FREQ_RES_LOW; /* set low frequency + resolution for + non-split frames */ + config->fResTransIsLow = + 1; /* for transient frames, set low frequency resolution */ + } + break; + default: + break; + } + if (bitRate <= 28000) { + /* + additionally restrict frequency resolution in FIXFIX frames + to further reduce SBR payload size */ + config->freq_res_fixfix[0] = FREQ_RES_LOW; + config->freq_res_fixfix[1] = FREQ_RES_LOW; + } + } + + /* adjust usage of parametric coding dependent on bitrate and speech config + * flag */ + if (useSpeechConfig) config->parametricCoding = 0; + + if (core == AOT_ER_AAC_ELD) { + if (bitRate < 28000) config->init_amp_res_FF = SBR_AMP_RES_3_0; + config->SendHeaderDataTime = -1; + } + + if (numChannels == 1) { + if (bitRate < 16000) { + config->parametricCoding = 0; + } + } else { + if (bitRate < 20000) { + config->parametricCoding = 0; + } + } + + config->useSpeechConfig = useSpeechConfig; + + /* PS settings */ + config->bParametricStereo = bParametricStereo; + + return 1; + } else { + return 0; + } +} + +/***************************************************************************** + + functionname: FDKsbrEnc_InitializeSbrDefaults + description: initializes the SBR configuration + returns: error status + input: - core codec type, + - factor of SBR to core frame length, + - core frame length + output: initialized SBR configuration + +*****************************************************************************/ +static UINT FDKsbrEnc_InitializeSbrDefaults(sbrConfigurationPtr config, + INT downSampleFactor, + UINT codecGranuleLen, + const INT isLowDelay) { + if ((downSampleFactor < 1 || downSampleFactor > 2) || + (codecGranuleLen * downSampleFactor > 64 * 32)) + return (0); /* error */ + + config->SendHeaderDataTime = 1000; + config->useWaveCoding = 0; + config->crcSbr = 0; + config->dynBwSupported = 1; + if (isLowDelay) + config->tran_thr = 6000; + else + config->tran_thr = 13000; + + config->parametricCoding = 1; + + config->sbrFrameSize = codecGranuleLen * downSampleFactor; + config->downSampleFactor = downSampleFactor; + + /* sbr default parameters */ + config->sbr_data_extra = 0; + config->amp_res = SBR_AMP_RES_3_0; + config->tran_fc = 0; + config->tran_det_mode = 1; + config->spread = 1; + config->stat = 0; + config->e = 1; + config->deltaTAcrossFrames = 1; + config->dF_edge_1stEnv = FL2FXCONST_DBL(0.3f); + config->dF_edge_incr = FL2FXCONST_DBL(0.3f); + + config->sbr_invf_mode = INVF_SWITCHED; + config->sbr_xpos_mode = XPOS_LC; + config->sbr_xpos_ctrl = SBR_XPOS_CTRL_DEFAULT; + config->sbr_xpos_level = 0; + config->useSaPan = 0; + config->dynBwEnabled = 0; + + /* the following parameters are overwritten by the + FDKsbrEnc_AdjustSbrSettings() function since they are included in the + tuning table */ + config->stereoMode = SBR_SWITCH_LRC; + config->ana_max_level = 6; + config->noiseFloorOffset = 0; + config->startFreq = 5; /* 5.9 respectively 6.0 kHz at fs = 44.1/48 kHz */ + config->stopFreq = 9; /* 16.2 respectively 16.8 kHz at fs = 44.1/48 kHz */ + config->freq_res_fixfix[0] = FREQ_RES_HIGH; /* non-split case */ + config->freq_res_fixfix[1] = FREQ_RES_HIGH; /* split case */ + config->fResTransIsLow = 0; /* for transient frames, set variable frequency + resolution according to freqResTable */ + + /* header_extra_1 */ + config->freqScale = SBR_FREQ_SCALE_DEFAULT; + config->alterScale = SBR_ALTER_SCALE_DEFAULT; + config->sbr_noise_bands = SBR_NOISE_BANDS_DEFAULT; + + /* header_extra_2 */ + config->sbr_limiter_bands = SBR_LIMITER_BANDS_DEFAULT; + config->sbr_limiter_gains = SBR_LIMITER_GAINS_DEFAULT; + config->sbr_interpol_freq = SBR_INTERPOL_FREQ_DEFAULT; + config->sbr_smoothing_length = SBR_SMOOTHING_LENGTH_DEFAULT; + + return 1; +} + +/***************************************************************************** + + functionname: DeleteEnvChannel + description: frees memory of one SBR channel + returns: - + input: handle of channel + output: released handle + +*****************************************************************************/ +static void deleteEnvChannel(HANDLE_ENV_CHANNEL hEnvCut) { + if (hEnvCut) { + FDKsbrEnc_DeleteTonCorrParamExtr(&hEnvCut->TonCorr); + + FDKsbrEnc_deleteExtractSbrEnvelope(&hEnvCut->sbrExtractEnvelope); + } +} + +/***************************************************************************** + + functionname: sbrEncoder_ChannelClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void sbrEncoder_ChannelClose(HANDLE_SBR_CHANNEL hSbrChannel) { + if (hSbrChannel != NULL) { + deleteEnvChannel(&hSbrChannel->hEnvChannel); + } +} + +/***************************************************************************** + + functionname: sbrEncoder_ElementClose + description: close the channel coding handle + returns: + input: phSbrChannel + output: + +*****************************************************************************/ +static void sbrEncoder_ElementClose(HANDLE_SBR_ELEMENT *phSbrElement) { + HANDLE_SBR_ELEMENT hSbrElement = *phSbrElement; + + if (hSbrElement != NULL) { + if (hSbrElement->sbrConfigData.v_k_master) + FreeRam_Sbr_v_k_master(&hSbrElement->sbrConfigData.v_k_master); + if (hSbrElement->sbrConfigData.freqBandTable[LO]) + FreeRam_Sbr_freqBandTableLO( + &hSbrElement->sbrConfigData.freqBandTable[LO]); + if (hSbrElement->sbrConfigData.freqBandTable[HI]) + FreeRam_Sbr_freqBandTableHI( + &hSbrElement->sbrConfigData.freqBandTable[HI]); + + FreeRam_SbrElement(phSbrElement); + } + return; +} + +void sbrEncoder_Close(HANDLE_SBR_ENCODER *phSbrEncoder) { + HANDLE_SBR_ENCODER hSbrEncoder = *phSbrEncoder; + + if (hSbrEncoder != NULL) { + int el, ch; + + for (el = 0; el < (8); el++) { + if (hSbrEncoder->sbrElement[el] != NULL) { + sbrEncoder_ElementClose(&hSbrEncoder->sbrElement[el]); + } + } + + /* Close sbr Channels */ + for (ch = 0; ch < (8); ch++) { + if (hSbrEncoder->pSbrChannel[ch]) { + sbrEncoder_ChannelClose(hSbrEncoder->pSbrChannel[ch]); + FreeRam_SbrChannel(&hSbrEncoder->pSbrChannel[ch]); + } + + if (hSbrEncoder->QmfAnalysis[ch].FilterStates) + FreeRam_Sbr_QmfStatesAnalysis( + (FIXP_QAS **)&hSbrEncoder->QmfAnalysis[ch].FilterStates); + } + + if (hSbrEncoder->hParametricStereo) + PSEnc_Destroy(&hSbrEncoder->hParametricStereo); + if (hSbrEncoder->qmfSynthesisPS.FilterStates) + FreeRam_PsQmfStatesSynthesis( + (FIXP_DBL **)&hSbrEncoder->qmfSynthesisPS.FilterStates); + + /* Release Overlay */ + if (hSbrEncoder->pSBRdynamic_RAM) + FreeRam_SbrDynamic_RAM((FIXP_DBL **)&hSbrEncoder->pSBRdynamic_RAM); + + FreeRam_SbrEncoder(phSbrEncoder); + } +} + +/***************************************************************************** + + functionname: updateFreqBandTable + description: updates vk_master + returns: - + input: config handle + output: error info + +*****************************************************************************/ +static INT updateFreqBandTable(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + const INT downSampleFactor) { + INT k0, k2; + + if (FDKsbrEnc_FindStartAndStopBand( + sbrConfigData->sampleFreq, + sbrConfigData->sampleFreq >> (downSampleFactor - 1), + sbrConfigData->noQmfBands, sbrHeaderData->sbr_start_frequency, + sbrHeaderData->sbr_stop_frequency, &k0, &k2)) + return (1); + + if (FDKsbrEnc_UpdateFreqScale( + sbrConfigData->v_k_master, &sbrConfigData->num_Master, k0, k2, + sbrHeaderData->freqScale, sbrHeaderData->alterScale)) + return (1); + + sbrHeaderData->sbr_xover_band = 0; + + if (FDKsbrEnc_UpdateHiRes(sbrConfigData->freqBandTable[HI], + &sbrConfigData->nSfb[HI], sbrConfigData->v_k_master, + sbrConfigData->num_Master, + &sbrHeaderData->sbr_xover_band)) + return (1); + + FDKsbrEnc_UpdateLoRes( + sbrConfigData->freqBandTable[LO], &sbrConfigData->nSfb[LO], + sbrConfigData->freqBandTable[HI], sbrConfigData->nSfb[HI]); + + sbrConfigData->xOverFreq = + (sbrConfigData->freqBandTable[LOW_RES][0] * sbrConfigData->sampleFreq / + sbrConfigData->noQmfBands + + 1) >> + 1; + + return (0); +} + +/***************************************************************************** + + functionname: resetEnvChannel + description: resets parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static INT resetEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv) { + /* note !!! hEnv->encEnvData.noOfnoisebands will be updated later in function + * FDKsbrEnc_extractSbrEnvelope !!!*/ + hEnv->TonCorr.sbrNoiseFloorEstimate.noiseBands = + sbrHeaderData->sbr_noise_bands; + + if (FDKsbrEnc_ResetTonCorrParamExtr( + &hEnv->TonCorr, sbrConfigData->xposCtrlSwitch, + sbrConfigData->freqBandTable[HI][0], sbrConfigData->v_k_master, + sbrConfigData->num_Master, sbrConfigData->sampleFreq, + sbrConfigData->freqBandTable, sbrConfigData->nSfb, + sbrConfigData->noQmfBands)) + return (1); + + hEnv->sbrCodeNoiseFloor.nSfb[LO] = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + hEnv->sbrCodeNoiseFloor.nSfb[HI] = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + hEnv->sbrCodeEnvelope.nSfb[LO] = sbrConfigData->nSfb[LO]; + hEnv->sbrCodeEnvelope.nSfb[HI] = sbrConfigData->nSfb[HI]; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + + hEnv->sbrCodeEnvelope.upDate = 0; + hEnv->sbrCodeNoiseFloor.upDate = 0; + + return (0); +} + +/* ****************************** FDKsbrEnc_SbrGetXOverFreq + * ******************************/ +/** + * @fn + * @brief calculates the closest possible crossover frequency + * @return the crossover frequency SBR accepts + * + */ +static INT FDKsbrEnc_SbrGetXOverFreq( + HANDLE_SBR_ELEMENT hEnv, /*!< handle to SBR encoder instance */ + INT xoverFreq) /*!< from core coder suggested crossover frequency */ +{ + INT band; + INT lastDiff, newDiff; + INT cutoffSb; + + UCHAR *RESTRICT pVKMaster = hEnv->sbrConfigData.v_k_master; + + /* Check if there is a matching cutoff frequency in the master table */ + cutoffSb = (4 * xoverFreq * hEnv->sbrConfigData.noQmfBands / + hEnv->sbrConfigData.sampleFreq + + 1) >> + 1; + lastDiff = cutoffSb; + for (band = 0; band < hEnv->sbrConfigData.num_Master; band++) { + newDiff = fixp_abs((INT)pVKMaster[band] - cutoffSb); + + if (newDiff >= lastDiff) { + band--; + break; + } + + lastDiff = newDiff; + } + + return ((pVKMaster[band] * hEnv->sbrConfigData.sampleFreq / + hEnv->sbrConfigData.noQmfBands + + 1) >> + 1); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvEncodeFrame + description: performs the sbr envelope calculation for one element + returns: + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_EnvEncodeFrame( + HANDLE_SBR_ENCODER hEnvEncoder, int iElement, + INT_PCM *samples, /*!< time samples, always deinterleaved */ + UINT samplesBufSize, /*!< time buffer channel stride */ + UINT *sbrDataBits, /*!< Size of SBR payload */ + UCHAR *sbrData, /*!< SBR payload */ + int clearOutput /*!< Do not consider any input signal */ +) { + HANDLE_SBR_ELEMENT hSbrElement = NULL; + FDK_CRCINFO crcInfo; + INT crcReg; + INT ch; + INT band; + INT cutoffSb; + INT newXOver; + + if (hEnvEncoder == NULL) return -1; + + hSbrElement = hEnvEncoder->sbrElement[iElement]; + + if (hSbrElement == NULL) return -1; + + /* header bitstream handling */ + HANDLE_SBR_BITSTREAM_DATA sbrBitstreamData = &hSbrElement->sbrBitstreamData; + + INT psHeaderActive = 0; + sbrBitstreamData->HeaderActive = 0; + + /* Anticipate PS header because of internal PS bitstream delay in order to be + * in sync with SBR header. */ + if (sbrBitstreamData->CountSendHeaderData == + (sbrBitstreamData->NrSendHeaderData - 1)) { + psHeaderActive = 1; + } + + /* Signal SBR header to be written into bitstream */ + if (sbrBitstreamData->CountSendHeaderData == 0) { + sbrBitstreamData->HeaderActive = 1; + } + + /* Increment header interval counter */ + if (sbrBitstreamData->NrSendHeaderData == 0) { + sbrBitstreamData->CountSendHeaderData = 1; + } else { + if (sbrBitstreamData->CountSendHeaderData >= 0) { + sbrBitstreamData->CountSendHeaderData++; + sbrBitstreamData->CountSendHeaderData %= + sbrBitstreamData->NrSendHeaderData; + } + } + + if (hSbrElement->CmonData.dynBwEnabled) { + INT i; + for (i = 4; i > 0; i--) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->dynXOverFreqDelay[i - 1]; + + hSbrElement->dynXOverFreqDelay[0] = hSbrElement->CmonData.dynXOverFreqEnc; + if (hSbrElement->dynXOverFreqDelay[1] > hSbrElement->dynXOverFreqDelay[2]) + newXOver = hSbrElement->dynXOverFreqDelay[2]; + else + newXOver = hSbrElement->dynXOverFreqDelay[1]; + + /* has the crossover frequency changed? */ + if (hSbrElement->sbrConfigData.dynXOverFreq != newXOver) { + /* get corresponding master band */ + cutoffSb = ((4 * newXOver * hSbrElement->sbrConfigData.noQmfBands / + hSbrElement->sbrConfigData.sampleFreq) + + 1) >> + 1; + + for (band = 0; band < hSbrElement->sbrConfigData.num_Master; band++) { + if (cutoffSb == hSbrElement->sbrConfigData.v_k_master[band]) break; + } + FDK_ASSERT(band < hSbrElement->sbrConfigData.num_Master); + + hSbrElement->sbrConfigData.dynXOverFreq = newXOver; + hSbrElement->sbrHeaderData.sbr_xover_band = band; + hSbrElement->sbrBitstreamData.HeaderActive = 1; + psHeaderActive = 1; /* ps header is one frame delayed */ + + /* + update vk_master table + */ + if (updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + hEnvEncoder->downSampleFactor)) + return (1); + + /* reset SBR channels */ + INT nEnvCh = hSbrElement->sbrConfigData.nChannels; + for (ch = 0; ch < nEnvCh; ch++) { + if (resetEnvChannel(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel)) + return (1); + } + } + } + + /* + allocate space for dummy header and crc + */ + crcReg = FDKsbrEnc_InitSbrBitstream( + &hSbrElement->CmonData, + hSbrElement->payloadDelayLine[hEnvEncoder->nBitstrDelay], + MAX_PAYLOAD_SIZE * sizeof(UCHAR), &crcInfo, + hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* Temporal Envelope Data */ + SBR_FRAME_TEMP_DATA _fData; + SBR_FRAME_TEMP_DATA *fData = &_fData; + SBR_ENV_TEMP_DATA eData[MAX_NUM_CHANNELS]; + + /* Init Temporal Envelope Data */ + { + int i; + + FDKmemclear(&eData[0], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(&eData[1], sizeof(SBR_ENV_TEMP_DATA)); + FDKmemclear(fData, sizeof(SBR_FRAME_TEMP_DATA)); + + for (i = 0; i < MAX_NUM_NOISE_VALUES; i++) fData->res[i] = FREQ_RES_HIGH; + } + + if (!clearOutput) { + /* + * Transform audio data into QMF domain + */ + for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) { + HANDLE_ENV_CHANNEL h_envChan = &hSbrElement->sbrChannel[ch]->hEnvChannel; + HANDLE_SBR_EXTRACT_ENVELOPE sbrExtrEnv = &h_envChan->sbrExtractEnvelope; + + if (hSbrElement->elInfo.fParametricStereo == 0) { + QMF_SCALE_FACTOR tmpScale; + FIXP_DBL **pQmfReal, **pQmfImag; + C_AALLOC_SCRATCH_START(qmfWorkBuffer, FIXP_DBL, 64 * 2) + + /* Obtain pointers to QMF buffers. */ + pQmfReal = sbrExtrEnv->rBuffer; + pQmfImag = sbrExtrEnv->iBuffer; + + qmfAnalysisFiltering( + hSbrElement->hQmfAnalysis[ch], pQmfReal, pQmfImag, &tmpScale, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, 0, + 1, qmfWorkBuffer); + + h_envChan->qmfScale = tmpScale.lb_scale + 7; + + C_AALLOC_SCRATCH_END(qmfWorkBuffer, FIXP_DBL, 64 * 2) + + } /* fParametricStereo == 0 */ + + /* + Parametric Stereo processing + */ + if (hSbrElement->elInfo.fParametricStereo) { + INT error = noError; + + /* Limit Parametric Stereo to one instance */ + FDK_ASSERT(ch == 0); + + if (error == noError) { + /* parametric stereo processing: + - input: + o left and right time domain samples + - processing: + o stereo qmf analysis + o stereo hybrid analysis + o ps parameter extraction + o downmix + hybrid synthesis + - output: + o downmixed qmf data is written to sbrExtrEnv->rBuffer and + sbrExtrEnv->iBuffer + */ + SCHAR qmfScale; + INT_PCM *pSamples[2] = { + samples + hSbrElement->elInfo.ChannelIndex[0] * samplesBufSize, + samples + hSbrElement->elInfo.ChannelIndex[1] * samplesBufSize}; + error = FDKsbrEnc_PSEnc_ParametricStereoProcessing( + hEnvEncoder->hParametricStereo, pSamples, samplesBufSize, + hSbrElement->hQmfAnalysis, sbrExtrEnv->rBuffer, + sbrExtrEnv->iBuffer, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, + &hEnvEncoder->qmfSynthesisPS, &qmfScale, psHeaderActive); + h_envChan->qmfScale = (int)qmfScale; + } + + } /* if (hEnvEncoder->hParametricStereo) */ + + /* + + Extract Envelope relevant things from QMF data + + */ + FDKsbrEnc_extractSbrEnvelope1(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + &hSbrElement->sbrBitstreamData, h_envChan, + &hSbrElement->CmonData, &eData[ch], fData); + + } /* hEnvEncoder->sbrConfigData.nChannels */ + } + + /* + Process Envelope relevant things and calculate envelope data and write + payload + */ + FDKsbrEnc_extractSbrEnvelope2( + &hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData, + (hSbrElement->elInfo.fParametricStereo) ? hEnvEncoder->hParametricStereo + : NULL, + &hSbrElement->sbrBitstreamData, &hSbrElement->sbrChannel[0]->hEnvChannel, + (hSbrElement->sbrConfigData.stereoMode != SBR_MONO) + ? &hSbrElement->sbrChannel[1]->hEnvChannel + : NULL, + &hSbrElement->CmonData, eData, fData, clearOutput); + + hSbrElement->sbrBitstreamData.rightBorderFIX = 0; + + /* + format payload, calculate crc + */ + FDKsbrEnc_AssembleSbrBitstream(&hSbrElement->CmonData, &crcInfo, crcReg, + hSbrElement->sbrConfigData.sbrSyntaxFlags); + + /* + save new payload, set to zero length if greater than MAX_PAYLOAD_SIZE + */ + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = + FDKgetValidBits(&hSbrElement->CmonData.sbrBitbuf); + + if (hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] > + (MAX_PAYLOAD_SIZE << 3)) + hSbrElement->payloadDelayLineSize[hEnvEncoder->nBitstrDelay] = 0; + + /* While filling the Delay lines, sbrData is NULL */ + if (sbrData) { + *sbrDataBits = hSbrElement->payloadDelayLineSize[0]; + FDKmemcpy(sbrData, hSbrElement->payloadDelayLine[0], + (hSbrElement->payloadDelayLineSize[0] + 7) >> 3); + } + + /* delay header active flag */ + if (hSbrElement->sbrBitstreamData.HeaderActive == 1) { + hSbrElement->sbrBitstreamData.HeaderActiveDelay = + 1 + hEnvEncoder->nBitstrDelay; + } else { + if (hSbrElement->sbrBitstreamData.HeaderActiveDelay > 0) { + hSbrElement->sbrBitstreamData.HeaderActiveDelay--; + } + } + + return (0); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_Downsample + description: performs downsampling and delay compensation of the core path + returns: + input: + output: + +*****************************************************************************/ +INT FDKsbrEnc_Downsample( + HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *samples, /*!< time samples, always deinterleaved */ + UINT samplesBufSize, /*!< time buffer size per channel */ + UINT numChannels, /*!< number of channels */ + UINT *sbrDataBits, /*!< Size of SBR payload */ + UCHAR *sbrData, /*!< SBR payload */ + int clearOutput /*!< Do not consider any input signal */ +) { + HANDLE_SBR_ELEMENT hSbrElement = NULL; + INT nOutSamples; + int el; + if (hSbrEncoder->downSampleFactor > 1) { + /* Do downsampling */ + + /* Loop over elements (LFE is handled later) */ + for (el = 0; el < hSbrEncoder->noElements; el++) { + hSbrElement = hSbrEncoder->sbrElement[el]; + if (hSbrEncoder->sbrElement[el] != NULL) { + if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) { + int ch; + int nChannels = hSbrElement->sbrConfigData.nChannels; + + for (ch = 0; ch < nChannels; ch++) { + FDKaacEnc_Downsample( + &hSbrElement->sbrChannel[ch]->downSampler, + samples + + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + hSbrElement->sbrConfigData.frameSize, + samples + hSbrElement->elInfo.ChannelIndex[ch] * samplesBufSize, + &nOutSamples); + } + } + } + } + + /* Handle LFE (if existing) */ + if (hSbrEncoder->lfeChIdx != -1) { /* lfe downsampler */ + FDKaacEnc_Downsample(&hSbrEncoder->lfeDownSampler, + samples + hSbrEncoder->lfeChIdx * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + hSbrEncoder->frameSize, + samples + hSbrEncoder->lfeChIdx * samplesBufSize, + &nOutSamples); + } + } else { + /* No downsampling. Still, some buffer shifting for correct delay */ + int samples2Copy = hSbrEncoder->frameSize; + if (hSbrEncoder->bufferOffset / (int)numChannels < samples2Copy) { + for (int c = 0; c < (int)numChannels; c++) { + /* Do memmove while taking care of overlapping memory areas. (memcpy + does not necessarily take care) Distinguish between oeverlapping and + non overlapping version due to reasons of complexity. */ + FDKmemmove(samples + c * samplesBufSize, + samples + c * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + samples2Copy * sizeof(INT_PCM)); + } + } else { + for (int c = 0; c < (int)numChannels; c++) { + /* Simple memcpy since the memory areas are not overlapping */ + FDKmemcpy(samples + c * samplesBufSize, + samples + c * samplesBufSize + + hSbrEncoder->bufferOffset / numChannels, + samples2Copy * sizeof(INT_PCM)); + } + } + } + + return 0; +} + +/***************************************************************************** + + functionname: createEnvChannel + description: initializes parameters and allocates memory + returns: error status + input: + output: hEnv + +*****************************************************************************/ + +static INT createEnvChannel(HANDLE_ENV_CHANNEL hEnv, INT channel, + UCHAR *dynamic_RAM) { + FDKmemclear(hEnv, sizeof(struct ENV_CHANNEL)); + + if (FDKsbrEnc_CreateTonCorrParamExtr(&hEnv->TonCorr, channel)) { + return (1); + } + + if (FDKsbrEnc_CreateExtractSbrEnvelope(&hEnv->sbrExtractEnvelope, channel, + /*chan*/ 0, dynamic_RAM)) { + return (1); + } + + return 0; +} + +/***************************************************************************** + + functionname: initEnvChannel + description: initializes parameters + returns: error status + input: + output: + +*****************************************************************************/ +static INT initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData, + HANDLE_SBR_HEADER_DATA sbrHeaderData, + HANDLE_ENV_CHANNEL hEnv, sbrConfigurationPtr params, + ULONG statesInitFlag, INT chanInEl, + UCHAR *dynamic_RAM) { + int frameShift, tran_off = 0; + INT e; + INT tran_fc; + INT timeSlots, timeStep, startIndex; + INT noiseBands[2] = {3, 3}; + + e = 1 << params->e; + + FDK_ASSERT(params->e >= 0); + + hEnv->encEnvData.freq_res_fixfix[0] = params->freq_res_fixfix[0]; + hEnv->encEnvData.freq_res_fixfix[1] = params->freq_res_fixfix[1]; + hEnv->encEnvData.fResTransIsLow = params->fResTransIsLow; + + hEnv->fLevelProtect = 0; + + hEnv->encEnvData.ldGrid = + (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) ? 1 : 0; + + hEnv->encEnvData.sbr_xpos_mode = (XPOS_MODE)params->sbr_xpos_mode; + + if (hEnv->encEnvData.sbr_xpos_mode == XPOS_SWITCHED) { + /* + no other type than XPOS_MDCT or XPOS_SPEECH allowed, + but enable switching + */ + sbrConfigData->switchTransposers = TRUE; + hEnv->encEnvData.sbr_xpos_mode = XPOS_MDCT; + } else { + sbrConfigData->switchTransposers = FALSE; + } + + hEnv->encEnvData.sbr_xpos_ctrl = params->sbr_xpos_ctrl; + + /* extended data */ + if (params->parametricCoding) { + hEnv->encEnvData.extended_data = 1; + } else { + hEnv->encEnvData.extended_data = 0; + } + + hEnv->encEnvData.extension_size = 0; + + startIndex = QMF_FILTER_PROTOTYPE_SIZE - sbrConfigData->noQmfBands; + + switch (params->sbrFrameSize) { + case 2304: + timeSlots = 18; + break; + case 2048: + case 1024: + case 512: + timeSlots = 16; + break; + case 1920: + case 960: + case 480: + timeSlots = 15; + break; + case 1152: + timeSlots = 9; + break; + default: + return (1); /* Illegal frame size */ + } + + timeStep = sbrConfigData->noQmfSlots / timeSlots; + + if (FDKsbrEnc_InitTonCorrParamExtr( + params->sbrFrameSize, &hEnv->TonCorr, sbrConfigData, timeSlots, + params->sbr_xpos_ctrl, params->ana_max_level, + sbrHeaderData->sbr_noise_bands, params->noiseFloorOffset, + params->useSpeechConfig)) + return (1); + + hEnv->encEnvData.noOfnoisebands = + hEnv->TonCorr.sbrNoiseFloorEstimate.noNoiseBands; + + noiseBands[0] = hEnv->encEnvData.noOfnoisebands; + noiseBands[1] = hEnv->encEnvData.noOfnoisebands; + + hEnv->encEnvData.sbr_invf_mode = (INVF_MODE)params->sbr_invf_mode; + + if (hEnv->encEnvData.sbr_invf_mode == INVF_SWITCHED) { + hEnv->encEnvData.sbr_invf_mode = INVF_MID_LEVEL; + hEnv->TonCorr.switchInverseFilt = TRUE; + } else { + hEnv->TonCorr.switchInverseFilt = FALSE; + } + + tran_fc = params->tran_fc; + + if (tran_fc == 0) { + tran_fc = fixMin( + 5000, FDKsbrEnc_getSbrStartFreqRAW(sbrHeaderData->sbr_start_frequency, + params->codecSettings.sampleFreq)); + } + + tran_fc = + (tran_fc * 4 * sbrConfigData->noQmfBands / sbrConfigData->sampleFreq + + 1) >> + 1; + + if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + frameShift = LD_PRETRAN_OFF; + tran_off = LD_PRETRAN_OFF + FRAME_MIDDLE_SLOT_512LD * timeStep; + } else { + frameShift = 0; + switch (timeSlots) { + /* The factor of 2 is by definition. */ + case NUMBER_TIME_SLOTS_2048: + tran_off = 8 + FRAME_MIDDLE_SLOT_2048 * timeStep; + break; + case NUMBER_TIME_SLOTS_1920: + tran_off = 7 + FRAME_MIDDLE_SLOT_1920 * timeStep; + break; + default: + return 1; + } + } + if (FDKsbrEnc_InitExtractSbrEnvelope( + &hEnv->sbrExtractEnvelope, sbrConfigData->noQmfSlots, + sbrConfigData->noQmfBands, startIndex, timeSlots, timeStep, tran_off, + statesInitFlag, chanInEl, dynamic_RAM, sbrConfigData->sbrSyntaxFlags)) + return (1); + + if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeEnvelope, sbrConfigData->nSfb, + params->deltaTAcrossFrames, + params->dF_edge_1stEnv, + params->dF_edge_incr)) + return (1); + + if (FDKsbrEnc_InitSbrCodeEnvelope(&hEnv->sbrCodeNoiseFloor, noiseBands, + params->deltaTAcrossFrames, 0, 0)) + return (1); + + sbrConfigData->initAmpResFF = params->init_amp_res_FF; + + if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope, + &hEnv->sbrCodeNoiseFloor, + sbrHeaderData->sbr_amp_res)) + return (1); + + FDKsbrEnc_initFrameInfoGenerator( + &hEnv->SbrEnvFrame, params->spread, e, params->stat, timeSlots, + hEnv->encEnvData.freq_res_fixfix, hEnv->encEnvData.fResTransIsLow, + hEnv->encEnvData.ldGrid); + + if (sbrConfigData->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + + { + INT bandwidth_qmf_slot = + (sbrConfigData->sampleFreq >> 1) / (sbrConfigData->noQmfBands); + if (FDKsbrEnc_InitSbrFastTransientDetector( + &hEnv->sbrFastTransientDetector, sbrConfigData->noQmfSlots, + bandwidth_qmf_slot, sbrConfigData->noQmfBands, + sbrConfigData->freqBandTable[0][0])) + return (1); + } + + /* The transient detector has to be initialized also if the fast transient + detector was active, because the values from the transient detector + structure are used. */ + if (FDKsbrEnc_InitSbrTransientDetector( + &hEnv->sbrTransientDetector, sbrConfigData->sbrSyntaxFlags, + sbrConfigData->frameSize, sbrConfigData->sampleFreq, params, tran_fc, + sbrConfigData->noQmfSlots, sbrConfigData->noQmfBands, + hEnv->sbrExtractEnvelope.YBufferWriteOffset, + hEnv->sbrExtractEnvelope.YBufferSzShift, frameShift, tran_off)) + return (1); + + sbrConfigData->xposCtrlSwitch = params->sbr_xpos_ctrl; + + hEnv->encEnvData.noHarmonics = sbrConfigData->nSfb[HI]; + hEnv->encEnvData.addHarmonicFlag = 0; + + return (0); +} + +INT sbrEncoder_Open(HANDLE_SBR_ENCODER *phSbrEncoder, INT nElements, + INT nChannels, INT supportPS) { + INT i; + INT errorStatus = 1; + HANDLE_SBR_ENCODER hSbrEncoder = NULL; + + if (phSbrEncoder == NULL) { + goto bail; + } + + hSbrEncoder = GetRam_SbrEncoder(); + if (hSbrEncoder == NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder, sizeof(SBR_ENCODER)); + + if (NULL == + (hSbrEncoder->pSBRdynamic_RAM = (UCHAR *)GetRam_SbrDynamic_RAM())) { + goto bail; + } + hSbrEncoder->dynamicRam = hSbrEncoder->pSBRdynamic_RAM; + + /* Create SBR elements */ + for (i = 0; i < nElements; i++) { + hSbrEncoder->sbrElement[i] = GetRam_SbrElement(i); + if (hSbrEncoder->sbrElement[i] == NULL) { + goto bail; + } + FDKmemclear(hSbrEncoder->sbrElement[i], sizeof(SBR_ELEMENT)); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] = + GetRam_Sbr_freqBandTableLO(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] = + GetRam_Sbr_freqBandTableHI(i); + hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master = + GetRam_Sbr_v_k_master(i); + if ((hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[LO] == NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.freqBandTable[HI] == NULL) || + (hSbrEncoder->sbrElement[i]->sbrConfigData.v_k_master == NULL)) { + goto bail; + } + } + + /* Create SBR channels */ + for (i = 0; i < nChannels; i++) { + hSbrEncoder->pSbrChannel[i] = GetRam_SbrChannel(i); + if (hSbrEncoder->pSbrChannel[i] == NULL) { + goto bail; + } + + if (createEnvChannel(&hSbrEncoder->pSbrChannel[i]->hEnvChannel, i, + hSbrEncoder->dynamicRam)) { + goto bail; + } + } + + /* Create QMF States */ + for (i = 0; i < fixMax(nChannels, (supportPS) ? 2 : 0); i++) { + hSbrEncoder->QmfAnalysis[i].FilterStates = GetRam_Sbr_QmfStatesAnalysis(i); + if (hSbrEncoder->QmfAnalysis[i].FilterStates == NULL) { + goto bail; + } + } + + /* Create Parametric Stereo handle */ + if (supportPS) { + if (PSEnc_Create(&hSbrEncoder->hParametricStereo)) { + goto bail; + } + + hSbrEncoder->qmfSynthesisPS.FilterStates = GetRam_PsQmfStatesSynthesis(); + if (hSbrEncoder->qmfSynthesisPS.FilterStates == NULL) { + goto bail; + } + } /* supportPS */ + + *phSbrEncoder = hSbrEncoder; + + errorStatus = 0; + return errorStatus; + +bail: + /* Close SBR encoder instance */ + sbrEncoder_Close(&hSbrEncoder); + return errorStatus; +} + +static INT FDKsbrEnc_Reallocate(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], + const INT noElements) { + INT totalCh = 0; + INT totalQmf = 0; + INT coreEl; + INT el = -1; + + hSbrEncoder->lfeChIdx = -1; /* default value, until lfe found */ + + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) { + el++; + } else { + if (elInfo[coreEl].elType == ID_LFE) { + hSbrEncoder->lfeChIdx = elInfo[coreEl].ChannelIndex[0]; + } + continue; + } + + SBR_ELEMENT_INFO *pelInfo = &elInfo[coreEl]; + HANDLE_SBR_ELEMENT hSbrElement = hSbrEncoder->sbrElement[el]; + + int ch; + for (ch = 0; ch < pelInfo->nChannelsInEl; ch++) { + hSbrElement->sbrChannel[ch] = hSbrEncoder->pSbrChannel[totalCh]; + totalCh++; + } + /* analysis QMF */ + for (ch = 0; + ch < ((pelInfo->fParametricStereo) ? 2 : pelInfo->nChannelsInEl); + ch++) { + hSbrElement->elInfo.ChannelIndex[ch] = pelInfo->ChannelIndex[ch]; + hSbrElement->hQmfAnalysis[ch] = &hSbrEncoder->QmfAnalysis[totalQmf++]; + } + + /* Copy Element info */ + hSbrElement->elInfo.elType = pelInfo->elType; + hSbrElement->elInfo.instanceTag = pelInfo->instanceTag; + hSbrElement->elInfo.nChannelsInEl = pelInfo->nChannelsInEl; + hSbrElement->elInfo.fParametricStereo = pelInfo->fParametricStereo; + hSbrElement->elInfo.fDualMono = pelInfo->fDualMono; + } /* coreEl */ + + return 0; +} + +/***************************************************************************** + + functionname: FDKsbrEnc_bsBufInit + description: initializes bitstream buffer + returns: initialized bitstream buffer in env encoder + input: + output: hEnv + +*****************************************************************************/ +static INT FDKsbrEnc_bsBufInit(HANDLE_SBR_ELEMENT hSbrElement, + int nBitstrDelay) { + UCHAR *bitstreamBuffer; + + /* initialize the bitstream buffer */ + bitstreamBuffer = hSbrElement->payloadDelayLine[nBitstrDelay]; + FDKinitBitStream(&hSbrElement->CmonData.sbrBitbuf, bitstreamBuffer, + MAX_PAYLOAD_SIZE * sizeof(UCHAR), 0, BS_WRITER); + + return (0); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_EnvInit + description: initializes parameters + returns: error status + input: + output: hEnv + +*****************************************************************************/ +static INT FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement, + sbrConfigurationPtr params, INT *coreBandWith, + AUDIO_OBJECT_TYPE aot, int nElement, + const int headerPeriod, ULONG statesInitFlag, + const SBRENC_DS_TYPE downsamplingMethod, + UCHAR *dynamic_RAM) { + int ch, i; + + if ((params->codecSettings.nChannels < 1) || + (params->codecSettings.nChannels > MAX_NUM_CHANNELS)) { + return (1); + } + + /* init and set syntax flags */ + hSbrElement->sbrConfigData.sbrSyntaxFlags = 0; + + switch (aot) { + case AOT_ER_AAC_ELD: + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_LOW_DELAY; + break; + default: + break; + } + if (params->crcSbr) { + hSbrElement->sbrConfigData.sbrSyntaxFlags |= SBR_SYNTAX_CRC; + } + + hSbrElement->sbrConfigData.noQmfBands = 64 >> (2 - params->downSampleFactor); + switch (hSbrElement->sbrConfigData.noQmfBands) { + case 64: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6; + break; + case 32: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 5; + break; + default: + hSbrElement->sbrConfigData.noQmfSlots = params->sbrFrameSize >> 6; + return (2); + } + + /* + now initialize sbrConfigData, sbrHeaderData and sbrBitstreamData, + */ + hSbrElement->sbrConfigData.nChannels = params->codecSettings.nChannels; + + if (params->codecSettings.nChannels == 2) { + if ((hSbrElement->elInfo.elType == ID_CPE) && + ((hSbrElement->elInfo.fDualMono == 1))) { + hSbrElement->sbrConfigData.stereoMode = SBR_LEFT_RIGHT; + } else { + hSbrElement->sbrConfigData.stereoMode = params->stereoMode; + } + } else { + hSbrElement->sbrConfigData.stereoMode = SBR_MONO; + } + + hSbrElement->sbrConfigData.frameSize = params->sbrFrameSize; + + hSbrElement->sbrConfigData.sampleFreq = + params->downSampleFactor * params->codecSettings.sampleFreq; + + hSbrElement->sbrBitstreamData.CountSendHeaderData = 0; + if (params->SendHeaderDataTime > 0) { + if (headerPeriod == -1) { + hSbrElement->sbrBitstreamData.NrSendHeaderData = (INT)( + params->SendHeaderDataTime * hSbrElement->sbrConfigData.sampleFreq / + (1000 * hSbrElement->sbrConfigData.frameSize)); + hSbrElement->sbrBitstreamData.NrSendHeaderData = + fixMax(hSbrElement->sbrBitstreamData.NrSendHeaderData, 1); + } else { + /* assure header period at least once per second */ + hSbrElement->sbrBitstreamData.NrSendHeaderData = fixMin( + fixMax(headerPeriod, 1), (hSbrElement->sbrConfigData.sampleFreq / + hSbrElement->sbrConfigData.frameSize)); + } + } else { + hSbrElement->sbrBitstreamData.NrSendHeaderData = 0; + } + + hSbrElement->sbrHeaderData.sbr_data_extra = params->sbr_data_extra; + hSbrElement->sbrBitstreamData.HeaderActive = 0; + hSbrElement->sbrBitstreamData.rightBorderFIX = 0; + hSbrElement->sbrHeaderData.sbr_start_frequency = params->startFreq; + hSbrElement->sbrHeaderData.sbr_stop_frequency = params->stopFreq; + hSbrElement->sbrHeaderData.sbr_xover_band = 0; + hSbrElement->sbrHeaderData.sbr_lc_stereo_mode = 0; + + /* data_extra */ + if (params->sbr_xpos_ctrl != SBR_XPOS_CTRL_DEFAULT) + hSbrElement->sbrHeaderData.sbr_data_extra = 1; + + hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res; + + /* header_extra_1 */ + hSbrElement->sbrHeaderData.freqScale = params->freqScale; + hSbrElement->sbrHeaderData.alterScale = params->alterScale; + hSbrElement->sbrHeaderData.sbr_noise_bands = params->sbr_noise_bands; + hSbrElement->sbrHeaderData.header_extra_1 = 0; + + if ((params->freqScale != SBR_FREQ_SCALE_DEFAULT) || + (params->alterScale != SBR_ALTER_SCALE_DEFAULT) || + (params->sbr_noise_bands != SBR_NOISE_BANDS_DEFAULT)) { + hSbrElement->sbrHeaderData.header_extra_1 = 1; + } + + /* header_extra_2 */ + hSbrElement->sbrHeaderData.sbr_limiter_bands = params->sbr_limiter_bands; + hSbrElement->sbrHeaderData.sbr_limiter_gains = params->sbr_limiter_gains; + + if ((hSbrElement->sbrConfigData.sampleFreq > 48000) && + (hSbrElement->sbrHeaderData.sbr_start_frequency >= 9)) { + hSbrElement->sbrHeaderData.sbr_limiter_gains = SBR_LIMITER_GAINS_INFINITE; + } + + hSbrElement->sbrHeaderData.sbr_interpol_freq = params->sbr_interpol_freq; + hSbrElement->sbrHeaderData.sbr_smoothing_length = + params->sbr_smoothing_length; + hSbrElement->sbrHeaderData.header_extra_2 = 0; + + if ((params->sbr_limiter_bands != SBR_LIMITER_BANDS_DEFAULT) || + (params->sbr_limiter_gains != SBR_LIMITER_GAINS_DEFAULT) || + (params->sbr_interpol_freq != SBR_INTERPOL_FREQ_DEFAULT) || + (params->sbr_smoothing_length != SBR_SMOOTHING_LENGTH_DEFAULT)) { + hSbrElement->sbrHeaderData.header_extra_2 = 1; + } + + /* other switches */ + hSbrElement->sbrConfigData.useWaveCoding = params->useWaveCoding; + hSbrElement->sbrConfigData.useParametricCoding = params->parametricCoding; + hSbrElement->sbrConfigData.thresholdAmpResFF_m = + params->threshold_AmpRes_FF_m; + hSbrElement->sbrConfigData.thresholdAmpResFF_e = + params->threshold_AmpRes_FF_e; + + /* init freq band table */ + if (updateFreqBandTable(&hSbrElement->sbrConfigData, + &hSbrElement->sbrHeaderData, + params->downSampleFactor)) { + return (1); + } + + /* now create envelope ext and QMF for each available channel */ + for (ch = 0; ch < hSbrElement->sbrConfigData.nChannels; ch++) { + if (initEnvChannel(&hSbrElement->sbrConfigData, &hSbrElement->sbrHeaderData, + &hSbrElement->sbrChannel[ch]->hEnvChannel, params, + statesInitFlag, ch, dynamic_RAM)) { + return (1); + } + + } /* nChannels */ + + /* reset and intialize analysis qmf */ + for (ch = 0; ch < ((hSbrElement->elInfo.fParametricStereo) + ? 2 + : hSbrElement->sbrConfigData.nChannels); + ch++) { + int err; + UINT qmfFlags = + (hSbrElement->sbrConfigData.sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) + ? QMF_FLAG_CLDFB + : 0; + if (statesInitFlag) + qmfFlags &= ~QMF_FLAG_KEEP_STATES; + else + qmfFlags |= QMF_FLAG_KEEP_STATES; + + err = qmfInitAnalysisFilterBank( + hSbrElement->hQmfAnalysis[ch], + (FIXP_QAS *)hSbrElement->hQmfAnalysis[ch]->FilterStates, + hSbrElement->sbrConfigData.noQmfSlots, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, + hSbrElement->sbrConfigData.noQmfBands, qmfFlags); + if (0 != err) { + return err; + } + } + + /* */ + hSbrElement->CmonData.xOverFreq = hSbrElement->sbrConfigData.xOverFreq; + hSbrElement->CmonData.dynBwEnabled = + (params->dynBwSupported && params->dynBwEnabled); + hSbrElement->CmonData.dynXOverFreqEnc = + FDKsbrEnc_SbrGetXOverFreq(hSbrElement, hSbrElement->CmonData.xOverFreq); + for (i = 0; i < 5; i++) + hSbrElement->dynXOverFreqDelay[i] = hSbrElement->CmonData.dynXOverFreqEnc; + hSbrElement->CmonData.sbrNumChannels = hSbrElement->sbrConfigData.nChannels; + hSbrElement->sbrConfigData.dynXOverFreq = hSbrElement->CmonData.xOverFreq; + + /* Update Bandwith to be passed to the core encoder */ + *coreBandWith = hSbrElement->CmonData.xOverFreq; + + return (0); +} + +INT sbrEncoder_GetInBufferSize(int noChannels) { + INT temp; + + temp = (2048); + temp += 1024 + MAX_SAMPLE_DELAY; + temp *= noChannels; + temp *= sizeof(INT_PCM); + return temp; +} + +/* + * Encode Dummy SBR payload frames to fill the delay lines. + */ +static INT FDKsbrEnc_DelayCompensation(HANDLE_SBR_ENCODER hEnvEnc, + INT_PCM *timeBuffer, + UINT timeBufferBufSize) { + int n, el; + + for (n = hEnvEnc->nBitstrDelay; n > 0; n--) { + for (el = 0; el < hEnvEnc->noElements; el++) { + if (FDKsbrEnc_EnvEncodeFrame( + hEnvEnc, el, + timeBuffer + hEnvEnc->downsampledOffset / hEnvEnc->nChannels, + timeBufferBufSize, NULL, NULL, 1)) + return -1; + } + sbrEncoder_UpdateBuffers(hEnvEnc, timeBuffer, timeBufferBufSize); + } + return 0; +} + +UINT sbrEncoder_LimitBitRate(UINT bitRate, UINT numChannels, + UINT coreSampleRate, AUDIO_OBJECT_TYPE aot) { + UINT newBitRate = bitRate; + INT index; + + FDK_ASSERT(numChannels > 0 && numChannels <= 2); + if (aot == AOT_PS) { + if (numChannels == 1) { + index = getPsTuningTableIndex(bitRate, &newBitRate); + if (index == INVALID_TABLE_IDX) { + bitRate = newBitRate; + } + } else { + return 0; + } + } + index = getSbrTuningTableIndex(bitRate, numChannels, coreSampleRate, aot, + &newBitRate); + if (index != INVALID_TABLE_IDX) { + newBitRate = bitRate; + } + + return newBitRate; +} + +UINT sbrEncoder_IsSingleRatePossible(AUDIO_OBJECT_TYPE aot) { + UINT isPossible = (AOT_PS == aot) ? 0 : 1; + return isPossible; +} + +/*****************************************************************************/ +/* */ +/*functionname: sbrEncoder_Init_delay */ +/*description: Determine Delay balancing and new encoder delay */ +/* */ +/*returns: - error status */ +/*input: - frame length of the core (i.e. e.g. AAC) */ +/* - number of channels */ +/* - downsample factor (1 for downsampled, 2 for dual-rate SBR) */ +/* - low delay presence */ +/* - ps presence */ +/* - downsampling method: QMF-, time domain or no downsampling */ +/* - various delay values (see DELAY_PARAM struct description) */ +/* */ +/*Example: Delay balancing for a HE-AACv1 encoder (time-domain downsampling) */ +/*========================================================================== */ +/* */ +/* +--------+ +--------+ +--------+ +--------+ +--------+ */ +/* |core | |ds 2:1 | |AAC | |QMF | |QMF | */ +/* +-+path +------------+ +-+core +-+analysis+-+overlap +-+ */ +/* | |offset | | | | | |32 bands| | | | */ +/* | +--------+ +--------+ +--------+ +--------+ +--------+ | */ +/* | core path +-------++ */ +/* | |QMF | */ +/*->+ +synth. +-> */ +/* | |64 bands| */ +/* | +-------++ */ +/* | +--------+ +--------+ +--------+ +--------+ | */ +/* | |SBR path| |QMF | |subband | |bs delay| | */ +/* +-+offset +-+analysis+-+sample +-+(full +-----------------------+ */ +/* | | |64 bands| |buffer | | frames)| */ +/* +--------+ +--------+ +--------+ +--------+ */ +/* SBR path */ +/* */ +/*****************************************************************************/ +static INT sbrEncoder_Init_delay( + const int coreFrameLength, /* input */ + const int numChannels, /* input */ + const int downSampleFactor, /* input */ + const int lowDelay, /* input */ + const int usePs, /* input */ + const int is212, /* input */ + const SBRENC_DS_TYPE downsamplingMethod, /* input */ + DELAY_PARAM *hDelayParam /* input/output */ +) { + int delayCorePath = 0; /* delay in core path */ + int delaySbrPath = 0; /* delay difference in QMF aka SBR path */ + int delayInput2Core = 0; /* delay from the input to the core */ + int delaySbrDec = 0; /* delay of the decoder's SBR module */ + + int delayCore = hDelayParam->delay; /* delay of the core */ + + /* Added delay by the SBR delay initialization */ + int corePathOffset = 0; /* core path */ + int sbrPathOffset = 0; /* sbr path */ + int bitstreamDelay = 0; /* sbr path, framewise */ + + int flCore = coreFrameLength; /* core frame length */ + + int returnValue = 0; /* return value - 0 means: no error */ + + /* 1) Calculate actual delay for core and SBR path */ + if (is212) { + delayCorePath = DELAY_COREPATH_ELDv2SBR(flCore, downSampleFactor); + delaySbrPath = DELAY_ELDv2SBR(flCore, downSampleFactor); + delaySbrDec = ((flCore) / 2) * (downSampleFactor); + } else if (lowDelay) { + delayCorePath = DELAY_COREPATH_ELDSBR(flCore, downSampleFactor); + delaySbrPath = DELAY_ELDSBR(flCore, downSampleFactor); + delaySbrDec = DELAY_QMF_POSTPROC(downSampleFactor); + } else if (usePs) { + delayCorePath = DELAY_COREPATH_PS(flCore, downSampleFactor); + delaySbrPath = DELAY_PS(flCore, downSampleFactor); + delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor); + } else { + delayCorePath = DELAY_COREPATH_SBR(flCore, downSampleFactor); + delaySbrPath = DELAY_SBR(flCore, downSampleFactor); + delaySbrDec = DELAY_COREPATH_SBR(flCore, downSampleFactor); + } + delayCorePath += delayCore * downSampleFactor; + delayCorePath += + (downsamplingMethod == SBRENC_DS_TIME) ? hDelayParam->dsDelay : 0; + + /* 2) Manage coupling of paths */ + if (downsamplingMethod == SBRENC_DS_QMF && delayCorePath > delaySbrPath) { + /* In case of QMF downsampling, both paths are coupled, i.e. the SBR path + offset would be added to both the SBR path and to the core path + as well, thus making it impossible to achieve delay balancing. + To overcome that problem, a framewise delay is added to the SBR path + first, until the overall delay of the core path is shorter than + the delay of the SBR path. When this is achieved, the missing delay + difference can be added as downsampled offset to the core path. + */ + while (delayCorePath > delaySbrPath) { + /* Add one frame delay to SBR path */ + delaySbrPath += flCore * downSampleFactor; + bitstreamDelay += 1; + } + } + + /* 3) Calculate necessary additional delay to balance the paths */ + if (delayCorePath > delaySbrPath) { + /* Delay QMF input */ + while (delayCorePath > delaySbrPath + (int)flCore * (int)downSampleFactor) { + /* Do bitstream frame-wise delay balancing if there are + more than SBR framelength samples delay difference */ + delaySbrPath += flCore * downSampleFactor; + bitstreamDelay += 1; + } + /* Multiply input offset by input channels */ + corePathOffset = 0; + sbrPathOffset = (delayCorePath - delaySbrPath) * numChannels; + } else { + /* Delay AAC data */ + /* Multiply downsampled offset by AAC core channels. Divide by 2 because of + half samplerate of downsampled data. */ + corePathOffset = ((delaySbrPath - delayCorePath) * numChannels) >> + (downSampleFactor - 1); + sbrPathOffset = 0; + } + + /* 4) Calculate delay from input to core */ + if (usePs) { + delayInput2Core = + (DELAY_QMF_ANA(downSampleFactor) + DELAY_QMF_DS + DELAY_HYB_SYN) + + (downSampleFactor * corePathOffset) + 1; + } else if (downsamplingMethod == SBRENC_DS_TIME) { + delayInput2Core = corePathOffset + hDelayParam->dsDelay; + } else { + delayInput2Core = corePathOffset; + } + + /* 6) Set output parameters */ + hDelayParam->delay = FDKmax(delayCorePath, delaySbrPath); /* overall delay */ + hDelayParam->sbrDecDelay = delaySbrDec; /* SBR decoder delay */ + hDelayParam->delayInput2Core = delayInput2Core; /* delay input - core */ + hDelayParam->bitstrDelay = bitstreamDelay; /* bitstream delay, in frames */ + hDelayParam->corePathOffset = corePathOffset; /* offset added to core path */ + hDelayParam->sbrPathOffset = sbrPathOffset; /* offset added to SBR path */ + + return returnValue; +} + +/***************************************************************************** + + functionname: sbrEncoder_Init + description: initializes the SBR encoder + returns: error status + +*****************************************************************************/ +INT sbrEncoder_Init(HANDLE_SBR_ENCODER hSbrEncoder, + SBR_ELEMENT_INFO elInfo[(8)], int noElements, + INT_PCM *inputBuffer, UINT inputBufferBufSize, + INT *coreBandwidth, INT *inputBufferOffset, + INT *numChannels, const UINT syntaxFlags, + INT *coreSampleRate, UINT *downSampleFactor, + INT *frameLength, AUDIO_OBJECT_TYPE aot, int *delay, + int transformFactor, const int headerPeriod, + ULONG statesInitFlag) { + HANDLE_ERROR_INFO errorInfo = noError; + sbrConfiguration sbrConfig[(8)]; + INT error = 0; + INT lowestBandwidth; + /* Save input parameters */ + INT inputSampleRate = *coreSampleRate; + int coreFrameLength = *frameLength; + int inputBandWidth = *coreBandwidth; + int inputChannels = *numChannels; + + SBRENC_DS_TYPE downsamplingMethod = SBRENC_DS_NONE; + int highestSbrStartFreq, highestSbrStopFreq; + int lowDelay = 0; + int usePs = 0; + int is212 = 0; + + DELAY_PARAM delayParam; + + /* check whether SBR setting is available for the current encoder + * configuration (bitrate, samplerate) */ + if (!sbrEncoder_IsSingleRatePossible(aot)) { + *downSampleFactor = 2; + } + + if (aot == AOT_PS || aot == AOT_DABPLUS_PS) { + usePs = 1; + } + if (aot == AOT_ER_AAC_ELD) { + lowDelay = 1; + } else if (aot == AOT_ER_AAC_LD) { + error = 1; + goto bail; + } + + /* Parametric Stereo */ + if (usePs) { + if (*numChannels == 2 && noElements == 1) { + /* Override Element type in case of Parametric stereo */ + elInfo[0].elType = ID_SCE; + elInfo[0].fParametricStereo = 1; + elInfo[0].nChannelsInEl = 1; + /* core encoder gets downmixed mono signal */ + *numChannels = 1; + } else { + error = 1; + goto bail; + } + } /* usePs */ + + /* set the core's sample rate */ + switch (*downSampleFactor) { + case 1: + *coreSampleRate = inputSampleRate; + downsamplingMethod = SBRENC_DS_NONE; + break; + case 2: + *coreSampleRate = inputSampleRate >> 1; + downsamplingMethod = usePs ? SBRENC_DS_QMF : SBRENC_DS_TIME; + break; + default: + *coreSampleRate = inputSampleRate >> 1; + return 0; /* return error */ + } + + /* check whether SBR setting is available for the current encoder + * configuration (bitrate, coreSampleRate) */ + { + int el, coreEl; + + /* Check if every element config is feasible */ + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType != ID_SCE && elInfo[coreEl].elType != ID_CPE) { + continue; + } + /* check if desired configuration is available */ + if (!FDKsbrEnc_IsSbrSettingAvail(elInfo[coreEl].bitRate, 0, + elInfo[coreEl].nChannelsInEl, + inputSampleRate, *coreSampleRate, aot)) { + error = 1; + goto bail; + } + } + + hSbrEncoder->nChannels = *numChannels; + hSbrEncoder->frameSize = coreFrameLength * *downSampleFactor; + hSbrEncoder->downsamplingMethod = downsamplingMethod; + hSbrEncoder->downSampleFactor = *downSampleFactor; + hSbrEncoder->estimateBitrate = 0; + hSbrEncoder->inputDataDelay = 0; + is212 = ((aot == AOT_ER_AAC_ELD) && (syntaxFlags & AC_LD_MPS)) ? 1 : 0; + + /* Open SBR elements */ + el = -1; + highestSbrStartFreq = highestSbrStopFreq = 0; + lowestBandwidth = 99999; + + /* Loop through each core encoder element and get a matching SBR element + * config */ + for (coreEl = 0; coreEl < noElements; coreEl++) { + /* SBR only handles SCE and CPE's */ + if (elInfo[coreEl].elType == ID_SCE || elInfo[coreEl].elType == ID_CPE) { + el++; + } else { + continue; + } + + /* Set parametric Stereo Flag. */ + if (usePs) { + elInfo[coreEl].fParametricStereo = 1; + } else { + elInfo[coreEl].fParametricStereo = 0; + } + + /* + * Init sbrConfig structure + */ + if (!FDKsbrEnc_InitializeSbrDefaults(&sbrConfig[el], *downSampleFactor, + coreFrameLength, IS_LOWDELAY(aot))) { + error = 1; + goto bail; + } + + /* + * Modify sbrConfig structure according to Element parameters + */ + if (!FDKsbrEnc_AdjustSbrSettings( + &sbrConfig[el], elInfo[coreEl].bitRate, + elInfo[coreEl].nChannelsInEl, *coreSampleRate, inputSampleRate, + transformFactor, 24000, 0, 0, /* useSpeechConfig */ + 0, /* lcsMode */ + usePs, /* bParametricStereo */ + aot)) { + error = 1; + goto bail; + } + + /* Find common frequency border for all SBR elements */ + highestSbrStartFreq = + fixMax(highestSbrStartFreq, sbrConfig[el].startFreq); + highestSbrStopFreq = fixMax(highestSbrStopFreq, sbrConfig[el].stopFreq); + + } /* first element loop */ + + /* Set element count (can be less than core encoder element count) */ + hSbrEncoder->noElements = el + 1; + + FDKsbrEnc_Reallocate(hSbrEncoder, elInfo, noElements); + + for (el = 0; el < hSbrEncoder->noElements; el++) { + int bandwidth = *coreBandwidth; + + /* Use lowest common bandwidth */ + sbrConfig[el].startFreq = highestSbrStartFreq; + sbrConfig[el].stopFreq = highestSbrStopFreq; + + /* initialize SBR element, and get core bandwidth */ + error = FDKsbrEnc_EnvInit(hSbrEncoder->sbrElement[el], &sbrConfig[el], + &bandwidth, aot, el, headerPeriod, + statesInitFlag, hSbrEncoder->downsamplingMethod, + hSbrEncoder->dynamicRam); + + if (error != 0) { + error = 2; + goto bail; + } + + /* Get lowest core encoder bandwidth to be returned later. */ + lowestBandwidth = fixMin(lowestBandwidth, bandwidth); + + } /* second element loop */ + + /* Initialize a downsampler for each channel in each SBR element */ + if (hSbrEncoder->downsamplingMethod == SBRENC_DS_TIME) { + for (el = 0; el < hSbrEncoder->noElements; el++) { + HANDLE_SBR_ELEMENT hSbrEl = hSbrEncoder->sbrElement[el]; + INT Wc, ch; + + Wc = 500; /* Cutoff frequency with full bandwidth */ + + for (ch = 0; ch < hSbrEl->elInfo.nChannelsInEl; ch++) { + FDKaacEnc_InitDownsampler(&hSbrEl->sbrChannel[ch]->downSampler, Wc, + *downSampleFactor); + FDK_ASSERT(hSbrEl->sbrChannel[ch]->downSampler.delay <= + MAX_DS_FILTER_DELAY); + } + } /* third element loop */ + + /* lfe */ + FDKaacEnc_InitDownsampler(&hSbrEncoder->lfeDownSampler, 0, + *downSampleFactor); + } + + /* Get delay information */ + delayParam.dsDelay = + hSbrEncoder->sbrElement[0]->sbrChannel[0]->downSampler.delay; + delayParam.delay = *delay; + + error = sbrEncoder_Init_delay(coreFrameLength, *numChannels, + *downSampleFactor, lowDelay, usePs, is212, + downsamplingMethod, &delayParam); + + if (error != 0) { + error = 3; + goto bail; + } + + hSbrEncoder->nBitstrDelay = delayParam.bitstrDelay; + hSbrEncoder->sbrDecDelay = delayParam.sbrDecDelay; + hSbrEncoder->inputDataDelay = delayParam.delayInput2Core; + + /* Assign core encoder Bandwidth */ + *coreBandwidth = lowestBandwidth; + + /* Estimate sbr bitrate, 2.5 kBit/s per sbr channel */ + hSbrEncoder->estimateBitrate += 2500 * (*numChannels); + + /* Initialize bitstream buffer for each element */ + for (el = 0; el < hSbrEncoder->noElements; el++) { + FDKsbrEnc_bsBufInit(hSbrEncoder->sbrElement[el], delayParam.bitstrDelay); + } + + /* initialize parametric stereo */ + if (usePs) { + PSENC_CONFIG psEncConfig; + FDK_ASSERT(hSbrEncoder->noElements == 1); + INT psTuningTableIdx = getPsTuningTableIndex(elInfo[0].bitRate, NULL); + + psEncConfig.frameSize = coreFrameLength; // sbrConfig.sbrFrameSize; + psEncConfig.qmfFilterMode = 0; + psEncConfig.sbrPsDelay = 0; + + /* tuning parameters */ + if (psTuningTableIdx != INVALID_TABLE_IDX) { + psEncConfig.nStereoBands = psTuningTable[psTuningTableIdx].nStereoBands; + psEncConfig.maxEnvelopes = psTuningTable[psTuningTableIdx].nEnvelopes; + psEncConfig.iidQuantErrorThreshold = + (FIXP_DBL)psTuningTable[psTuningTableIdx].iidQuantErrorThreshold; + + /* calculation is not quite linear, increased number of envelopes causes + * more bits */ + /* assume avg. 50 bits per frame for 10 stereo bands / 1 envelope + * configuration */ + hSbrEncoder->estimateBitrate += + ((((*coreSampleRate) * 5 * psEncConfig.nStereoBands * + psEncConfig.maxEnvelopes) / + hSbrEncoder->frameSize)); + + } else { + error = ERROR(CDI, "Invalid ps tuning table index."); + goto bail; + } + + qmfInitSynthesisFilterBank( + &hSbrEncoder->qmfSynthesisPS, + (FIXP_DBL *)hSbrEncoder->qmfSynthesisPS.FilterStates, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands >> 1, + (statesInitFlag) ? 0 : QMF_FLAG_KEEP_STATES); + + if (errorInfo == noError) { + /* update delay */ + psEncConfig.sbrPsDelay = + FDKsbrEnc_GetEnvEstDelay(&hSbrEncoder->sbrElement[0] + ->sbrChannel[0] + ->hEnvChannel.sbrExtractEnvelope); + + errorInfo = + PSEnc_Init(hSbrEncoder->hParametricStereo, &psEncConfig, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfSlots, + hSbrEncoder->sbrElement[0]->sbrConfigData.noQmfBands, + hSbrEncoder->dynamicRam); + } + } + + hSbrEncoder->downsampledOffset = delayParam.corePathOffset; + hSbrEncoder->bufferOffset = delayParam.sbrPathOffset; + *delay = delayParam.delay; + + { hSbrEncoder->downmixSize = coreFrameLength * (*numChannels); } + + /* Delay Compensation: fill bitstream delay buffer with zero input signal */ + if (hSbrEncoder->nBitstrDelay > 0) { + error = FDKsbrEnc_DelayCompensation(hSbrEncoder, inputBuffer, + inputBufferBufSize); + if (error != 0) goto bail; + } + + /* Set Output frame length */ + *frameLength = coreFrameLength * *downSampleFactor; + /* Input buffer offset */ + *inputBufferOffset = + fixMax(delayParam.sbrPathOffset, delayParam.corePathOffset); + } + + return error; + +bail: + /* Restore input settings */ + *coreSampleRate = inputSampleRate; + *frameLength = coreFrameLength; + *numChannels = inputChannels; + *coreBandwidth = inputBandWidth; + + return error; +} + +INT sbrEncoder_EncodeFrame(HANDLE_SBR_ENCODER hSbrEncoder, INT_PCM *samples, + UINT samplesBufSize, UINT sbrDataBits[(8)], + UCHAR sbrData[(8)][MAX_PAYLOAD_SIZE]) { + INT error; + int el; + + for (el = 0; el < hSbrEncoder->noElements; el++) { + if (hSbrEncoder->sbrElement[el] != NULL) { + error = FDKsbrEnc_EnvEncodeFrame( + hSbrEncoder, el, + samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels, + samplesBufSize, &sbrDataBits[el], sbrData[el], 0); + if (error) return error; + } + } + + error = FDKsbrEnc_Downsample( + hSbrEncoder, + samples + hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels, + samplesBufSize, hSbrEncoder->nChannels, &sbrDataBits[el], sbrData[el], 0); + if (error) return error; + + return 0; +} + +INT sbrEncoder_UpdateBuffers(HANDLE_SBR_ENCODER hSbrEncoder, + INT_PCM *timeBuffer, UINT timeBufferBufSize) { + if (hSbrEncoder->downsampledOffset > 0) { + int c; + int nd = hSbrEncoder->downmixSize / hSbrEncoder->nChannels; + + for (c = 0; c < hSbrEncoder->nChannels; c++) { + /* Move delayed downsampled data */ + FDKmemcpy(timeBuffer + timeBufferBufSize * c, + timeBuffer + timeBufferBufSize * c + nd, + sizeof(INT_PCM) * + (hSbrEncoder->downsampledOffset / hSbrEncoder->nChannels)); + } + } else { + int c; + + for (c = 0; c < hSbrEncoder->nChannels; c++) { + /* Move delayed input data */ + FDKmemcpy( + timeBuffer + timeBufferBufSize * c, + timeBuffer + timeBufferBufSize * c + hSbrEncoder->frameSize, + sizeof(INT_PCM) * hSbrEncoder->bufferOffset / hSbrEncoder->nChannels); + } + } + if (hSbrEncoder->nBitstrDelay > 0) { + int el; + + for (el = 0; el < hSbrEncoder->noElements; el++) { + FDKmemmove( + hSbrEncoder->sbrElement[el]->payloadDelayLine[0], + hSbrEncoder->sbrElement[el]->payloadDelayLine[1], + sizeof(UCHAR) * (hSbrEncoder->nBitstrDelay * MAX_PAYLOAD_SIZE)); + + FDKmemmove(&hSbrEncoder->sbrElement[el]->payloadDelayLineSize[0], + &hSbrEncoder->sbrElement[el]->payloadDelayLineSize[1], + sizeof(UINT) * (hSbrEncoder->nBitstrDelay)); + } + } + return 0; +} + +INT sbrEncoder_SendHeader(HANDLE_SBR_ENCODER hSbrEncoder) { + INT error = -1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + if ((hSbrEncoder->noElements == 1) && + (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData = + hSbrEncoder->sbrElement[el]->sbrBitstreamData.NrSendHeaderData - 1; + } else { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.CountSendHeaderData = 0; + } + } + error = 0; + } + return error; +} + +INT sbrEncoder_ContainsHeader(HANDLE_SBR_ENCODER hSbrEncoder) { + INT sbrHeader = 1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + sbrHeader &= + (hSbrEncoder->sbrElement[el]->sbrBitstreamData.HeaderActiveDelay == 1) + ? 1 + : 0; + } + } + return sbrHeader; +} + +INT sbrEncoder_GetHeaderDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + if ((hSbrEncoder->noElements == 1) && + (hSbrEncoder->sbrElement[0]->elInfo.fParametricStereo == 1)) { + delay = hSbrEncoder->nBitstrDelay + 1; + } else { + delay = hSbrEncoder->nBitstrDelay; + } + } + return delay; +} +INT sbrEncoder_GetBsDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->nBitstrDelay; + } + return delay; +} + +INT sbrEncoder_SAPPrepare(HANDLE_SBR_ENCODER hSbrEncoder) { + INT error = -1; + if (hSbrEncoder) { + int el; + for (el = 0; el < hSbrEncoder->noElements; el++) { + hSbrEncoder->sbrElement[el]->sbrBitstreamData.rightBorderFIX = 1; + } + error = 0; + } + return error; +} + +INT sbrEncoder_GetEstimateBitrate(HANDLE_SBR_ENCODER hSbrEncoder) { + INT estimateBitrate = 0; + + if (hSbrEncoder) { + estimateBitrate += hSbrEncoder->estimateBitrate; + } + + return estimateBitrate; +} + +INT sbrEncoder_GetInputDataDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->inputDataDelay; + } + return delay; +} + +INT sbrEncoder_GetSbrDecDelay(HANDLE_SBR_ENCODER hSbrEncoder) { + INT delay = -1; + + if (hSbrEncoder) { + delay = hSbrEncoder->sbrDecDelay; + } + return delay; +} + +INT sbrEncoder_GetLibInfo(LIB_INFO *info) { + int i; + + if (info == NULL) { + return -1; + } + /* search for next free tab */ + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) { + return -1; + } + info += i; + + info->module_id = FDK_SBRENC; + info->version = + LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2); + LIB_VERSION_STRING(info); +#ifdef __ANDROID__ + info->build_date = ""; + info->build_time = ""; +#else + info->build_date = __DATE__; + info->build_time = __TIME__; +#endif + info->title = "SBR Encoder"; + + /* Set flags */ + info->flags = 0 | CAPF_SBR_HQ | CAPF_SBR_PS_MPEG; + /* End of flags */ + + return 0; +} diff --git a/fdk-aac/libSBRenc/src/sbr_misc.cpp b/fdk-aac/libSBRenc/src/sbr_misc.cpp new file mode 100644 index 0000000..83d7e36 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbr_misc.cpp @@ -0,0 +1,265 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr miscellaneous helper functions $Revision: 36750 $ +*/ +#include "sbr_misc.h" + +void FDKsbrEnc_Shellsort_fract(FIXP_DBL *in, INT n) { + FIXP_DBL v; + INT i, j; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i - 1]; + j = i; + while (in[j - inc - 1] > v) { + in[j - 1] = in[j - inc - 1]; + j -= inc; + if (j <= inc) break; + } + in[j - 1] = v; + } + } while (inc > 1); +} + +/* Sorting routine */ +void FDKsbrEnc_Shellsort_int(INT *in, INT n) { + INT i, j, v; + INT inc = 1; + + do + inc = 3 * inc + 1; + while (inc <= n); + + do { + inc = inc / 3; + for (i = inc + 1; i <= n; i++) { + v = in[i - 1]; + j = i; + while (in[j - inc - 1] > v) { + in[j - 1] = in[j - inc - 1]; + j -= inc; + if (j <= inc) break; + } + in[j - 1] = v; + } + } while (inc > 1); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecLeft + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddVecLeft(INT *dst, INT *length_dst, INT *src, INT length_src) { + INT i; + + for (i = length_src - 1; i >= 0; i--) + FDKsbrEnc_AddLeft(dst, length_dst, src[i]); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddLeft + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddLeft(INT *vector, INT *length_vector, INT value) { + INT i; + + for (i = *length_vector; i > 0; i--) vector[i] = vector[i - 1]; + vector[0] = value; + (*length_vector)++; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddRight + ******************************************************************************* + + Description: + + Arguments: INT* vector, INT* length_vector, INT value + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddRight(INT *vector, INT *length_vector, INT value) { + vector[*length_vector] = value; + (*length_vector)++; +} + +/******************************************************************************* + Functionname: FDKsbrEnc_AddVecRight + ******************************************************************************* + + Description: + + Arguments: INT* dst, INT* length_dst, INT* src, INT length_src) + + Return: none + +*******************************************************************************/ +void FDKsbrEnc_AddVecRight(INT *dst, INT *length_dst, INT *src, + INT length_src) { + INT i; + for (i = 0; i < length_src; i++) FDKsbrEnc_AddRight(dst, length_dst, src[i]); +} + +/***************************************************************************** + + functionname: FDKsbrEnc_LSI_divide_scale_fract + + description: Calculates division with best precision and scales the result. + + return: num*scale/denom + +*****************************************************************************/ +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, + FIXP_DBL scale) { + FIXP_DBL tmp = FL2FXCONST_DBL(0.0f); + if (num != FL2FXCONST_DBL(0.0f)) { + INT shiftCommon; + INT shiftNum = CountLeadingBits(num); + INT shiftDenom = CountLeadingBits(denom); + INT shiftScale = CountLeadingBits(scale); + + num = num << shiftNum; + scale = scale << shiftScale; + + tmp = fMultDiv2(num, scale); + + if (denom > (tmp >> fixMin(shiftNum + shiftScale - 1, (DFRACT_BITS - 1)))) { + denom = denom << shiftDenom; + tmp = schur_div(tmp, denom, 15); + shiftCommon = + fixMin((shiftNum - shiftDenom + shiftScale - 1), (DFRACT_BITS - 1)); + if (shiftCommon < 0) + tmp <<= -shiftCommon; + else + tmp >>= shiftCommon; + } else { + tmp = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL; + } + } + + return (tmp); +} diff --git a/fdk-aac/libSBRenc/src/sbr_misc.h b/fdk-aac/libSBRenc/src/sbr_misc.h new file mode 100644 index 0000000..fad853f --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbr_misc.h @@ -0,0 +1,127 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Sbr miscellaneous helper functions prototypes $Revision: 92790 $ + \author +*/ + +#ifndef SBR_MISC_H +#define SBR_MISC_H + +#include "sbr_encoder.h" + +/* Sorting routines */ +void FDKsbrEnc_Shellsort_fract(FIXP_DBL *in, INT n); +void FDKsbrEnc_Shellsort_int(INT *in, INT n); + +void FDKsbrEnc_AddLeft(INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddRight(INT *vector, INT *length_vector, INT value); +void FDKsbrEnc_AddVecLeft(INT *dst, INT *length_dst, INT *src, INT length_src); +void FDKsbrEnc_AddVecRight(INT *dst, INT *length_vector_dst, INT *src, + INT length_src); + +FIXP_DBL FDKsbrEnc_LSI_divide_scale_fract(FIXP_DBL num, FIXP_DBL denom, + FIXP_DBL scale); + +#endif diff --git a/fdk-aac/libSBRenc/src/sbrenc_freq_sca.cpp b/fdk-aac/libSBRenc/src/sbrenc_freq_sca.cpp new file mode 100644 index 0000000..c86e047 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_freq_sca.cpp @@ -0,0 +1,674 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief frequency scale $Revision: 95225 $ +*/ + +#include "sbrenc_freq_sca.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +/* StartFreq */ +static INT getStartFreq(INT fsCore, const INT start_freq); + +/* StopFreq */ +static INT getStopFreq(INT fsCore, const INT stop_freq); + +static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor); +static void CalcBands(INT *diff, INT start, INT stop, INT num_bands); +static INT modifyBands(INT max_band, INT *diff, INT length); +static void cumSum(INT start_value, INT *diff, INT length, UCHAR *start_adress); + +/******************************************************************************* + Functionname: FDKsbrEnc_getSbrStartFreqRAW + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ + +INT FDKsbrEnc_getSbrStartFreqRAW(INT startFreq, INT fsCore) { + INT result; + + if (startFreq < 0 || startFreq > 15) { + return -1; + } + /* Update startFreq struct */ + result = getStartFreq(fsCore, startFreq); + + result = + (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); + +} /* End FDKsbrEnc_getSbrStartFreqRAW */ + +/******************************************************************************* + Functionname: getSbrStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq, INT fsCore) { + INT result; + + if (stopFreq < 0 || stopFreq > 13) return -1; + + /* Uppdate stopFreq struct */ + result = getStopFreq(fsCore, stopFreq); + result = + (result * (fsCore >> 5) + 1) >> 1; /* (result*fsSBR/QMFbands+1)>>1; */ + + return (result); +} /* End getSbrStopFreq */ + +/******************************************************************************* + Functionname: getStartFreq + ******************************************************************************* + Description: + + Arguments: fsCore - core sampling rate + + + Return: + *******************************************************************************/ +static INT getStartFreq(INT fsCore, const INT start_freq) { + INT k0_min; + + switch (fsCore) { + case 8000: + k0_min = 24; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 11025: + k0_min = 17; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 12000: + k0_min = 16; /* (3000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 16000: + k0_min = 16; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 22050: + k0_min = 12; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 24000: + k0_min = 11; /* (4000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 32000: + k0_min = 10; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 44100: + k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 48000: + k0_min = 7; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + case 96000: + k0_min = 3; /* (5000 * nQmfChannels / fsSBR ) + 0.5 */ + break; + default: + k0_min = 11; /* illegal fs */ + } + + switch (fsCore) { + case 8000: { + INT v_offset[] = {-8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7}; + return (k0_min + v_offset[start_freq]); + } + case 11025: { + INT v_offset[] = {-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13}; + return (k0_min + v_offset[start_freq]); + } + case 12000: { + INT v_offset[] = {-5, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 16000: { + INT v_offset[] = {-6, -4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16}; + return (k0_min + v_offset[start_freq]); + } + case 22050: + case 24000: + case 32000: { + INT v_offset[] = {-4, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20}; + return (k0_min + v_offset[start_freq]); + } + case 44100: + case 48000: + case 96000: { + INT v_offset[] = {-2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24}; + return (k0_min + v_offset[start_freq]); + } + default: { + INT v_offset[] = {0, 1, 2, 3, 4, 5, 6, 7, 9, 11, 13, 16, 20, 24, 28, 33}; + return (k0_min + v_offset[start_freq]); + } + } +} /* End getStartFreq */ + +/******************************************************************************* + Functionname: getStopFreq + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +static INT getStopFreq(INT fsCore, const INT stop_freq) { + INT result, i; + INT k1_min; + INT v_dstop[13]; + + INT *v_stop_freq = NULL; + INT v_stop_freq_16[14] = {48, 49, 50, 51, 52, 54, 55, + 56, 57, 59, 60, 61, 63, 64}; + INT v_stop_freq_22[14] = {35, 37, 38, 40, 42, 44, 46, + 48, 51, 53, 56, 58, 61, 64}; + INT v_stop_freq_24[14] = {32, 34, 36, 38, 40, 42, 44, + 46, 49, 52, 55, 58, 61, 64}; + INT v_stop_freq_32[14] = {32, 34, 36, 38, 40, 42, 44, + 46, 49, 52, 55, 58, 61, 64}; + INT v_stop_freq_44[14] = {23, 25, 27, 29, 32, 34, 37, + 40, 43, 47, 51, 55, 59, 64}; + INT v_stop_freq_48[14] = {21, 23, 25, 27, 30, 32, 35, + 38, 42, 45, 49, 54, 59, 64}; + INT v_stop_freq_64[14] = {20, 22, 24, 26, 29, 31, 34, + 37, 41, 45, 49, 54, 59, 64}; + INT v_stop_freq_88[14] = {15, 17, 19, 21, 23, 26, 29, + 33, 37, 41, 46, 51, 57, 64}; + INT v_stop_freq_96[14] = {13, 15, 17, 19, 21, 24, 27, + 31, 35, 39, 44, 50, 57, 64}; + INT v_stop_freq_192[14] = {7, 8, 10, 12, 14, 16, 19, + 23, 27, 32, 38, 46, 54, 64}; + + switch (fsCore) { + case 8000: + k1_min = 48; + v_stop_freq = v_stop_freq_16; + break; + case 11025: + k1_min = 35; + v_stop_freq = v_stop_freq_22; + break; + case 12000: + k1_min = 32; + v_stop_freq = v_stop_freq_24; + break; + case 16000: + k1_min = 32; + v_stop_freq = v_stop_freq_32; + break; + case 22050: + k1_min = 23; + v_stop_freq = v_stop_freq_44; + break; + case 24000: + k1_min = 21; + v_stop_freq = v_stop_freq_48; + break; + case 32000: + k1_min = 20; + v_stop_freq = v_stop_freq_64; + break; + case 44100: + k1_min = 15; + v_stop_freq = v_stop_freq_88; + break; + case 48000: + k1_min = 13; + v_stop_freq = v_stop_freq_96; + break; + case 96000: + k1_min = 7; + v_stop_freq = v_stop_freq_192; + break; + default: + k1_min = 21; /* illegal fs */ + } + + /* Ensure increasing bandwidth */ + for (i = 0; i <= 12; i++) { + v_dstop[i] = v_stop_freq[i + 1] - v_stop_freq[i]; + } + + FDKsbrEnc_Shellsort_int(v_dstop, 13); /* Sort bandwidth changes */ + + result = k1_min; + for (i = 0; i < stop_freq; i++) { + result = result + v_dstop[i]; + } + + return (result); + +} /* End getStopFreq */ + +/******************************************************************************* + Functionname: FDKsbrEnc_FindStartAndStopBand + ******************************************************************************* + Description: + + Arguments: srSbr SBR sampling freqency + srCore AAC core sampling freqency + noChannels Number of QMF channels + startFreq SBR start frequency in QMF bands + stopFreq SBR start frequency in QMF bands + + *k0 Output parameter + *k2 Output parameter + + Return: Error code (0 is OK) + *******************************************************************************/ +INT FDKsbrEnc_FindStartAndStopBand(const INT srSbr, const INT srCore, + const INT noChannels, const INT startFreq, + const INT stopFreq, INT *k0, INT *k2) { + /* Update startFreq struct */ + *k0 = getStartFreq(srCore, startFreq); + + /* Test if start freq is outside corecoder range */ + if (srSbr * noChannels < *k0 * srCore) { + return ( + 1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling frequency) */ + } + + /*Update stopFreq struct */ + if (stopFreq < 14) { + *k2 = getStopFreq(srCore, stopFreq); + } else if (stopFreq == 14) { + *k2 = 2 * *k0; + } else { + *k2 = 3 * *k0; + } + + /* limit to Nyqvist */ + if (*k2 > noChannels) { + *k2 = noChannels; + } + + /* Test for invalid k0 k2 combinations */ + if ((srCore == 22050) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS44100)) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for + fs=44.1kHz */ + + if ((srCore >= 24000) && ((*k2 - *k0) > MAX_FREQ_COEFFS_FS48000)) + return (1); /* Number of bands exceeds valid range of MAX_FREQ_COEFFS for + fs>=48kHz */ + + if ((*k2 - *k0) > MAX_FREQ_COEFFS) + return (1); /*Number of bands exceeds valid range of MAX_FREQ_COEFFS */ + + if ((*k2 - *k0) < 0) return (1); /* Number of bands is negative */ + + return (0); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateFreqScale + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_UpdateFreqScale(UCHAR *v_k_master, INT *h_num_bands, const INT k0, + const INT k2, const INT freqScale, + const INT alterScale) + +{ + INT b_p_o = 0; /* bands_per_octave */ + FIXP_DBL warp = FL2FXCONST_DBL(0.0f); + INT dk = 0; + + /* Internal variables */ + INT k1 = 0, i; + INT num_bands0; + INT num_bands1; + INT diff_tot[MAX_OCTAVE + MAX_SECOND_REGION]; + INT *diff0 = diff_tot; + INT *diff1 = diff_tot + MAX_OCTAVE; + INT k2_achived; + INT k2_diff; + INT incr = 0; + + /* Init */ + if (freqScale == 1) b_p_o = 12; + if (freqScale == 2) b_p_o = 10; + if (freqScale == 3) b_p_o = 8; + + if (freqScale > 0) /*Bark*/ + { + if (alterScale == 0) + warp = FL2FXCONST_DBL(0.5f); /* 1.0/(1.0*2.0) */ + else + warp = FL2FXCONST_DBL(1.0f / 2.6f); /* 1.0/(1.3*2.0); */ + + if (4 * k2 >= 9 * k0) /*two or more regions (how many times the basis band + is copied)*/ + { + k1 = 2 * k0; + + num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + num_bands1 = numberOfBands(b_p_o, k1, k2, warp); + + CalcBands(diff0, k0, k1, num_bands0); /*CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int(diff0, num_bands0); /*SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling + frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */ + + CalcBands(diff1, k1, k2, num_bands1); /* CalcBands2 => diff1 */ + FDKsbrEnc_Shellsort_int(diff1, num_bands1); /* SortBands sort diff1 */ + if (diff0[num_bands0 - 1] > diff1[0]) /* max(1) > min(2) */ + { + if (modifyBands(diff0[num_bands0 - 1], diff1, num_bands1)) return (1); + } + + /* Add 2'nd region */ + cumSum(k1, diff1, num_bands1, &v_k_master[num_bands0]); + *h_num_bands = num_bands0 + num_bands1; /* Output nr of bands */ + + } else /* one region */ + { + k1 = k2; + + num_bands0 = numberOfBands(b_p_o, k0, k1, FL2FXCONST_DBL(0.5f)); + CalcBands(diff0, k0, k1, num_bands0); /* CalcBands1 => diff0 */ + FDKsbrEnc_Shellsort_int(diff0, num_bands0); /* SortBands sort diff0 */ + + if (diff0[0] == 0) /* too wide FB bands for target tuning */ + { + return (1); /* raise the cross-over frequency and/or lower the number + of target bands per octave (or lower the sampling + frequency */ + } + + cumSum(k0, diff0, num_bands0, v_k_master); /* cumsum */ + *h_num_bands = num_bands0; /* Output nr of bands */ + } + } else /* Linear mode */ + { + if (alterScale == 0) { + dk = 1; + num_bands0 = 2 * ((k2 - k0) / 2); /* FLOOR to get to few number of bands*/ + } else { + dk = 2; + num_bands0 = + 2 * (((k2 - k0) / dk + 1) / 2); /* ROUND to get closest fit */ + } + + k2_achived = k0 + num_bands0 * dk; + k2_diff = k2 - k2_achived; + + for (i = 0; i < num_bands0; i++) diff_tot[i] = dk; + + /* If linear scale wasn't achived */ + /* and we got wide SBR are */ + if (k2_diff < 0) { + incr = 1; + i = 0; + } + + /* If linear scale wasn't achived */ + /* and we got small SBR are */ + if (k2_diff > 0) { + incr = -1; + i = num_bands0 - 1; + } + + /* Adjust diff vector to get sepc. SBR range */ + while (k2_diff != 0) { + diff_tot[i] = diff_tot[i] - incr; + i = i + incr; + k2_diff = k2_diff + incr; + } + + cumSum(k0, diff_tot, num_bands0, v_k_master); /* cumsum */ + *h_num_bands = num_bands0; /* Output nr of bands */ + } + + if (*h_num_bands < 1) return (1); /*To small sbr area */ + + return (0); +} /* End FDKsbrEnc_UpdateFreqScale */ + +static INT numberOfBands(INT b_p_o, INT start, INT stop, FIXP_DBL warp_factor) { + INT result = 0; + /* result = 2* (INT) ( (double)b_p_o * + * (double)(FDKlog((double)stop/(double)start)/FDKlog((double)2)) * + * (double)FX_DBL2FL(warp_factor) + 0.5); */ + result = ((b_p_o * fMult((CalcLdInt(stop) - CalcLdInt(start)), warp_factor) + + (FL2FX_DBL(0.5f) >> LD_DATA_SHIFT)) >> + ((DFRACT_BITS - 1) - LD_DATA_SHIFT)) + << 1; /* do not optimize anymore (rounding!!) */ + + return (result); +} + +static void CalcBands(INT *diff, INT start, INT stop, INT num_bands) { + INT i, qb, qe, qtmp; + INT previous; + INT current; + FIXP_DBL base, exp, tmp; + + previous = start; + for (i = 1; i <= num_bands; i++) { + base = fDivNorm((FIXP_DBL)stop, (FIXP_DBL)start, &qb); + exp = fDivNorm((FIXP_DBL)i, (FIXP_DBL)num_bands, &qe); + tmp = fPow(base, qb, exp, qe, &qtmp); + tmp = fMult(tmp, (FIXP_DBL)(start << 24)); + current = (INT)scaleValue(tmp, qtmp - 23); + current = (current + 1) >> 1; /* rounding*/ + diff[i - 1] = current - previous; + previous = current; + } + +} /* End CalcBands */ + +static void cumSum(INT start_value, INT *diff, INT length, + UCHAR *start_adress) { + INT i; + start_adress[0] = start_value; + for (i = 1; i <= length; i++) + start_adress[i] = start_adress[i - 1] + diff[i - 1]; +} /* End cumSum */ + +static INT modifyBands(INT max_band_previous, INT *diff, INT length) { + INT change = max_band_previous - diff[0]; + + /* Limit the change so that the last band cannot get narrower than the first + * one */ + if (change > (diff[length - 1] - diff[0]) / 2) + change = (diff[length - 1] - diff[0]) / 2; + + diff[0] += change; + diff[length - 1] -= change; + FDKsbrEnc_Shellsort_int(diff, length); + + return (0); +} /* End modifyBands */ + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateHiRes + ******************************************************************************* + Description: + + + Arguments: + + Return: + *******************************************************************************/ +INT FDKsbrEnc_UpdateHiRes(UCHAR *h_hires, INT *num_hires, UCHAR *v_k_master, + INT num_master, INT *xover_band) { + INT i; + INT max1, max2; + + if ((v_k_master[*xover_band] > + 32) || /* v_k_master[*xover_band] > noQMFChannels(dualRate)/divider */ + (*xover_band > num_master)) { + /* xover_band error, too big for this startFreq. Will be clipped */ + + /* Calculate maximum value for xover_band */ + max1 = 0; + max2 = num_master; + while ((v_k_master[max1 + 1] < 32) && /* noQMFChannels(dualRate)/divider */ + ((max1 + 1) < max2)) { + max1++; + } + + *xover_band = max1; + } + + *num_hires = num_master - *xover_band; + for (i = *xover_band; i <= num_master; i++) { + h_hires[i - *xover_band] = v_k_master[i]; + } + + return (0); +} /* End FDKsbrEnc_UpdateHiRes */ + +/******************************************************************************* + Functionname: FDKsbrEnc_UpdateLoRes + ******************************************************************************* + Description: + + Arguments: + + Return: + *******************************************************************************/ +void FDKsbrEnc_UpdateLoRes(UCHAR *h_lores, INT *num_lores, UCHAR *h_hires, + INT num_hires) { + INT i; + + if (num_hires % 2 == 0) /* if even number of hires bands */ + { + *num_lores = num_hires / 2; + /* Use every second lores=hires[0,2,4...] */ + for (i = 0; i <= *num_lores; i++) h_lores[i] = h_hires[i * 2]; + + } else /* odd number of hires which means xover is odd */ + { + *num_lores = (num_hires + 1) / 2; + + /* Use lores=hires[0,1,3,5 ...] */ + h_lores[0] = h_hires[0]; + for (i = 1; i <= *num_lores; i++) { + h_lores[i] = h_hires[i * 2 - 1]; + } + } + +} /* End FDKsbrEnc_UpdateLoRes */ diff --git a/fdk-aac/libSBRenc/src/sbrenc_freq_sca.h b/fdk-aac/libSBRenc/src/sbrenc_freq_sca.h new file mode 100644 index 0000000..9b8d360 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_freq_sca.h @@ -0,0 +1,132 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief frequency scale prototypes $Revision: 92790 $ +*/ +#ifndef SBRENC_FREQ_SCA_H +#define SBRENC_FREQ_SCA_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +#define MAX_OCTAVE 29 +#define MAX_SECOND_REGION 50 + +INT FDKsbrEnc_UpdateFreqScale(UCHAR *v_k_master, INT *h_num_bands, const INT k0, + const INT k2, const INT freq_scale, + const INT alter_scale); + +INT FDKsbrEnc_UpdateHiRes(UCHAR *h_hires, INT *num_hires, UCHAR *v_k_master, + INT num_master, INT *xover_band); + +void FDKsbrEnc_UpdateLoRes(UCHAR *v_lores, INT *num_lores, UCHAR *v_hires, + INT num_hires); + +INT FDKsbrEnc_FindStartAndStopBand(const INT srSbr, const INT srCore, + const INT noChannels, const INT startFreq, + const INT stop_freq, INT *k0, INT *k2); + +INT FDKsbrEnc_getSbrStartFreqRAW(INT startFreq, INT fsCore); +INT FDKsbrEnc_getSbrStopFreqRAW(INT stopFreq, INT fsCore); +#endif diff --git a/fdk-aac/libSBRenc/src/sbrenc_ram.cpp b/fdk-aac/libSBRenc/src/sbrenc_ram.cpp new file mode 100644 index 0000000..fb30fa2 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_ram.cpp @@ -0,0 +1,249 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Memory layout + $Revision: 92864 $ + + This module declares all static and dynamic memory spaces +*/ +#include "sbrenc_ram.h" + +#include "sbr.h" +#include "genericStds.h" + +C_AALLOC_MEM(Ram_SbrDynamic_RAM, FIXP_DBL, + ((SBR_ENC_DYN_RAM_SIZE) / sizeof(FIXP_DBL))) + +/*! + \name StaticSbrData + + Static memory areas, must not be overwritten in other sections of the encoder +*/ +/* @{ */ + +/*! static sbr encoder instance for one encoder (2 channels) + all major static and dynamic memory areas are located + in module sbr_ram and sbr rom +*/ +C_ALLOC_MEM(Ram_SbrEncoder, SBR_ENCODER, 1) +C_ALLOC_MEM2(Ram_SbrChannel, SBR_CHANNEL, 1, (8)) +C_ALLOC_MEM2(Ram_SbrElement, SBR_ELEMENT, 1, (8)) + +/*! Filter states for QMF-analysis.
+ Dimension: #MAXNRSBRCHANNELS * #SBR_QMF_FILTER_LENGTH +*/ +C_AALLOC_MEM2_L(Ram_Sbr_QmfStatesAnalysis, FIXP_QAS, 640, (8), SECT_DATA_L1) + +/*! Matrix holding the quota values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2_L(Ram_Sbr_quotaMatrix, FIXP_DBL, (MAX_NO_OF_ESTIMATES * 64), (8), + SECT_DATA_L1) + +/*! Matrix holding the sign values for all estimates, all channels + Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_CHANNELS* #MAX_NO_OF_ESTIMATES +*/ +C_ALLOC_MEM2(Ram_Sbr_signMatrix, INT, (MAX_NO_OF_ESTIMATES * 64), (8)) + +/*! Frequency band table (low res)
+ Dimension #MAX_FREQ_COEFFS/2+1 +*/ +C_ALLOC_MEM2(Ram_Sbr_freqBandTableLO, UCHAR, (MAX_FREQ_COEFFS / 2 + 1), (8)) + +/*! Frequency band table (high res)
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2(Ram_Sbr_freqBandTableHI, UCHAR, (MAX_FREQ_COEFFS + 1), (8)) + +/*! vk matser table
+ Dimension #MAX_FREQ_COEFFS +1 +*/ +C_ALLOC_MEM2(Ram_Sbr_v_k_master, UCHAR, (MAX_FREQ_COEFFS + 1), (8)) + +/* + Missing harmonics detection +*/ + +/*! sbr_detectionVectors
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_detectionVectors, UCHAR, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) + +/*! sbr_prevCompVec[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_prevEnvelopeCompensation, UCHAR, MAX_FREQ_COEFFS, (8)) +/*! sbr_guideScfb[
+ Dimension #MAX_NUM_CHANNELS*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_guideScfb, UCHAR, MAX_FREQ_COEFFS, (8)) + +/*! sbr_guideVectorDetected
+ Dimension #MAX_NUM_CHANNELS*#MAX_NO_OF_ESTIMATES*#MAX_FREQ_COEFFS] +*/ +C_ALLOC_MEM2(Ram_Sbr_guideVectorDetected, UCHAR, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2(Ram_Sbr_guideVectorDiff, FIXP_DBL, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) +C_ALLOC_MEM2(Ram_Sbr_guideVectorOrig, FIXP_DBL, + (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS), (8)) + +/* + Static Parametric Stereo memory +*/ +C_AALLOC_MEM_L(Ram_PsQmfStatesSynthesis, FIXP_DBL, 640 / 2, SECT_DATA_L1) + +C_ALLOC_MEM_L(Ram_PsEncode, PS_ENCODE, 1, SECT_DATA_L1) +C_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO, 1) + +/* @} */ + +/*! + \name DynamicSbrData + + Dynamic memory areas, might be reused in other algorithm sections, + e.g. the core encoder. +*/ +/* @{ */ + +/*! Energy buffer for envelope extraction
+ Dimension #MAXNRSBRCHANNELS * +#SBR_QMF_SLOTS * #SBR_QMF_CHANNELS +*/ +C_ALLOC_MEM2(Ram_Sbr_envYBuffer, FIXP_DBL, (32 / 2 * 64), (8)) + +FIXP_DBL* GetRam_Sbr_envYBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_NRG + (n*Y_2_BUF_BYTE)) is sufficiently aligned, so + * the cast is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + OFFSET_NRG + (n * Y_2_BUF_BYTE))); +} + +/* + * QMF data + */ +/* The SBR encoder uses a single channel overlapping buffer set (always n=0), + * but PS does not. */ +FIXP_DBL* GetRam_Sbr_envRBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_QMF + (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE))) is + * sufficiently aligned, so the cast is safe */ + return reinterpret_cast(reinterpret_cast( + dynamic_RAM + OFFSET_QMF + (n * (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE)))); +} +FIXP_DBL* GetRam_Sbr_envIBuffer(int n, UCHAR* dynamic_RAM) { + FDK_ASSERT(dynamic_RAM != 0); + /* The reinterpret_cast is used to suppress a compiler warning. We know that + * (dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + + * (n*(ENV_R_BUFF_BYTE+ENV_I_BUFF_BYTE))) is sufficiently aligned, so the cast + * is safe */ + return reinterpret_cast( + reinterpret_cast(dynamic_RAM + OFFSET_QMF + (ENV_R_BUFF_BYTE) + + (n * (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE)))); +} + +/* @} */ diff --git a/fdk-aac/libSBRenc/src/sbrenc_ram.h b/fdk-aac/libSBRenc/src/sbrenc_ram.h new file mode 100644 index 0000000..cf23378 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_ram.h @@ -0,0 +1,199 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Memory layout +$Revision: 92790 $ +*/ +#ifndef SBRENC_RAM_H +#define SBRENC_RAM_H + +#include "sbr_def.h" +#include "env_est.h" +#include "sbr_encoder.h" +#include "sbr.h" + +#include "ps_main.h" +#include "ps_encode.h" + +#define ENV_TRANSIENTS_BYTE ((sizeof(FIXP_DBL) * (MAX_NUM_CHANNELS * 3 * 32))) + +#define ENV_R_BUFF_BYTE ((sizeof(FIXP_DBL) * ((32) * MAX_HYBRID_BANDS))) +#define ENV_I_BUFF_BYTE ((sizeof(FIXP_DBL) * ((32) * MAX_HYBRID_BANDS))) +#define Y_BUF_CH_BYTE \ + ((2 * sizeof(FIXP_DBL) * (((32) - (32 / 2)) * MAX_HYBRID_BANDS))) + +#define ENV_R_BUF_PS_BYTE ((sizeof(FIXP_DBL) * 32 * 64 / 2)) +#define ENV_I_BUF_PS_BYTE ((sizeof(FIXP_DBL) * 32 * 64 / 2)) + +#define TON_BUF_CH_BYTE \ + ((sizeof(FIXP_DBL) * (MAX_NO_OF_ESTIMATES * MAX_FREQ_COEFFS))) + +#define Y_2_BUF_BYTE (Y_BUF_CH_BYTE) + +/* Workbuffer RAM - Allocation */ +/* + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + | OFFSET_QMF | OFFSET_NRG | + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + ------------------------- ------------------------- + | | 0.5 * | + | sbr_envRBuffer | sbr_envYBuffer_size | + | sbr_envIBuffer | | + ------------------------- ------------------------- + +*/ +#define BUF_NRG_SIZE ((MAX_NUM_CHANNELS * Y_2_BUF_BYTE)) +#define BUF_QMF_SIZE (ENV_R_BUFF_BYTE + ENV_I_BUFF_BYTE) + +/* Size of the shareable memory region than can be reused */ +#define SBR_ENC_DYN_RAM_SIZE (BUF_QMF_SIZE + BUF_NRG_SIZE) + +#define OFFSET_QMF (0) +#define OFFSET_NRG (OFFSET_QMF + BUF_QMF_SIZE) + +/* + ***************************************************************************************************** + */ + +H_ALLOC_MEM(Ram_SbrDynamic_RAM, FIXP_DBL) + +H_ALLOC_MEM(Ram_SbrEncoder, SBR_ENCODER) +H_ALLOC_MEM(Ram_SbrChannel, SBR_CHANNEL) +H_ALLOC_MEM(Ram_SbrElement, SBR_ELEMENT) + +H_ALLOC_MEM(Ram_Sbr_quotaMatrix, FIXP_DBL) +H_ALLOC_MEM(Ram_Sbr_signMatrix, INT) + +H_ALLOC_MEM(Ram_Sbr_QmfStatesAnalysis, FIXP_QAS) + +H_ALLOC_MEM(Ram_Sbr_freqBandTableLO, UCHAR) +H_ALLOC_MEM(Ram_Sbr_freqBandTableHI, UCHAR) +H_ALLOC_MEM(Ram_Sbr_v_k_master, UCHAR) + +H_ALLOC_MEM(Ram_Sbr_detectionVectors, UCHAR) +H_ALLOC_MEM(Ram_Sbr_prevEnvelopeCompensation, UCHAR) +H_ALLOC_MEM(Ram_Sbr_guideScfb, UCHAR) +H_ALLOC_MEM(Ram_Sbr_guideVectorDetected, UCHAR) + +/* Dynamic Memory Allocation */ + +H_ALLOC_MEM(Ram_Sbr_envYBuffer, FIXP_DBL) +FIXP_DBL* GetRam_Sbr_envYBuffer(int n, UCHAR* dynamic_RAM); +FIXP_DBL* GetRam_Sbr_envRBuffer(int n, UCHAR* dynamic_RAM); +FIXP_DBL* GetRam_Sbr_envIBuffer(int n, UCHAR* dynamic_RAM); + +H_ALLOC_MEM(Ram_Sbr_guideVectorDiff, FIXP_DBL) +H_ALLOC_MEM(Ram_Sbr_guideVectorOrig, FIXP_DBL) + +H_ALLOC_MEM(Ram_PsQmfStatesSynthesis, FIXP_DBL) + +H_ALLOC_MEM(Ram_PsEncode, PS_ENCODE) + +FIXP_DBL* FDKsbrEnc_SliceRam_PsRqmf(FIXP_DBL* rQmfData, UCHAR* dynamic_RAM, + int n, int i, int qmfSlots); +FIXP_DBL* FDKsbrEnc_SliceRam_PsIqmf(FIXP_DBL* iQmfData, UCHAR* dynamic_RAM, + int n, int i, int qmfSlots); + +H_ALLOC_MEM(Ram_ParamStereo, PARAMETRIC_STEREO) +#endif diff --git a/fdk-aac/libSBRenc/src/sbrenc_rom.cpp b/fdk-aac/libSBRenc/src/sbrenc_rom.cpp new file mode 100644 index 0000000..737afaf --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_rom.cpp @@ -0,0 +1,910 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: Definition of constant tables + +*******************************************************************************/ + +/*! + \file + \brief Definition of constant tables + $Revision: 95404 $ + + This module contains most of the constant data that can be stored in ROM. +*/ + +#include "sbrenc_rom.h" +#include "genericStds.h" + +//@{ +/******************************************************************************* + + Table Overview: + + o envelope level, 1.5 dB: + 1a) v_Huff_envelopeLevelC10T[121] + 1b) v_Huff_envelopeLevelL10T[121] + 2a) v_Huff_envelopeLevelC10F[121] + 2b) v_Huff_envelopeLevelL10F[121] + + o envelope balance, 1.5 dB: + 3a) bookSbrEnvBalanceC10T[49] + 3b) bookSbrEnvBalanceL10T[49] + 4a) bookSbrEnvBalanceC10F[49] + 4b) bookSbrEnvBalanceL10F[49] + + o envelope level, 3.0 dB: + 5a) v_Huff_envelopeLevelC11T[63] + 5b) v_Huff_envelopeLevelL11T[63] + 6a) v_Huff_envelopeLevelC11F[63] + 6b) v_Huff_envelopeLevelC11F[63] + + o envelope balance, 3.0 dB: + 7a) bookSbrEnvBalanceC11T[25] + 7b) bookSbrEnvBalanceL11T[25] + 8a) bookSbrEnvBalanceC11F[25] + 8b) bookSbrEnvBalanceL11F[25] + + o noise level, 3.0 dB: + 9a) v_Huff_NoiseLevelC11T[63] + 9b) v_Huff_NoiseLevelL11T[63] + - ) (v_Huff_envelopeLevelC11F[63] is used for freq dir) + - ) (v_Huff_envelopeLevelL11F[63] is used for freq dir) + + o noise balance, 3.0 dB: + 10a) bookSbrNoiseBalanceC11T[25] + 10b) bookSbrNoiseBalanceL11T[25] + - ) (bookSbrEnvBalanceC11F[25] is used for freq dir) + - ) (bookSbrEnvBalanceL11F[25] is used for freq dir) + + + (1.5 dB is never used for noise) + +********************************************************************************/ + +/*******************************************************************************/ +/* table : envelope level, 1.5 dB */ +/* theor range : [-58,58], CODE_BOOK_SCF_LAV = 58 */ +/* implem range: [-60,60], CODE_BOOK_SCF_LAV10 = 60 */ +/* raw stats : envelopeLevel_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10T[121] = { + 0x0003FFD6, 0x0003FFD7, 0x0003FFD8, 0x0003FFD9, 0x0003FFDA, 0x0003FFDB, + 0x0007FFB8, 0x0007FFB9, 0x0007FFBA, 0x0007FFBB, 0x0007FFBC, 0x0007FFBD, + 0x0007FFBE, 0x0007FFBF, 0x0007FFC0, 0x0007FFC1, 0x0007FFC2, 0x0007FFC3, + 0x0007FFC4, 0x0007FFC5, 0x0007FFC6, 0x0007FFC7, 0x0007FFC8, 0x0007FFC9, + 0x0007FFCA, 0x0007FFCB, 0x0007FFCC, 0x0007FFCD, 0x0007FFCE, 0x0007FFCF, + 0x0007FFD0, 0x0007FFD1, 0x0007FFD2, 0x0007FFD3, 0x0001FFE6, 0x0003FFD4, + 0x0000FFF0, 0x0001FFE9, 0x0003FFD5, 0x0001FFE7, 0x0000FFF1, 0x0000FFEC, + 0x0000FFED, 0x0000FFEE, 0x00007FF4, 0x00003FF9, 0x00003FF7, 0x00001FFA, + 0x00001FF9, 0x00000FFB, 0x000007FC, 0x000003FC, 0x000001FD, 0x000000FD, + 0x0000007D, 0x0000003D, 0x0000001D, 0x0000000D, 0x00000005, 0x00000001, + 0x00000000, 0x00000004, 0x0000000C, 0x0000001C, 0x0000003C, 0x0000007C, + 0x000000FC, 0x000001FC, 0x000003FD, 0x00000FFA, 0x00001FF8, 0x00003FF6, + 0x00003FF8, 0x00007FF5, 0x0000FFEF, 0x0001FFE8, 0x0000FFF2, 0x0007FFD4, + 0x0007FFD5, 0x0007FFD6, 0x0007FFD7, 0x0007FFD8, 0x0007FFD9, 0x0007FFDA, + 0x0007FFDB, 0x0007FFDC, 0x0007FFDD, 0x0007FFDE, 0x0007FFDF, 0x0007FFE0, + 0x0007FFE1, 0x0007FFE2, 0x0007FFE3, 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, + 0x0007FFE7, 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, 0x0007FFEC, + 0x0007FFED, 0x0007FFEE, 0x0007FFEF, 0x0007FFF0, 0x0007FFF1, 0x0007FFF2, + 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, 0x0007FFF7, 0x0007FFF8, + 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, 0x0007FFFD, 0x0007FFFE, + 0x0007FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00T_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10T[121] = { + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x11, 0x12, 0x10, 0x11, 0x12, 0x11, 0x10, 0x10, 0x10, 0x10, + 0x0F, 0x0E, 0x0E, 0x0D, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x10, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nChex_cF + built by : FH 01-07-05 */ + +const INT v_Huff_envelopeLevelC10F[121] = { + 0x0007FFE7, 0x0007FFE8, 0x000FFFD2, 0x000FFFD3, 0x000FFFD4, 0x000FFFD5, + 0x000FFFD6, 0x000FFFD7, 0x000FFFD8, 0x0007FFDA, 0x000FFFD9, 0x000FFFDA, + 0x000FFFDB, 0x000FFFDC, 0x0007FFDB, 0x000FFFDD, 0x0007FFDC, 0x0007FFDD, + 0x000FFFDE, 0x0003FFE4, 0x000FFFDF, 0x000FFFE0, 0x000FFFE1, 0x0007FFDE, + 0x000FFFE2, 0x000FFFE3, 0x000FFFE4, 0x0007FFDF, 0x000FFFE5, 0x0007FFE0, + 0x0003FFE8, 0x0007FFE1, 0x0003FFE0, 0x0003FFE9, 0x0001FFEF, 0x0003FFE5, + 0x0001FFEC, 0x0001FFED, 0x0001FFEE, 0x0000FFF4, 0x0000FFF3, 0x0000FFF0, + 0x00007FF7, 0x00007FF6, 0x00003FFA, 0x00001FFA, 0x00001FF9, 0x00000FFA, + 0x00000FF8, 0x000007F9, 0x000003FB, 0x000001FC, 0x000001FA, 0x000000FB, + 0x0000007C, 0x0000003C, 0x0000001C, 0x0000000C, 0x00000005, 0x00000001, + 0x00000000, 0x00000004, 0x0000000D, 0x0000001D, 0x0000003D, 0x000000FA, + 0x000000FC, 0x000001FB, 0x000003FA, 0x000007F8, 0x000007FA, 0x000007FB, + 0x00000FF9, 0x00000FFB, 0x00001FF8, 0x00001FFB, 0x00003FF8, 0x00003FF9, + 0x0000FFF1, 0x0000FFF2, 0x0001FFEA, 0x0001FFEB, 0x0003FFE1, 0x0003FFE2, + 0x0003FFEA, 0x0003FFE3, 0x0003FFE6, 0x0003FFE7, 0x0003FFEB, 0x000FFFE6, + 0x0007FFE2, 0x000FFFE7, 0x000FFFE8, 0x000FFFE9, 0x000FFFEA, 0x000FFFEB, + 0x000FFFEC, 0x0007FFE3, 0x000FFFED, 0x000FFFEE, 0x000FFFEF, 0x000FFFF0, + 0x0007FFE4, 0x000FFFF1, 0x0003FFEC, 0x000FFFF2, 0x000FFFF3, 0x0007FFE5, + 0x0007FFE6, 0x000FFFF4, 0x000FFFF5, 0x000FFFF6, 0x000FFFF7, 0x000FFFF8, + 0x000FFFF9, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, 0x000FFFFD, 0x000FFFFE, + 0x000FFFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C2FIX.m/envelopeLevel_00F_cF.mat/v_nLhex_cF + built by : FH 01-07-05 */ + +const UCHAR v_Huff_envelopeLevelL10F[121] = { + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x13, 0x14, 0x13, 0x13, 0x14, 0x12, 0x14, 0x14, + 0x14, 0x13, 0x14, 0x14, 0x14, 0x13, 0x14, 0x13, 0x12, 0x13, 0x12, + 0x12, 0x11, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x10, 0x0F, 0x0F, + 0x0E, 0x0D, 0x0D, 0x0C, 0x0C, 0x0B, 0x0A, 0x09, 0x09, 0x08, 0x07, + 0x06, 0x05, 0x04, 0x03, 0x02, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, + 0x08, 0x09, 0x0A, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0D, 0x0D, 0x0E, + 0x0E, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x14, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x13, 0x14, 0x12, 0x14, 0x14, 0x13, 0x13, 0x14, + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; + +/*******************************************************************************/ +/* table : envelope balance, 1.5 dB */ +/* theor range : [-48,48], CODE_BOOK_SCF_LAV = 48 */ +/* implem range: same but mapped to [-24,24], CODE_BOOK_SCF_LAV_BALANCE10 = 24 + */ +/* raw stats : envelopePan_00 (yes, wrong suffix in name) KK 01-03-09 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10T[49] = { + 0x0000FFE4, 0x0000FFE5, 0x0000FFE6, 0x0000FFE7, 0x0000FFE8, 0x0000FFE9, + 0x0000FFEA, 0x0000FFEB, 0x0000FFEC, 0x0000FFED, 0x0000FFEE, 0x0000FFEF, + 0x0000FFF0, 0x0000FFF1, 0x0000FFF2, 0x0000FFF3, 0x0000FFF4, 0x0000FFE2, + 0x00000FFC, 0x000007FC, 0x000001FE, 0x0000007E, 0x0000001E, 0x00000006, + 0x00000000, 0x00000002, 0x0000000E, 0x0000003E, 0x000000FE, 0x000007FD, + 0x00000FFD, 0x00007FF0, 0x0000FFE3, 0x0000FFF5, 0x0000FFF6, 0x0000FFF7, + 0x0000FFF8, 0x0000FFF9, 0x0000FFFA, 0x0001FFF6, 0x0001FFF7, 0x0001FFF8, + 0x0001FFF9, 0x0001FFFA, 0x0001FFFB, 0x0001FFFC, 0x0001FFFD, 0x0001FFFE, + 0x0001FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10T[49] = { + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0C, 0x0B, + 0x09, 0x07, 0x05, 0x03, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0B, + 0x0C, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC10F[49] = { + 0x0003FFE2, 0x0003FFE3, 0x0003FFE4, 0x0003FFE5, 0x0003FFE6, 0x0003FFE7, + 0x0003FFE8, 0x0003FFE9, 0x0003FFEA, 0x0003FFEB, 0x0003FFEC, 0x0003FFED, + 0x0003FFEE, 0x0003FFEF, 0x0003FFF0, 0x0000FFF7, 0x0001FFF0, 0x00003FFC, + 0x000007FE, 0x000007FC, 0x000000FE, 0x0000007E, 0x0000000E, 0x00000002, + 0x00000000, 0x00000006, 0x0000001E, 0x0000003E, 0x000001FE, 0x000007FD, + 0x00000FFE, 0x00007FFA, 0x0000FFF6, 0x0003FFF1, 0x0003FFF2, 0x0003FFF3, + 0x0003FFF4, 0x0003FFF5, 0x0003FFF6, 0x0003FFF7, 0x0003FFF8, 0x0003FFF9, + 0x0003FFFA, 0x0003FFFB, 0x0003FFFC, 0x0003FFFD, 0x0003FFFE, 0x0007FFFE, + 0x0007FFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopePan_00F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL10F[49] = { + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x10, 0x11, 0x0E, 0x0B, 0x0B, + 0x08, 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, 0x09, 0x0B, + 0x0C, 0x0F, 0x10, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, + 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13}; + +/*******************************************************************************/ +/* table : envelope level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : envelopeLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11T[63] = { + 0x0003FFED, 0x0003FFEE, 0x0007FFDE, 0x0007FFDF, 0x0007FFE0, 0x0007FFE1, + 0x0007FFE2, 0x0007FFE3, 0x0007FFE4, 0x0007FFE5, 0x0007FFE6, 0x0007FFE7, + 0x0007FFE8, 0x0007FFE9, 0x0007FFEA, 0x0007FFEB, 0x0007FFEC, 0x0001FFF4, + 0x0000FFF7, 0x0000FFF9, 0x0000FFF8, 0x00003FFB, 0x00003FFA, 0x00003FF8, + 0x00001FFA, 0x00000FFC, 0x000007FC, 0x000000FE, 0x0000003E, 0x0000000E, + 0x00000002, 0x00000000, 0x00000006, 0x0000001E, 0x0000007E, 0x000001FE, + 0x000007FD, 0x00001FFB, 0x00003FF9, 0x00003FFC, 0x00007FFA, 0x0000FFF6, + 0x0001FFF5, 0x0003FFEC, 0x0007FFED, 0x0007FFEE, 0x0007FFEF, 0x0007FFF0, + 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, 0x0007FFF4, 0x0007FFF5, 0x0007FFF6, + 0x0007FFF7, 0x0007FFF8, 0x0007FFF9, 0x0007FFFA, 0x0007FFFB, 0x0007FFFC, + 0x0007FFFD, 0x0007FFFE, 0x0007FFFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11T[63] = { + 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x11, 0x10, 0x10, 0x10, 0x0E, + 0x0E, 0x0E, 0x0D, 0x0C, 0x0B, 0x08, 0x06, 0x04, 0x02, 0x01, 0x03, + 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x0E, 0x0F, 0x10, 0x11, 0x12, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, + 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13}; + +/* direction: freq + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_envelopeLevelC11F[63] = { + 0x000FFFF0, 0x000FFFF1, 0x000FFFF2, 0x000FFFF3, 0x000FFFF4, 0x000FFFF5, + 0x000FFFF6, 0x0003FFF3, 0x0007FFF5, 0x0007FFEE, 0x0007FFEF, 0x0007FFF6, + 0x0003FFF4, 0x0003FFF2, 0x000FFFF7, 0x0007FFF0, 0x0001FFF5, 0x0003FFF0, + 0x0001FFF4, 0x0000FFF7, 0x0000FFF6, 0x00007FF8, 0x00003FFB, 0x00000FFD, + 0x000007FD, 0x000003FD, 0x000001FD, 0x000000FD, 0x0000003E, 0x0000000E, + 0x00000002, 0x00000000, 0x00000006, 0x0000001E, 0x000000FC, 0x000001FC, + 0x000003FC, 0x000007FC, 0x00000FFC, 0x00001FFC, 0x00003FFA, 0x00007FF9, + 0x00007FFA, 0x0000FFF8, 0x0000FFF9, 0x0001FFF6, 0x0001FFF7, 0x0003FFF5, + 0x0003FFF6, 0x0003FFF1, 0x000FFFF8, 0x0007FFF1, 0x0007FFF2, 0x0007FFF3, + 0x000FFFF9, 0x0007FFF7, 0x0007FFF4, 0x000FFFFA, 0x000FFFFB, 0x000FFFFC, + 0x000FFFFD, 0x000FFFFE, 0x000FFFFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_envelopeLevelL11F[63] = { + 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12, 0x13, 0x13, 0x13, + 0x13, 0x12, 0x12, 0x14, 0x13, 0x11, 0x12, 0x11, 0x10, 0x10, 0x0F, + 0x0E, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01, 0x03, + 0x05, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x0F, 0x10, + 0x10, 0x11, 0x11, 0x12, 0x12, 0x12, 0x14, 0x13, 0x13, 0x13, 0x14, + 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14}; + +/*******************************************************************************/ +/* table : envelope balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 + */ +/* raw stats : envelopeBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11T[25] = { + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, + 0x00001FF7, 0x00001FF8, 0x00000FF8, 0x000000FE, 0x0000007E, + 0x0000000E, 0x00000006, 0x00000000, 0x00000002, 0x0000001E, + 0x0000003E, 0x000001FE, 0x00001FF9, 0x00001FFA, 0x00001FFB, + 0x00001FFC, 0x00001FFD, 0x00001FFE, 0x00003FFE, 0x00003FFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11T.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11T[25] = { + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x08, + 0x07, 0x04, 0x03, 0x01, 0x02, 0x05, 0x06, 0x09, 0x0D, + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E}; + +/* direction: freq + contents : codewords + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrEnvBalanceC11F[25] = { + 0x00001FF7, 0x00001FF8, 0x00001FF9, 0x00001FFA, 0x00001FFB, + 0x00003FF8, 0x00003FF9, 0x000007FC, 0x000000FE, 0x0000007E, + 0x0000000E, 0x00000002, 0x00000000, 0x00000006, 0x0000001E, + 0x0000003E, 0x000001FE, 0x00000FFA, 0x00001FF6, 0x00003FFA, + 0x00003FFB, 0x00003FFC, 0x00003FFD, 0x00003FFE, 0x00003FFF}; + +/* direction: freq + contents : codeword lengths + raw table: HuffCode3C.m/envelopeBalance_11F.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrEnvBalanceL11F[25] = { + 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0B, 0x08, + 0x07, 0x04, 0x02, 0x01, 0x03, 0x05, 0x06, 0x09, 0x0C, + 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E}; + +/*******************************************************************************/ +/* table : noise level, 3.0 dB */ +/* theor range : [-29,29], CODE_BOOK_SCF_LAV = 29 */ +/* implem range: [-31,31], CODE_BOOK_SCF_LAV11 = 31 */ +/* raw stats : noiseLevel_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const INT v_Huff_NoiseLevelC11T[63] = { + 0x00001FCE, 0x00001FCF, 0x00001FD0, 0x00001FD1, 0x00001FD2, 0x00001FD3, + 0x00001FD4, 0x00001FD5, 0x00001FD6, 0x00001FD7, 0x00001FD8, 0x00001FD9, + 0x00001FDA, 0x00001FDB, 0x00001FDC, 0x00001FDD, 0x00001FDE, 0x00001FDF, + 0x00001FE0, 0x00001FE1, 0x00001FE2, 0x00001FE3, 0x00001FE4, 0x00001FE5, + 0x00001FE6, 0x00001FE7, 0x000007F2, 0x000000FD, 0x0000003E, 0x0000000E, + 0x00000006, 0x00000000, 0x00000002, 0x0000001E, 0x000000FC, 0x000003F8, + 0x00001FCC, 0x00001FE8, 0x00001FE9, 0x00001FEA, 0x00001FEB, 0x00001FEC, + 0x00001FCD, 0x00001FED, 0x00001FEE, 0x00001FEF, 0x00001FF0, 0x00001FF1, + 0x00001FF2, 0x00001FF3, 0x00001FF4, 0x00001FF5, 0x00001FF6, 0x00001FF7, + 0x00001FF8, 0x00001FF9, 0x00001FFA, 0x00001FFB, 0x00001FFC, 0x00001FFD, + 0x00001FFE, 0x00003FFE, 0x00003FFF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode2.m + built by : FH 00-02-04 */ + +const UCHAR v_Huff_NoiseLevelL11T[63] = { + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000B, 0x00000008, 0x00000006, 0x00000004, + 0x00000003, 0x00000001, 0x00000002, 0x00000005, 0x00000008, 0x0000000A, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, 0x0000000D, + 0x0000000D, 0x0000000E, 0x0000000E}; + +/*******************************************************************************/ +/* table : noise balance, 3.0 dB */ +/* theor range : [-24,24], CODE_BOOK_SCF_LAV = 24 */ +/* implem range: same but mapped to [-12,12], CODE_BOOK_SCF_LAV_BALANCE11 = 12 + */ +/* raw stats : noiseBalance_11 KK 00-02-03 */ +/*******************************************************************************/ + +/* direction: time + contents : codewords + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nBhex + built by : FH 01-05-15 */ + +const INT bookSbrNoiseBalanceC11T[25] = { + 0x000000EC, 0x000000ED, 0x000000EE, 0x000000EF, 0x000000F0, + 0x000000F1, 0x000000F2, 0x000000F3, 0x000000F4, 0x000000F5, + 0x0000001C, 0x00000002, 0x00000000, 0x00000006, 0x0000003A, + 0x000000F6, 0x000000F7, 0x000000F8, 0x000000F9, 0x000000FA, + 0x000000FB, 0x000000FC, 0x000000FD, 0x000000FE, 0x000000FF}; + +/* direction: time + contents : codeword lengths + raw table: HuffCode3C.m/noiseBalance_11.mat/v_nLhex + built by : FH 01-05-15 */ + +const UCHAR bookSbrNoiseBalanceL11T[25] = { + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x05, 0x02, 0x01, 0x03, 0x06, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; + +/* + tuningTable +*/ +const sbrTuningTable_t sbrTuningTable[] = { + /* Some of the low bitrates are commented out here, this is because the + encoder could lose frames at those bitrates and throw an error + because it has insufficient bits to encode for some test items. + */ + + /*** HE-AAC section ***/ + /* sf,sfsp,sf,sfsp,nnb,nfo,saml,SM,FS*/ + + /*** mono ***/ + + /* 8/16 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 8000, 1, 7, 6, 11, 10, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 8000, 1, 11, 7, 13, 12, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16001, 8000, 1, 14, 10, 13, 13, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 24000, 8000, 1, 14, 10, 14, 14, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 24000, 32000, 8000, 1, 14, 10, 14, 14, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48001, 8000, 1, 14, 11, 15, 15, 2, 0, 3, SBR_MONO, 2}, + + /* 11/22 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 11025, 1, 5, 4, 6, 6, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 11025, 1, 8, 5, 12, 9, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 20000, 11025, 1, 12, 8, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 20000, 24001, 11025, 1, 13, 9, 13, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 24000, 32000, 11025, 1, 14, 10, 14, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48000, 11025, 1, 15, 11, 15, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 48000, 64001, 11025, 1, 15, 11, 15, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 12/24 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 12000, 1, 4, 3, 6, 6, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 12000, 1, 7, 4, 11, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 20000, 12000, 1, 11, 7, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 20000, 24001, 12000, 1, 12, 8, 12, 8, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 24000, 32000, 12000, 1, 13, 9, 13, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 32000, 48000, 12000, 1, 14, 10, 14, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 48000, 64001, 12000, 1, 14, 11, 15, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 16/32 kHz dual rate */ + {CODEC_AAC, 8000, 10000, 16000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 10000, 12000, 16000, 1, 2, 1, 6, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 12000, 16000, 16000, 1, 4, 2, 6, 0, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 16000, 1, 4, 2, 8, 3, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 16000, 1, 6, 5, 11, 7, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 16000, 1, 10, 9, 12, 8, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 16000, 1, 12, 12, 13, 13, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 16000, 1, 14, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 16000, 1, 14, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + + /* 22.05/44.1 kHz dual rate */ + /* { CODEC_AAC, 8000, 11369, 22050, 1, 1, 1, 1, 1, 1, 0, 6, + SBR_MONO, 3 }, */ + {CODEC_AAC, 11369, 16000, 22050, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 22050, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 22050, 1, 4, 4, 8, 5, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 22050, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 22050, 1, 10, 10, 9, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 22050, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 22050, 1, 13, 13, 12, 12, 2, 0, 3, SBR_MONO, 1}, + + /* 24/48 kHz dual rate */ + /* { CODEC_AAC, 8000, 12000, 24000, 1, 1, 1, 1, 1, 1, 0, 6, + SBR_MONO, 3 }, */ + {CODEC_AAC, 12000, 16000, 24000, 1, 3, 1, 4, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 16000, 18000, 24000, 1, 3, 1, 5, 4, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AAC, 18000, 22000, 24000, 1, 4, 3, 8, 5, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 22000, 28000, 24000, 1, 7, 6, 8, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AAC, 28000, 36000, 24000, 1, 10, 10, 9, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 36000, 44000, 24000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 44000, 64001, 24000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AAC, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 32000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 32000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AAC, 24000, 36000, 44100, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 44100, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 44100, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 44100, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 44100, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AAC, 32000, 36000, 48000, 1, 4, 4, 9, 9, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AAC, 36000, 60000, 48000, 1, 7, 7, 10, 10, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AAC, 60000, 72000, 48000, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 72000, 100000, 48000, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AAC, 100000, 160001, 48000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, 1}, + + /*** stereo ***/ + /* 08/16 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 8000, 2, 6, 6, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, 3}, + {CODEC_AAC, 24000, 28000, 8000, 2, 9, 9, 11, 9, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 8000, 2, 11, 9, 11, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 8000, 2, 13, 11, 13, 11, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 8000, 2, 14, 12, 13, 12, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 8000, 2, 14, 14, 13, 13, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AAC, 60000, 76000, 8000, 2, 14, 14, 13, 13, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 76000, 128001, 8000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 11/22 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 11025, 2, 7, 5, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 11025, 2, 10, 8, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 11025, 2, 12, 8, 12, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 11025, 2, 13, 9, 13, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 11025, 2, 14, 11, 13, 11, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 11025, 2, 15, 15, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 12/24 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 12000, 2, 6, 4, 9, 7, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 12000, 2, 9, 7, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 12000, 2, 11, 7, 12, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 12000, 2, 12, 9, 12, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 12000, 2, 13, 12, 13, 12, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 12000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 16/32 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 16000, 2, 4, 2, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 16000, 2, 8, 7, 10, 8, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 16000, 2, 10, 9, 12, 11, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 16000, 2, 13, 13, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 44000, 52000, 16000, 2, 14, 14, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AAC, 52000, 60000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 22050, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 22050, 2, 5, 4, 6, 5, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 32000, 22050, 2, 5, 4, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 32000, 36000, 22050, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 22050, 2, 10, 10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 22050, 2, 12, 12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 22050, 2, 13, 13, 10, 10, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 22050, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 22050, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AAC, 16000, 24000, 24000, 2, 2, 1, 1, 0, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 24000, 28000, 24000, 2, 5, 5, 6, 6, 1, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 28000, 36000, 24000, 2, 7, 6, 8, 7, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 36000, 44000, 24000, 2, 10, 10, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 44000, 52000, 24000, 2, 12, 12, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 52000, 60000, 24000, 2, 13, 13, 10, 10, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AAC, 60000, 76000, 24000, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 76000, 128001, 24000, 2, 14, 14, 12, 12, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AAC, 32000, 60000, 32000, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 32000, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 32000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AAC, 32000, 60000, 44100, 2, 4, 4, 4, 4, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 44100, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 44100, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 44100, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AAC, 36000, 60000, 48000, 2, 4, 4, 9, 9, 2, 0, -3, SBR_SWITCH_LRC, + 3}, + {CODEC_AAC, 60000, 80000, 48000, 2, 7, 7, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AAC, 80000, 112000, 48000, 2, 9, 9, 10, 10, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AAC, 112000, 144000, 48000, 2, 11, 11, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AAC, 144000, 256001, 48000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /** AAC LOW DELAY SECTION **/ + + /* 24 kHz dual rate - 12kHz singlerate is not allowed (deactivated in + FDKsbrEnc_IsSbrSettingAvail()) */ + {CODEC_AACLD, 8000, 32000, 12000, 1, 1, 1, 0, 0, 1, 0, 6, SBR_MONO, 3}, + + /*** mono ***/ + /* 16/32 kHz dual rate */ + {CODEC_AACLD, 16000, 18000, 16000, 1, 4, 5, 9, 7, 1, 0, 6, SBR_MONO, 3}, + {CODEC_AACLD, 18000, 22000, 16000, 1, 7, 7, 12, 12, 1, 6, 9, SBR_MONO, 3}, + {CODEC_AACLD, 22000, 28000, 16000, 1, 6, 6, 9, 9, 2, 3, 6, SBR_MONO, 3}, + {CODEC_AACLD, 28000, 36000, 16000, 1, 8, 8, 12, 7, 2, 9, 12, SBR_MONO, 3}, + {CODEC_AACLD, 36000, 44000, 16000, 1, 10, 14, 12, 13, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 44000, 64001, 16000, 1, 11, 14, 13, 13, 2, 0, 3, SBR_MONO, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AACLD, 18000, 22000, 22050, 1, 4, 4, 5, 5, 2, 0, 6, SBR_MONO, 3}, + {CODEC_AACLD, 22000, 28000, 22050, 1, 5, 5, 6, 6, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AACLD, 28000, 36000, 22050, 1, 7, 8, 8, 8, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 36000, 44000, 22050, 1, 9, 9, 9, 9, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 44000, 52000, 22050, 1, 12, 11, 11, 11, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 52000, 64001, 22050, 1, 13, 11, 11, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AACLD, 20000, 22000, 24000, 1, 3, 4, 8, 8, 2, 0, 6, SBR_MONO, 2}, + {CODEC_AACLD, 22000, 28000, 24000, 1, 3, 8, 8, 7, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 28000, 36000, 24000, 1, 4, 8, 8, 7, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 36000, 56000, 24000, 1, 8, 9, 9, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 56000, 64001, 24000, 1, 13, 11, 11, 10, 2, 0, 3, SBR_MONO, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AACLD, 24000, 36000, 32000, 1, 4, 4, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AACLD, 36000, 60000, 32000, 1, 7, 7, 6, 6, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 60000, 72000, 32000, 1, 9, 9, 8, 8, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 32000, 1, 11, 11, 10, 10, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 32000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /* 44/88 kHz dual rate */ + {CODEC_AACLD, 36000, 60000, 44100, 1, 8, 7, 6, 9, 2, 0, 3, SBR_MONO, 2}, + {CODEC_AACLD, 60000, 72000, 44100, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 44100, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 44100, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /* 48/96 kHz dual rate */ /* 32 and 40kbps line tuned for dual-rate SBR + */ + {CODEC_AACLD, 36000, 60000, 48000, 1, 4, 7, 4, 4, 2, 0, 3, SBR_MONO, 3}, + {CODEC_AACLD, 60000, 72000, 48000, 1, 9, 9, 10, 10, 2, 0, 3, SBR_MONO, 1}, + {CODEC_AACLD, 72000, 100000, 48000, 1, 11, 11, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + {CODEC_AACLD, 100000, 160001, 48000, 1, 13, 13, 11, 11, 2, 0, 3, SBR_MONO, + 1}, + + /*** stereo ***/ + /* 16/32 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 16000, 2, 10, 9, 12, 11, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 36000, 44000, 16000, 2, 13, 13, 13, 13, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 44000, 52000, 16000, 2, 10, 9, 11, 9, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 52000, 60000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_SWITCH_LRC, 1}, + {CODEC_AACLD, 60000, 76000, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 128001, 16000, 2, 14, 14, 13, 13, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 22.05/44.1 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 22050, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 36000, 44000, 22050, 2, 5, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 44000, 52000, 22050, 2, 7, 10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 52000, 60000, 22050, 2, 9, 11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AACLD, 60000, 76000, 22050, 2, 10, 12, 10, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 82000, 22050, 2, 12, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 82000, 128001, 22050, 2, 13, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 24/48 kHz dual rate */ + {CODEC_AACLD, 32000, 36000, 24000, 2, 5, 4, 7, 6, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 36000, 44000, 24000, 2, 4, 8, 8, 8, 2, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 44000, 52000, 24000, 2, 6, 10, 8, 8, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 52000, 60000, 24000, 2, 9, 11, 9, 9, 3, 0, -3, SBR_SWITCH_LRC, + 1}, + {CODEC_AACLD, 60000, 76000, 24000, 2, 11, 12, 10, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 76000, 88000, 24000, 2, 12, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 88000, 128001, 24000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 32/64 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 32000, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 80000, 112000, 32000, 2, 9, 9, 8, 8, 3, 0, -3, SBR_LEFT_RIGHT, + 1}, + {CODEC_AACLD, 112000, 144000, 32000, 2, 11, 11, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 256001, 32000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 44.1/88.2 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 44100, 2, 7, 7, 6, 6, 3, 0, -3, SBR_SWITCH_LRC, + 2}, + {CODEC_AACLD, 80000, 112000, 44100, 2, 10, 10, 8, 8, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 112000, 144000, 44100, 2, 12, 12, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 256001, 44100, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + + /* 48/96 kHz dual rate */ + {CODEC_AACLD, 60000, 80000, 48000, 2, 7, 7, 10, 10, 2, 0, -3, + SBR_SWITCH_LRC, 2}, + {CODEC_AACLD, 80000, 112000, 48000, 2, 9, 9, 10, 10, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 112000, 144000, 48000, 2, 11, 11, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 144000, 176000, 48000, 2, 12, 12, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + {CODEC_AACLD, 176000, 256001, 48000, 2, 13, 13, 11, 11, 3, 0, -3, + SBR_LEFT_RIGHT, 1}, + +}; + +const int sbrTuningTableSize = + sizeof(sbrTuningTable) / sizeof(sbrTuningTable[0]); + +const psTuningTable_t psTuningTable[4] = { + {8000, 22000, PSENC_STEREO_BANDS_10, PSENC_NENV_1, + FL2FXCONST_DBL(3.0f / 4.0f)}, + {22000, 28000, PSENC_STEREO_BANDS_20, PSENC_NENV_1, + FL2FXCONST_DBL(2.0f / 4.0f)}, + {28000, 36000, PSENC_STEREO_BANDS_20, PSENC_NENV_2, + FL2FXCONST_DBL(1.5f / 4.0f)}, + {36000, 160001, PSENC_STEREO_BANDS_20, PSENC_NENV_4, + FL2FXCONST_DBL(1.1f / 4.0f)}, +}; + +//@} diff --git a/fdk-aac/libSBRenc/src/sbrenc_rom.h b/fdk-aac/libSBRenc/src/sbrenc_rom.h new file mode 100644 index 0000000..18c1fb9 --- /dev/null +++ b/fdk-aac/libSBRenc/src/sbrenc_rom.h @@ -0,0 +1,145 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! +\file +\brief Declaration of constant tables +$Revision: 92790 $ +*/ +#ifndef SBRENC_ROM_H +#define SBRENC_ROM_H + +#include "sbr_def.h" +#include "sbr_encoder.h" + +#include "ps_main.h" + +/* + huffman tables +*/ +extern const INT v_Huff_envelopeLevelC10T[121]; +extern const UCHAR v_Huff_envelopeLevelL10T[121]; +extern const INT v_Huff_envelopeLevelC10F[121]; +extern const UCHAR v_Huff_envelopeLevelL10F[121]; +extern const INT bookSbrEnvBalanceC10T[49]; +extern const UCHAR bookSbrEnvBalanceL10T[49]; +extern const INT bookSbrEnvBalanceC10F[49]; +extern const UCHAR bookSbrEnvBalanceL10F[49]; +extern const INT v_Huff_envelopeLevelC11T[63]; +extern const UCHAR v_Huff_envelopeLevelL11T[63]; +extern const INT v_Huff_envelopeLevelC11F[63]; +extern const UCHAR v_Huff_envelopeLevelL11F[63]; +extern const INT bookSbrEnvBalanceC11T[25]; +extern const UCHAR bookSbrEnvBalanceL11T[25]; +extern const INT bookSbrEnvBalanceC11F[25]; +extern const UCHAR bookSbrEnvBalanceL11F[25]; +extern const INT v_Huff_NoiseLevelC11T[63]; +extern const UCHAR v_Huff_NoiseLevelL11T[63]; +extern const INT bookSbrNoiseBalanceC11T[25]; +extern const UCHAR bookSbrNoiseBalanceL11T[25]; + +extern const sbrTuningTable_t sbrTuningTable[]; +extern const int sbrTuningTableSize; + +extern const psTuningTable_t psTuningTable[4]; + +#endif diff --git a/fdk-aac/libSBRenc/src/ton_corr.cpp b/fdk-aac/libSBRenc/src/ton_corr.cpp new file mode 100644 index 0000000..1c050e2 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ton_corr.cpp @@ -0,0 +1,891 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +#include "ton_corr.h" + +#include "sbrenc_ram.h" +#include "sbr_misc.h" +#include "genericStds.h" +#include "autocorr2nd.h" + +#define BAND_V_SIZE 32 +#define NUM_V_COMBINE \ + 8 /* Must be a divisor of 64 and fulfill the ASSERTs below */ + +/**************************************************************************/ +/*! + \brief Calculates the tonal to noise ration for different frequency bands + and time segments. + + The ratio between the predicted energy (tonal energy A) and the total + energy (A + B) is calculated. This is converted to the ratio between + the predicted energy (tonal energy A) and the non-predictable energy + (noise energy B). Hence the quota-matrix contains A/B = q/(1-q). + + The samples in nrgVector are scaled by 1.0/16.0 + The samples in pNrgVectorFreq are scaled by 1.0/2.0 + The samples in quotaMatrix are scaled by RELAXATION + + \return none. + +*/ +/**************************************************************************/ + +void FDKsbrEnc_CalculateTonalityQuotas( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + FIXP_DBL **RESTRICT + sourceBufferReal, /*!< The real part of the QMF-matrix. */ + FIXP_DBL **RESTRICT + sourceBufferImag, /*!< The imaginary part of the QMF-matrix. */ + INT usb, /*!< upper side band, highest + 1 QMF band in the SBR range. */ + INT qmfScale /*!< sclefactor of QMF subsamples */ +) { + INT i, k, r, r2, timeIndex, autoCorrScaling; + + INT startIndexMatrix = hTonCorr->startIndexMatrix; + INT totNoEst = hTonCorr->numberOfEstimates; + INT noEstPerFrame = hTonCorr->numberOfEstimatesPerFrame; + INT move = hTonCorr->move; + INT noQmfChannels = hTonCorr->noQmfChannels; /* Number of Bands */ + INT buffLen = hTonCorr->bufferLength; /* Number of Slots */ + INT stepSize = hTonCorr->stepSize; + INT *pBlockLength = hTonCorr->lpcLength; + INT **RESTRICT signMatrix = hTonCorr->signMatrix; + FIXP_DBL *RESTRICT nrgVector = hTonCorr->nrgVector; + FIXP_DBL **RESTRICT quotaMatrix = hTonCorr->quotaMatrix; + FIXP_DBL *RESTRICT pNrgVectorFreq = hTonCorr->nrgVectorFreq; + + FIXP_DBL *realBuf; + FIXP_DBL *imagBuf; + + FIXP_DBL alphar[2], alphai[2], fac; + + C_ALLOC_SCRATCH_START(ac, ACORR_COEFS, 1) + C_ALLOC_SCRATCH_START(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE) + realBuf = realBufRef; + imagBuf = realBuf + BAND_V_SIZE * NUM_V_COMBINE; + + FDK_ASSERT(buffLen <= BAND_V_SIZE); + FDK_ASSERT(sizeof(FIXP_DBL) * NUM_V_COMBINE * BAND_V_SIZE * 2 < + (1024 * sizeof(FIXP_DBL) - sizeof(ACORR_COEFS))); + + /* + * Buffering of the quotaMatrix and the quotaMatrixTransp. + *********************************************************/ + for (i = 0; i < move; i++) { + FDKmemcpy(quotaMatrix[i], quotaMatrix[i + noEstPerFrame], + noQmfChannels * sizeof(FIXP_DBL)); + FDKmemcpy(signMatrix[i], signMatrix[i + noEstPerFrame], + noQmfChannels * sizeof(INT)); + } + + FDKmemmove(nrgVector, nrgVector + noEstPerFrame, move * sizeof(FIXP_DBL)); + FDKmemclear(nrgVector + startIndexMatrix, + (totNoEst - startIndexMatrix) * sizeof(FIXP_DBL)); + FDKmemclear(pNrgVectorFreq, noQmfChannels * sizeof(FIXP_DBL)); + + /* + * Calculate the quotas for the current time steps. + **************************************************/ + + for (r = 0; r < usb; r++) { + int blockLength; + + k = hTonCorr->nextSample; /* startSample */ + timeIndex = startIndexMatrix; + /* Copy as many as possible Band across all Slots at once */ + if (realBuf != realBufRef) { + realBuf -= BAND_V_SIZE; + imagBuf -= BAND_V_SIZE; + } else { + realBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1); + imagBuf += BAND_V_SIZE * (NUM_V_COMBINE - 1); + + for (i = 0; i < buffLen; i++) { + int v; + FIXP_DBL *ptr; + ptr = realBuf + i; + for (v = 0; v < NUM_V_COMBINE; v++) { + ptr[0] = sourceBufferReal[i][r + v]; + ptr[0 + BAND_V_SIZE * NUM_V_COMBINE] = sourceBufferImag[i][r + v]; + ptr -= BAND_V_SIZE; + } + } + } + + blockLength = pBlockLength[0]; + + while (k <= buffLen - blockLength) { + autoCorrScaling = fixMin( + getScalefactor(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength), + getScalefactor(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength)); + autoCorrScaling = fixMax(0, autoCorrScaling - 1); + + scaleValues(&realBuf[k - LPC_ORDER], LPC_ORDER + blockLength, + autoCorrScaling); + scaleValues(&imagBuf[k - LPC_ORDER], LPC_ORDER + blockLength, + autoCorrScaling); + + autoCorrScaling <<= 1; /* consider qmf buffer scaling twice */ + autoCorrScaling += + autoCorr2nd_cplx(ac, realBuf + k, imagBuf + k, blockLength); + + if (ac->det == FL2FXCONST_DBL(0.0f)) { + alphar[1] = alphai[1] = FL2FXCONST_DBL(0.0f); + + alphar[0] = (ac->r01r) >> 2; + alphai[0] = (ac->r01i) >> 2; + + fac = fMultDiv2(ac->r00r, ac->r11r) >> 1; + } else { + alphar[1] = (fMultDiv2(ac->r01r, ac->r12r) >> 1) - + (fMultDiv2(ac->r01i, ac->r12i) >> 1) - + (fMultDiv2(ac->r02r, ac->r11r) >> 1); + alphai[1] = (fMultDiv2(ac->r01i, ac->r12r) >> 1) + + (fMultDiv2(ac->r01r, ac->r12i) >> 1) - + (fMultDiv2(ac->r02i, ac->r11r) >> 1); + + alphar[0] = (fMultDiv2(ac->r01r, ac->det) >> (ac->det_scale + 1)) + + fMult(alphar[1], ac->r12r) + fMult(alphai[1], ac->r12i); + alphai[0] = (fMultDiv2(ac->r01i, ac->det) >> (ac->det_scale + 1)) + + fMult(alphai[1], ac->r12r) - fMult(alphar[1], ac->r12i); + + fac = fMultDiv2(ac->r00r, fMult(ac->det, ac->r11r)) >> + (ac->det_scale + 1); + } + + if (fac == FL2FXCONST_DBL(0.0f)) { + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + signMatrix[timeIndex][r] = 0; + } else { + /* quotaMatrix is scaled with the factor RELAXATION + parse RELAXATION in fractional part and shift factor: 1/(1/0.524288 * + 2^RELAXATION_SHIFT) */ + FIXP_DBL tmp, num, denom; + INT numShift, denomShift, commonShift; + INT sign; + + num = fMultDiv2(alphar[0], ac->r01r) + fMultDiv2(alphai[0], ac->r01i) - + fMultDiv2(alphar[1], fMult(ac->r02r, ac->r11r)) - + fMultDiv2(alphai[1], fMult(ac->r02i, ac->r11r)); + num = fixp_abs(num); + + denom = (fac >> 1) + + (fMultDiv2(fac, RELAXATION_FRACT) >> RELAXATION_SHIFT) - num; + denom = fixp_abs(denom); + + num = fMult(num, RELAXATION_FRACT); + + numShift = CountLeadingBits(num) - 2; + num = scaleValue(num, numShift); + + denomShift = CountLeadingBits(denom); + denom = (FIXP_DBL)denom << denomShift; + + if ((num > FL2FXCONST_DBL(0.0f)) && (denom != FL2FXCONST_DBL(0.0f))) { + commonShift = + fixMin(numShift - denomShift + RELAXATION_SHIFT, DFRACT_BITS - 1); + if (commonShift < 0) { + commonShift = -commonShift; + tmp = schur_div(num, denom, 16); + commonShift = fixMin(commonShift, CountLeadingBits(tmp)); + quotaMatrix[timeIndex][r] = tmp << commonShift; + } else { + quotaMatrix[timeIndex][r] = + schur_div(num, denom, 16) >> commonShift; + } + } else { + quotaMatrix[timeIndex][r] = FL2FXCONST_DBL(0.0f); + } + + if (ac->r11r != FL2FXCONST_DBL(0.0f)) { + if (((ac->r01r >= FL2FXCONST_DBL(0.0f)) && + (ac->r11r >= FL2FXCONST_DBL(0.0f))) || + ((ac->r01r < FL2FXCONST_DBL(0.0f)) && + (ac->r11r < FL2FXCONST_DBL(0.0f)))) { + sign = 1; + } else { + sign = -1; + } + } else { + sign = 1; + } + + if (sign < 0) { + r2 = r; /* (INT) pow(-1, band); */ + } else { + r2 = r + 1; /* (INT) pow(-1, band+1); */ + } + signMatrix[timeIndex][r] = 1 - 2 * (r2 & 0x1); + } + + nrgVector[timeIndex] += + ((ac->r00r) >> + fixMin(DFRACT_BITS - 1, + (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC))); + /* pNrgVectorFreq[r] finally has to be divided by noEstPerFrame, replaced + * division by shifting with one */ + pNrgVectorFreq[r] = + pNrgVectorFreq[r] + + ((ac->r00r) >> + fixMin(DFRACT_BITS - 1, + (2 * qmfScale + autoCorrScaling + SCALE_NRGVEC))); + + blockLength = pBlockLength[1]; + k += stepSize; + timeIndex++; + } + } + + C_ALLOC_SCRATCH_END(realBufRef, FIXP_DBL, 2 * BAND_V_SIZE * NUM_V_COMBINE) + C_ALLOC_SCRATCH_END(ac, ACORR_COEFS, 1) +} + +/**************************************************************************/ +/*! + \brief Extracts the parameters required in the decoder to obtain the + correct tonal to noise ratio after SBR. + + Estimates the tonal to noise ratio of the original signal (using LPC). + Predicts the tonal to noise ration of the SBR signal (in the decoder) by + patching the tonal to noise ratio values similar to the patching of the + lowband in the decoder. Given the tonal to noise ratio of the original + and the SBR signal, it estimates the required amount of inverse filtering, + additional noise as well as any additional sines. + + \return none. + +*/ +/**************************************************************************/ +void FDKsbrEnc_TonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE *infVec, /*!< Vector where the inverse filtering levels will be + stored. */ + FIXP_DBL *noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT *missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any + strong sines are missing.*/ + UCHAR *missingHarmonicsIndex, /*!< Vector indicating where sines are + missing. */ + UCHAR *envelopeCompensation, /*!< Vector to store compensation values for + the energies in. */ + const SBR_FRAME_INFO *frameInfo, /*!< Frame info struct, contains the time + and frequency grid of the current + frame.*/ + UCHAR *transientInfo, /*!< Transient info.*/ + UCHAR *freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags) { + INT band; + INT transientFlag = transientInfo[1]; /*!< Flag indicating if a transient is + present in the current frame. */ + INT transientPos = transientInfo[0]; /*!< Position of the transient.*/ + INT transientFrame, transientFrameInvfEst; + INVF_MODE *infVecPtr; + + /* Determine if this is a frame where a transient starts... + + The detection of noise-floor, missing harmonics and invf_est, is not in sync + for the non-buf-opt decoder such as AAC. Hence we need to keep track on the + transient in the present frame as well as in the next. + */ + transientFrame = 0; + if (hTonCorr->transientNextFrame) { /* The transient was detected in the + previous frame, but is actually */ + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + + if (transientFlag) { + if (transientPos + hTonCorr->transientPosOffset >= + frameInfo->borders[frameInfo->nEnvelopes]) { + hTonCorr->transientNextFrame = 1; + } + } + } else { + if (transientFlag) { + if (transientPos + hTonCorr->transientPosOffset < + frameInfo->borders[frameInfo->nEnvelopes]) { + transientFrame = 1; + hTonCorr->transientNextFrame = 0; + } else { + hTonCorr->transientNextFrame = 1; + } + } + } + transientFrameInvfEst = transientFrame; + + /* + Estimate the required invese filtereing level. + */ + if (hTonCorr->switchInverseFilt) + FDKsbrEnc_qmfInverseFilteringDetector( + &hTonCorr->sbrInvFilt, hTonCorr->quotaMatrix, hTonCorr->nrgVector, + hTonCorr->indexVector, hTonCorr->frameStartIndexInvfEst, + hTonCorr->numberOfEstimatesPerFrame + hTonCorr->frameStartIndexInvfEst, + transientFrameInvfEst, infVec); + + /* + Detect what tones will be missing. + */ + if (xposType == XPOS_LC) { + FDKsbrEnc_SbrMissingHarmonicsDetectorQmf( + &hTonCorr->sbrMissingHarmonicsDetector, hTonCorr->quotaMatrix, + hTonCorr->signMatrix, hTonCorr->indexVector, frameInfo, transientInfo, + missingHarmonicFlag, missingHarmonicsIndex, freqBandTable, nSfb, + envelopeCompensation, hTonCorr->nrgVectorFreq); + } else { + *missingHarmonicFlag = 0; + FDKmemclear(missingHarmonicsIndex, nSfb * sizeof(UCHAR)); + } + + /* + Noise floor estimation + */ + + infVecPtr = hTonCorr->sbrInvFilt.prevInvfMode; + + FDKsbrEnc_sbrNoiseFloorEstimateQmf( + &hTonCorr->sbrNoiseFloorEstimate, frameInfo, noiseLevels, + hTonCorr->quotaMatrix, hTonCorr->indexVector, *missingHarmonicFlag, + hTonCorr->frameStartIndex, hTonCorr->numberOfEstimatesPerFrame, + transientFrame, infVecPtr, sbrSyntaxFlags); + + /* Store the invfVec data for the next frame...*/ + for (band = 0; band < hTonCorr->sbrInvFilt.noDetectorBands; band++) { + hTonCorr->sbrInvFilt.prevInvfMode[band] = infVec[band]; + } +} + +/**************************************************************************/ +/*! + \brief Searches for the closest match in the frequency master table. + + + + \return closest entry. + +*/ +/**************************************************************************/ +static INT findClosestEntry(INT goalSb, UCHAR *v_k_master, INT numMaster, + INT direction) { + INT index; + + if (goalSb <= v_k_master[0]) return v_k_master[0]; + + if (goalSb >= v_k_master[numMaster]) return v_k_master[numMaster]; + + if (direction) { + index = 0; + while (v_k_master[index] < goalSb) { + index++; + } + } else { + index = numMaster; + while (v_k_master[index] > goalSb) { + index--; + } + } + + return v_k_master[index]; +} + +/**************************************************************************/ +/*! + \brief resets the patch + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +static INT resetPatch( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency. */ + INT noChannels) /*!< Number of QMF-channels. */ +{ + INT patch, k, i; + INT targetStopBand; + + PATCH_PARAM *patchParam = hTonCorr->patchParam; + + INT sbGuard = hTonCorr->guard; + INT sourceStartBand; + INT patchDistance; + INT numBandsInPatch; + + INT lsb = + v_k_master[0]; /* Lowest subband related to the synthesis filterbank */ + INT usb = v_k_master[numMaster]; /* Stop subband related to the synthesis + filterbank */ + INT xoverOffset = + highBandStartSb - + v_k_master[0]; /* Calculate distance in subbands between k0 and kx */ + + INT goalSb; + + /* + * Initialize the patching parameter + */ + + if (xposctrl == 1) { + lsb += xoverOffset; + xoverOffset = 0; + } + + goalSb = (INT)((2 * noChannels * 16000 + (fs >> 1)) / fs); /* 16 kHz band */ + goalSb = findClosestEntry(goalSb, v_k_master, numMaster, + 1); /* Adapt region to master-table */ + + /* First patch */ + sourceStartBand = hTonCorr->shiftStartSb + xoverOffset; + targetStopBand = lsb + xoverOffset; + + /* even (odd) numbered channel must be patched to even (odd) numbered channel + */ + patch = 0; + while (targetStopBand < usb) { + /* To many patches */ + if (patch >= MAX_NUM_PATCHES) return (1); /*Number of patches to high */ + + patchParam[patch].guardStartBand = targetStopBand; + targetStopBand += sbGuard; + patchParam[patch].targetStartBand = targetStopBand; + + numBandsInPatch = + goalSb - targetStopBand; /* get the desired range of the patch */ + + if (numBandsInPatch >= lsb - sourceStartBand) { + /* desired number bands are not available -> patch whole source range */ + patchDistance = + targetStopBand - sourceStartBand; /* get the targetOffset */ + patchDistance = + patchDistance & ~1; /* rounding off odd numbers and make all even */ + numBandsInPatch = lsb - (targetStopBand - patchDistance); + numBandsInPatch = findClosestEntry(targetStopBand + numBandsInPatch, + v_k_master, numMaster, 0) - + targetStopBand; /* Adapt region to master-table */ + } + + /* desired number bands are available -> get the minimal even patching + * distance */ + patchDistance = + numBandsInPatch + targetStopBand - lsb; /* get minimal distance */ + patchDistance = (patchDistance + 1) & + ~1; /* rounding up odd numbers and make all even */ + + if (numBandsInPatch <= 0) { + patch--; + } else { + patchParam[patch].sourceStartBand = targetStopBand - patchDistance; + patchParam[patch].targetBandOffs = patchDistance; + patchParam[patch].numBandsInPatch = numBandsInPatch; + patchParam[patch].sourceStopBand = + patchParam[patch].sourceStartBand + numBandsInPatch; + + targetStopBand += patchParam[patch].numBandsInPatch; + } + + /* All patches but first */ + sourceStartBand = hTonCorr->shiftStartSb; + + /* Check if we are close to goalSb */ + if (fixp_abs(targetStopBand - goalSb) < 3) { + goalSb = usb; + } + + patch++; + } + + patch--; + + /* if highest patch contains less than three subband: skip it */ + if (patchParam[patch].numBandsInPatch < 3 && patch > 0) { + patch--; + } + + hTonCorr->noOfPatches = patch + 1; + + /* Assign the index-vector, so we know where to look for the high-band. + -1 represents a guard-band. */ + for (k = 0; k < hTonCorr->patchParam[0].guardStartBand; k++) + hTonCorr->indexVector[k] = k; + + for (i = 0; i < hTonCorr->noOfPatches; i++) { + INT sourceStart = hTonCorr->patchParam[i].sourceStartBand; + INT targetStart = hTonCorr->patchParam[i].targetStartBand; + INT numberOfBands = hTonCorr->patchParam[i].numBandsInPatch; + INT startGuardBand = hTonCorr->patchParam[i].guardStartBand; + + for (k = 0; k < (targetStart - startGuardBand); k++) + hTonCorr->indexVector[startGuardBand + k] = -1; + + for (k = 0; k < numberOfBands; k++) + hTonCorr->indexVector[targetStart + k] = sourceStart + k; + } + + return (0); +} + +/**************************************************************************/ +/*! + \brief Creates an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT FDKsbrEnc_CreateTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan) /*!< Channel index, needed for mem allocation */ +{ + INT i; + FIXP_DBL *quotaMatrix = GetRam_Sbr_quotaMatrix(chan); + INT *signMatrix = GetRam_Sbr_signMatrix(chan); + + if ((NULL == quotaMatrix) || (NULL == signMatrix)) { + goto bail; + } + + FDKmemclear(hTonCorr, sizeof(SBR_TON_CORR_EST)); + + for (i = 0; i < MAX_NO_OF_ESTIMATES; i++) { + hTonCorr->quotaMatrix[i] = quotaMatrix + (i * 64); + hTonCorr->signMatrix[i] = signMatrix + (i * 64); + } + + if (0 != FDKsbrEnc_CreateSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, chan)) { + goto bail; + } + + return 0; + +bail: + hTonCorr->quotaMatrix[0] = quotaMatrix; + hTonCorr->signMatrix[0] = signMatrix; + + FDKsbrEnc_DeleteTonCorrParamExtr(hTonCorr); + + return -1; +} + +/**************************************************************************/ +/*! + \brief Initialize an instance of the tonality correction parameter module. + + The module includes modules for inverse filtering level estimation, + missing harmonics detection and noise floor level estimation. + + \return errorCode, noError if successful. +*/ +/**************************************************************************/ +INT FDKsbrEnc_InitTonCorrParamExtr( + INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA + sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig) /*!< Speech or music tuning. */ +{ + INT nCols = sbrCfg->noQmfSlots; + INT fs = sbrCfg->sampleFreq; + INT noQmfChannels = sbrCfg->noQmfBands; + + INT highBandStartSb = sbrCfg->freqBandTable[LOW_RES][0]; + UCHAR *v_k_master = sbrCfg->v_k_master; + INT numMaster = sbrCfg->num_Master; + + UCHAR **freqBandTable = sbrCfg->freqBandTable; + INT *nSfb = sbrCfg->nSfb; + + INT i; + + /* + Reset the patching and allocate memory for the quota matrix. + Assuming parameters for the LPC analysis. + */ + if (sbrCfg->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + switch (timeSlots) { + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 7 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 7 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 8 - LPC_ORDER; + hTonCorr->lpcLength[1] = 8 - LPC_ORDER; + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LD; + hTonCorr->numberOfEstimatesPerFrame = 2; /* sbrCfg->noQmfSlots / 8 */ + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_512LD; + break; + } + } else + switch (timeSlots) { + case NUMBER_TIME_SLOTS_2048: + hTonCorr->lpcLength[0] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 16 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 16; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_2048; + break; + case NUMBER_TIME_SLOTS_1920: + hTonCorr->lpcLength[0] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->lpcLength[1] = 15 - LPC_ORDER; /* blockLength[0] */ + hTonCorr->numberOfEstimates = NO_OF_ESTIMATES_LC; + hTonCorr->numberOfEstimatesPerFrame = sbrCfg->noQmfSlots / 15; + hTonCorr->frameStartIndexInvfEst = 0; + hTonCorr->transientPosOffset = FRAME_MIDDLE_SLOT_1920; + break; + default: + return -1; + } + + hTonCorr->bufferLength = nCols; + hTonCorr->stepSize = + hTonCorr->lpcLength[0] + LPC_ORDER; /* stepSize[0] implicitly 0. */ + + hTonCorr->nextSample = LPC_ORDER; /* firstSample */ + hTonCorr->move = hTonCorr->numberOfEstimates - + hTonCorr->numberOfEstimatesPerFrame; /* Number of estimates + to move when + buffering.*/ + if (hTonCorr->move < 0) { + return -1; + } + hTonCorr->startIndexMatrix = + hTonCorr->numberOfEstimates - + hTonCorr->numberOfEstimatesPerFrame; /* Where to store the latest + estimations in the tonality + Matrix.*/ + hTonCorr->frameStartIndex = 0; /* Where in the tonality matrix the current + frame (to be sent to the decoder) starts. */ + hTonCorr->prevTransientFlag = 0; + hTonCorr->transientNextFrame = 0; + + hTonCorr->noQmfChannels = noQmfChannels; + + for (i = 0; i < hTonCorr->numberOfEstimates; i++) { + FDKmemclear(hTonCorr->quotaMatrix[i], sizeof(FIXP_DBL) * noQmfChannels); + FDKmemclear(hTonCorr->signMatrix[i], sizeof(INT) * noQmfChannels); + } + + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if (resetPatch(hTonCorr, xposCtrl, highBandStartSb, v_k_master, numMaster, fs, + noQmfChannels)) + return (1); + + if (FDKsbrEnc_InitSbrNoiseFloorEstimate( + &hTonCorr->sbrNoiseFloorEstimate, ana_max_level, freqBandTable[LO], + nSfb[LO], noiseBands, noiseFloorOffset, timeSlots, useSpeechConfig)) + return (1); + + if (FDKsbrEnc_initInvFiltDetector( + &hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands, useSpeechConfig)) + return (1); + + if (FDKsbrEnc_InitSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, fs, frameSize, nSfb[HI], + noQmfChannels, hTonCorr->numberOfEstimates, hTonCorr->move, + hTonCorr->numberOfEstimatesPerFrame, sbrCfg->sbrSyntaxFlags)) + return (1); + + return (0); +} + +/**************************************************************************/ +/*! + \brief resets tonality correction parameter module. + + + + \return errorCode, noError if successful. + +*/ +/**************************************************************************/ +INT FDKsbrEnc_ResetTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR *v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR * + *freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT *nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ +) { + /* Reset the patch.*/ + hTonCorr->guard = 0; + hTonCorr->shiftStartSb = 1; + + if (resetPatch(hTonCorr, xposctrl, highBandStartSb, v_k_master, numMaster, fs, + noQmfChannels)) + return (1); + + /* Reset the noise floor estimate.*/ + if (FDKsbrEnc_resetSbrNoiseFloorEstimate(&hTonCorr->sbrNoiseFloorEstimate, + freqBandTable[LO], nSfb[LO])) + return (1); + + /* + Reset the inveerse filtereing detector. + */ + if (FDKsbrEnc_resetInvFiltDetector( + &hTonCorr->sbrInvFilt, + hTonCorr->sbrNoiseFloorEstimate.freqBandTableQmf, + hTonCorr->sbrNoiseFloorEstimate.noNoiseBands)) + return (1); + /* Reset the missing harmonics detector. */ + if (FDKsbrEnc_ResetSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector, nSfb[HI])) + return (1); + + return (0); +} + +/**************************************************************************/ +/*! + \brief Deletes the tonality correction paramtere module. + + + + \return none + +*/ +/**************************************************************************/ +void FDKsbrEnc_DeleteTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr) /*!< Handle to SBR_TON_CORR struct. */ +{ + if (hTonCorr) { + FreeRam_Sbr_quotaMatrix(hTonCorr->quotaMatrix); + + FreeRam_Sbr_signMatrix(hTonCorr->signMatrix); + + FDKsbrEnc_DeleteSbrMissingHarmonicsDetector( + &hTonCorr->sbrMissingHarmonicsDetector); + } +} diff --git a/fdk-aac/libSBRenc/src/ton_corr.h b/fdk-aac/libSBRenc/src/ton_corr.h new file mode 100644 index 0000000..91aa278 --- /dev/null +++ b/fdk-aac/libSBRenc/src/ton_corr.h @@ -0,0 +1,258 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief General tonality correction detector module. +*/ +#ifndef TON_CORR_H +#define TON_CORR_H + +#include "sbr_encoder.h" +#include "mh_det.h" +#include "nf_est.h" +#include "invf_est.h" + +#define MAX_NUM_PATCHES 6 +#define SCALE_NRGVEC 4 + +/** parameter set for one single patch */ +typedef struct { + INT sourceStartBand; /*!< first band in lowbands where to take the samples + from */ + INT sourceStopBand; /*!< first band in lowbands which is not included in the + patch anymore */ + INT guardStartBand; /*!< first band in highbands to be filled with zeros in + order to reduce interferences between patches */ + INT targetStartBand; /*!< first band in highbands to be filled with whitened + lowband signal */ + INT targetBandOffs; /*!< difference between 'startTargetBand' and + 'startSourceBand' */ + INT numBandsInPatch; /*!< number of consecutive bands in this one patch */ +} PATCH_PARAM; + +typedef struct { + INT switchInverseFilt; /*!< Flag to enable dynamic adaption of invf. detection + */ + INT noQmfChannels; + INT bufferLength; /*!< Length of the r and i buffers. */ + INT stepSize; /*!< Stride for the lpc estimate. */ + INT numberOfEstimates; /*!< The total number of estiamtes, available in the + quotaMatrix.*/ + UINT numberOfEstimatesPerFrame; /*!< The number of estimates per frame + available in the quotaMatrix.*/ + INT lpcLength[2]; /*!< Segment length used for second order LPC analysis.*/ + INT nextSample; /*!< Where to start the LPC analysis of the current frame.*/ + INT move; /*!< How many estimates to move in the quotaMatrix, when buffering. + */ + INT frameStartIndex; /*!< The start index for the current frame in the r and i + buffers. */ + INT startIndexMatrix; /*!< The start index for the current frame in the + quotaMatrix. */ + INT frameStartIndexInvfEst; /*!< The start index of the inverse filtering, not + the same as the others, dependent on what + decoder is used (buffer opt, or no buffer opt). + */ + INT prevTransientFlag; /*!< The transisent flag (from the transient detector) + for the previous frame. */ + INT transientNextFrame; /*!< Flag to indicate that the transient will show up + in the next frame. */ + INT transientPosOffset; /*!< An offset value to match the transient pos as + calculated by the transient detector with the + actual position in the frame.*/ + + INT* signMatrix[MAX_NO_OF_ESTIMATES]; /*!< Matrix holding the sign of each + channe, i.e. indicating in what part + of a QMF channel a possible sine is. + */ + + FIXP_DBL* quotaMatrix[MAX_NO_OF_ESTIMATES]; /*!< Matrix holding the quota + values for all estimates, all + channels. */ + + FIXP_DBL nrgVector[MAX_NO_OF_ESTIMATES]; /*!< Vector holding the averaged + energies for every QMF band. */ + FIXP_DBL nrgVectorFreq[64]; /*!< Vector holding the averaged energies for + every QMF channel */ + + SCHAR indexVector[64]; /*!< Index vector poINTing to the correct lowband + channel, when indexing a highband channel, -1 + represents a guard band */ + PATCH_PARAM + patchParam[MAX_NUM_PATCHES]; /*!< new parameter set for patching */ + INT guard; /*!< number of guardbands between every patch */ + INT shiftStartSb; /*!< lowest subband of source range to be included in the + patches */ + INT noOfPatches; /*!< number of patches */ + + SBR_MISSING_HARMONICS_DETECTOR + sbrMissingHarmonicsDetector; /*!< SBR_MISSING_HARMONICS_DETECTOR struct. + */ + SBR_NOISE_FLOOR_ESTIMATE + sbrNoiseFloorEstimate; /*!< SBR_NOISE_FLOOR_ESTIMATE struct. */ + SBR_INV_FILT_EST sbrInvFilt; /*!< SBR_INV_FILT_EST struct. */ +} SBR_TON_CORR_EST; + +typedef SBR_TON_CORR_EST* HANDLE_SBR_TON_CORR_EST; + +void FDKsbrEnc_TonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INVF_MODE* infVec, /*!< Vector where the inverse filtering levels will be + stored. */ + FIXP_DBL* noiseLevels, /*!< Vector where the noise levels will be stored. */ + INT* missingHarmonicFlag, /*!< Flag set to one or zero, dependent on if any + strong sines are missing.*/ + UCHAR* missingHarmonicsIndex, /*!< Vector indicating where sines are + missing. */ + UCHAR* envelopeCompensation, /*!< Vector to store compensation values for + the energies in. */ + const SBR_FRAME_INFO* frameInfo, /*!< Frame info struct, contains the time + and frequency grid of the current + frame.*/ + UCHAR* transientInfo, /*!< Transient info.*/ + UCHAR* freqBandTable, /*!< Frequency band tables for high-res.*/ + INT nSfb, /*!< Number of scalefactor bands for high-res. */ + XPOS_MODE xposType, /*!< Type of transposer used in the decoder.*/ + UINT sbrSyntaxFlags); + +INT FDKsbrEnc_CreateTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + INT chan); /*!< Channel index, needed for mem allocation */ + +INT FDKsbrEnc_InitTonCorrParamExtr( + INT frameSize, /*!< Current SBR frame size. */ + HANDLE_SBR_TON_CORR_EST + hTonCorr, /*!< Pointer to handle to SBR_TON_CORR struct. */ + HANDLE_SBR_CONFIG_DATA + sbrCfg, /*!< Pointer to SBR configuration parameters. */ + INT timeSlots, /*!< Number of time-slots per frame */ + INT xposCtrl, /*!< Different patch modes. */ + INT ana_max_level, /*!< Maximum level of the adaptive noise. */ + INT noiseBands, /*!< Number of noise bands per octave. */ + INT noiseFloorOffset, /*!< Noise floor offset. */ + UINT useSpeechConfig /*!< Speech or music tuning. */ +); + +void FDKsbrEnc_DeleteTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr); /*!< Handle to SBR_TON_CORR struct. */ + +void FDKsbrEnc_CalculateTonalityQuotas( + HANDLE_SBR_TON_CORR_EST hTonCorr, FIXP_DBL** sourceBufferReal, + FIXP_DBL** sourceBufferImag, INT usb, + INT qmfScale /*!< sclefactor of QMF subsamples */ +); + +INT FDKsbrEnc_ResetTonCorrParamExtr( + HANDLE_SBR_TON_CORR_EST hTonCorr, /*!< Handle to SBR_TON_CORR struct. */ + INT xposctrl, /*!< Different patch modes. */ + INT highBandStartSb, /*!< Start band of the SBR range. */ + UCHAR* v_k_master, /*!< Master frequency table from which all other table + are derived.*/ + INT numMaster, /*!< Number of elements in the master table. */ + INT fs, /*!< Sampling frequency (of the SBR part). */ + UCHAR** + freqBandTable, /*!< Frequency band table for low-res and high-res. */ + INT* nSfb, /*!< Number of frequency bands (hig-res and low-res). */ + INT noQmfChannels /*!< Number of QMF channels. */ +); +#endif diff --git a/fdk-aac/libSBRenc/src/tran_det.cpp b/fdk-aac/libSBRenc/src/tran_det.cpp new file mode 100644 index 0000000..3b6765a --- /dev/null +++ b/fdk-aac/libSBRenc/src/tran_det.cpp @@ -0,0 +1,1092 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): Tobias Chalupka + + Description: SBR encoder transient detector + +*******************************************************************************/ + +#include "tran_det.h" + +#include "fram_gen.h" +#include "sbrenc_ram.h" +#include "sbr_misc.h" + +#include "genericStds.h" + +#define NORM_QMF_ENERGY 9.31322574615479E-10 /* 2^-30 */ + +/* static FIXP_DBL ABS_THRES = fixMax( FL2FXCONST_DBL(1.28e5 * + * NORM_QMF_ENERGY), (FIXP_DBL)1) Minimum threshold for detecting changes */ +#define ABS_THRES ((FIXP_DBL)16) + +/******************************************************************************* + Functionname: spectralChange + ******************************************************************************* + \brief Calculates a measure for the spectral change within the frame + + The function says how good it would be to split the frame at the given border + position into 2 envelopes. + + The return value delta_sum is scaled with the factor 1/64 + + \return calculated value +*******************************************************************************/ +#define NRG_SHIFT 3 /* for energy summation */ + +static FIXP_DBL spectralChange( + FIXP_DBL Energies[NUMBER_TIME_SLOTS_2304][MAX_FREQ_COEFFS], + INT *scaleEnergies, FIXP_DBL EnergyTotal, INT nSfb, INT start, INT border, + INT YBufferWriteOffset, INT stop, INT *result_e) { + INT i, j; + INT len1, len2; + SCHAR energies_e_diff[NUMBER_TIME_SLOTS_2304], energies_e, energyTotal_e = 19, + energies_e_add; + SCHAR prevEnergies_e_diff, newEnergies_e_diff; + FIXP_DBL tmp0, tmp1; + FIXP_DBL delta, delta_sum; + INT accu_e, tmp_e; + + delta_sum = FL2FXCONST_DBL(0.0f); + *result_e = 0; + + len1 = border - start; + len2 = stop - border; + + /* prefer borders near the middle of the frame */ + FIXP_DBL pos_weight; + pos_weight = FL2FXCONST_DBL(0.5f) - (len1 * GetInvInt(len1 + len2)); + pos_weight = /*FL2FXCONST_DBL(1.0)*/ (FIXP_DBL)MAXVAL_DBL - + (fMult(pos_weight, pos_weight) << 2); + + /*** Calc scaling for energies ***/ + FDK_ASSERT(scaleEnergies[0] >= 0); + FDK_ASSERT(scaleEnergies[1] >= 0); + + energies_e = 19 - fMin(scaleEnergies[0], scaleEnergies[1]); + + /* limit shift for energy accumulation, energies_e can be -10 min. */ + if (energies_e < -10) { + energies_e_add = -10 - energies_e; + energies_e = -10; + } else if (energies_e > 17) { + energies_e_add = energies_e - 17; + energies_e = 17; + } else { + energies_e_add = 0; + } + + /* compensate scaling differences between scaleEnergies[0] and + * scaleEnergies[1] */ + prevEnergies_e_diff = scaleEnergies[0] - + fMin(scaleEnergies[0], scaleEnergies[1]) + + energies_e_add + NRG_SHIFT; + newEnergies_e_diff = scaleEnergies[1] - + fMin(scaleEnergies[0], scaleEnergies[1]) + + energies_e_add + NRG_SHIFT; + + prevEnergies_e_diff = fMin(prevEnergies_e_diff, DFRACT_BITS - 1); + newEnergies_e_diff = fMin(newEnergies_e_diff, DFRACT_BITS - 1); + + for (i = start; i < YBufferWriteOffset; i++) { + energies_e_diff[i] = prevEnergies_e_diff; + } + for (i = YBufferWriteOffset; i < stop; i++) { + energies_e_diff[i] = newEnergies_e_diff; + } + + /* Sum up energies of all QMF-timeslots for both halfs */ + FDK_ASSERT(len1 <= 8); /* otherwise an overflow is possible */ + FDK_ASSERT(len2 <= 8); /* otherwise an overflow is possible */ + + for (j = 0; j < nSfb; j++) { + FIXP_DBL accu1 = FL2FXCONST_DBL(0.f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.f); + accu_e = energies_e + 3; + + /* Sum up energies in first half */ + for (i = start; i < border; i++) { + accu1 += scaleValue(Energies[i][j], -energies_e_diff[i]); + } + + /* Sum up energies in second half */ + for (i = border; i < stop; i++) { + accu2 += scaleValue(Energies[i][j], -energies_e_diff[i]); + } + + /* Ensure certain energy to prevent division by zero and to prevent + * splitting for very low levels */ + accu1 = fMax(accu1, (FIXP_DBL)len1); + accu2 = fMax(accu2, (FIXP_DBL)len2); + +/* Energy change in current band */ +#define LN2 FL2FXCONST_DBL(0.6931471806f) /* ln(2) */ + tmp0 = fLog2(accu2, accu_e) - fLog2(accu1, accu_e); + tmp1 = fLog2((FIXP_DBL)len1, 31) - fLog2((FIXP_DBL)len2, 31); + delta = fMult(LN2, (tmp0 + tmp1)); + delta = (FIXP_DBL)fAbs(delta); + + /* Weighting with amplitude ratio of this band */ + accu_e++; /* scale at least one bit due to (accu1+accu2) */ + accu1 >>= 1; + accu2 >>= 1; + + if (accu_e & 1) { + accu_e++; /* for a defined square result exponent, the exponent has to be + even */ + accu1 >>= 1; + accu2 >>= 1; + } + + delta_sum += fMult(sqrtFixp(accu1 + accu2), delta); + *result_e = ((accu_e >> 1) + LD_DATA_SHIFT); + } + + if (energyTotal_e & 1) { + energyTotal_e += 1; /* for a defined square result exponent, the exponent + has to be even */ + EnergyTotal >>= 1; + } + + delta_sum = fMult(delta_sum, invSqrtNorm2(EnergyTotal, &tmp_e)); + *result_e = *result_e + (tmp_e - (energyTotal_e >> 1)); + + return fMult(delta_sum, pos_weight); +} + +/******************************************************************************* + Functionname: addLowbandEnergies + ******************************************************************************* + \brief Calculates total lowband energy + + The input values Energies[0] (low-band) are scaled by the factor + 2^(14-*scaleEnergies[0]) + The input values Energies[1] (high-band) are scaled by the factor + 2^(14-*scaleEnergies[1]) + + \return total energy in the lowband, scaled by the factor 2^19 +*******************************************************************************/ +static FIXP_DBL addLowbandEnergies(FIXP_DBL **Energies, int *scaleEnergies, + int YBufferWriteOffset, int nrgSzShift, + int tran_off, UCHAR *freqBandTable, + int slots) { + INT nrgTotal_e; + FIXP_DBL nrgTotal_m; + FIXP_DBL accu1 = FL2FXCONST_DBL(0.0f); + FIXP_DBL accu2 = FL2FXCONST_DBL(0.0f); + int tran_offdiv2 = tran_off >> nrgSzShift; + const int sc1 = + DFRACT_BITS - + fNormz((FIXP_DBL)fMax( + 1, (freqBandTable[0] * (YBufferWriteOffset - tran_offdiv2) - 1))); + const int sc2 = + DFRACT_BITS - + fNormz((FIXP_DBL)fMax( + 1, (freqBandTable[0] * + (tran_offdiv2 + (slots >> nrgSzShift) - YBufferWriteOffset) - + 1))); + int ts, k; + + /* Sum up lowband energy from one frame at offset tran_off */ + /* freqBandTable[LORES] has MAX_FREQ_COEFFS/2 +1 coeefs max. */ + for (ts = tran_offdiv2; ts < YBufferWriteOffset; ts++) { + for (k = 0; k < freqBandTable[0]; k++) { + accu1 += Energies[ts][k] >> sc1; + } + } + for (; ts < tran_offdiv2 + (slots >> nrgSzShift); ts++) { + for (k = 0; k < freqBandTable[0]; k++) { + accu2 += Energies[ts][k] >> sc2; + } + } + + nrgTotal_m = fAddNorm(accu1, (sc1 - 5) - scaleEnergies[0], accu2, + (sc2 - 5) - scaleEnergies[1], &nrgTotal_e); + nrgTotal_m = scaleValueSaturate(nrgTotal_m, nrgTotal_e); + + return (nrgTotal_m); +} + +/******************************************************************************* + Functionname: addHighbandEnergies + ******************************************************************************* + \brief Add highband energies + + Highband energies are mapped to an array with smaller dimension: + Its time resolution is only 1 SBR-timeslot and its frequency resolution + is 1 SBR-band. Therefore the data to be fed into the spectralChange + function is reduced. + + The values EnergiesM are scaled by the factor (2^19-scaleEnergies[0]) for + slots=YBufferWriteOffset. + + \return total energy in the highband, scaled by factor 2^19 +*******************************************************************************/ + +static FIXP_DBL addHighbandEnergies( + FIXP_DBL **RESTRICT Energies, /*!< input */ + INT *scaleEnergies, INT YBufferWriteOffset, + FIXP_DBL EnergiesM[NUMBER_TIME_SLOTS_2304] + [MAX_FREQ_COEFFS], /*!< Combined output */ + UCHAR *RESTRICT freqBandTable, INT nSfb, INT sbrSlots, INT timeStep) { + INT i, j, k, slotIn, slotOut, scale[2]; + INT li, ui; + FIXP_DBL nrgTotal; + FIXP_DBL accu = FL2FXCONST_DBL(0.0f); + + /* Combine QMF-timeslots to SBR-timeslots, + combine QMF-bands to SBR-bands, + combine Left and Right channel */ + for (slotOut = 0; slotOut < sbrSlots; slotOut++) { + /* Note: Below slotIn = slotOut and not slotIn = timeStep*slotOut + because the Energies[] time resolution is always the SBR slot resolution + regardless of the timeStep. */ + slotIn = slotOut; + + for (j = 0; j < nSfb; j++) { + accu = FL2FXCONST_DBL(0.0f); + + li = freqBandTable[j]; + ui = freqBandTable[j + 1]; + + for (k = li; k < ui; k++) { + for (i = 0; i < timeStep; i++) { + accu += Energies[slotIn][k] >> 5; + } + } + EnergiesM[slotOut][j] = accu; + } + } + + /* scale energies down before add up */ + scale[0] = fixMin(8, scaleEnergies[0]); + scale[1] = fixMin(8, scaleEnergies[1]); + + if ((scaleEnergies[0] - scale[0]) > (DFRACT_BITS - 1) || + (scaleEnergies[1] - scale[1]) > (DFRACT_BITS - 1)) + nrgTotal = FL2FXCONST_DBL(0.0f); + else { + /* Now add all energies */ + accu = FL2FXCONST_DBL(0.0f); + + for (slotOut = 0; slotOut < YBufferWriteOffset; slotOut++) { + for (j = 0; j < nSfb; j++) { + accu += (EnergiesM[slotOut][j] >> scale[0]); + } + } + nrgTotal = accu >> (scaleEnergies[0] - scale[0]); + + for (slotOut = YBufferWriteOffset; slotOut < sbrSlots; slotOut++) { + for (j = 0; j < nSfb; j++) { + accu += (EnergiesM[slotOut][j] >> scale[0]); + } + } + nrgTotal = fAddSaturate(nrgTotal, accu >> (scaleEnergies[1] - scale[1])); + } + + return (nrgTotal); +} + +/******************************************************************************* + Functionname: FDKsbrEnc_frameSplitter + ******************************************************************************* + \brief Decides if a FIXFIX-frame shall be splitted into 2 envelopes + + If no transient has been detected before, the frame can still be splitted + into 2 envelopes. +*******************************************************************************/ +void FDKsbrEnc_frameSplitter( + FIXP_DBL **Energies, INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, UCHAR *freqBandTable, + UCHAR *tran_vector, int YBufferWriteOffset, int YBufferSzShift, int nSfb, + int timeStep, int no_cols, FIXP_DBL *tonality) { + if (tran_vector[1] == 0) /* no transient was detected */ + { + FIXP_DBL delta; + INT delta_e; + FIXP_DBL(*EnergiesM)[MAX_FREQ_COEFFS]; + FIXP_DBL EnergyTotal, newLowbandEnergy, newHighbandEnergy; + INT border; + INT sbrSlots = fMultI(GetInvInt(timeStep), no_cols); + C_ALLOC_SCRATCH_START(_EnergiesM, FIXP_DBL, + NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS) + + FDK_ASSERT(sbrSlots * timeStep == no_cols); + + EnergiesM = (FIXP_DBL(*)[MAX_FREQ_COEFFS])_EnergiesM; + + /* + Get Lowband-energy over a range of 2 frames (Look half a frame back and + ahead). + */ + newLowbandEnergy = addLowbandEnergies( + Energies, scaleEnergies, YBufferWriteOffset, YBufferSzShift, + h_sbrTransientDetector->tran_off, freqBandTable, no_cols); + + newHighbandEnergy = + addHighbandEnergies(Energies, scaleEnergies, YBufferWriteOffset, + EnergiesM, freqBandTable, nSfb, sbrSlots, timeStep); + + { + /* prevLowBandEnergy: Corresponds to 1 frame, starting with half a frame + look-behind newLowbandEnergy: Corresponds to 1 frame, starting in the + middle of the current frame */ + EnergyTotal = (newLowbandEnergy >> 1) + + (h_sbrTransientDetector->prevLowBandEnergy >> + 1); /* mean of new and prev LB NRG */ + EnergyTotal = + fAddSaturate(EnergyTotal, newHighbandEnergy); /* Add HB NRG */ + /* The below border should specify the same position as the middle border + of a FIXFIX-frame with 2 envelopes. */ + border = (sbrSlots + 1) >> 1; + + if ((INT)EnergyTotal & 0xffffffe0 && + (scaleEnergies[0] < 32 || scaleEnergies[1] < 32)) /* i.e. > 31 */ { + delta = spectralChange(EnergiesM, scaleEnergies, EnergyTotal, nSfb, 0, + border, YBufferWriteOffset, sbrSlots, &delta_e); + } else { + delta = FL2FXCONST_DBL(0.0f); + delta_e = 0; + + /* set tonality to 0 when energy is very low, since the amplitude + resolution should then be low as well */ + *tonality = FL2FXCONST_DBL(0.0f); + } + + if (fIsLessThan(h_sbrTransientDetector->split_thr_m, + h_sbrTransientDetector->split_thr_e, delta, delta_e)) { + tran_vector[0] = 1; /* Set flag for splitting */ + } else { + tran_vector[0] = 0; + } + } + + /* Update prevLowBandEnergy */ + h_sbrTransientDetector->prevLowBandEnergy = newLowbandEnergy; + h_sbrTransientDetector->prevHighBandEnergy = newHighbandEnergy; + C_ALLOC_SCRATCH_END(_EnergiesM, FIXP_DBL, + NUMBER_TIME_SLOTS_2304 * MAX_FREQ_COEFFS) + } +} + +/* + * Calculate transient energy threshold for each QMF band + */ +static void calculateThresholds(FIXP_DBL **RESTRICT Energies, + INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, + int YBufferWriteOffset, int YBufferSzShift, + int noCols, int noRows, int tran_off) { + FIXP_DBL mean_val, std_val, temp; + FIXP_DBL i_noCols; + FIXP_DBL i_noCols1; + FIXP_DBL accu, accu0, accu1; + int scaleFactor0, scaleFactor1, commonScale; + int i, j; + + i_noCols = GetInvInt(noCols + tran_off) << YBufferSzShift; + i_noCols1 = GetInvInt(noCols + tran_off - 1) << YBufferSzShift; + + /* calc minimum scale of energies of previous and current frame */ + commonScale = fixMin(scaleEnergies[0], scaleEnergies[1]); + + /* calc scalefactors to adapt energies to common scale */ + scaleFactor0 = fixMin((scaleEnergies[0] - commonScale), (DFRACT_BITS - 1)); + scaleFactor1 = fixMin((scaleEnergies[1] - commonScale), (DFRACT_BITS - 1)); + + FDK_ASSERT((scaleFactor0 >= 0) && (scaleFactor1 >= 0)); + + /* calculate standard deviation in every subband */ + for (i = 0; i < noRows; i++) { + int startEnergy = (tran_off >> YBufferSzShift); + int endEnergy = ((noCols >> YBufferSzShift) + tran_off); + int shift; + + /* calculate mean value over decimated energy values (downsampled by 2). */ + accu0 = accu1 = FL2FXCONST_DBL(0.0f); + + for (j = startEnergy; j < YBufferWriteOffset; j++) + accu0 = fMultAddDiv2(accu0, Energies[j][i], i_noCols); + for (; j < endEnergy; j++) + accu1 = fMultAddDiv2(accu1, Energies[j][i], i_noCols); + + mean_val = ((accu0 << 1) >> scaleFactor0) + + ((accu1 << 1) >> scaleFactor1); /* average */ + shift = fixMax( + 0, CountLeadingBits(mean_val) - + 6); /* -6 to keep room for accumulating upto N = 24 values */ + + /* calculate standard deviation */ + accu = FL2FXCONST_DBL(0.0f); + + /* summe { ((mean_val-nrg)^2) * i_noCols1 } */ + for (j = startEnergy; j < YBufferWriteOffset; j++) { + temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor0)) + << shift; + temp = fPow2Div2(temp); + accu = fMultAddDiv2(accu, temp, i_noCols1); + } + for (; j < endEnergy; j++) { + temp = ((FIXP_DBL)mean_val - ((FIXP_DBL)Energies[j][i] >> scaleFactor1)) + << shift; + temp = fPow2Div2(temp); + accu = fMultAddDiv2(accu, temp, i_noCols1); + } + accu <<= 2; + std_val = sqrtFixp(accu) >> shift; /* standard deviation */ + + /* + Take new threshold as average of calculated standard deviation ratio + and old threshold if greater than absolute threshold + */ + temp = (commonScale <= (DFRACT_BITS - 1)) + ? fMult(FL2FXCONST_DBL(0.66f), thresholds[i]) + + (fMult(FL2FXCONST_DBL(0.34f), std_val) >> commonScale) + : (FIXP_DBL)0; + + thresholds[i] = fixMax(ABS_THRES, temp); + + FDK_ASSERT(commonScale >= 0); + } +} + +/* + * Calculate transient levels for each QMF time slot. + */ +static void extractTransientCandidates( + FIXP_DBL **RESTRICT Energies, INT *RESTRICT scaleEnergies, + FIXP_DBL *RESTRICT thresholds, FIXP_DBL *RESTRICT transients, + int YBufferWriteOffset, int YBufferSzShift, int noCols, int start_band, + int stop_band, int tran_off, int addPrevSamples) { + FIXP_DBL i_thres; + C_ALLOC_SCRATCH_START(EnergiesTemp, FIXP_DBL, 2 * 32) + int tmpScaleEnergies0, tmpScaleEnergies1; + int endCond; + int startEnerg, endEnerg; + int i, j, jIndex, jpBM; + + tmpScaleEnergies0 = scaleEnergies[0]; + tmpScaleEnergies1 = scaleEnergies[1]; + + /* Scale value for first energies, upto YBufferWriteOffset */ + tmpScaleEnergies0 = fixMin(tmpScaleEnergies0, MAX_SHIFT_DBL); + /* Scale value for first energies, from YBufferWriteOffset upwards */ + tmpScaleEnergies1 = fixMin(tmpScaleEnergies1, MAX_SHIFT_DBL); + + FDK_ASSERT((tmpScaleEnergies0 >= 0) && (tmpScaleEnergies1 >= 0)); + + /* Keep addPrevSamples extra previous transient candidates. */ + FDKmemmove(transients, transients + noCols - addPrevSamples, + (tran_off + addPrevSamples) * sizeof(FIXP_DBL)); + FDKmemclear(transients + tran_off + addPrevSamples, + noCols * sizeof(FIXP_DBL)); + + endCond = noCols; /* Amount of new transient values to be calculated. */ + startEnerg = (tran_off - 3) >> YBufferSzShift; /* >>YBufferSzShift because of + amount of energy values. -3 + because of neighbors being + watched. */ + endEnerg = + ((noCols + (YBufferWriteOffset << YBufferSzShift)) - 1) >> + YBufferSzShift; /* YBufferSzShift shifts because of half energy values. */ + + /* Compute differential values with two different weightings in every subband + */ + for (i = start_band; i < stop_band; i++) { + FIXP_DBL thres = thresholds[i]; + + if ((LONG)thresholds[i] >= 256) + i_thres = (LONG)((LONG)MAXVAL_DBL / ((((LONG)thresholds[i])) + 1)) + << (32 - 24); + else + i_thres = (LONG)MAXVAL_DBL; + + /* Copy one timeslot and de-scale and de-squish */ + if (YBufferSzShift == 1) { + for (j = startEnerg; j < YBufferWriteOffset; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] = + tmp >> tmpScaleEnergies0; + } + for (; j <= endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[(j << 1) + 1] = EnergiesTemp[j << 1] = + tmp >> tmpScaleEnergies1; + } + } else { + for (j = startEnerg; j < YBufferWriteOffset; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[j] = tmp >> tmpScaleEnergies0; + } + for (; j <= endEnerg; j++) { + FIXP_DBL tmp = Energies[j][i]; + EnergiesTemp[j] = tmp >> tmpScaleEnergies1; + } + } + + /* Detect peaks in energy values. */ + + jIndex = tran_off; + jpBM = jIndex + addPrevSamples; + + for (j = endCond; j--; jIndex++, jpBM++) { + FIXP_DBL delta, tran; + int d; + + delta = (FIXP_DBL)0; + tran = (FIXP_DBL)0; + + for (d = 1; d < 4; d++) { + delta += EnergiesTemp[jIndex + d]; /* R */ + delta -= EnergiesTemp[jIndex - d]; /* L */ + delta -= thres; + + if (delta > (FIXP_DBL)0) { + tran = fMultAddDiv2(tran, i_thres, delta); + } + } + transients[jpBM] += (tran << 1); + } + } + C_ALLOC_SCRATCH_END(EnergiesTemp, FIXP_DBL, 2 * 32) +} + +void FDKsbrEnc_transientDetect(HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTran, + FIXP_DBL **Energies, INT *scaleEnergies, + UCHAR *transient_info, int YBufferWriteOffset, + int YBufferSzShift, int timeStep, + int frameMiddleBorder) { + int no_cols = h_sbrTran->no_cols; + int qmfStartSample; + int addPrevSamples; + int timeStepShift = 0; + int i, cond; + + /* Where to start looking for transients in the transient candidate buffer */ + qmfStartSample = timeStep * frameMiddleBorder; + /* We need to look one value backwards in the transients, so we might need one + * more previous value. */ + addPrevSamples = (qmfStartSample > 0) ? 0 : 1; + + switch (timeStep) { + case 1: + timeStepShift = 0; + break; + case 2: + timeStepShift = 1; + break; + case 4: + timeStepShift = 2; + break; + } + + calculateThresholds(Energies, scaleEnergies, h_sbrTran->thresholds, + YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, + h_sbrTran->no_rows, h_sbrTran->tran_off); + + extractTransientCandidates( + Energies, scaleEnergies, h_sbrTran->thresholds, h_sbrTran->transients, + YBufferWriteOffset, YBufferSzShift, h_sbrTran->no_cols, 0, + h_sbrTran->no_rows, h_sbrTran->tran_off, addPrevSamples); + + transient_info[0] = 0; + transient_info[1] = 0; + transient_info[2] = 0; + + /* Offset by the amount of additional previous transient candidates being + * kept. */ + qmfStartSample += addPrevSamples; + + /* Check for transients in second granule (pick the last value of subsequent + * values) */ + for (i = qmfStartSample; i < qmfStartSample + no_cols; i++) { + cond = (h_sbrTran->transients[i] < + fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) && + (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + transient_info[0] = (i - qmfStartSample) >> timeStepShift; + transient_info[1] = 1; + break; + } + } + + if (h_sbrTran->frameShift != 0) { + /* transient prediction for LDSBR */ + /* Check for transients in first qmf-slots of second frame */ + for (i = qmfStartSample + no_cols; + i < qmfStartSample + no_cols + h_sbrTran->frameShift; i++) { + cond = (h_sbrTran->transients[i] < + fMult(FL2FXCONST_DBL(0.9f), h_sbrTran->transients[i - 1])) && + (h_sbrTran->transients[i - 1] > h_sbrTran->tran_thr); + + if (cond) { + int pos = (int)((i - qmfStartSample - no_cols) >> timeStepShift); + if ((pos < 3) && (transient_info[1] == 0)) { + transient_info[2] = 1; + } + break; + } + } + } +} + +int FDKsbrEnc_InitSbrTransientDetector( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, INT sampleFreq, sbrConfigurationPtr params, int tran_fc, + int no_cols, int no_rows, int YBufferWriteOffset, int YBufferSzShift, + int frameShift, int tran_off) { + INT totalBitrate = + params->codecSettings.standardBitrate * params->codecSettings.nChannels; + INT codecBitrate = params->codecSettings.bitRate; + FIXP_DBL bitrateFactor_m, framedur_fix; + INT bitrateFactor_e, tmp_e; + + FDKmemclear(h_sbrTransientDetector, sizeof(SBR_TRANSIENT_DETECTOR)); + + h_sbrTransientDetector->frameShift = frameShift; + h_sbrTransientDetector->tran_off = tran_off; + + if (codecBitrate) { + bitrateFactor_m = fDivNorm((FIXP_DBL)totalBitrate, + (FIXP_DBL)(codecBitrate << 2), &bitrateFactor_e); + bitrateFactor_e += 2; + } else { + bitrateFactor_m = FL2FXCONST_DBL(1.0 / 4.0); + bitrateFactor_e = 2; + } + + framedur_fix = fDivNorm(frameSize, sampleFreq); + + /* The longer the frames, the more often should the FIXFIX- + case transmit 2 envelopes instead of 1. + Frame durations below 10 ms produce the highest threshold + so that practically always only 1 env is transmitted. */ + FIXP_DBL tmp = framedur_fix - FL2FXCONST_DBL(0.010); + + tmp = fixMax(tmp, FL2FXCONST_DBL(0.0001)); + tmp = fDivNorm(FL2FXCONST_DBL(0.000075), fPow2(tmp), &tmp_e); + + bitrateFactor_e = (tmp_e + bitrateFactor_e); + + if (sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { + bitrateFactor_e--; /* divide by 2 */ + } + + FDK_ASSERT(no_cols <= 32); + FDK_ASSERT(no_rows <= 64); + + h_sbrTransientDetector->no_cols = no_cols; + h_sbrTransientDetector->tran_thr = + (FIXP_DBL)((params->tran_thr << (32 - 24 - 1)) / no_rows); + h_sbrTransientDetector->tran_fc = tran_fc; + h_sbrTransientDetector->split_thr_m = fMult(tmp, bitrateFactor_m); + h_sbrTransientDetector->split_thr_e = bitrateFactor_e; + h_sbrTransientDetector->no_rows = no_rows; + h_sbrTransientDetector->mode = params->tran_det_mode; + h_sbrTransientDetector->prevLowBandEnergy = FL2FXCONST_DBL(0.0f); + + return (0); +} + +#define ENERGY_SCALING_SIZE 32 + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, const INT bandwidth_qmf_slot, + const INT no_qmf_channels, const INT sbr_qmf_1st_band) { + int i; + int buff_size; + FIXP_DBL myExp; + FIXP_DBL myExpSlot; + + h_sbrFastTransientDetector->lookahead = TRAN_DET_LOOKAHEAD; + h_sbrFastTransientDetector->nTimeSlots = time_slots_per_frame; + + buff_size = h_sbrFastTransientDetector->nTimeSlots + + h_sbrFastTransientDetector->lookahead; + + for (i = 0; i < buff_size; i++) { + h_sbrFastTransientDetector->delta_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->energy_timeSlots[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->lowpass_energy[i] = FL2FXCONST_DBL(0.0f); + h_sbrFastTransientDetector->transientCandidates[i] = 0; + } + + FDK_ASSERT(bandwidth_qmf_slot > 0.f); + h_sbrFastTransientDetector->stopBand = + fMin(TRAN_DET_STOP_FREQ / bandwidth_qmf_slot, no_qmf_channels); + h_sbrFastTransientDetector->startBand = + fMin(sbr_qmf_1st_band, + h_sbrFastTransientDetector->stopBand - TRAN_DET_MIN_QMFBANDS); + + FDK_ASSERT(h_sbrFastTransientDetector->startBand < no_qmf_channels); + FDK_ASSERT(h_sbrFastTransientDetector->startBand < + h_sbrFastTransientDetector->stopBand); + FDK_ASSERT(h_sbrFastTransientDetector->startBand > 1); + FDK_ASSERT(h_sbrFastTransientDetector->stopBand > 1); + + /* the energy weighting and adding up has a headroom of 6 Bits, + so up to 64 bands can be added without potential overflow. */ + FDK_ASSERT(h_sbrFastTransientDetector->stopBand - + h_sbrFastTransientDetector->startBand <= + 64); + +/* QMF_HP_dB_SLOPE_FIX says that we want a 20 dB per 16 kHz HP filter. + The following lines map this to the QMF bandwidth. */ +#define EXP_E 7 /* 64 (=64) multiplications max, max. allowed sum is 0.5 */ + myExp = fMultNorm(QMF_HP_dBd_SLOPE_FIX, 0, (FIXP_DBL)bandwidth_qmf_slot, + DFRACT_BITS - 1, EXP_E); + myExpSlot = myExp; + + for (i = 0; i < 64; i++) { + /* Calculate dBf over all qmf bands: + dBf = (10^(0.002266f/10*bw(slot)))^(band) = + = 2^(log2(10)*0.002266f/10*bw(slot)*band) = + = 2^(0.00075275f*bw(slot)*band) */ + + FIXP_DBL dBf_m; /* dBf mantissa */ + INT dBf_e; /* dBf exponent */ + INT tmp; + + INT dBf_int; /* dBf integer part */ + FIXP_DBL dBf_fract; /* dBf fractional part */ + + /* myExp*(i+1) = myExp_int - myExp_fract + myExp*(i+1) is split up here for better accuracy of CalcInvLdData(), + for its result can be split up into an integer and a fractional part */ + + /* Round up to next integer */ + FIXP_DBL myExp_int = + (myExpSlot & (FIXP_DBL)0xfe000000) + (FIXP_DBL)0x02000000; + + /* This is the fractional part that needs to be substracted */ + FIXP_DBL myExp_fract = myExp_int - myExpSlot; + + /* Calc integer part */ + dBf_int = CalcInvLdData(myExp_int); + /* The result needs to be re-scaled. The ld(myExp_int) had been scaled by + EXP_E, the CalcInvLdData expects the operand to be scaled by + LD_DATA_SHIFT. Therefore, the correctly scaled result is + dBf_int^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_int^2 */ + + if (dBf_int <= + 46340) { /* compare with maximum allowed value for signed integer + multiplication, 46340 = + (INT)floor(sqrt((double)(((UINT)1<<(DFRACT_BITS-1))-1))) */ + dBf_int *= dBf_int; + + /* Calc fractional part */ + dBf_fract = CalcInvLdData(-myExp_fract); + /* The result needs to be re-scaled. The ld(myExp_fract) had been scaled + by EXP_E, the CalcInvLdData expects the operand to be scaled by + LD_DATA_SHIFT. Therefore, the correctly scaled result is + dBf_fract^(2^(EXP_E-LD_DATA_SHIFT)), which is dBf_fract^2 */ + dBf_fract = fMultNorm(dBf_fract, dBf_fract, &tmp); + + /* Get worst case scaling of multiplication result */ + dBf_e = (DFRACT_BITS - 1 - tmp) - CountLeadingBits(dBf_int); + + /* Now multiply integer with fractional part of the result, thus resulting + in the overall accurate fractional result */ + dBf_m = fMultNorm(dBf_int, DFRACT_BITS - 1, dBf_fract, tmp, dBf_e); + + myExpSlot += myExp; + } else { + dBf_m = (FIXP_DBL)0; + dBf_e = 0; + } + + /* Keep the results */ + h_sbrFastTransientDetector->dBf_m[i] = dBf_m; + h_sbrFastTransientDetector->dBf_e[i] = dBf_e; + } + + /* Make sure that dBf is greater than 1.0 (because it should be a highpass) */ + /* ... */ + + return 0; +} + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, const int *const scaleEnergies, + const INT YBufferWriteOffset, UCHAR *const tran_vector) { + int timeSlot, band; + + FIXP_DBL max_delta_energy; /* helper to store maximum energy ratio */ + int max_delta_energy_scale; /* helper to store scale of maximum energy ratio + */ + int ind_max = 0; /* helper to store index of maximum energy ratio */ + int isTransientInFrame = 0; + + const int nTimeSlots = h_sbrFastTransientDetector->nTimeSlots; + const int lookahead = h_sbrFastTransientDetector->lookahead; + const int startBand = h_sbrFastTransientDetector->startBand; + const int stopBand = h_sbrFastTransientDetector->stopBand; + + int *transientCandidates = h_sbrFastTransientDetector->transientCandidates; + + FIXP_DBL *energy_timeSlots = h_sbrFastTransientDetector->energy_timeSlots; + int *energy_timeSlots_scale = + h_sbrFastTransientDetector->energy_timeSlots_scale; + + FIXP_DBL *delta_energy = h_sbrFastTransientDetector->delta_energy; + int *delta_energy_scale = h_sbrFastTransientDetector->delta_energy_scale; + + const FIXP_DBL thr = TRAN_DET_THRSHLD; + const INT thr_scale = TRAN_DET_THRSHLD_SCALE; + + /*reset transient info*/ + tran_vector[2] = 0; + + /* reset transient candidates */ + FDKmemclear(transientCandidates + lookahead, nTimeSlots * sizeof(int)); + + for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + int i, norm; + FIXP_DBL tmpE = FL2FXCONST_DBL(0.0f); + int headroomEnSlot = DFRACT_BITS - 1; + + FIXP_DBL smallNRG = FL2FXCONST_DBL(1e-2f); + FIXP_DBL denominator; + INT denominator_scale; + + /* determine minimum headroom of energy values for this timeslot */ + for (band = startBand; band < stopBand; band++) { + int tmp_headroom = fNormz(Energies[timeSlot][band]) - 1; + if (tmp_headroom < headroomEnSlot) { + headroomEnSlot = tmp_headroom; + } + } + + for (i = 0, band = startBand; band < stopBand; band++, i++) { + /* energy is weighted by weightingfactor stored in dBf_m array */ + /* dBf_m index runs from 0 to stopBand-startband */ + /* energy shifted by calculated headroom for maximum precision */ + FIXP_DBL weightedEnergy = + fMult(Energies[timeSlot][band] << headroomEnSlot, + h_sbrFastTransientDetector->dBf_m[i]); + + /* energy is added up */ + /* shift by 6 to have a headroom for maximum 64 additions */ + /* shift by dBf_e to handle weighting factor dependent scale factors */ + tmpE += + weightedEnergy >> (6 + (10 - h_sbrFastTransientDetector->dBf_e[i])); + } + + /* store calculated energy for timeslot */ + energy_timeSlots[timeSlot] = tmpE; + + /* calculate overall scale factor for energy of this timeslot */ + /* = original scale factor of energies + * (-scaleEnergies[0]+2*QMF_SCALE_OFFSET or + * -scaleEnergies[1]+2*QMF_SCALE_OFFSET */ + /* depending on YBufferWriteOffset) */ + /* + weighting factor scale (10) */ + /* + adding up scale factor ( 6) */ + /* - headroom of energy value (headroomEnSlot) */ + if (timeSlot < YBufferWriteOffset) { + energy_timeSlots_scale[timeSlot] = + (-scaleEnergies[0] + 2 * QMF_SCALE_OFFSET) + (10 + 6) - + headroomEnSlot; + } else { + energy_timeSlots_scale[timeSlot] = + (-scaleEnergies[1] + 2 * QMF_SCALE_OFFSET) + (10 + 6) - + headroomEnSlot; + } + + /* Add a small energy to the denominator, thus making the transient + detection energy-dependent. Loud transients are being detected, + silent ones not. */ + + /* make sure that smallNRG does not overflow */ + if (-energy_timeSlots_scale[timeSlot - 1] + 1 > 5) { + denominator = smallNRG; + denominator_scale = 0; + } else { + /* Leave an additional headroom of 1 bit for this addition. */ + smallNRG = + scaleValue(smallNRG, -(energy_timeSlots_scale[timeSlot - 1] + 1)); + denominator = (energy_timeSlots[timeSlot - 1] >> 1) + smallNRG; + denominator_scale = energy_timeSlots_scale[timeSlot - 1] + 1; + } + + delta_energy[timeSlot] = + fDivNorm(energy_timeSlots[timeSlot], denominator, &norm); + delta_energy_scale[timeSlot] = + energy_timeSlots_scale[timeSlot] - denominator_scale + norm; + } + + /*get transient candidates*/ + /* For every timeslot, check if delta(E) exceeds the threshold. If it did, + it could potentially be marked as a transient candidate. However, the 2 + slots before the current one must not be transients with an energy higher + than 1.4*E(current). If both aren't transients or if the energy of the + current timesolot is more than 1.4 times higher than the energy in the + last or the one before the last slot, it is marked as a transient.*/ + + FDK_ASSERT(lookahead >= 2); + for (timeSlot = lookahead; timeSlot < nTimeSlots + lookahead; timeSlot++) { + FIXP_DBL energy_cur_slot_weighted = + fMult(energy_timeSlots[timeSlot], FL2FXCONST_DBL(1.0f / 1.4f)); + if (!fIsLessThan(delta_energy[timeSlot], delta_energy_scale[timeSlot], thr, + thr_scale) && + (((transientCandidates[timeSlot - 2] == 0) && + (transientCandidates[timeSlot - 1] == 0)) || + !fIsLessThan(energy_cur_slot_weighted, + energy_timeSlots_scale[timeSlot], + energy_timeSlots[timeSlot - 1], + energy_timeSlots_scale[timeSlot - 1]) || + !fIsLessThan(energy_cur_slot_weighted, + energy_timeSlots_scale[timeSlot], + energy_timeSlots[timeSlot - 2], + energy_timeSlots_scale[timeSlot - 2]))) { + /* in case of strong transients, subsequent + * qmf slots might be recognized as transients. */ + transientCandidates[timeSlot] = 1; + } + } + + /*get transient with max energy*/ + max_delta_energy = FL2FXCONST_DBL(0.0f); + max_delta_energy_scale = 0; + ind_max = 0; + isTransientInFrame = 0; + for (timeSlot = 0; timeSlot < nTimeSlots; timeSlot++) { + int scale = fMax(delta_energy_scale[timeSlot], max_delta_energy_scale); + if (transientCandidates[timeSlot] && + ((delta_energy[timeSlot] >> (scale - delta_energy_scale[timeSlot])) > + (max_delta_energy >> (scale - max_delta_energy_scale)))) { + max_delta_energy = delta_energy[timeSlot]; + max_delta_energy_scale = scale; + ind_max = timeSlot; + isTransientInFrame = 1; + } + } + + /*from all transient candidates take the one with the biggest energy*/ + if (isTransientInFrame) { + tran_vector[0] = ind_max; + tran_vector[1] = 1; + } else { + /*reset transient info*/ + tran_vector[0] = tran_vector[1] = 0; + } + + /*check for transients in lookahead*/ + for (timeSlot = nTimeSlots; timeSlot < nTimeSlots + lookahead; timeSlot++) { + if (transientCandidates[timeSlot]) { + tran_vector[2] = 1; + } + } + + /*update buffers*/ + for (timeSlot = 0; timeSlot < lookahead; timeSlot++) { + transientCandidates[timeSlot] = transientCandidates[nTimeSlots + timeSlot]; + + /* fixpoint stuff */ + energy_timeSlots[timeSlot] = energy_timeSlots[nTimeSlots + timeSlot]; + energy_timeSlots_scale[timeSlot] = + energy_timeSlots_scale[nTimeSlots + timeSlot]; + + delta_energy[timeSlot] = delta_energy[nTimeSlots + timeSlot]; + delta_energy_scale[timeSlot] = delta_energy_scale[nTimeSlots + timeSlot]; + } +} diff --git a/fdk-aac/libSBRenc/src/tran_det.h b/fdk-aac/libSBRenc/src/tran_det.h new file mode 100644 index 0000000..d10a7db --- /dev/null +++ b/fdk-aac/libSBRenc/src/tran_det.h @@ -0,0 +1,191 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/**************************** SBR encoder library ****************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/*! + \file + \brief Transient detector prototypes $Revision: 95111 $ +*/ +#ifndef TRAN_DET_H +#define TRAN_DET_H + +#include "sbr_encoder.h" +#include "sbr_def.h" + +typedef struct { + FIXP_DBL transients[32 + (32 / 2)]; + FIXP_DBL thresholds[64]; + FIXP_DBL tran_thr; /* Master threshold for transient signals */ + FIXP_DBL split_thr_m; /* Threshold for splitting FIXFIX-frames into 2 env */ + INT split_thr_e; /* Scale for splitting threshold */ + FIXP_DBL prevLowBandEnergy; /* Energy of low band */ + FIXP_DBL prevHighBandEnergy; /* Energy of high band */ + INT tran_fc; /* Number of lowband subbands to discard */ + INT no_cols; + INT no_rows; + INT mode; + + int frameShift; + int tran_off; /* Offset for reading energy values. */ +} SBR_TRANSIENT_DETECTOR; + +typedef SBR_TRANSIENT_DETECTOR *HANDLE_SBR_TRANSIENT_DETECTOR; + +#define TRAN_DET_LOOKAHEAD 2 +#define TRAN_DET_START_FREQ 4500 /*start frequency for transient detection*/ +#define TRAN_DET_STOP_FREQ 13500 /*stop frequency for transient detection*/ +#define TRAN_DET_MIN_QMFBANDS \ + 4 /* minimum qmf bands for transient detection \ + */ +#define QMF_HP_dBd_SLOPE_FIX \ + FL2FXCONST_DBL(0.00075275f) /* 0.002266f/10 * log2(10) */ +#define TRAN_DET_THRSHLD FL2FXCONST_DBL(5.0f / 8.0f) +#define TRAN_DET_THRSHLD_SCALE (3) + +typedef struct { + INT transientCandidates[32 + TRAN_DET_LOOKAHEAD]; + INT nTimeSlots; + INT lookahead; + INT startBand; + INT stopBand; + + FIXP_DBL dBf_m[64]; + INT dBf_e[64]; + + FIXP_DBL energy_timeSlots[32 + TRAN_DET_LOOKAHEAD]; + INT energy_timeSlots_scale[32 + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL delta_energy[32 + TRAN_DET_LOOKAHEAD]; + INT delta_energy_scale[32 + TRAN_DET_LOOKAHEAD]; + + FIXP_DBL lowpass_energy[32 + TRAN_DET_LOOKAHEAD]; + INT lowpass_energy_scale[32 + TRAN_DET_LOOKAHEAD]; +} FAST_TRAN_DETECTOR; +typedef FAST_TRAN_DETECTOR *HANDLE_FAST_TRAN_DET; + +INT FDKsbrEnc_InitSbrFastTransientDetector( + HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const INT time_slots_per_frame, const INT bandwidth_qmf_slot, + const INT no_qmf_channels, const INT sbr_qmf_1st_band); + +void FDKsbrEnc_fastTransientDetect( + const HANDLE_FAST_TRAN_DET h_sbrFastTransientDetector, + const FIXP_DBL *const *Energies, const int *const scaleEnergies, + const INT YBufferWriteOffset, UCHAR *const tran_vector); + +void FDKsbrEnc_transientDetect( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, FIXP_DBL **Energies, + INT *scaleEnergies, UCHAR *tran_vector, int YBufferWriteOffset, + int YBufferSzShift, int timeStep, int frameMiddleBorder); + +int FDKsbrEnc_InitSbrTransientDetector( + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, + UINT sbrSyntaxFlags, /* SBR syntax flags derived from AOT. */ + INT frameSize, INT sampleFreq, sbrConfigurationPtr params, int tran_fc, + int no_cols, int no_rows, int YBufferWriteOffset, int YBufferSzShift, + int frameShift, int tran_off); + +void FDKsbrEnc_frameSplitter( + FIXP_DBL **Energies, INT *scaleEnergies, + HANDLE_SBR_TRANSIENT_DETECTOR h_sbrTransientDetector, UCHAR *freqBandTable, + UCHAR *tran_vector, int YBufferWriteOffset, int YBufferSzShift, int nSfb, + int timeStep, int no_cols, FIXP_DBL *tonality); +#endif diff --git a/fdk-aac/libSYS/include/FDK_audio.h b/fdk-aac/libSYS/include/FDK_audio.h new file mode 100644 index 0000000..d69c008 --- /dev/null +++ b/fdk-aac/libSYS/include/FDK_audio.h @@ -0,0 +1,827 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Manuel Jander + + Description: + +*******************************************************************************/ + +/** \file FDK_audio.h + * \brief Global audio struct and constant definitions. + */ + +#ifndef FDK_AUDIO_H +#define FDK_AUDIO_H + +#include "machine_type.h" +#include "genericStds.h" +#include "syslib_channelMapDescr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * File format identifiers. + */ +typedef enum { + FF_UNKNOWN = -1, /**< Unknown format. */ + FF_RAW = 0, /**< No container, bit stream data conveyed "as is". */ + + FF_MP4_3GPP = 3, /**< 3GPP file format. */ + FF_MP4_MP4F = 4, /**< MPEG-4 File format. */ + + FF_RAWPACKETS = 5 /**< Proprietary raw packet file. */ + +} FILE_FORMAT; + +/** + * Transport type identifiers. + */ +typedef enum { + TT_UNKNOWN = -1, /**< Unknown format. */ + TT_MP4_RAW = 0, /**< "as is" access units (packet based since there is + obviously no sync layer) */ + TT_MP4_ADIF = 1, /**< ADIF bitstream format. */ + TT_MP4_ADTS = 2, /**< ADTS bitstream format. */ + + TT_MP4_LATM_MCP1 = 6, /**< Audio Mux Elements with muxConfigPresent = 1 */ + TT_MP4_LATM_MCP0 = 7, /**< Audio Mux Elements with muxConfigPresent = 0, out + of band StreamMuxConfig */ + + TT_MP4_LOAS = 10, /**< Audio Sync Stream. */ + + TT_DRM = 12, /**< Digital Radio Mondial (DRM30/DRM+) bitstream format. */ + TT_DABPLUS = 13 /**< Digital Audio Broadcastong (DAB+) superframes bitstream format. */ + +} TRANSPORT_TYPE; + +#define TT_IS_PACKET(x) \ + (((x) == TT_MP4_RAW) || ((x) == TT_DRM) || ((x) == TT_MP4_LATM_MCP0) || \ + ((x) == TT_MP4_LATM_MCP1)) + +/** + * Audio Object Type definitions. + */ +typedef enum { + AOT_NONE = -1, + AOT_NULL_OBJECT = 0, + AOT_AAC_MAIN = 1, /**< Main profile */ + AOT_AAC_LC = 2, /**< Low Complexity object */ + AOT_AAC_SSR = 3, + AOT_AAC_LTP = 4, + AOT_SBR = 5, + AOT_AAC_SCAL = 6, + AOT_TWIN_VQ = 7, + AOT_CELP = 8, + AOT_HVXC = 9, + AOT_RSVD_10 = 10, /**< (reserved) */ + AOT_RSVD_11 = 11, /**< (reserved) */ + AOT_TTSI = 12, /**< TTSI Object */ + AOT_MAIN_SYNTH = 13, /**< Main Synthetic object */ + AOT_WAV_TAB_SYNTH = 14, /**< Wavetable Synthesis object */ + AOT_GEN_MIDI = 15, /**< General MIDI object */ + AOT_ALG_SYNTH_AUD_FX = 16, /**< Algorithmic Synthesis and Audio FX object */ + AOT_ER_AAC_LC = 17, /**< Error Resilient(ER) AAC Low Complexity */ + AOT_RSVD_18 = 18, /**< (reserved) */ + AOT_ER_AAC_LTP = 19, /**< Error Resilient(ER) AAC LTP object */ + AOT_ER_AAC_SCAL = 20, /**< Error Resilient(ER) AAC Scalable object */ + AOT_ER_TWIN_VQ = 21, /**< Error Resilient(ER) TwinVQ object */ + AOT_ER_BSAC = 22, /**< Error Resilient(ER) BSAC object */ + AOT_ER_AAC_LD = 23, /**< Error Resilient(ER) AAC LowDelay object */ + AOT_ER_CELP = 24, /**< Error Resilient(ER) CELP object */ + AOT_ER_HVXC = 25, /**< Error Resilient(ER) HVXC object */ + AOT_ER_HILN = 26, /**< Error Resilient(ER) HILN object */ + AOT_ER_PARA = 27, /**< Error Resilient(ER) Parametric object */ + AOT_RSVD_28 = 28, /**< might become SSC */ + AOT_PS = 29, /**< PS, Parametric Stereo (includes SBR) */ + AOT_MPEGS = 30, /**< MPEG Surround */ + + AOT_ESCAPE = 31, /**< Signal AOT uses more than 5 bits */ + + AOT_MP3ONMP4_L1 = 32, /**< MPEG-Layer1 in mp4 */ + AOT_MP3ONMP4_L2 = 33, /**< MPEG-Layer2 in mp4 */ + AOT_MP3ONMP4_L3 = 34, /**< MPEG-Layer3 in mp4 */ + AOT_RSVD_35 = 35, /**< might become DST */ + AOT_RSVD_36 = 36, /**< might become ALS */ + AOT_AAC_SLS = 37, /**< AAC + SLS */ + AOT_SLS = 38, /**< SLS */ + AOT_ER_AAC_ELD = 39, /**< AAC Enhanced Low Delay */ + + AOT_USAC = 42, /**< USAC */ + AOT_SAOC = 43, /**< SAOC */ + AOT_LD_MPEGS = 44, /**< Low Delay MPEG Surround */ + + AOT_DABPLUS_AAC_LC = 135, /**< Virtual AOT for DAB plus AAC-LC */ + AOT_DABPLUS_SBR = 136, /**< Virtual AOT for DAB plus HE-AAC */ + AOT_DABPLUS_PS = 137, /**< Virtual AOT for DAB plus HE-AAC v2 */ + + + /* Pseudo AOTs */ + AOT_MP2_AAC_LC = 129, /**< Virtual AOT MP2 Low Complexity profile */ + AOT_MP2_SBR = 132, /**< Virtual AOT MP2 Low Complexity Profile with SBR */ + + AOT_DRM_AAC = 143, /**< Virtual AOT for DRM (ER-AAC-SCAL without SBR) */ + AOT_DRM_SBR = 144, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR) */ + AOT_DRM_MPEG_PS = + 145, /**< Virtual AOT for DRM (ER-AAC-SCAL with SBR and MPEG-PS) */ + AOT_DRM_SURROUND = + 146, /**< Virtual AOT for DRM Surround (ER-AAC-SCAL (+SBR) +MPS) */ + AOT_DRM_USAC = 147 /**< Virtual AOT for DRM with USAC */ + +} AUDIO_OBJECT_TYPE; + +#define CAN_DO_PS(aot) \ + ((aot) == AOT_AAC_LC || (aot) == AOT_SBR || (aot) == AOT_PS || \ + (aot) == AOT_ER_BSAC || (aot) == AOT_DRM_AAC) + +#define IS_USAC(aot) ((aot) == AOT_USAC) + +#define IS_LOWDELAY(aot) ((aot) == AOT_ER_AAC_LD || (aot) == AOT_ER_AAC_ELD) + +/** Channel Mode ( 1-7 equals MPEG channel configurations, others are + * arbitrary). */ +typedef enum { + MODE_INVALID = -1, + MODE_UNKNOWN = 0, + MODE_1 = 1, /**< C */ + MODE_2 = 2, /**< L+R */ + MODE_1_2 = 3, /**< C, L+R */ + MODE_1_2_1 = 4, /**< C, L+R, Rear */ + MODE_1_2_2 = 5, /**< C, L+R, LS+RS */ + MODE_1_2_2_1 = 6, /**< C, L+R, LS+RS, LFE */ + MODE_1_2_2_2_1 = 7, /**< C, LC+RC, L+R, LS+RS, LFE */ + + MODE_6_1 = 11, /**< C, L+R, LS+RS, Crear, LFE */ + MODE_7_1_BACK = 12, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ + MODE_7_1_TOP_FRONT = 14, /**< C, L+R, LS+RS, LFE, Ltop+Rtop */ + + MODE_7_1_REAR_SURROUND = 33, /**< C, L+R, LS+RS, Lrear+Rrear, LFE */ + MODE_7_1_FRONT_CENTER = 34, /**< C, LC+RC, L+R, LS+RS, LFE */ + + MODE_212 = 128 /**< 212 configuration, used in ELDv2 */ + +} CHANNEL_MODE; + +/** + * Speaker description tags. + * Do not change the enumeration values unless it keeps the following + * segmentation: + * - Bit 0-3: Horizontal postion (0: none, 1: front, 2: side, 3: back, 4: lfe) + * - Bit 4-7: Vertical position (0: normal, 1: top, 2: bottom) + */ +typedef enum { + ACT_NONE = 0x00, + ACT_FRONT = 0x01, /*!< Front speaker position (at normal height) */ + ACT_SIDE = 0x02, /*!< Side speaker position (at normal height) */ + ACT_BACK = 0x03, /*!< Back speaker position (at normal height) */ + ACT_LFE = 0x04, /*!< Low frequency effect speaker postion (front) */ + + ACT_TOP = + 0x10, /*!< Top speaker area (for combination with speaker positions) */ + ACT_FRONT_TOP = 0x11, /*!< Top front speaker = (ACT_FRONT|ACT_TOP) */ + ACT_SIDE_TOP = 0x12, /*!< Top side speaker = (ACT_SIDE |ACT_TOP) */ + ACT_BACK_TOP = 0x13, /*!< Top back speaker = (ACT_BACK |ACT_TOP) */ + + ACT_BOTTOM = + 0x20, /*!< Bottom speaker area (for combination with speaker positions) */ + ACT_FRONT_BOTTOM = 0x21, /*!< Bottom front speaker = (ACT_FRONT|ACT_BOTTOM) */ + ACT_SIDE_BOTTOM = 0x22, /*!< Bottom side speaker = (ACT_SIDE |ACT_BOTTOM) */ + ACT_BACK_BOTTOM = 0x23 /*!< Bottom back speaker = (ACT_BACK |ACT_BOTTOM) */ + +} AUDIO_CHANNEL_TYPE; + +typedef enum { + SIG_UNKNOWN = -1, + SIG_IMPLICIT = 0, + SIG_EXPLICIT_BW_COMPATIBLE = 1, + SIG_EXPLICIT_HIERARCHICAL = 2 + +} SBR_PS_SIGNALING; + +/** + * Audio Codec flags. + */ +#define AC_ER_VCB11 \ + 0x000001 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use \ + virtual codebooks */ +#define AC_ER_RVLC \ + 0x000002 /*!< aacSpectralDataResilienceFlag flag (from ASC): 1 means use \ + huffman codeword reordering */ +#define AC_ER_HCR \ + 0x000004 /*!< aacSectionDataResilienceFlag flag (from ASC): 1 means use \ + virtual codebooks */ +#define AC_SCALABLE 0x000008 /*!< AAC Scalable*/ +#define AC_ELD 0x000010 /*!< AAC-ELD */ +#define AC_LD 0x000020 /*!< AAC-LD */ +#define AC_ER 0x000040 /*!< ER syntax */ +#define AC_BSAC 0x000080 /*!< BSAC */ +#define AC_USAC 0x000100 /*!< USAC */ +#define AC_RSV603DA 0x000200 /*!< RSVD60 3D audio */ +#define AC_HDAAC 0x000400 /*!< HD-AAC */ +#define AC_RSVD50 0x004000 /*!< Rsvd50 */ +#define AC_SBR_PRESENT 0x008000 /*!< SBR present flag (from ASC) */ +#define AC_SBRCRC \ + 0x010000 /*!< SBR CRC present flag. Only relevant for AAC-ELD for now. */ +#define AC_PS_PRESENT 0x020000 /*!< PS present flag (from ASC or implicit) */ +#define AC_MPS_PRESENT \ + 0x040000 /*!< MPS present flag (from ASC or implicit) \ + */ +#define AC_DRM 0x080000 /*!< DRM bit stream syntax */ +#define AC_INDEP 0x100000 /*!< Independency flag */ +#define AC_MPEGD_RES 0x200000 /*!< MPEG-D residual individual channel data. */ +#define AC_SAOC_PRESENT 0x400000 /*!< SAOC Present Flag */ +#define AC_DAB 0x800000 /*!< DAB bit stream syntax */ +#define AC_ELD_DOWNSCALE 0x1000000 /*!< ELD Downscaled playout */ +#define AC_LD_MPS 0x2000000 /*!< Low Delay MPS. */ +#define AC_DRC_PRESENT \ + 0x4000000 /*!< Dynamic Range Control (DRC) data found. \ + */ +#define AC_USAC_SCFGI3 \ + 0x8000000 /*!< USAC flag: If stereoConfigIndex is 3 the flag is set. */ +/** + * Audio Codec flags (reconfiguration). + */ +#define AC_CM_DET_CFG_CHANGE \ + 0x000001 /*!< Config mode signalizes the callback to work in config change \ + detection mode */ +#define AC_CM_ALLOC_MEM \ + 0x000002 /*!< Config mode signalizes the callback to work in memory \ + allocation mode */ + +/** + * Audio Codec flags (element specific). + */ +#define AC_EL_USAC_TW 0x000001 /*!< USAC time warped filter bank is active */ +#define AC_EL_USAC_NOISE 0x000002 /*!< USAC noise filling is active */ +#define AC_EL_USAC_ITES 0x000004 /*!< USAC SBR inter-TES tool is active */ +#define AC_EL_USAC_PVC \ + 0x000008 /*!< USAC SBR predictive vector coding tool is active */ +#define AC_EL_USAC_MPS212 0x000010 /*!< USAC MPS212 tool is active */ +#define AC_EL_USAC_LFE 0x000020 /*!< USAC element is LFE */ +#define AC_EL_USAC_CP_POSSIBLE \ + 0x000040 /*!< USAC may use Complex Stereo Prediction in this channel element \ + */ +#define AC_EL_ENHANCED_NOISE 0x000080 /*!< Enhanced noise filling*/ +#define AC_EL_IGF_AFTER_TNS 0x000100 /*!< IGF after TNS */ +#define AC_EL_IGF_INDEP_TILING 0x000200 /*!< IGF independent tiling */ +#define AC_EL_IGF_USE_ENF 0x000400 /*!< IGF use enhanced noise filling */ +#define AC_EL_FULLBANDLPD 0x000800 /*!< enable fullband LPD tools */ +#define AC_EL_LPDSTEREOIDX 0x001000 /*!< LPD-stereo-tool stereo index */ +#define AC_EL_LFE 0x002000 /*!< The element is of type LFE. */ + +/* CODER_CONFIG::flags */ +#define CC_MPEG_ID 0x00100000 +#define CC_IS_BASELAYER 0x00200000 +#define CC_PROTECTION 0x00400000 +#define CC_SBR 0x00800000 +#define CC_SBRCRC 0x00010000 +#define CC_SAC 0x00020000 +#define CC_RVLC 0x01000000 +#define CC_VCB11 0x02000000 +#define CC_HCR 0x04000000 +#define CC_PSEUDO_SURROUND 0x08000000 +#define CC_USAC_NOISE 0x10000000 +#define CC_USAC_TW 0x20000000 +#define CC_USAC_HBE 0x40000000 + +/** Generic audio coder configuration structure. */ +typedef struct { + AUDIO_OBJECT_TYPE aot; /**< Audio Object Type (AOT). */ + AUDIO_OBJECT_TYPE extAOT; /**< Extension Audio Object Type (SBR). */ + CHANNEL_MODE channelMode; /**< Channel mode. */ + UCHAR channelConfigZero; /**< Use channel config zero + pce although a + standard channel config could be signaled. */ + INT samplingRate; /**< Sampling rate. */ + INT extSamplingRate; /**< Extended samplerate (SBR). */ + INT downscaleSamplingRate; /**< Downscale sampling rate (ELD downscaled mode) + */ + INT bitRate; /**< Average bitrate. */ + int samplesPerFrame; /**< Number of PCM samples per codec frame and audio + channel. */ + int noChannels; /**< Number of audio channels. */ + int bitsFrame; + int nSubFrames; /**< Amount of encoder subframes. 1 means no subframing. */ + int BSACnumOfSubFrame; /**< The number of the sub-frames which are grouped and + transmitted in a super-frame (BSAC). */ + int BSAClayerLength; /**< The average length of the large-step layers in bytes + (BSAC). */ + UINT flags; /**< flags */ + UCHAR matrixMixdownA; /**< Matrix mixdown index to put into PCE. Default value + 0 means no mixdown coefficient, valid values are 1-4 + which correspond to matrix_mixdown_idx 0-3. */ + UCHAR headerPeriod; /**< Frame period for sending in band configuration + buffers in the transport layer. */ + + UCHAR stereoConfigIndex; /**< USAC MPS stereo mode */ + UCHAR sbrMode; /**< USAC SBR mode */ + SBR_PS_SIGNALING sbrSignaling; /**< 0: implicit signaling, 1: backwards + compatible explicit signaling, 2: + hierarcical explicit signaling */ + + UCHAR rawConfig[64]; /**< raw codec specific config as bit stream */ + int rawConfigBits; /**< Size of rawConfig in bits */ + + UCHAR sbrPresent; + UCHAR psPresent; +} CODER_CONFIG; + +#define USAC_ID_BIT 16 /** USAC element IDs start at USAC_ID_BIT */ + +/** MP4 Element IDs. */ +typedef enum { + /* mp4 element IDs */ + ID_NONE = -1, /**< Invalid Element helper ID. */ + ID_SCE = 0, /**< Single Channel Element. */ + ID_CPE = 1, /**< Channel Pair Element. */ + ID_CCE = 2, /**< Coupling Channel Element. */ + ID_LFE = 3, /**< LFE Channel Element. */ + ID_DSE = 4, /**< Currently one Data Stream Element for ancillary data is + supported. */ + ID_PCE = 5, /**< Program Config Element. */ + ID_FIL = 6, /**< Fill Element. */ + ID_END = 7, /**< Arnie (End Element = Terminator). */ + ID_EXT = 8, /**< Extension Payload (ER only). */ + ID_SCAL = 9, /**< AAC scalable element (ER only). */ + /* USAC element IDs */ + ID_USAC_SCE = 0 + USAC_ID_BIT, /**< Single Channel Element. */ + ID_USAC_CPE = 1 + USAC_ID_BIT, /**< Channel Pair Element. */ + ID_USAC_LFE = 2 + USAC_ID_BIT, /**< LFE Channel Element. */ + ID_USAC_EXT = 3 + USAC_ID_BIT, /**< Extension Element. */ + ID_USAC_END = 4 + USAC_ID_BIT, /**< Arnie (End Element = Terminator). */ + ID_LAST +} MP4_ELEMENT_ID; + +/* usacConfigExtType q.v. ISO/IEC DIS 23008-3 Table 52 and ISO/IEC FDIS + * 23003-3:2011(E) Table 74*/ +typedef enum { + /* USAC and RSVD60 3DA */ + ID_CONFIG_EXT_FILL = 0, + /* RSVD60 3DA */ + ID_CONFIG_EXT_DOWNMIX = 1, + ID_CONFIG_EXT_LOUDNESS_INFO = 2, + ID_CONFIG_EXT_AUDIOSCENE_INFO = 3, + ID_CONFIG_EXT_HOA_MATRIX = 4, + ID_CONFIG_EXT_SIG_GROUP_INFO = 6 + /* 5-127 => reserved for ISO use */ + /* > 128 => reserved for use outside of ISO scope */ +} CONFIG_EXT_ID; + +#define IS_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_SCE || (elementId) == ID_CPE || (elementId) == ID_LFE || \ + (elementId) == ID_USAC_SCE || (elementId) == ID_USAC_CPE || \ + (elementId) == ID_USAC_LFE) + +#define IS_MP4_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_SCE || (elementId) == ID_CPE || (elementId) == ID_LFE) + +#define EXT_ID_BITS 4 /**< Size in bits of extension payload type tags. */ + +/** Extension payload types. */ +typedef enum { + EXT_FIL = 0x00, + EXT_FILL_DATA = 0x01, + EXT_DATA_ELEMENT = 0x02, + EXT_DATA_LENGTH = 0x03, + EXT_UNI_DRC = 0x04, + EXT_LDSAC_DATA = 0x09, + EXT_SAOC_DATA = 0x0a, + EXT_DYNAMIC_RANGE = 0x0b, + EXT_SAC_DATA = 0x0c, + EXT_SBR_DATA = 0x0d, + EXT_SBR_DATA_CRC = 0x0e +} EXT_PAYLOAD_TYPE; + +#define IS_USAC_CHANNEL_ELEMENT(elementId) \ + ((elementId) == ID_USAC_SCE || (elementId) == ID_USAC_CPE || \ + (elementId) == ID_USAC_LFE) + +/** MPEG-D USAC & RSVD60 3D audio Extension Element Types. */ +typedef enum { + /* usac */ + ID_EXT_ELE_FILL = 0x00, + ID_EXT_ELE_MPEGS = 0x01, + ID_EXT_ELE_SAOC = 0x02, + ID_EXT_ELE_AUDIOPREROLL = 0x03, + ID_EXT_ELE_UNI_DRC = 0x04, + /* rsv603da */ + ID_EXT_ELE_OBJ_METADATA = 0x05, + ID_EXT_ELE_SAOC_3D = 0x06, + ID_EXT_ELE_HOA = 0x07, + ID_EXT_ELE_FMT_CNVRTR = 0x08, + ID_EXT_ELE_MCT = 0x09, + ID_EXT_ELE_ENHANCED_OBJ_METADATA = 0x0d, + /* reserved for use outside of ISO scope */ + ID_EXT_ELE_VR_METADATA = 0x81, + ID_EXT_ELE_UNKNOWN = 0xFF +} USAC_EXT_ELEMENT_TYPE; + +/** + * Proprietary raw packet file configuration data type identifier. + */ +typedef enum { + TC_NOTHING = 0, /* No configuration available -> in-band configuration. */ + TC_RAW_ADTS = 2, /* Transfer type is ADTS. */ + TC_RAW_LATM_MCP1 = 6, /* Transfer type is LATM with SMC present. */ + TC_RAW_SDC = 21 /* Configuration data field is Drm SDC. */ + +} TP_CONFIG_TYPE; + +/* + * ############################################################################################## + * Library identification and error handling + * ############################################################################################## + */ +/* \cond */ + +typedef enum { + FDK_NONE = 0, + FDK_TOOLS = 1, + FDK_SYSLIB = 2, + FDK_AACDEC = 3, + FDK_AACENC = 4, + FDK_SBRDEC = 5, + FDK_SBRENC = 6, + FDK_TPDEC = 7, + FDK_TPENC = 8, + FDK_MPSDEC = 9, + FDK_MPEGFILEREAD = 10, + FDK_MPEGFILEWRITE = 11, + FDK_PCMDMX = 31, + FDK_MPSENC = 34, + FDK_TDLIMIT = 35, + FDK_UNIDRCDEC = 38, + + FDK_MODULE_LAST + +} FDK_MODULE_ID; + +/* AAC capability flags */ +#define CAPF_AAC_LC 0x00000001 /**< Support flag for AAC Low Complexity. */ +#define CAPF_ER_AAC_LD \ + 0x00000002 /**< Support flag for AAC Low Delay with Error Resilience tools. \ + */ +#define CAPF_ER_AAC_SCAL 0x00000004 /**< Support flag for AAC Scalable. */ +#define CAPF_ER_AAC_LC \ + 0x00000008 /**< Support flag for AAC Low Complexity with Error Resilience \ + tools. */ +#define CAPF_AAC_480 \ + 0x00000010 /**< Support flag for AAC with 480 framelength. */ +#define CAPF_AAC_512 \ + 0x00000020 /**< Support flag for AAC with 512 framelength. */ +#define CAPF_AAC_960 \ + 0x00000040 /**< Support flag for AAC with 960 framelength. */ +#define CAPF_AAC_1024 \ + 0x00000080 /**< Support flag for AAC with 1024 framelength. */ +#define CAPF_AAC_HCR \ + 0x00000100 /**< Support flag for AAC with Huffman Codeword Reordering. */ +#define CAPF_AAC_VCB11 \ + 0x00000200 /**< Support flag for AAC Virtual Codebook 11. */ +#define CAPF_AAC_RVLC \ + 0x00000400 /**< Support flag for AAC Reversible Variable Length Coding. */ +#define CAPF_AAC_MPEG4 0x00000800 /**< Support flag for MPEG file format. */ +#define CAPF_AAC_DRC \ + 0x00001000 /**< Support flag for AAC Dynamic Range Control. */ +#define CAPF_AAC_CONCEALMENT \ + 0x00002000 /**< Support flag for AAC concealment. */ +#define CAPF_AAC_DRM_BSFORMAT \ + 0x00004000 /**< Support flag for AAC DRM bistream format. */ +#define CAPF_ER_AAC_ELD \ + 0x00008000 /**< Support flag for AAC Enhanced Low Delay with Error \ + Resilience tools. */ +#define CAPF_ER_AAC_BSAC \ + 0x00010000 /**< Support flag for AAC BSAC. */ +#define CAPF_AAC_ELD_DOWNSCALE \ + 0x00040000 /**< Support flag for AAC-ELD Downscaling */ +#define CAPF_AAC_USAC_LP \ + 0x00100000 /**< Support flag for USAC low power mode. */ +#define CAPF_AAC_USAC \ + 0x00200000 /**< Support flag for Unified Speech and Audio Coding (USAC). */ +#define CAPF_ER_AAC_ELDV2 \ + 0x00800000 /**< Support flag for AAC Enhanced Low Delay with MPS 212. */ +#define CAPF_AAC_UNIDRC \ + 0x01000000 /**< Support flag for MPEG-D Dynamic Range Control (uniDrc). */ + +/* Transport capability flags */ +#define CAPF_ADTS \ + 0x00000001 /**< Support flag for ADTS transport format. */ +#define CAPF_ADIF \ + 0x00000002 /**< Support flag for ADIF transport format. */ +#define CAPF_LATM \ + 0x00000004 /**< Support flag for LATM transport format. */ +#define CAPF_LOAS \ + 0x00000008 /**< Support flag for LOAS transport format. */ +#define CAPF_RAWPACKETS \ + 0x00000010 /**< Support flag for RAW PACKETS transport format. */ +#define CAPF_DRM \ + 0x00000020 /**< Support flag for DRM/DRM+ transport format. */ +#define CAPF_RSVD50 \ + 0x00000040 /**< Support flag for RSVD50 transport format */ + +/* SBR capability flags */ +#define CAPF_SBR_LP \ + 0x00000001 /**< Support flag for SBR Low Power mode. */ +#define CAPF_SBR_HQ \ + 0x00000002 /**< Support flag for SBR High Quality mode. */ +#define CAPF_SBR_DRM_BS \ + 0x00000004 /**< Support flag for */ +#define CAPF_SBR_CONCEALMENT \ + 0x00000008 /**< Support flag for SBR concealment. */ +#define CAPF_SBR_DRC \ + 0x00000010 /**< Support flag for SBR Dynamic Range Control. */ +#define CAPF_SBR_PS_MPEG \ + 0x00000020 /**< Support flag for MPEG Parametric Stereo. */ +#define CAPF_SBR_PS_DRM \ + 0x00000040 /**< Support flag for DRM Parametric Stereo. */ +#define CAPF_SBR_ELD_DOWNSCALE \ + 0x00000080 /**< Support flag for ELD reduced delay mode */ +#define CAPF_SBR_HBEHQ \ + 0x00000100 /**< Support flag for HQ HBE */ + +/* DAB capability flags */ +#define CAPF_DAB_MP2 0x00000001 /**< Support flag for Layer2 DAB. */ +#define CAPF_DAB_AAC 0x00000002 /**< Support flag for DAB+ (HE-AAC v2). */ +#define CAPF_DAB_PAD 0x00000004 /**< Support flag for PAD extraction. */ +#define CAPF_DAB_DRC 0x00000008 /**< Support flag for Dynamic Range Control. */ +#define CAPF_DAB_SURROUND 0x00000010 /**< Support flag for DAB Surround (MPS). */ + + +/* PCM utils capability flags */ +#define CAPF_DMX_BLIND \ + 0x00000001 /**< Support flag for blind downmixing. */ +#define CAPF_DMX_PCE \ + 0x00000002 /**< Support flag for guided downmix with data from MPEG-2/4 \ + Program Config Elements (PCE). */ +#define CAPF_DMX_ARIB \ + 0x00000004 /**< Support flag for PCE guided downmix with slightly different \ + equations and levels to fulfill ARIB standard. */ +#define CAPF_DMX_DVB \ + 0x00000008 /**< Support flag for guided downmix with data from DVB ancillary \ + data fields. */ +#define CAPF_DMX_CH_EXP \ + 0x00000010 /**< Support flag for simple upmixing by dublicating channels or \ + adding zero channels. */ +#define CAPF_DMX_6_CH \ + 0x00000020 /**< Support flag for 5.1 channel configuration (input and \ + output). */ +#define CAPF_DMX_8_CH \ + 0x00000040 /**< Support flag for 6 and 7.1 channel configurations (input and \ + output). */ +#define CAPF_DMX_24_CH \ + 0x00000080 /**< Support flag for 22.2 channel configuration (input and \ + output). */ +#define CAPF_LIMITER \ + 0x00002000 /**< Support flag for signal level limiting. \ + */ + +/* MPEG Surround capability flags */ +#define CAPF_MPS_STD \ + 0x00000001 /**< Support flag for MPEG Surround. */ +#define CAPF_MPS_LD \ + 0x00000002 /**< Support flag for Low Delay MPEG Surround. \ + */ +#define CAPF_MPS_USAC \ + 0x00000004 /**< Support flag for USAC MPEG Surround. */ +#define CAPF_MPS_HQ \ + 0x00000010 /**< Support flag indicating if high quality processing is \ + supported */ +#define CAPF_MPS_LP \ + 0x00000020 /**< Support flag indicating if partially complex (low power) \ + processing is supported */ +#define CAPF_MPS_BLIND \ + 0x00000040 /**< Support flag indicating if blind processing is supported */ +#define CAPF_MPS_BINAURAL \ + 0x00000080 /**< Support flag indicating if binaural output is possible */ +#define CAPF_MPS_2CH_OUT \ + 0x00000100 /**< Support flag indicating if 2ch output is possible */ +#define CAPF_MPS_6CH_OUT \ + 0x00000200 /**< Support flag indicating if 6ch output is possible */ +#define CAPF_MPS_8CH_OUT \ + 0x00000400 /**< Support flag indicating if 8ch output is possible */ +#define CAPF_MPS_1CH_IN \ + 0x00001000 /**< Support flag indicating if 1ch dmx input is possible */ +#define CAPF_MPS_2CH_IN \ + 0x00002000 /**< Support flag indicating if 2ch dmx input is possible */ +#define CAPF_MPS_6CH_IN \ + 0x00004000 /**< Support flag indicating if 5ch dmx input is possible */ + +/* \endcond */ + +/* + * ############################################################################################## + * Library versioning + * ############################################################################################## + */ + +/** + * Convert each member of version numbers to one single numeric version + * representation. + * \param lev0 1st level of version number. + * \param lev1 2nd level of version number. + * \param lev2 3rd level of version number. + */ +#define LIB_VERSION(lev0, lev1, lev2) \ + ((lev0 << 24 & 0xff000000) | (lev1 << 16 & 0x00ff0000) | \ + (lev2 << 8 & 0x0000ff00)) + +/** + * Build text string of version. + */ +#define LIB_VERSION_STRING(info) \ + FDKsprintf((info)->versionStr, "%d.%d.%d", (((info)->version >> 24) & 0xff), \ + (((info)->version >> 16) & 0xff), \ + (((info)->version >> 8) & 0xff)) + +/** + * Library information. + */ +typedef struct LIB_INFO { + const char* title; + const char* build_date; + const char* build_time; + FDK_MODULE_ID module_id; + INT version; + UINT flags; + char versionStr[32]; +} LIB_INFO; + +#ifdef __cplusplus +#define FDK_AUDIO_INLINE inline +#else +#define FDK_AUDIO_INLINE +#endif + +/** Initialize library info. */ +static FDK_AUDIO_INLINE void FDKinitLibInfo(LIB_INFO* info) { + int i; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + info[i].module_id = FDK_NONE; + } +} + +/** Aquire supported features of library. */ +static FDK_AUDIO_INLINE UINT +FDKlibInfo_getCapabilities(const LIB_INFO* info, FDK_MODULE_ID module_id) { + int i; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == module_id) { + return info[i].flags; + } + } + return 0; +} + +/** Search for next free tab. */ +static FDK_AUDIO_INLINE INT FDKlibInfo_lookup(const LIB_INFO* info, + FDK_MODULE_ID module_id) { + int i = -1; + + for (i = 0; i < FDK_MODULE_LAST; i++) { + if (info[i].module_id == module_id) return -1; + if (info[i].module_id == FDK_NONE) break; + } + if (i == FDK_MODULE_LAST) return -1; + + return i; +} + +/* + * ############################################################################################## + * Buffer description + * ############################################################################################## + */ + +/** + * I/O buffer descriptor. + */ +typedef struct FDK_bufDescr { + void** ppBase; /*!< Pointer to an array containing buffer base addresses. + Set to NULL for buffer requirement info. */ + UINT* pBufSize; /*!< Pointer to an array containing the number of elements + that can be placed in the specific buffer. */ + UINT* pEleSize; /*!< Pointer to an array containing the element size for each + buffer in bytes. That is mostly the number returned by the + sizeof() operator for the data type used for the specific + buffer. */ + UINT* + pBufType; /*!< Pointer to an array of bit fields containing a description + for each buffer. See XXX below for more details. */ + UINT numBufs; /*!< Total number of buffers. */ + +} FDK_bufDescr; + +/** + * Buffer type description field. + */ +#define FDK_BUF_TYPE_MASK_IO ((UINT)0x03 << 30) +#define FDK_BUF_TYPE_MASK_DESCR ((UINT)0x3F << 16) +#define FDK_BUF_TYPE_MASK_ID ((UINT)0xFF) + +#define FDK_BUF_TYPE_INPUT ((UINT)0x1 << 30) +#define FDK_BUF_TYPE_OUTPUT ((UINT)0x2 << 30) + +#define FDK_BUF_TYPE_PCM_DATA ((UINT)0x1 << 16) +#define FDK_BUF_TYPE_ANC_DATA ((UINT)0x2 << 16) +#define FDK_BUF_TYPE_BS_DATA ((UINT)0x4 << 16) + +#ifdef __cplusplus +} +#endif + +#endif /* FDK_AUDIO_H */ diff --git a/fdk-aac/libSYS/include/genericStds.h b/fdk-aac/libSYS/include/genericStds.h new file mode 100644 index 0000000..8828ba7 --- /dev/null +++ b/fdk-aac/libSYS/include/genericStds.h @@ -0,0 +1,584 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/** \file genericStds.h + \brief Generic Run-Time Support function wrappers and heap allocation + monitoring. + */ + +#if !defined(GENERICSTDS_H) +#define GENERICSTDS_H + +#include "machine_type.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 /*!< Pi. Only used in example projects. */ +#endif + +/** + * Identifiers for various memory locations. They are used along with memory + * allocation functions like FDKcalloc_L() to specify the requested memory's + * location. + */ +typedef enum { + /* Internal */ + SECT_DATA_L1 = 0x2000, + SECT_DATA_L2, + SECT_DATA_L1_A, + SECT_DATA_L1_B, + SECT_CONSTDATA_L1, + + /* External */ + SECT_DATA_EXTERN = 0x4000, + SECT_CONSTDATA_EXTERN + +} MEMORY_SECTION; + +/*! \addtogroup SYSLIB_MEMORY_MACROS FDK memory macros + * + * The \c H_ prefix indicates that the macro is to be used in a header file, the + * \c C_ prefix indicates that the macro is to be used in a source file. + * + * Declaring memory areas requires to specify a unique name and a data type. + * + * For defining a memory area you require additionally one or two sizes, + * depending if the memory should be organized into one or two dimensions. + * + * The macros containing the keyword \c AALLOC instead of \c ALLOC additionally + * take care of returning aligned memory addresses (beyond the natural alignment + * of its type). The preprocesor macro + * ::ALIGNMENT_DEFAULT indicates the aligment to be used (this is hardware + * specific). + * + * The \c _L suffix indicates that the memory will be located in a specific + * section. This is useful to allocate critical memory section into fast + * internal SRAM for example. + * + * @{ + */ + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define H_ALLOC_MEM(name, type) \ + type *Get##name(int n = 0); \ + void Free##name(type **p); \ + UINT GetRequiredMem##name(void); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define H_ALLOC_MEM_OVERLAY(name, type) \ + type *Get##name(int n = 0); \ + void Free##name(type **p); \ + UINT GetRequiredMem##name(void); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM(name, type, num) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) == 0); \ + return ((type *)FDKcalloc(num, sizeof(type))); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM2(name, type, n1, n2) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) < (n2)); \ + return ((type *)FDKcalloc(n1, sizeof(type))); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM(name, type, num) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) == 0); \ + ap = ((type *)FDKaalloc((num) * sizeof(type), ALIGNMENT_DEFAULT)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM2(name, type, n1, n2) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) < (n2)); \ + ap = ((type *)FDKaalloc((n1) * sizeof(type), ALIGNMENT_DEFAULT)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)) * \ + (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM_L(name, type, num, s) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) == 0); \ + return ((type *)FDKcalloc_L(num, sizeof(type), s)); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM2_L(name, type, n1, n2, s) \ + type *Get##name(int n) { \ + FDK_ASSERT((n) < (n2)); \ + return (type *)FDKcalloc_L(n1, sizeof(type), s); \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKfree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type)) * (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM_L(name, type, num, s) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) == 0); \ + ap = ((type *)FDKaalloc_L((num) * sizeof(type), ALIGNMENT_DEFAULT, s)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((num) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_MEM2_L(name, type, n1, n2, s) \ + type *Get##name(int n) { \ + type *ap; \ + FDK_ASSERT((n) < (n2)); \ + ap = ((type *)FDKaalloc_L((n1) * sizeof(type), ALIGNMENT_DEFAULT, s)); \ + return ap; \ + } \ + void Free##name(type **p) { \ + if (p != NULL) { \ + FDKafree_L(*p); \ + *p = NULL; \ + } \ + } \ + UINT GetRequiredMem##name(void) { \ + return ALGN_SIZE_EXTRES((n1) * sizeof(type) + ALIGNMENT_DEFAULT + \ + sizeof(void *)) * \ + (n2); \ + } + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_MEM_OVERLAY(name, type, num, sect, tag) \ + C_AALLOC_MEM_L(name, type, num, sect) + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_SCRATCH_START(name, type, n) \ + type _##name[(n) + (ALIGNMENT_DEFAULT + sizeof(type) - 1)]; \ + type *name = (type *)ALIGN_PTR(_##name); \ + C_ALLOC_ALIGNED_REGISTER(name, (n) * sizeof(type)); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_SCRATCH_START(name, type, n) type name[n]; + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_SCRATCH_END(name, type, n) C_ALLOC_ALIGNED_UNREGISTER(name); +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_ALLOC_SCRATCH_END(name, type, n) + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_STACK_START(name, type, n) \ + type _##name[(n) + (ALIGNMENT_DEFAULT + sizeof(type) - 1)]; \ + type *name = (type *)ALIGN_PTR(_##name); \ + C_ALLOC_ALIGNED_REGISTER(name, (n) * sizeof(type)); + +/** See \ref SYSLIB_MEMORY_MACROS for description. */ +#define C_AALLOC_STACK_END(name, type, n) C_ALLOC_ALIGNED_UNREGISTER(name); + +/*! @} */ + +#define C_ALLOC_ALIGNED_REGISTER(x, size) +#define C_ALLOC_ALIGNED_UNREGISTER(x) +#define C_ALLOC_ALIGNED_CHECK(x) +#define C_ALLOC_ALIGNED_CHECK2(x, y) +#define FDK_showBacktrace(a, b) + +/*! \addtogroup SYSLIB_EXITCODES Unified exit codes + * Exit codes to be used as return values of FDK software test and + * demonstration applications. Not as return values of product modules and/or + * libraries. + * @{ + */ +#define FDK_EXITCODE_OK 0 /*!< Successful termination. No errors. */ +#define FDK_EXITCODE_USAGE \ + 64 /*!< The command/application was used incorrectly, e.g. with the wrong \ + number of arguments, a bad flag, a bad syntax in a parameter, or \ + whatever. */ +#define FDK_EXITCODE_DATAERROR \ + 65 /*!< The input data was incorrect in some way. This should only be used \ + for user data and not system files. */ +#define FDK_EXITCODE_NOINPUT \ + 66 /*!< An input file (not a system file) did not exist or was not readable. \ + */ +#define FDK_EXITCODE_UNAVAILABLE \ + 69 /*!< A service is unavailable. This can occur if a support program or \ + file does not exist. This can also be used as a catchall message when \ + something you wanted to do doesn't work, but you don't know why. */ +#define FDK_EXITCODE_SOFTWARE \ + 70 /*!< An internal software error has been detected. This should be limited \ + to non- operating system related errors as possible. */ +#define FDK_EXITCODE_CANTCREATE \ + 73 /*!< A (user specified) output file cannot be created. */ +#define FDK_EXITCODE_IOERROR \ + 74 /*!< An error occurred while doing I/O on some file. */ +/*! @} */ + +/*-------------------------------------------- + * Runtime support declarations + *---------------------------------------------*/ +#ifdef __cplusplus +extern "C" { +#endif + +void FDKprintf(const char *szFmt, ...); + +void FDKprintfErr(const char *szFmt, ...); + +/** Wrapper for 's getchar(). */ +int FDKgetchar(void); + +INT FDKfprintf(void *stream, const char *format, ...); +INT FDKsprintf(char *str, const char *format, ...); + +char *FDKstrchr(char *s, INT c); +const char *FDKstrstr(const char *haystack, const char *needle); +char *FDKstrcpy(char *dest, const char *src); +char *FDKstrncpy(char *dest, const char *src, const UINT n); + +#define FDK_MAX_OVERLAYS 8 /**< Maximum number of memory overlays. */ + +void *FDKcalloc(const UINT n, const UINT size); +void *FDKmalloc(const UINT size); +void FDKfree(void *ptr); + +/** + * Allocate and clear an aligned memory area. Use FDKafree() instead of + * FDKfree() for these memory areas. + * + * \param size Size of requested memory in bytes. + * \param alignment Alignment of requested memory in bytes. + * \return Pointer to allocated memory. + */ +void *FDKaalloc(const UINT size, const UINT alignment); + +/** + * Free an aligned memory area. + * + * \param ptr Pointer to be freed. + */ +void FDKafree(void *ptr); + +/** + * Allocate memory in a specific memory section. + * Requests can be made for internal or external memory. If internal memory is + * requested, FDKcalloc_L() first tries to use L1 memory, which sizes are + * defined by ::DATA_L1_A_SIZE and ::DATA_L1_B_SIZE. If no L1 memory is + * available, then FDKcalloc_L() tries to use L2 memory. If that fails as well, + * the requested memory is allocated at an extern location using the fallback + * FDKcalloc(). + * + * \param n See MSDN documentation on calloc(). + * \param size See MSDN documentation on calloc(). + * \param s Memory section. + * \return See MSDN documentation on calloc(). + */ +void *FDKcalloc_L(const UINT n, const UINT size, MEMORY_SECTION s); + +/** + * Allocate aligned memory in a specific memory section. + * See FDKcalloc_L() description for details - same applies here. + */ +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s); + +/** + * Free memory that was allocated in a specific memory section. + */ +void FDKfree_L(void *ptr); + +/** + * Free aligned memory that was allocated in a specific memory section. + */ +void FDKafree_L(void *ptr); + +/** + * Copy memory. Source and destination memory must not overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memcpy(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemcpy(void *dst, const void *src, const UINT size); + +/** + * Copy memory. Source and destination memory are allowed to overlap. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memmove(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemmove(void *dst, const void *src, const UINT size); + +/** + * Clear memory. + * Either use implementation from a Standard Library, or, if no Standard Library + * is available, a generic implementation. + * The define ::USE_BUILTIN_MEM_FUNCTIONS in genericStds.cpp controls what to + * use. The function arguments correspond to the standard memclear(). Please see + * MSDN documentation for details on how to use it. + */ +void FDKmemclear(void *memPtr, const UINT size); + +/** + * Fill memory with values. + * The function arguments correspond to the standard memset(). Please see MSDN + * documentation for details on how to use it. + */ +void FDKmemset(void *memPtr, const INT value, const UINT size); + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size); +INT FDKstrcmp(const char *s1, const char *s2); +INT FDKstrncmp(const char *s1, const char *s2, const UINT size); + +UINT FDKstrlen(const char *s); + +#define FDKmax(a, b) ((a) > (b) ? (a) : (b)) +#define FDKmin(a, b) ((a) < (b) ? (a) : (b)) + +#define FDK_INT_MAX ((INT)0x7FFFFFFF) +#define FDK_INT_MIN ((INT)0x80000000) + +/* FILE I/O */ + +/*! + * Check platform for endianess. + * + * \return 1 if platform is little endian, non-1 if platform is big endian. + */ +int IS_LITTLE_ENDIAN(void); + +/*! + * Convert input value to little endian format. + * + * \param val Value to be converted. It may be in both big or little endian. + * \return Value in little endian format. + */ +UINT TO_LITTLE_ENDIAN(UINT val); + +/*! + * \fn FDKFILE *FDKfopen(const char *filename, const char *mode); + * Standard fopen() wrapper. + * \fn INT FDKfclose(FDKFILE *FP); + * Standard fclose() wrapper. + * \fn INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); + * Standard fseek() wrapper. + * \fn INT FDKftell(FDKFILE *FP); + * Standard ftell() wrapper. + * \fn INT FDKfflush(FDKFILE *fp); + * Standard fflush() wrapper. + * \fn UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + * Standard fwrite() wrapper. + * \fn UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); + * Standard fread() wrapper. + */ +typedef void FDKFILE; +extern const INT FDKSEEK_SET, FDKSEEK_CUR, FDKSEEK_END; + +FDKFILE *FDKfopen(const char *filename, const char *mode); +INT FDKfclose(FDKFILE *FP); +INT FDKfseek(FDKFILE *FP, LONG OFFSET, int WHENCE); +INT FDKftell(FDKFILE *FP); +INT FDKfflush(FDKFILE *fp); +UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp); +char *FDKfgets(void *dst, INT size, FDKFILE *fp); +void FDKrewind(FDKFILE *fp); +INT FDKfeof(FDKFILE *fp); + +/** + * \brief Write each member in little endian order. Convert automatically + * to host endianess. + * \param ptrf Pointer to memory where to read data from. + * \param size Size of each item to be written. + * \param nmemb Number of items to be written. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfwrite_EL(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp); + +/** + * \brief Read variable of size "size" as little endian. Convert + * automatically to host endianess. 4-byte alignment is enforced for 24 bit + * data, at 32 bit full scale. + * \param dst Pointer to memory where to store data into. + * \param size Size of each item to be read. + * \param nmemb Number of items to be read. + * \param fp File pointer of type FDKFILE. + * \return Number of items read on success and fread() error on failure. + */ +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp); + +/** + * \brief Print FDK software disclaimer. + */ +void FDKprintDisclaimer(void); + +#ifdef __cplusplus +} +#endif + +#endif /* GENERICSTDS_H */ diff --git a/fdk-aac/libSYS/include/machine_type.h b/fdk-aac/libSYS/include/machine_type.h new file mode 100644 index 0000000..bd97669 --- /dev/null +++ b/fdk-aac/libSYS/include/machine_type.h @@ -0,0 +1,411 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: + +*******************************************************************************/ + +/** \file machine_type.h + * \brief Type defines for various processors and compiler tools. + */ + +#if !defined(MACHINE_TYPE_H) +#define MACHINE_TYPE_H + +#include /* Needed to define size_t */ + +#if defined(__ANDROID__) && (__GNUC__ == 4) && (__GNUC_MINOR__ == 4) && \ + (__GNUC_GNU_INLINE__ == 1) +typedef unsigned long long uint64_t; +#include +#endif + +/* Library calling convention spec. __cdecl and friends might be added here as + * required. */ +#define LINKSPEC_H +#define LINKSPEC_CPP + +/* for doxygen the following docu parts must be separated */ +/** \var SCHAR + * Data type representing at least 1 byte signed integer on all supported + * platforms. + */ +/** \var UCHAR + * Data type representing at least 1 byte unsigned integer on all + * supported platforms. + */ +/** \var INT + * Data type representing at least 4 byte signed integer on all supported + * platforms. + */ +/** \var UINT + * Data type representing at least 4 byte unsigned integer on all + * supported platforms. + */ +/** \var LONG + * Data type representing 4 byte signed integer on all supported + * platforms. + */ +/** \var ULONG + * Data type representing 4 byte unsigned integer on all supported + * platforms. + */ +/** \var SHORT + * Data type representing 2 byte signed integer on all supported + * platforms. + */ +/** \var USHORT + * Data type representing 2 byte unsigned integer on all supported + * platforms. + */ +/** \var INT64 + * Data type representing 8 byte signed integer on all supported + * platforms. + */ +/** \var UINT64 + * Data type representing 8 byte unsigned integer on all supported + * platforms. + */ +/** \def SHORT_BITS + * Number of bits the data type short represents. sizeof() is not suited + * to get this info, because a byte is not always defined as 8 bits. + */ +/** \def CHAR_BITS + * Number of bits the data type char represents. sizeof() is not suited + * to get this info, because a byte is not always defined as 8 bits. + */ +/** \var INT_PCM + * Data type representing the width of input and output PCM samples. + */ + +typedef signed int INT; +typedef unsigned int UINT; +#ifdef __LP64__ +/* force FDK long-datatypes to 4 byte */ +/* Use defines to avoid type alias problems on 64 bit machines. */ +#define LONG INT +#define ULONG UINT +#else /* __LP64__ */ +typedef signed long LONG; +typedef unsigned long ULONG; +#endif /* __LP64__ */ +typedef signed short SHORT; +typedef unsigned short USHORT; +typedef signed char SCHAR; +typedef unsigned char UCHAR; + +#define SHORT_BITS 16 +#define CHAR_BITS 8 + +/* Define 64 bit base integer type. */ +#ifdef _MSC_VER +typedef __int64 INT64; +typedef unsigned __int64 UINT64; +#else +typedef long long INT64; +typedef unsigned long long UINT64; +#endif + +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif + +#if ((defined(__i686__) || defined(__i586__) || defined(__i386__) || \ + defined(__x86_64__)) || \ + (defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64)))) && \ + !defined(FDK_ASSERT_ENABLE) +#define FDK_ASSERT_ENABLE +#endif + +#if defined(FDK_ASSERT_ENABLE) +#include +#define FDK_ASSERT(x) assert(x) +#else +#define FDK_ASSERT(ignore) +#endif + +typedef SHORT INT_PCM; +#define MAXVAL_PCM MAXVAL_SGL +#define MINVAL_PCM MINVAL_SGL +#define WAV_BITS 16 +#define SAMPLE_BITS 16 +#define SAMPLE_MAX ((INT_PCM)(((ULONG)1 << (SAMPLE_BITS - 1)) - 1)) +#define SAMPLE_MIN (~SAMPLE_MAX) + +/*! +* \def RAM_ALIGN +* Used to align memory as prefix before memory declaration. For example: + \code + RAM_ALIGN + int myArray[16]; + \endcode + + Note, that not all platforms support this mechanism. For example with TI +compilers a preprocessor pragma is used, but to do something like + + \code + #define RAM_ALIGN #pragma DATA_ALIGN(x) + \endcode + + would require the preprocessor to process this line twice to fully resolve +it. Hence, a fully platform-independant way to use alignment is not supported. + +* \def ALIGNMENT_DEFAULT +* Default alignment in bytes. +*/ + +#define ALIGNMENT_DEFAULT 8 + +/* RAM_ALIGN keyword causes memory alignment of global variables. */ +#if defined(_MSC_VER) +#define RAM_ALIGN __declspec(align(ALIGNMENT_DEFAULT)) +#elif defined(__GNUC__) +#define RAM_ALIGN __attribute__((aligned(ALIGNMENT_DEFAULT))) +#else +#define RAM_ALIGN +#endif + +/*! + * \def RESTRICT + * The restrict keyword is supported by some platforms and RESTRICT maps + * to either the corresponding keyword on each platform or to void if the + * compiler does not provide such feature. It tells the compiler that a + * pointer points to memory that does not overlap with other memories pointed to + * by other pointers. If this keyword is used and the assumption of no + * overlap is not true the resulting code might crash. + * + * \def WORD_ALIGNED(x) + * Tells the compiler that pointer x is 16 bit aligned. It does not cause + * the address itself to be aligned, but serves as a hint to the optimizer. The + * alignment of the pointer must be guarranteed, if not the code might + * crash. + * + * \def DWORD_ALIGNED(x) + * Tells the compiler that pointer x is 32 bit aligned. It does not cause + * the address itself to be aligned, but serves as a hint to the optimizer. The + * alignment of the pointer must be guarranteed, if not the code might + * crash. + * + */ +#define RESTRICT +#define WORD_ALIGNED(x) C_ALLOC_ALIGNED_CHECK2((const void *)(x), 2); +#define DWORD_ALIGNED(x) C_ALLOC_ALIGNED_CHECK2((const void *)(x), 4); + +/*----------------------------------------------------------------------------------- + * ALIGN_SIZE + *-----------------------------------------------------------------------------------*/ +/*! + * \brief This macro aligns a given value depending on ::ALIGNMENT_DEFAULT. + * + * For example if #ALIGNMENT_DEFAULT equals 8, then: + * - ALIGN_SIZE(3) returns 8 + * - ALIGN_SIZE(8) returns 8 + * - ALIGN_SIZE(9) returns 16 + */ +#define ALIGN_SIZE(a) \ + ((a) + (((INT)ALIGNMENT_DEFAULT - ((size_t)(a) & (ALIGNMENT_DEFAULT - 1))) & \ + (ALIGNMENT_DEFAULT - 1))) + +/*! + * \brief This macro aligns a given address depending on ::ALIGNMENT_DEFAULT. + */ +#define ALIGN_PTR(a) \ + ((void *)((unsigned char *)(a) + \ + ((((INT)ALIGNMENT_DEFAULT - \ + ((size_t)(a) & (ALIGNMENT_DEFAULT - 1))) & \ + (ALIGNMENT_DEFAULT - 1))))) + +/* Alignment macro for libSYS heap implementation */ +#define ALIGNMENT_EXTRES (ALIGNMENT_DEFAULT) +#define ALGN_SIZE_EXTRES(a) \ + ((a) + (((INT)ALIGNMENT_EXTRES - ((INT)(a) & (ALIGNMENT_EXTRES - 1))) & \ + (ALIGNMENT_EXTRES - 1))) + +/*! + * \def FDK_FORCEINLINE + * Sometimes compiler do not do what they are told to do, and in case of + * inlining some additional command might be necessary depending on the + * platform. + * + * \def FDK_INLINE + * Defines how the compiler is told to inline stuff. + */ +#ifndef FDK_FORCEINLINE +#if defined(__GNUC__) && !defined(__SDE_MIPS__) +#define FDK_FORCEINLINE inline __attribute((always_inline)) +#else +#define FDK_FORCEINLINE inline +#endif +#endif + +#define FDK_INLINE static inline + +/*! + * \def LNK_SECTION_DATA_L1 + * The LNK_SECTION_* defines allow memory to be drawn from specific memory + * sections. Used as prefix before variable declaration. + * + * \def LNK_SECTION_DATA_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_A + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_L1_DATA_B + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CONSTDATA + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L1 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_CODE_L2 + * See ::LNK_SECTION_DATA_L1 + * \def LNK_SECTION_INITCODE + * See ::LNK_SECTION_DATA_L1 + */ +/************************************************** + * Code Section macros + **************************************************/ +#define LNK_SECTION_CODE_L1 +#define LNK_SECTION_CODE_L2 +#define LNK_SECTION_INITCODE + +/* Memory section macros. */ + +/* default fall back */ +#define LNK_SECTION_DATA_L1 +#define LNK_SECTION_DATA_L2 +#define LNK_SECTION_CONSTDATA +#define LNK_SECTION_CONSTDATA_L1 + +#define LNK_SECTION_L1_DATA_A +#define LNK_SECTION_L1_DATA_B + +/************************************************** + * Macros regarding static code analysis + **************************************************/ +#ifdef __cplusplus +#if !defined(__has_cpp_attribute) +#define __has_cpp_attribute(x) 0 +#endif +#if defined(__clang__) && __has_cpp_attribute(clang::fallthrough) +#define FDK_FALLTHROUGH [[clang::fallthrough]] +#endif +#endif + +#ifndef FDK_FALLTHROUGH +#if defined(__GNUC__) && (__GNUC__ >= 7) +#define FDK_FALLTHROUGH __attribute__((fallthrough)) +#else +#define FDK_FALLTHROUGH +#endif +#endif + +#ifdef _MSC_VER +/* + * Sometimes certain features are excluded from compilation and therefore the + * warning 4065 may occur: "switch statement contains 'default' but no 'case' + * labels" We consider this warning irrelevant and disable it. + */ +#pragma warning(disable : 4065) +#endif + +#endif /* MACHINE_TYPE_H */ diff --git a/fdk-aac/libSYS/include/syslib_channelMapDescr.h b/fdk-aac/libSYS/include/syslib_channelMapDescr.h new file mode 100644 index 0000000..375a24d --- /dev/null +++ b/fdk-aac/libSYS/include/syslib_channelMapDescr.h @@ -0,0 +1,202 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Thomas Dietzen + + Description: + +*******************************************************************************/ + +/** \file syslib_channelMapDescr.h + * \brief Function and structure declarations for the channel map descriptor implementation. + */ + +#ifndef SYSLIB_CHANNELMAPDESCR_H +#define SYSLIB_CHANNELMAPDESCR_H + +#include "machine_type.h" + +/** + * \brief Contains information needed for a single channel map. + */ +typedef struct { + const UCHAR* + pChannelMap; /*!< Actual channel mapping for one single configuration. */ + UCHAR numChannels; /*!< The number of channels for the channel map which is + the maximum used channel index+1. */ +} CHANNEL_MAP_INFO; + +/** + * \brief This is the main data struct. It contains the mapping for all + * channel configurations such as administration information. + * + * CAUTION: Do not access this structure directly from a algorithm specific + * library. Always use one of the API access functions below! + */ +typedef struct { + const CHANNEL_MAP_INFO* pMapInfoTab; /*!< Table of channel maps. */ + UINT mapInfoTabLen; /*!< Length of the channel map table array. */ + UINT fPassThrough; /*!< Flag that defines whether the specified mapping shall + be applied (value: 0) or the input just gets passed + through (MPEG mapping). */ +} FDK_channelMapDescr; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Initialize a given channel map descriptor. + * + * \param pMapDescr Pointer to a channel map descriptor to be initialized. + * \param pMapInfoTab Table of channel maps to initizalize the descriptor + with. + * If a NULL pointer is given a default table for + WAV-like mapping will be used. + * \param mapInfoTabLen Length of the channel map table array (pMapInfoTab). + If a zero length is given a default table for WAV-like mapping will be used. + * \param fPassThrough If the flag is set the reordering (given by + pMapInfoTab) will be bypassed. + */ +void FDK_chMapDescr_init(FDK_channelMapDescr* const pMapDescr, + const CHANNEL_MAP_INFO* const pMapInfoTab, + const UINT mapInfoTabLen, const UINT fPassThrough); + +/** + * \brief Change the channel reordering state of a given channel map + * descriptor. + * + * \param pMapDescr Pointer to a (initialized) channel map descriptor. + * \param fPassThrough If the flag is set the reordering (given by + * pMapInfoTab) will be bypassed. + * \return Value unequal to zero if set operation was not + * successful. And zero on success. + */ +int FDK_chMapDescr_setPassThrough(FDK_channelMapDescr* const pMapDescr, + UINT fPassThrough); + +/** + * \brief Get the mapping value for a specific channel and map index. + * + * \param pMapDescr Pointer to channel map descriptor. + * \param chIdx Channel index. + * \param mapIdx Mapping index (corresponding to the channel configuration + * index). + * \return Mapping value. + */ +UCHAR FDK_chMapDescr_getMapValue(const FDK_channelMapDescr* const pMapDescr, + const UCHAR chIdx, const UINT mapIdx); + +/** + * \brief Evaluate whether channel map descriptor is reasonable or not. + * + * \param pMapDescr Pointer to channel map descriptor. + * \return Value unequal to zero if descriptor is valid, otherwise + * zero. + */ +int FDK_chMapDescr_isValid(const FDK_channelMapDescr* const pMapDescr); + +/** + * Extra variables for setting up Wg4 channel mapping. + */ +extern const CHANNEL_MAP_INFO FDK_mapInfoTabWg4[]; +extern const UINT FDK_mapInfoTabLenWg4; + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(SYSLIB_CHANNELMAPDESCR_H) */ diff --git a/fdk-aac/libSYS/src/genericStds.cpp b/fdk-aac/libSYS/src/genericStds.cpp new file mode 100644 index 0000000..f98d0a9 --- /dev/null +++ b/fdk-aac/libSYS/src/genericStds.cpp @@ -0,0 +1,419 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): + + Description: - Generic memory, stdio, string, etc. function wrappers or + builtins. + - OS dependant function wrappers. + +*******************************************************************************/ + +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS +#endif + +#define __GENERICSTDS_CPP__ + +#include "genericStds.h" + +/* library info */ +#define SYS_LIB_VL0 2 +#define SYS_LIB_VL1 0 +#define SYS_LIB_VL2 0 +#define SYS_LIB_TITLE "System Integration Library" +#ifdef __ANDROID__ +#define SYS_LIB_BUILD_DATE "" +#define SYS_LIB_BUILD_TIME "" +#else +#define SYS_LIB_BUILD_DATE __DATE__ +#define SYS_LIB_BUILD_TIME __TIME__ +#endif + +#include +#include +#include +#include + +/*************************************************************** + * memory allocation monitoring variables + ***************************************************************/ + +/* Include OS/System specific implementations. */ + +#include +#include +#include + +void FDKprintf(const char *szFmt, ...) { + va_list ap; + va_start(ap, szFmt); + vprintf(szFmt, ap); + va_end(ap); +} + +void FDKprintfErr(const char *szFmt, ...) { + va_list ap; + va_start(ap, szFmt); + vfprintf(stderr, szFmt, ap); + va_end(ap); +} + +int FDKgetchar(void) { return getchar(); } + +INT FDKfprintf(FDKFILE *stream, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vfprintf((FILE *)stream, format, ap); + va_end(ap); + return chars; +} + +INT FDKsprintf(char *str, const char *format, ...) { + INT chars = 0; + va_list ap; + va_start(ap, format); + chars += vsprintf(str, format, ap); + va_end(ap); + return chars; +} + +/************************************************************************************************/ + +/************************************************************************************************/ + +char *FDKstrchr(char *s, INT c) { return strchr(s, c); } +const char *FDKstrstr(const char *haystack, const char *needle) { + return strstr(haystack, needle); +} +char *FDKstrcpy(char *dest, const char *src) { return strcpy(dest, src); } +char *FDKstrncpy(char *dest, const char *src, UINT n) { + return strncpy(dest, src, n); +} + +/************************************************************************* + * DYNAMIC MEMORY management (heap) + *************************************************************************/ + +void *FDKcalloc(const UINT n, const UINT size) { + void *ptr; + + ptr = calloc(n, size); + + return ptr; +} + +void *FDKmalloc(const UINT size) { + void *ptr; + + ptr = malloc(size); + + return ptr; +} + +void FDKfree(void *ptr) { free((INT *)ptr); } + +void *FDKaalloc(const UINT size, const UINT alignment) { + void *addr, *result = NULL; + addr = FDKcalloc(1, size + alignment + + (UINT)sizeof(void *)); /* Malloc and clear memory. */ + + if (addr != NULL) { + result = ALIGN_PTR((unsigned char *)addr + + sizeof(void *)); /* Get aligned memory base address. */ + *(((void **)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + C_ALLOC_ALIGNED_REGISTER(result, size); + } + + return result; /* Return aligned address. */ +} + +void FDKafree(void *ptr) { + void *addr; + addr = *(((void **)ptr) - 1); /* Get pointer to malloc'ed memory. */ + + C_ALLOC_ALIGNED_UNREGISTER(ptr); + + FDKfree(addr); /* Free malloc'ed memory area. */ +} + +/*--------------------------------------------------------------------------* + * DATA MEMORY L1/L2 (fallback) + *--------------------------------------------------------------------------*/ + +/*--------------------------------------------------------------------------* + * FDKcalloc_L + *--------------------------------------------------------------------------*/ +void *FDKcalloc_L(const UINT dim, const UINT size, MEMORY_SECTION s) { + return FDKcalloc(dim, size); +} + +void FDKfree_L(void *p) { FDKfree(p); } + +void *FDKaalloc_L(const UINT size, const UINT alignment, MEMORY_SECTION s) { + void *addr, *result = NULL; + addr = FDKcalloc_L(1, size + alignment + (UINT)sizeof(void *), + s); /* Malloc and clear memory. */ + + if (addr != NULL) { + result = ALIGN_PTR((unsigned char *)addr + + sizeof(void *)); /* Get aligned memory base address. */ + *(((void **)result) - 1) = addr; /* Save malloc'ed memory pointer. */ + C_ALLOC_ALIGNED_REGISTER(result, size); + } + + return result; /* Return aligned address. */ +} + +void FDKafree_L(void *ptr) { + void *addr; + + addr = *(((void **)ptr) - 1); /* Get pointer to malloc'ed memory. */ + + C_ALLOC_ALIGNED_UNREGISTER(ptr); + + FDKfree_L(addr); /* Free malloc'ed memory area. */ +} + +/*--------------------------------------------------------------------------------------- + * FUNCTION: FDKmemcpy + * DESCRIPTION: - copies memory from "src" to "dst" with length "size" bytes + * - compiled with FDK_DEBUG will give you warnings + *---------------------------------------------------------------------------------------*/ +void FDKmemcpy(void *dst, const void *src, const UINT size) { + /* -- check for overlapping memory areas -- */ + FDK_ASSERT(((const unsigned char *)dst - (const unsigned char *)src) >= + (ptrdiff_t)size || + ((const unsigned char *)src - (const unsigned char *)dst) >= + (ptrdiff_t)size); + + /* do the copy */ + memcpy(dst, src, size); +} + +void FDKmemmove(void *dst, const void *src, const UINT size) { + memmove(dst, src, size); +} + +void FDKmemset(void *memPtr, const INT value, const UINT size) { + memset(memPtr, value, size); +} + +void FDKmemclear(void *memPtr, const UINT size) { FDKmemset(memPtr, 0, size); } + +UINT FDKstrlen(const char *s) { return (UINT)strlen(s); } + +/* Compare function wrappers */ +INT FDKmemcmp(const void *s1, const void *s2, const UINT size) { + return memcmp(s1, s2, size); +} +INT FDKstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); } +INT FDKstrncmp(const char *s1, const char *s2, const UINT size) { + return strncmp(s1, s2, size); +} + +int IS_LITTLE_ENDIAN(void) { + int __dummy = 1; + return (*((UCHAR *)(&(__dummy)))); +} + +UINT TO_LITTLE_ENDIAN(UINT val) { + return IS_LITTLE_ENDIAN() + ? val + : (((val & 0xff) << 24) | ((val & 0xff00) << 8) | + ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24)); +} + +/* ==================== FILE I/O ====================== */ + +FDKFILE *FDKfopen(const char *filename, const char *mode) { + return fopen(filename, mode); +} +INT FDKfclose(FDKFILE *fp) { return fclose((FILE *)fp); } +INT FDKfseek(FDKFILE *fp, LONG OFFSET, int WHENCE) { + return fseek((FILE *)fp, OFFSET, WHENCE); +} +INT FDKftell(FDKFILE *fp) { return ftell((FILE *)fp); } +INT FDKfflush(FDKFILE *fp) { return fflush((FILE *)fp); } +const INT FDKSEEK_SET = SEEK_SET; +const INT FDKSEEK_CUR = SEEK_CUR; +const INT FDKSEEK_END = SEEK_END; + +UINT FDKfwrite(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { + return (UINT)fwrite(ptrf, size, nmemb, (FILE *)fp); +} +UINT FDKfread(void *dst, INT size, UINT nmemb, FDKFILE *fp) { + return (UINT)fread(dst, size, nmemb, (FILE *)fp); +} +char *FDKfgets(void *dst, INT size, FDKFILE *fp) { + return fgets((char *)dst, size, (FILE *)fp); +} +void FDKrewind(FDKFILE *fp) { FDKfseek((FILE *)fp, 0, FDKSEEK_SET); } + +UINT FDKfwrite_EL(const void *ptrf, INT size, UINT nmemb, FDKFILE *fp) { + if (IS_LITTLE_ENDIAN()) { + FDKfwrite(ptrf, size, nmemb, fp); + } else { + UINT n; + INT s; + + const UCHAR *ptr = (const UCHAR *)ptrf; + + for (n = 0; n < nmemb; n++) { + for (s = size - 1; s >= 0; s--) { + FDKfwrite(ptr + s, 1, 1, fp); + } + ptr = ptr + size; + } + } + return nmemb; +} + +UINT FDKfread_EL(void *dst, INT size, UINT nmemb, FDKFILE *fp) { + UINT n, s0, s1, err; + UCHAR tmp, *ptr; + UCHAR tmp24[3]; + + /* Enforce alignment of 24 bit data. */ + if (size == 3) { + ptr = (UCHAR *)dst; + for (n = 0; n < nmemb; n++) { + if ((err = FDKfread(tmp24, 1, 3, fp)) != 3) { + return err; + } + *ptr++ = tmp24[0]; + *ptr++ = tmp24[1]; + *ptr++ = tmp24[2]; + /* Sign extension */ + if (tmp24[2] & 0x80) { + *ptr++ = 0xff; + } else { + *ptr++ = 0; + } + } + err = nmemb; + size = sizeof(LONG); + } else { + if ((err = FDKfread(dst, size, nmemb, fp)) != nmemb) { + return err; + } + } + if (!IS_LITTLE_ENDIAN() && size > 1) { + ptr = (UCHAR *)dst; + for (n = 0; n < nmemb; n++) { + for (s0 = 0, s1 = size - 1; s0 < s1; s0++, s1--) { + tmp = ptr[s0]; + ptr[s0] = ptr[s1]; + ptr[s1] = tmp; + } + ptr += size; + } + } + return err; +} + +INT FDKfeof(FDKFILE *fp) { return feof((FILE *)fp); } + +/* Global initialization/cleanup */ + +void FDKprintDisclaimer(void) { + FDKprintf( + "This program is protected by copyright law and international treaties.\n" + "Any reproduction or distribution of this program, or any portion\n" + "of it, may result in severe civil and criminal penalties, and will be\n" + "prosecuted to the maximum extent possible under law.\n\n"); +} diff --git a/fdk-aac/libSYS/src/syslib_channelMapDescr.cpp b/fdk-aac/libSYS/src/syslib_channelMapDescr.cpp new file mode 100644 index 0000000..d22a30d --- /dev/null +++ b/fdk-aac/libSYS/src/syslib_channelMapDescr.cpp @@ -0,0 +1,315 @@ +/* ----------------------------------------------------------------------------- +Software License for The Fraunhofer FDK AAC Codec Library for Android + +© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten +Forschung e.V. All rights reserved. + + 1. INTRODUCTION +The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software +that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding +scheme for digital audio. This FDK AAC Codec software is intended to be used on +a wide variety of Android devices. + +AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient +general perceptual audio codecs. AAC-ELD is considered the best-performing +full-bandwidth communications codec by independent studies and is widely +deployed. AAC has been standardized by ISO and IEC as part of the MPEG +specifications. + +Patent licenses for necessary patent claims for the FDK AAC Codec (including +those of Fraunhofer) may be obtained through Via Licensing +(www.vialicensing.com) or through the respective patent owners individually for +the purpose of encoding or decoding bit streams in products that are compliant +with the ISO/IEC MPEG audio standards. Please note that most manufacturers of +Android devices already license these patent claims through Via Licensing or +directly from the patent owners, and therefore FDK AAC Codec software may +already be covered under those patent licenses when it is used for those +licensed purposes only. + +Commercially-licensed AAC software libraries, including floating-point versions +with enhanced sound quality, are also available from Fraunhofer. Users are +encouraged to check the Fraunhofer website for additional applications +information and documentation. + +2. COPYRIGHT LICENSE + +Redistribution and use in source and binary forms, with or without modification, +are permitted without payment of copyright license fees provided that you +satisfy the following conditions: + +You must retain the complete text of this software license in redistributions of +the FDK AAC Codec or your modifications thereto in source code form. + +You must retain the complete text of this software license in the documentation +and/or other materials provided with redistributions of the FDK AAC Codec or +your modifications thereto in binary form. You must make available free of +charge copies of the complete source code of the FDK AAC Codec and your +modifications thereto to recipients of copies in binary form. + +The name of Fraunhofer may not be used to endorse or promote products derived +from this library without prior written permission. + +You may not charge copyright license fees for anyone to use, copy or distribute +the FDK AAC Codec software or your modifications thereto. + +Your modified versions of the FDK AAC Codec must carry prominent notices stating +that you changed the software and the date of any change. For modified versions +of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" +must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK +AAC Codec Library for Android." + +3. NO PATENT LICENSE + +NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without +limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. +Fraunhofer provides no warranty of patent non-infringement with respect to this +software. + +You may use this FDK AAC Codec software or modifications thereto only for +purposes that are authorized by appropriate patent licenses. + +4. DISCLAIMER + +This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright +holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, +including but not limited to the implied warranties of merchantability and +fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, +or consequential damages, including but not limited to procurement of substitute +goods or services; loss of use, data, or profits, or business interruption, +however caused and on any theory of liability, whether in contract, strict +liability, or tort (including negligence), arising in any way out of the use of +this software, even if advised of the possibility of such damage. + +5. CONTACT INFORMATION + +Fraunhofer Institute for Integrated Circuits IIS +Attention: Audio and Multimedia Departments - FDK AAC LL +Am Wolfsmantel 33 +91058 Erlangen, Germany + +www.iis.fraunhofer.de/amm +amm-info@iis.fraunhofer.de +----------------------------------------------------------------------------- */ + +/************************* System integration library ************************** + + Author(s): Thomas Dietzen + + Description: + +*******************************************************************************/ + +/** \file syslib_channelMapDescr.cpp + * \brief Implementation of routines that handle the channel map descriptor. + */ + +#include "syslib_channelMapDescr.h" + +#define DFLT_CH_MAP_TAB_LEN \ + (15) /* Length of the default channel map info table. */ + +/** + * \brief The following arrays provide a channel map for each channel config (0 + * to 14). + * + * The i-th channel will be mapped to the postion a[i-1]+1 + * with i>0 and a[] is one of the following mapping arrays. + */ +static const UCHAR mapFallback[] = {0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23}; +static const UCHAR mapCfg1[] = {0, 1}; +static const UCHAR mapCfg2[] = {0, 1}; +static const UCHAR mapCfg3[] = {2, 0, 1}; +static const UCHAR mapCfg4[] = {2, 0, 1, 3}; +static const UCHAR mapCfg5[] = {2, 0, 1, 3, 4}; +static const UCHAR mapCfg6[] = {2, 0, 1, 4, 5, 3}; +static const UCHAR mapCfg7[] = {2, 6, 7, 0, 1, 4, 5, 3}; +static const UCHAR mapCfg11[] = {2, 0, 1, 4, 5, 6, 3}; +static const UCHAR mapCfg12[] = {2, 0, 1, 6, 7, 4, 5, 3}; +static const UCHAR mapCfg13[] = {2, 6, 7, 0, 1, 10, 11, 4, + 5, 8, 3, 9, 14, 12, 13, 18, + 19, 15, 16, 17, 20, 21, 22, 23}; +static const UCHAR mapCfg14[] = {2, 0, 1, 4, 5, 3, 6, 7}; + +/** + * \brief Default table comprising channel map information for each channel + * config (0 to 14). + */ +static const CHANNEL_MAP_INFO mapInfoTabDflt[DFLT_CH_MAP_TAB_LEN] = + {/* chCfg, map, numCh */ + /* 0 */ {mapFallback, 24}, + /* 1 */ {mapCfg1, 2}, + /* 2 */ {mapCfg2, 2}, + /* 3 */ {mapCfg3, 3}, + /* 4 */ {mapCfg4, 4}, + /* 5 */ {mapCfg5, 5}, + /* 6 */ {mapCfg6, 6}, + /* 7 */ {mapCfg7, 8}, + /* 8 */ {mapFallback, 24}, + /* 9 */ {mapFallback, 24}, + /* 10 */ {mapFallback, 24}, + /* 11 */ {mapCfg11, 7}, + /* 12 */ {mapCfg12, 8}, + /* 13 */ {mapCfg13, 24}, + /* 14 */ {mapCfg14, 8}}; + + +static const UCHAR mapWg4Cfg1[] = {0, 1}; +static const UCHAR mapWg4Cfg2[] = {0, 1}; +static const UCHAR mapWg4Cfg3[] = {2, 0, 1}; +static const UCHAR mapWg4Cfg4[] = {3, 0, 1, 2}; +static const UCHAR mapWg4Cfg5[] = {4, 0, 1, 2, 3}; +static const UCHAR mapWg4Cfg6[] = {4, 0, 1, 2, 3, 5}; +static const UCHAR mapWg4Cfg7[] = {6, 0, 1, 2, 3, 4, 5, 7}; +static const UCHAR mapWg4Cfg14[] = {6, 0, 1, 2, 3, 4, 5, 7}; + +const CHANNEL_MAP_INFO FDK_mapInfoTabWg4[] = + {/* chCfg, map, numCh */ + /* 0 */ {mapFallback, 24}, + /* 1 */ {mapWg4Cfg1, 2}, + /* 2 */ {mapWg4Cfg2, 2}, + /* 3 */ {mapWg4Cfg3, 3}, + /* 4 */ {mapWg4Cfg4, 4}, + /* 5 */ {mapWg4Cfg5, 5}, + /* 6 */ {mapWg4Cfg6, 6}, + /* 7 */ {mapWg4Cfg7, 8}, + /* 8 */ {mapFallback, 24}, + /* 9 */ {mapFallback, 24}, + /* 10 */ {mapFallback, 24}, + /* 11 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 12 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 13 */ {mapFallback, 24}, // Unhandled for Wg4 yet + /* 14 */ {mapFallback, 24}}; // Unhandled for Wg4 yet + +const UINT FDK_mapInfoTabLenWg4 = sizeof(FDK_mapInfoTabWg4)/sizeof(FDK_mapInfoTabWg4[0]); + + +/** + * Get the mapping value for a specific channel and map index. + */ +UCHAR FDK_chMapDescr_getMapValue(const FDK_channelMapDescr* const pMapDescr, + const UCHAR chIdx, const UINT mapIdx) { + UCHAR mapValue = chIdx; /* Pass through by default. */ + + FDK_ASSERT(pMapDescr != NULL); + + if ((pMapDescr->fPassThrough == 0) && (pMapDescr->pMapInfoTab != NULL) && + (pMapDescr->mapInfoTabLen > mapIdx)) { /* Nest sanity check to avoid + possible memory access + violation. */ + if (chIdx < pMapDescr->pMapInfoTab[mapIdx].numChannels) { + mapValue = pMapDescr->pMapInfoTab[mapIdx].pChannelMap[chIdx]; + } + } + return mapValue; +} + +/** + * \brief Evaluate whether single channel map is reasonable or not. + * + * \param pMapInfo Pointer to channel map. + * \return Value unequal to zero if map is valid, otherwise zero. + */ +static int fdk_chMapDescr_isValidMap(const CHANNEL_MAP_INFO* const pMapInfo) { + int result = 1; + UINT i; + + if (pMapInfo == NULL) { + result = 0; + } else { + UINT numChannels = pMapInfo->numChannels; + + /* Check for all map values if they are inside the range 0 to numChannels-1 + * and unique. */ + if (numChannels < 32) { /* Optimized version for less than 32 channels. + Needs only one loop. */ + UINT mappedChMask = 0x0; + for (i = 0; i < numChannels; i += 1) { + mappedChMask |= 1 << pMapInfo->pChannelMap[i]; + } + if (mappedChMask != (((UINT)1 << numChannels) - 1)) { + result = 0; + } + } else { /* General case that can handle all number of channels but needs + one more loop. */ + for (i = 0; (i < numChannels) && result; i += 1) { + UINT j; + UCHAR value0 = pMapInfo->pChannelMap[i]; + + if (value0 > numChannels - 1) { /* out of range? */ + result = 0; + } + for (j = numChannels - 1; (j > i) && result; j -= 1) { + if (value0 == pMapInfo->pChannelMap[j]) { /* not unique */ + result = 0; + } + } + } + } + } + + return result; +} + +/** + * Evaluate whether channel map descriptor is reasonable or not. + */ +int FDK_chMapDescr_isValid(const FDK_channelMapDescr* const pMapDescr) { + int result = 0; + UINT i; + + if (pMapDescr != NULL) { + result = 1; + for (i = 0; (i < pMapDescr->mapInfoTabLen) && result; i += 1) { + if (!fdk_chMapDescr_isValidMap(&pMapDescr->pMapInfoTab[i])) { + result = 0; + } + } + } + return result; +} + +/** + * Initialize the complete channel map descriptor. + */ +void FDK_chMapDescr_init(FDK_channelMapDescr* const pMapDescr, + const CHANNEL_MAP_INFO* const pMapInfoTab, + const UINT mapInfoTabLen, const UINT fPassThrough) { + if (pMapDescr != NULL) { + int useDefaultTab = 1; + + pMapDescr->fPassThrough = (fPassThrough == 0) ? 0 : 1; + + if ((pMapInfoTab != NULL) && (mapInfoTabLen > 0)) { + /* Set the valid custom mapping table. */ + pMapDescr->pMapInfoTab = pMapInfoTab; + pMapDescr->mapInfoTabLen = mapInfoTabLen; + /* Validate the complete descriptor. */ + useDefaultTab = (FDK_chMapDescr_isValid(pMapDescr) == 0) ? 1 : 0; + } + if (useDefaultTab != 0) { + /* Set default table. */ + pMapDescr->pMapInfoTab = mapInfoTabDflt; + pMapDescr->mapInfoTabLen = DFLT_CH_MAP_TAB_LEN; + } + } +} + +/** + * Set channel mapping bypass flag in a given channel map descriptor. + */ +int FDK_chMapDescr_setPassThrough(FDK_channelMapDescr* const pMapDescr, + UINT fPassThrough) { + int err = 1; + + if (pMapDescr != NULL) { + if ((pMapDescr->pMapInfoTab != NULL) && (pMapDescr->mapInfoTabLen > 0)) { + pMapDescr->fPassThrough = (fPassThrough == 0) ? 0 : 1; + err = 0; + } + } + + return err; +} diff --git a/fdk-aac/m4/.gitkeep b/fdk-aac/m4/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/fdk-aac/wavreader.c b/fdk-aac/wavreader.c new file mode 100644 index 0000000..898eb9c --- /dev/null +++ b/fdk-aac/wavreader.c @@ -0,0 +1,193 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#include "wavreader.h" +#include +#include +#include +#include + +#define TAG(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +struct wav_reader { + FILE *wav; + uint32_t data_length; + + int format; + int sample_rate; + int bits_per_sample; + int channels; + int byte_rate; + int block_align; + + int streamed; +}; + +static uint32_t read_tag(struct wav_reader* wr) { + uint32_t tag = 0; + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + tag = (tag << 8) | fgetc(wr->wav); + return tag; +} + +static uint32_t read_int32(struct wav_reader* wr) { + uint32_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + value |= fgetc(wr->wav) << 16; + value |= fgetc(wr->wav) << 24; + return value; +} + +static uint16_t read_int16(struct wav_reader* wr) { + uint16_t value = 0; + value |= fgetc(wr->wav) << 0; + value |= fgetc(wr->wav) << 8; + return value; +} + +static void skip(FILE *f, int n) { + int i; + for (i = 0; i < n; i++) + fgetc(f); +} + +void* wav_read_open(const char *filename) { + struct wav_reader* wr = (struct wav_reader*) malloc(sizeof(*wr)); + long data_pos = 0; + memset(wr, 0, sizeof(*wr)); + + if (!strcmp(filename, "-")) + wr->wav = stdin; + else + wr->wav = fopen(filename, "rb"); + if (wr->wav == NULL) { + free(wr); + return NULL; + } + + while (1) { + uint32_t tag, tag2, length; + tag = read_tag(wr); + if (feof(wr->wav)) + break; + length = read_int32(wr); + if (!length || length >= 0x7fff0000) { + wr->streamed = 1; + length = ~0; + } + if (tag != TAG('R', 'I', 'F', 'F') || length < 4) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + tag2 = read_tag(wr); + length -= 4; + if (tag2 != TAG('W', 'A', 'V', 'E')) { + fseek(wr->wav, length, SEEK_CUR); + continue; + } + // RIFF chunk found, iterate through it + while (length >= 8) { + uint32_t subtag, sublength; + subtag = read_tag(wr); + if (feof(wr->wav)) + break; + sublength = read_int32(wr); + length -= 8; + if (length < sublength) + break; + if (subtag == TAG('f', 'm', 't', ' ')) { + if (sublength < 16) { + // Insufficient data for 'fmt ' + break; + } + wr->format = read_int16(wr); + wr->channels = read_int16(wr); + wr->sample_rate = read_int32(wr); + wr->byte_rate = read_int32(wr); + wr->block_align = read_int16(wr); + wr->bits_per_sample = read_int16(wr); + if (wr->format == 0xfffe) { + if (sublength < 28) { + // Insufficient data for waveformatex + break; + } + skip(wr->wav, 8); + wr->format = read_int32(wr); + skip(wr->wav, sublength - 28); + } else { + skip(wr->wav, sublength - 16); + } + } else if (subtag == TAG('d', 'a', 't', 'a')) { + data_pos = ftell(wr->wav); + wr->data_length = sublength; + if (!wr->data_length || wr->streamed) { + wr->streamed = 1; + return wr; + } + fseek(wr->wav, sublength, SEEK_CUR); + } else { + skip(wr->wav, sublength); + } + length -= sublength; + } + if (length > 0) { + // Bad chunk? + fseek(wr->wav, length, SEEK_CUR); + } + } + fseek(wr->wav, data_pos, SEEK_SET); + return wr; +} + +void wav_read_close(void* obj) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (wr->wav != stdin) + fclose(wr->wav); + free(wr); +} + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length) { + struct wav_reader* wr = (struct wav_reader*) obj; + if (format) + *format = wr->format; + if (channels) + *channels = wr->channels; + if (sample_rate) + *sample_rate = wr->sample_rate; + if (bits_per_sample) + *bits_per_sample = wr->bits_per_sample; + if (data_length) + *data_length = wr->data_length; + return wr->format && wr->sample_rate; +} + +int wav_read_data(void* obj, unsigned char* data, unsigned int length) { + struct wav_reader* wr = (struct wav_reader*) obj; + int n; + if (wr->wav == NULL) + return -1; + if (length > wr->data_length && !wr->streamed) + length = wr->data_length; + n = fread(data, 1, length, wr->wav); + wr->data_length -= length; + return n; +} + diff --git a/fdk-aac/wavreader.h b/fdk-aac/wavreader.h new file mode 100644 index 0000000..57a13ff --- /dev/null +++ b/fdk-aac/wavreader.h @@ -0,0 +1,37 @@ +/* ------------------------------------------------------------------ + * Copyright (C) 2009 Martin Storsjo + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. + * See the License for the specific language governing permissions + * and limitations under the License. + * ------------------------------------------------------------------- + */ + +#ifndef WAVREADER_H +#define WAVREADER_H + +#ifdef __cplusplus +extern "C" { +#endif + +void* wav_read_open(const char *filename); +void wav_read_close(void* obj); + +int wav_get_header(void* obj, int* format, int* channels, int* sample_rate, int* bits_per_sample, unsigned int* data_length); +int wav_read_data(void* obj, unsigned char* data, unsigned int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/fdk-aac/win32/getopt.h b/fdk-aac/win32/getopt.h new file mode 100644 index 0000000..7402521 --- /dev/null +++ b/fdk-aac/win32/getopt.h @@ -0,0 +1,904 @@ +#ifndef __GETOPT_H__ +/** + * DISCLAIMER + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * + * The mingw-w64 runtime package and its code is distributed in the hope that it + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + */ +/* + * Implementation of the `getopt', `getopt_long' and `getopt_long_only' + * APIs, for inclusion in the MinGW runtime library. + * + * This file is part of the MinGW32 package set. + * + * Written by Keith Marshall + * Copyright (C) 2008, 2009, 2011, 2012, MinGW.org Project. + * + * --------------------------------------------------------------------------- + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice, this permission notice, and the following + * disclaimer shall be included in all copies or substantial portions of + * the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * --------------------------------------------------------------------------- + * + */ + +#define __GETOPT_H__ + +/* All the headers include this file. */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int optind; /* index of first non-option in argv */ +extern int optopt; /* single option character, as parsed */ +extern int opterr; /* flag to enable built-in diagnostics... */ + /* (user may set to zero, to suppress) */ + +extern char *optarg; /* pointer to argument of current option */ + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +extern int getopt(int nargc, char * const *nargv, const char *options); + +#ifdef _BSD_SOURCE +/* + * BSD adds the non-standard `optreset' feature, for reinitialisation + * of `getopt' parsing. We support this feature, for applications which + * proclaim their BSD heritage, before including this header; however, + * to maintain portability, developers are advised to avoid it. + */ +# define optreset __mingw_optreset +extern int optreset; +#endif +#ifdef __cplusplus +} +#endif +/* + * POSIX requires the `getopt' API to be specified in `unistd.h'; + * thus, `unistd.h' includes this header. However, we do not want + * to expose the `getopt_long' or `getopt_long_only' APIs, when + * included in this manner. Thus, close the standard __GETOPT_H__ + * declarations block, and open an additional __GETOPT_LONG_H__ + * specific block, only when *not* __UNISTD_H_SOURCED__, in which + * to declare the extended API. + */ +#endif /* !defined(__GETOPT_H__) */ + +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) +#define __GETOPT_LONG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct option /* specification for a long form option... */ +{ + const char *name; /* option name, without leading hyphens */ + int has_arg; /* does it take an argument? */ + int *flag; /* where to save its status, or NULL */ + int val; /* its associated status value */ +}; + +enum /* permitted values for its `has_arg' field... */ +{ + no_argument = 0, /* option never takes an argument */ + required_argument, /* option always requires an argument */ + optional_argument /* option may take an argument */ +}; + +extern int getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +extern int getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx); +/* + * Previous MinGW implementation had... + */ +#ifndef HAVE_DECL_GETOPT +/* + * ...for the long form API only; keep this for compatibility. + */ +# define HAVE_DECL_GETOPT 1 +#endif + + + +/* Identify how to get the calling program name, for use in messages... + */ +#ifdef __CYGWIN__ +/* + * CYGWIN uses this DLL reference... + */ +# define PROGNAME __progname +extern char __declspec(dllimport) *__progname; +#else +/* + * ...while elsewhere, we simply use the first argument passed. + */ +# define PROGNAME *argv +#endif + +/* Initialise the public variables. */ + +int optind = 1; /* index for first non-option arg */ +int opterr = 1; /* enable built-in error messages */ + +char *optarg = NULL; /* pointer to current option argument */ + +#define CHAR char /* argument type selector */ + +#define getopt_switchar '-' /* option prefix character in argv */ +#define getopt_pluschar '+' /* prefix for POSIX mode in optstring */ +#define getopt_takes_argument ':' /* marker for optarg in optstring */ +#define getopt_arg_assign '=' /* longopt argument field separator */ +#define getopt_unknown '?' /* return code for unmatched option */ +#define getopt_ordered 1 /* return code for ordered non-option */ + +#define getopt_all_done -1 /* return code to indicate completion */ + +enum +{ /* All `getopt' API functions are implemented via calls to the + * common static function `getopt_parse()'; these `mode' selectors + * determine the behaviour of `getopt_parse()', to deliver the + * appropriate result in each case. + */ + getopt_mode_standard = 0, /* getopt() */ + getopt_mode_long, /* getopt_long() */ + getopt_mode_long_only /* getopt_long_only() */ +}; + +enum +{ /* When attempting to match a command line argument to a long form option, + * these indicate the status of the match. + */ + getopt_no_match = 0, /* no successful match */ + getopt_abbreviated_match, /* argument is an abbreviation for an option */ + getopt_exact_match /* argument matches the full option name */ +}; + +int optopt = getopt_unknown; /* return value for option being evaluated */ + +/* Some BSD applications expect to be able to reinitialise `getopt' parsing + * by setting a global variable called `optreset'. We provide an obfuscated + * API, which allows applications to emulate this brain damage; however, any + * use of this is non-portable, and is strongly discouraged. + */ +#define optreset __mingw_optreset +int optreset = 0; + +static +int getopt_missing_arg( const CHAR *optstring ) +{ + /* Helper function to determine the appropriate return value, + * for the case where a required option argument is missing. + */ + if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) ) + ++optstring; + return (*optstring == getopt_takes_argument) + ? getopt_takes_argument + : getopt_unknown; +} + +/* `complain' macro facilitates the generation of simple built-in + * error messages, displayed on various fault conditions, provided + * `opterr' is non-zero. + */ +#define complain( MSG, ARG ) if( opterr ) \ + fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG ) + +static +int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval ) +{ + /* Helper function, to generate more complex built-in error + * messages, for invalid arguments to long form options ... + */ + if( opterr ) + { + /* ... but, displayed only if `opterr' is non-zero. + */ + char flag[] = "--"; + if( mode != getopt_mode_long ) + /* + * only display one hyphen, for implicit long form options, + * improperly resolved by `getopt_long_only()'. + */ + flag[1] = 0; + /* + * always preface the program name ... + */ + fprintf( stderr, "%s: ", prog ); + /* + * to the appropriate, option specific message. + */ + fprintf( stderr, fmt, flag, opt->name ); + } + /* Whether displaying the message, or not, always set `optopt' + * to identify the faulty option ... + */ + optopt = opt->val; + /* + * and return the `invalid option' indicator. + */ + return retval; +} + +/* `getopt_conventions' establish behavioural options, to control + * the operation of `getopt_parse()', e.g. to select between POSIX + * and GNU style argument parsing behaviour. + */ +#define getopt_set_conventions 0x1000 +#define getopt_posixly_correct 0x0010 + +static +int getopt_conventions( int flags ) +{ + static int conventions = 0; + + if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) ) + { + /* default conventions have not yet been established; + * initialise them now! + */ + conventions = getopt_set_conventions; + if( flags == getopt_pluschar ) + conventions |= getopt_posixly_correct; + } + + else if( flags & getopt_set_conventions ) + /* + * default conventions may have already been established, + * but this is a specific request to augment them. + */ + conventions |= flags; + + /* in any event, return the currently established conventions. + */ + return conventions; +} + +static +int is_switchar( CHAR flag ) +{ + /* A simple helper function, used to identify the switch character + * introducing an optional command line argument. + */ + return flag == getopt_switchar; +} + +static +const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string ) +{ + /* Helper function, used to identify short form options. + */ + if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) ) + ++opt_string; + if( *opt_string == getopt_takes_argument ) + ++opt_string; + do if( lookup == *opt_string ) return opt_string; + while( *++opt_string ); + return NULL; +} + +static +int getopt_match_long( const CHAR *nextchar, const CHAR *optname ) +{ + /* Helper function, used to identify potential matches for + * long form options. + */ + CHAR matchchar; + while( (matchchar = *nextchar++) && (matchchar == *optname) ) + /* + * skip over initial substring which DOES match. + */ + ++optname; + + if( matchchar ) + { + /* did NOT match the entire argument to an initial substring + * of a defined option name ... + */ + if( matchchar != getopt_arg_assign ) + /* + * ... and didn't stop at an `=' internal field separator, + * so this is NOT a possible match. + */ + return getopt_no_match; + + /* DID stop at an `=' internal field separator, + * so this IS a possible match, and what follows is an + * argument to the possibly matched option. + */ + optarg = (char *)(nextchar); + } + return *optname + /* + * if we DIDN'T match the ENTIRE text of the option name, + * then it's a possible abbreviated match ... + */ + ? getopt_abbreviated_match + /* + * but if we DID match the entire option name, + * then it's a DEFINITE EXACT match. + */ + : getopt_exact_match; +} + +static +int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind, +struct option *opt, int index, int *retindex, const CHAR *optstring ) +{ + /* Helper function to establish appropriate return conditions, + * on resolution of a long form option. + */ + if( retindex != NULL ) + *retindex = index; + + /* On return, `optind' should normally refer to the argument, if any, + * which follows the current one; it is convenient to set this, before + * checking for the presence of any `optarg'. + */ + optind = *argind + 1; + + if( optarg && (opt[index].has_arg == no_argument) ) + /* + * it is an error for the user to specify an option specific argument + * with an option which doesn't expect one! + */ + return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n", + PROGNAME, opt + index, getopt_unknown ); + + else if( (optarg == NULL) && (opt[index].has_arg == required_argument) ) + { + /* similarly, it is an error if no argument is specified + * with an option which requires one ... + */ + if( optind < argc ) + /* + * ... except that the requirement may be satisfied from + * the following command line argument, if any ... + */ + optarg = argv[*argind = optind++]; + + else + /* so fail this case, only if no such argument exists! + */ + return getopt_argerror( mode, "option `%s%s' requires an argument\n", + PROGNAME, opt + index, getopt_missing_arg( optstring ) ); + } + + /* when the caller has provided a return buffer ... + */ + if( opt[index].flag != NULL ) + { + /* ... then we place the proper return value there, + * and return a status code of zero ... + */ + *(opt[index].flag) = opt[index].val; + return 0; + } + /* ... otherwise, the return value becomes the status code. + */ + return opt[index].val; +} + +static +int getopt_verify( const CHAR *nextchar, const CHAR *optstring ) +{ + /* Helper function, called by getopt_parse() when invoked + * by getopt_long_only(), to verify when an unmatched or an + * ambiguously matched long form option string is valid as + * a short form option specification. + */ + if( ! (nextchar && *nextchar && optstring && *optstring) ) + /* + * There are no characters to be matched, or there are no + * valid short form option characters to which they can be + * matched, so this can never be valid. + */ + return 0; + + while( *nextchar ) + { + /* For each command line character in turn ... + */ + const CHAR *test; + if( (test = getopt_match( *nextchar++, optstring )) == NULL ) + /* + * ... there is no short form option to match the current + * candidate, so the entire argument fails. + */ + return 0; + + if( test[1] == getopt_takes_argument ) + /* + * The current candidate is valid, and it matches an option + * which takes an argument, so this command line argument is + * a valid short form option specification; accept it. + */ + return 1; + } + /* If we get to here, then every character in the command line + * argument was valid as a short form option; accept it. + */ + return 1; +} + +static +#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring +int getopt_parse( int mode, getopt_std_args, ... ) +{ + /* Common core implementation for ALL `getopt' functions. + */ + static int argind = 0; + static int optbase = 0; + static const CHAR *nextchar = NULL; + static int optmark = 0; + + if( (optreset |= (optind < 1)) || (optind < optbase) ) + { + /* POSIX does not prescribe any definitive mechanism for restarting + * a `getopt' scan, but some applications may require such capability. + * We will support it, by allowing the caller to adjust the value of + * `optind' downwards, (nominally setting it to zero). Since POSIX + * wants `optind' to have an initial value of one, but we want all + * of our internal place holders to be initialised to zero, when we + * are called for the first time, we will handle such a reset by + * adjusting all of the internal place holders to one less than + * the adjusted `optind' value, (but never to less than zero). + */ + if( optreset ) + { + /* User has explicitly requested reinitialisation... + * We need to reset `optind' to it's normal initial value of 1, + * to avoid a potential infinitely recursive loop; by doing this + * up front, we also ensure that the remaining place holders + * will be correctly reinitialised to no less than zero. + */ + optind = 1; + + /* We also need to clear the `optreset' request... + */ + optreset = 0; + } + + /* Now, we may safely reinitialise the internal place holders, to + * one less than `optind', without fear of making them negative. + */ + optmark = optbase = argind = optind - 1; + nextchar = NULL; + } + + /* From a POSIX perspective, the following is `undefined behaviour'; + * we implement it thus, for compatibility with GNU and BSD getopt. + */ + else if( optind > (argind + 1) ) + { + /* Some applications expect to be able to manipulate `optind', + * causing `getopt' to skip over one or more elements of `argv'; + * POSIX doesn't require us to support this brain-damaged concept; + * (indeed, POSIX defines no particular behaviour, in the event of + * such usage, so it must be considered a bug for an application + * to rely on any particular outcome); nonetheless, Mac-OS-X and + * BSD actually provide *documented* support for this capability, + * so we ensure that our internal place holders keep track of + * external `optind' increments; (`argind' must lag by one). + */ + argind = optind - 1; + + /* When `optind' is misused, in this fashion, we also abandon any + * residual text in the argument we had been parsing; this is done + * without any further processing of such abandoned text, assuming + * that the caller is equipped to handle it appropriately. + */ + nextchar = NULL; + } + + if( nextchar && *nextchar ) + { + /* we are parsing a standard, or short format, option argument ... + */ + const CHAR *optchar; + if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL ) + { + /* we have identified it as valid ... + */ + if( optchar[1] == getopt_takes_argument ) + { + /* and determined that it requires an associated argument ... + */ + if( ! *(optarg = (char *)(nextchar)) ) + { + /* the argument is NOT attached ... + */ + if( optchar[2] == getopt_takes_argument ) + /* + * but this GNU extension marks it as optional, + * so we don't provide one on this occasion. + */ + optarg = NULL; + + /* otherwise this option takes a mandatory argument, + * so, provided there is one available ... + */ + else if( (argc - argind) > 1 ) + /* + * we take the following command line argument, + * as the appropriate option argument. + */ + optarg = argv[++argind]; + + /* but if no further argument is available, + * then there is nothing we can do, except for + * issuing the requisite diagnostic message. + */ + else + { + complain( "option requires an argument -- %c", optopt ); + return getopt_missing_arg( optstring ); + } + } + optind = argind + 1; + nextchar = NULL; + } + else + optarg = NULL; + optind = (nextchar && *nextchar) ? argind : argind + 1; + return optopt; + } + /* if we didn't find a valid match for the specified option character, + * then we fall through to here, so take appropriate diagnostic action. + */ + if( mode == getopt_mode_long_only ) + { + complain( "unrecognised option `-%s'", --nextchar ); + nextchar = NULL; + optopt = 0; + } + else + complain( "invalid option -- %c", optopt ); + optind = (nextchar && *nextchar) ? argind : argind + 1; + return getopt_unknown; + } + + if( optmark > optbase ) + { + /* This can happen, in GNU parsing mode ONLY, when we have + * skipped over non-option arguments, and found a subsequent + * option argument; in this case we permute the arguments. + */ + int index; + /* + * `optspan' specifies the number of contiguous arguments + * which are spanned by the current option, and so must be + * moved together during permutation. + */ + const int optspan = argind - optmark + 1; + /* + * we use `this_arg' to store these temporarily. + */ + CHAR **this_arg = malloc(sizeof(CHAR*) * optspan); + /* + * we cannot manipulate `argv' directly, since the `getopt' + * API prototypes it as `read-only'; this cast to `arglist' + * allows us to work around that restriction. + */ + CHAR **arglist = (char **)(argv); + + /* save temporary copies of the arguments which are associated + * with the current option ... + */ + for( index = 0; index < optspan; ++index ) + this_arg[index] = arglist[optmark + index]; + + /* move all preceding non-option arguments to the right, + * overwriting these saved arguments, while making space + * to replace them in their permuted location. + */ + for( --optmark; optmark >= optbase; --optmark ) + arglist[optmark + optspan] = arglist[optmark]; + + /* restore the temporarily saved option arguments to + * their permuted location. + */ + for( index = 0; index < optspan; ++index ) + arglist[optbase + index] = this_arg[index]; + + /* adjust `optbase', to account for the relocated option. + */ + optbase += optspan; + + free(this_arg); + } + + else + /* no permutation occurred ... + * simply adjust `optbase' for all options parsed so far. + */ + optbase = argind + 1; + + /* enter main parsing loop ... + */ + while( argc > ++argind ) + { + /* inspect each argument in turn, identifying possible options ... + */ + if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar ) + { + /* we've found a candidate option argument ... */ + + if( is_switchar( *nextchar ) ) + { + /* it's a double hyphen argument ... */ + + const CHAR *refchar = nextchar; + if( *++refchar ) + { + /* and it looks like a long format option ... + * `getopt_long' mode must be active to accept it as such, + * `getopt_long_only' also qualifies, but we must downgrade + * it to force explicit handling as a long format option. + */ + if( mode >= getopt_mode_long ) + { + nextchar = refchar; + mode = getopt_mode_long; + } + } + else + { + /* this is an explicit `--' end of options marker, so wrap up now! + */ + if( optmark > optbase ) + { + /* permuting the argument list as necessary ... + * (note use of `this_arg' and `arglist', as above). + */ + CHAR *this_arg = argv[optmark]; + CHAR **arglist = (CHAR **)(argv); + + /* move all preceding non-option arguments to the right ... + */ + do arglist[optmark] = arglist[optmark - 1]; + while( optmark-- > optbase ); + + /* reinstate the `--' marker, in its permuted location. + */ + arglist[optbase] = this_arg; + } + /* ... before finally bumping `optbase' past the `--' marker, + * and returning the `all done' completion indicator. + */ + optind = ++optbase; + return getopt_all_done; + } + } + else if( mode < getopt_mode_long_only ) + { + /* it's not an explicit long option, and `getopt_long_only' isn't active, + * so we must explicitly try to match it as a short option. + */ + mode = getopt_mode_standard; + } + + if( mode >= getopt_mode_long ) + { + /* the current argument is a long form option, (either explicitly, + * introduced by a double hyphen, or implicitly because we were called + * by `getopt_long_only'); this is where we parse it. + */ + int lookup; + int matched = -1; + + /* we need to fetch the `extra' function arguments, which are + * specified for the `getopt_long' APIs. + */ + va_list refptr; + struct option *longopts; + int *optindex; + va_start( refptr, optstring ); + longopts = va_arg( refptr, struct option * ); + optindex = va_arg( refptr, int * ); + va_end( refptr ); + + /* ensuring that `optarg' does not inherit any junk, from parsing + * preceding arguments ... + */ + optarg = NULL; + for( lookup = 0; longopts && longopts[lookup].name; ++lookup ) + { + /* scan the list of defined long form options ... + */ + switch( getopt_match_long( nextchar, longopts[lookup].name ) ) + { + /* looking for possible matches for the current argument. + */ + case getopt_exact_match: + /* + * when an exact match is found, + * return it immediately, setting `nextchar' to NULL, + * to ensure we don't mistakenly try to match any + * subsequent characters as short form options. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, lookup, optindex, optstring ); + + case getopt_abbreviated_match: + /* + * but, for a partial (initial substring) match ... + */ + if( matched >= 0 ) + { + /* if this is not the first, then we have an ambiguity ... + */ + if( (mode == getopt_mode_long_only) + /* + * However, in the case of getopt_long_only(), if + * the entire ambiguously matched string represents + * a valid short option specification, then we may + * proceed to interpret it as such. + */ + && getopt_verify( nextchar, optstring ) ) + return getopt_parse( mode, argc, argv, optstring ); + + /* If we get to here, then the ambiguously matched + * partial long option isn't valid for short option + * evaluation; reset parser context to resume with + * the following command line argument, diagnose + * ambiguity, and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "option `%s' is ambiguous", argv[argind] ); + return getopt_unknown; + } + /* otherwise just note that we've found a possible match ... + */ + matched = lookup; + } + } + if( matched >= 0 ) + { + /* if we get to here, then we found exactly one partial match, + * so return it, as for an exact match. + */ + nextchar = NULL; + return getopt_resolved( mode, argc, argv, &argind, + longopts, matched, optindex, optstring ); + } + /* if here, then we had what SHOULD have been a long form option, + * but it is unmatched ... + */ + if( (mode < getopt_mode_long_only) + /* + * ... although paradoxically, `mode == getopt_mode_long_only' + * allows us to still try to match it as a short form option. + */ + || (getopt_verify( nextchar, optstring ) == 0) ) + { + /* When it cannot be matched, reset the parsing context to + * resume from the next argument, diagnose the failed match, + * and bail out. + */ + optopt = 0; + nextchar = NULL; + optind = argind + 1; + complain( "unrecognised option `%s'", argv[argind] ); + return getopt_unknown; + } + } + /* fall through to handle standard short form options... + * when the option argument format is neither explictly identified + * as long, nor implicitly matched as such, and the argument isn't + * just a bare hyphen, (which isn't an option), then we make one + * recursive call to explicitly interpret it as short format. + */ + if( *nextchar ) + return getopt_parse( mode, argc, argv, optstring ); + } + /* if we get to here, then we've parsed a non-option argument ... + * in GNU compatibility mode, we step over it, so we can permute + * any subsequent option arguments, but ... + */ + if( *optstring == getopt_switchar ) + { + /* if `optstring' begins with a `-' character, this special + * GNU specific behaviour requires us to return the non-option + * arguments in strict order, as pseudo-arguments to a special + * option, with return value defined as `getopt_ordered'. + */ + nextchar = NULL; + optind = argind + 1; + optarg = argv[argind]; + return getopt_ordered; + } + if( getopt_conventions( *optstring ) & getopt_posixly_correct ) + /* + * otherwise ... + * for POSIXLY_CORRECT behaviour, or if `optstring' begins with + * a `+' character, then we break out of the parsing loop, so that + * the scan ends at the current argument, with no permutation. + */ + break; + } + /* fall through when all arguments have been evaluated, + */ + optind = optbase; + return getopt_all_done; +} + +/* All three public API entry points are trivially defined, + * in terms of the internal `getopt_parse' function. + */ +int getopt( getopt_std_args ) +{ + return getopt_parse( getopt_mode_standard, argc, argv, optstring ); +} + +int getopt_long( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index ); +} + +int getopt_long_only( getopt_std_args, const struct option *opts, int *index ) +{ + return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index ); +} + +#ifdef __weak_alias +/* + * These Microsnot style uglified aliases are provided for compatibility + * with the previous MinGW implementation of the getopt API. + */ +__weak_alias( getopt, _getopt ) +__weak_alias( getopt_long, _getopt_long ) +__weak_alias( getopt_long_only, _getopt_long_only ) +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ -- cgit v1.2.3